diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 80717b4fd..6e56dc748 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,25 +1,25 @@ - - - - - -## [FEATURE] _REPLACE THIS WITH A BRIEF SUMMARY OF THE SUGGESTED SNIPPET_ -**Category:** -### Description - - - - - -## [BUG] _REPLACE THIS WITH A BRIEF SUMMARY OF YOUR ISSUE_ -### Expected Snippet Behavior - - - -### Current Snippet Behavior - - - -### Possible Solution - - + + + + + +## [FEATURE] _REPLACE THIS WITH A BRIEF SUMMARY OF THE SUGGESTED SNIPPET_ +**Category:** +### Description + + + + + +## [BUG] _REPLACE THIS WITH A BRIEF SUMMARY OF YOUR ISSUE_ +### Expected Snippet Behavior + + + +### Current Snippet Behavior + + + +### Possible Solution + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d768fd4d5..e4d8fedac 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,27 +1,27 @@ - - - - -## Description - -**Resolves** #(issue number) - -## What does your PR belong to? -- [ ] Website -- [ ] Snippets -- [ ] General / Things regarding the repository (like CI Integration) - -## Types of changes -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] Enhancement (non-breaking improvement of a snippet) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to change) - -## Checklist: - -- [ ] My code follows the code style of this project. -- [ ] My change requires a change to the documentation. -- [ ] I have updated the documentation accordingly. -- [ ] I have checked that the changes are working properly -- [ ] I have checked that there isn't any PR doing the same -- [ ] I have read the **CONTRIBUTING** document. + + + + +## Description + +**Resolves** #(issue number) + +## What does your PR belong to? +- [ ] Website +- [ ] Snippets +- [ ] General / Things regarding the repository (like CI Integration) + +## Types of changes +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] Enhancement (non-breaking improvement of a snippet) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Checklist: + +- [ ] My code follows the code style of this project. +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have checked that the changes are working properly +- [ ] I have checked that there isn't any PR doing the same +- [ ] I have read the **CONTRIBUTING** document. diff --git a/.gitignore b/.gitignore index c18dd8d83..58200d4d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -__pycache__/ +__pycache__/ diff --git a/.travis.yml b/.travis.yml index 11a0b06ac..e1957f877 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,20 @@ -language: python -cache: - directories: - - __pycache__ -python: -- "3.6" -before_install: -- sudo pip install -r requirements.txt -script: -- python scripts/lint.py -- python scripts/readme.py -- python scripts/tdd.py -- python3 website/main.py -after_success: -- chmod +x .travis/push.sh -- .travis/push.sh -group: deprecated-2017Q4 -env: - global: - - secure: RucoyHikFKD7yQq7FBHxOpwYSHSFYUO7QS/5VEXvU55AMnHwB97aI0DcQSMa+XHaSFVsqd4fR7nAP+5H6GMW/lUhIdeXIGzehgBTfuNeQmng2djGgS1lWY9fEOsn2XEL7JlXMi2P5YdZDpOAfiiLqT3W8EaCWDdV60tkizbSQhig2R3exI/649AjmGkIws+NqoYqrEfNpnTvgxJkp2jNuKfBkr0aaVdYuxdI6Kf2KnipEeuKsKJFds+tTjduEUKTg7I8lNSB+tQ9wIHNTDZffZrzODzE2esAZtnflxhkGQ6q7fW8DEj0rheuer+yD4WBWfph1CIxTL6B3VZgT6XQXCu09XzqgRUack0KIS6SBRKjRYJymH3eKNlxZGPpk4s90bX0Qo0a0vvcT4g/iejyVb917pcn2LjRZmmsFQUfJOcCJgU6EUvqNpfM9SWV8fJhaPOacvUnzDxFav3eRdDHaZYgXf0tzJfLAjsTv7rFbLZEnpqtvyKbHrXYLf9sICyPlHbCy4L5KAfguu735v0YPXko5Aabl6PvGcfafyLxVUb/0Y5ot3pLtGVJflfHeqYz8qbkoqp5RovSvTXntx/vVlx20TSE/rQP2l6JUNt98sGFJ+yOZ3SkMnyMdjE1YqeEngxZdzukec2SM3PtnaWxSbxV8Ue1XnM8D5nzhTf4UI8= +language: python +cache: + directories: + - __pycache__ +python: +- "3.6" +before_install: +- sudo pip install -r requirements.txt +script: +- python scripts/lint.py +- python scripts/readme.py +- python scripts/tdd.py +- python3 website/main.py +after_success: +- chmod +x .travis/push.sh +- .travis/push.sh +group: deprecated-2017Q4 +env: + global: + - secure: RucoyHikFKD7yQq7FBHxOpwYSHSFYUO7QS/5VEXvU55AMnHwB97aI0DcQSMa+XHaSFVsqd4fR7nAP+5H6GMW/lUhIdeXIGzehgBTfuNeQmng2djGgS1lWY9fEOsn2XEL7JlXMi2P5YdZDpOAfiiLqT3W8EaCWDdV60tkizbSQhig2R3exI/649AjmGkIws+NqoYqrEfNpnTvgxJkp2jNuKfBkr0aaVdYuxdI6Kf2KnipEeuKsKJFds+tTjduEUKTg7I8lNSB+tQ9wIHNTDZffZrzODzE2esAZtnflxhkGQ6q7fW8DEj0rheuer+yD4WBWfph1CIxTL6B3VZgT6XQXCu09XzqgRUack0KIS6SBRKjRYJymH3eKNlxZGPpk4s90bX0Qo0a0vvcT4g/iejyVb917pcn2LjRZmmsFQUfJOcCJgU6EUvqNpfM9SWV8fJhaPOacvUnzDxFav3eRdDHaZYgXf0tzJfLAjsTv7rFbLZEnpqtvyKbHrXYLf9sICyPlHbCy4L5KAfguu735v0YPXko5Aabl6PvGcfafyLxVUb/0Y5ot3pLtGVJflfHeqYz8qbkoqp5RovSvTXntx/vVlx20TSE/rQP2l6JUNt98sGFJ+yOZ3SkMnyMdjE1YqeEngxZdzukec2SM3PtnaWxSbxV8Ue1XnM8D5nzhTf4UI8= diff --git a/.travis/push.sh b/.travis/push.sh index e6a4e9bc2..96d8ca2a8 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -1,44 +1,44 @@ -#!/bin/bash -setup_git() { - git config --global user.email "mst10041967@gmail.com" - git config --global user.name "Rohit Tanwar" -} - -commit_website_files() { - if [ $TRAVIS_EVENT_TYPE != "pull_request" ]; then - if [ $TRAVIS_BRANCH == "master" ]; then - git checkout master - echo "Committing to master branch..." - git add -A - echo "All files added" - git status - if [ $TRAVIS_EVENT_TYPE == "cron" ]; then - git commit --message "Travis build: $TRAVIS_BUILD_NUMBER [cron]" - elif [ $TRAVIS_EVENT_TYPE == "api" ]; then - git commit --message "Travis build: $TRAVIS_BUILD_NUMBER [custom]" - else - git commit --message "Travis build: $TRAVIS_BUILD_NUMBER" - fi - echo "Files commited" - git status - fi - fi -} - -upload_files() { - if [ $TRAVIS_EVENT_TYPE != "pull_request" ]; then - if [ $TRAVIS_BRANCH == "master" ]; then - echo "Pushing to master branch..." - git push --force "https://${GH_TOKEN}@github.com/kriadmin/30-seconds-of-python-code.git" master > /dev/null 2>&1 - echo "Pushing done" - echo "Pushing to website" - git subtree push --prefix website "https://${GH_TOKEN}@github.com/kriadmin/30-seconds-of-python-code.git" website - echo "Pushed to master branch" - git status - fi - fi -} - -setup_git -commit_website_files -upload_files +#!/bin/bash +setup_git() { + git config --global user.email "mst10041967@gmail.com" + git config --global user.name "Rohit Tanwar" +} + +commit_website_files() { + if [ $TRAVIS_EVENT_TYPE != "pull_request" ]; then + if [ $TRAVIS_BRANCH == "master" ]; then + git checkout master + echo "Committing to master branch..." + git add -A + echo "All files added" + git status + if [ $TRAVIS_EVENT_TYPE == "cron" ]; then + git commit --message "Travis build: $TRAVIS_BUILD_NUMBER [cron]" + elif [ $TRAVIS_EVENT_TYPE == "api" ]; then + git commit --message "Travis build: $TRAVIS_BUILD_NUMBER [custom]" + else + git commit --message "Travis build: $TRAVIS_BUILD_NUMBER" + fi + echo "Files commited" + git status + fi + fi +} + +upload_files() { + if [ $TRAVIS_EVENT_TYPE != "pull_request" ]; then + if [ $TRAVIS_BRANCH == "master" ]; then + echo "Pushing to master branch..." + git push --force "https://${GH_TOKEN}@github.com/kriadmin/30-seconds-of-python-code.git" master > /dev/null 2>&1 + echo "Pushing done" + echo "Pushing to website" + git subtree push --prefix website "https://${GH_TOKEN}@github.com/kriadmin/30-seconds-of-python-code.git" website + echo "Pushed to master branch" + git status + fi + fi +} + +setup_git +commit_website_files +upload_files diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 7e28edb1d..0e3d4ccc7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,73 +1,73 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [mst10041967@gmail.com]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [mst10041967@gmail.com]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3c3656cb..57677ca6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,70 +1,70 @@ -## Contributing - -**30 seconds of python code** is a community effort, so feel free to contribute in any way you can. Every contribution helps! - -Here's what you can do to help: - -- [Open issues](https://github.com/kriadmin/30-seconds-of-python-code/issues/new) for things you want to see added or modified. -- Be part of the discussion by helping out with [existing issues](https://github.com/kriadmin/30-seconds-of-python-code/issues) or talking on our [gitter channel](https://gitter.im/30-seconds-of-python-code/Lobby). -- Submit [pull requests](https://github.com/kriadmin/30-seconds-of-python-code/pulls) with snippets you have created (see below for guidelines). -- Fix typos in existing snippets, improve snippet descriptions and explanations or provide better examples. -- Before submitting a PR for any new snippets go through [this](https://github.com/kriadmin/30-seconds-of-python-code/projects/1) project. If your snippet is not there, then go ahead and submit a PR. Else if it is in the done column, sorry it has been already implemented.If it is in any other column submit a PR and give the card's link in the description section of PR. -- **Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) - -### Snippet submission and Pull request guidelines - -- **DO NOT MODIFY THE README.md FILE!** Make changes to individual snippet files. The `travis_ci` automatically builds the `README.md` file when your pull request is merged. -- **Snippet filenames** must correspond to the title of the snippet and to the function name. For example, if your snippet is titled `### awesome_snippet` the filename should be `awesome_snippet.md` and the function name should be `awesome_snippet`. - - Use `snake_case`, not `kebab-case` or `camelCase`. - - Avoid capitalization of words. - - Please follow the (PEP8)[https://www.python.org/dev/peps/pep-0008/] guidelines. -- **Snippet titles** should have be the same as the name of the function that is present in the snippet. - - All snippet titles must be prefixed with `###` and be at the very first line of your snippet. - - Snippet titles must be unique (although if you cannot find a better title, just add some placeholder at the end of the filename and title and we will figure it out). - - Follow snippet titles with an empty line. -- **Snippet descriptions** must be short and to the point. Try to explain *what* the snippet does and *how* the snippet works and what **inbuilt** features/modules are used. Remember to include what functions you are using and why. - - Follow snippet descriptions with an empty line. -- **Snippets _CAN NOT_ use any external modules**. Only the modules and function inbuilt in `python 3.6` shall be used. -- **Snippet code** must be enclosed inside ` ```python ` and ` ``` `. - - Remember to start your snippet's code on a new line below the opening backticks. - - You can write the code in any style you like but eventually it will be formated by our prettifier so the formatting will change. Just make sure to have consistent spacing. - - Try to keep your snippets' code short and to the point. Use modern techniques and features. Make sure to test your code before submitting. - - All snippets must be followed by one (more if necessary) test case after the code, in a new block enclosed inside ` ```python ` and ` ``` `. The syntax for this is `my_function('test_input') # 'test_output'`. Use multiline examples only if necessary. - - Try to make your function name unique, so that it does not conflict with existing snippets. - - Snippet functions do not have to handle errors in input, unless it's necessary (e.g. a mathematical function that cannot be extended to negative numbers should handle negative input appropriately). -- Snippets should be short (usually below 20 - 30 lines). If your snippet is longer than that, you can still submit it, and we can help you shorten it or figure out ways to improve it. -- Snippets *should* solve real-world problems, no matter how simple. -- Snippets *should* be abstract enough to be applied to different scenarios. -- It is not mandatory but highly appreciated if you provide **test cases** and/or performance tests. -- You can start creating a new snippet, by using the [snippet template](snippet_template.md) to format your snippets. -- Updating the README.md file should only be done by altering the scripts in the **scripts** folder or altering their relative static parts in the **static-parts** folder. -- You may tag your snippet in tag_databse although it is _not_ necessary. -- You may also run `scripts\lint.py` & `scripts\readme.py`. - - +## Contributing + +**30 seconds of python code** is a community effort, so feel free to contribute in any way you can. Every contribution helps! + +Here's what you can do to help: + +- [Open issues](https://github.com/kriadmin/30-seconds-of-python-code/issues/new) for things you want to see added or modified. +- Be part of the discussion by helping out with [existing issues](https://github.com/kriadmin/30-seconds-of-python-code/issues) or talking on our [gitter channel](https://gitter.im/30-seconds-of-python-code/Lobby). +- Submit [pull requests](https://github.com/kriadmin/30-seconds-of-python-code/pulls) with snippets you have created (see below for guidelines). +- Fix typos in existing snippets, improve snippet descriptions and explanations or provide better examples. +- Before submitting a PR for any new snippets go through [this](https://github.com/kriadmin/30-seconds-of-python-code/projects/1) project. If your snippet is not there, then go ahead and submit a PR. Else if it is in the done column, sorry it has been already implemented.If it is in any other column submit a PR and give the card's link in the description section of PR. +- **Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) + +### Snippet submission and Pull request guidelines + +- **DO NOT MODIFY THE README.md FILE!** Make changes to individual snippet files. The `travis_ci` automatically builds the `README.md` file when your pull request is merged. +- **Snippet filenames** must correspond to the title of the snippet and to the function name. For example, if your snippet is titled `### awesome_snippet` the filename should be `awesome_snippet.md` and the function name should be `awesome_snippet`. + - Use `snake_case`, not `kebab-case` or `camelCase`. + - Avoid capitalization of words. + - Please follow the (PEP8)[https://www.python.org/dev/peps/pep-0008/] guidelines. +- **Snippet titles** should have be the same as the name of the function that is present in the snippet. + - All snippet titles must be prefixed with `###` and be at the very first line of your snippet. + - Snippet titles must be unique (although if you cannot find a better title, just add some placeholder at the end of the filename and title and we will figure it out). + - Follow snippet titles with an empty line. +- **Snippet descriptions** must be short and to the point. Try to explain *what* the snippet does and *how* the snippet works and what **inbuilt** features/modules are used. Remember to include what functions you are using and why. + - Follow snippet descriptions with an empty line. +- **Snippets _CAN NOT_ use any external modules**. Only the modules and function inbuilt in `python 3.6` shall be used. +- **Snippet code** must be enclosed inside ` ```python ` and ` ``` `. + - Remember to start your snippet's code on a new line below the opening backticks. + - You can write the code in any style you like but eventually it will be formated by our prettifier so the formatting will change. Just make sure to have consistent spacing. + - Try to keep your snippets' code short and to the point. Use modern techniques and features. Make sure to test your code before submitting. + - All snippets must be followed by one (more if necessary) test case after the code, in a new block enclosed inside ` ```python ` and ` ``` `. The syntax for this is `my_function('test_input') # 'test_output'`. Use multiline examples only if necessary. + - Try to make your function name unique, so that it does not conflict with existing snippets. + - Snippet functions do not have to handle errors in input, unless it's necessary (e.g. a mathematical function that cannot be extended to negative numbers should handle negative input appropriately). +- Snippets should be short (usually below 20 - 30 lines). If your snippet is longer than that, you can still submit it, and we can help you shorten it or figure out ways to improve it. +- Snippets *should* solve real-world problems, no matter how simple. +- Snippets *should* be abstract enough to be applied to different scenarios. +- It is not mandatory but highly appreciated if you provide **test cases** and/or performance tests. +- You can start creating a new snippet, by using the [snippet template](snippet_template.md) to format your snippets. +- Updating the README.md file should only be done by altering the scripts in the **scripts** folder or altering their relative static parts in the **static-parts** folder. +- You may tag your snippet in tag_databse although it is _not_ necessary. +- You may also run `scripts\lint.py` & `scripts\readme.py`. + + diff --git a/LICENSE b/LICENSE index 94a9ed024..818433ecc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 1d6d0a509..298e2a05c 100644 --- a/README.md +++ b/README.md @@ -1,758 +1,758 @@ -![Logo](/icon.png) - -# 30-seconds-of-python-code -[![License](https://img.shields.io/aur/license/yaourt.svg)](https://github.com/kriadmin/30-seconds-of-python-code/blob/master/LICENSE) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-python-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Travis Build](https://travis-ci.org/kriadmin/30-seconds-of-python-code.svg?branch=master)](https://travis-ci.org/kriadmin/30-seconds-of-python-code) [![Insight.io](https://img.shields.io/badge/insight.io-Ready-brightgreen.svg)](https://insight.io/github.com/kriadmin/30-seconds-of-python-code/tree/master/?source=0) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_shield) - ->Python implementation of 30-seconds-of-code. - -**Note**:- This is in no way affiliated with the original [30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code/). - - -## Table of Contents -### :heavy_division_sign: Math - -
View contents
- -### :books: List - -
View contents
- -### :scroll: String - -
View contents
- -
- -## :heavy_division_sign: Math - -### average - -:information_source: Already implemented via `statistics.mean`. `statistics.mean` takes an array as an argument whereas this function takes variadic arguments. - -Returns the average of two or more numbers. - -Takes the sum of all the `args` and divides it by `len(args)`. The secind argument `0.0` in sum is to handle floating point division in `python2`. - -```py -def average(*args): - return sum(args, 0.0) / len(args) - - ``` - -
View Examples - -```py - -average(*[1, 2, 3]) # 2.0 -average(1, 2, 3) # 2.0 - -``` -
- -
:arrow_up: Back to top - -### factorial - -Calculates the factorial of a number. - -Use recursion. If `num` is less than or equal to `1`, return `1`. Otherwise, return the product of `num` and the factorial of `num - 1`. Throws an exception if `num` is a negative or a floating point number. - -```py -def factorial(num): - if not ((num >= 0) & (num % 1 == 0)): - raise Exception( - f"Number( {num} ) can't be floating point or negative ") - return 1 if num == 0 else num * factorial(num - 1) - - ``` -
View Examples - -```py - -factorial(6) # 720 - -``` -
- -
:arrow_up: Back to top - -### gcd - -:information_source: `math.gcd` works with only two numbers - -Calculates the greatest common divisor between two or more numbers/lists. - -The `helperGcdfunction` uses recursion. Base case is when `y` equals `0`. In this case, return `x`. Otherwise, return the GCD of `y` and the remainder of the division `x/y`. - -Uses the reduce function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. - -```py -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def gcd(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - - return reduce((lambda x, y: _gcd(x, y)), numbers) - - ``` - - -
View Examples - -```py - -gcd(8,36) # 4 - -``` -
- -
:arrow_up: Back to top - -### lcm - -Returns the least common multiple of two or more numbers. - -Use the `greatest common divisor (GCD)` formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. The GCD formula uses recursion. - -Uses `reduce` function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. - -```py -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def lcm(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - - def _lcm(x, y): - return x * y / _gcd(x, y) - - return reduce((lambda x, y: _lcm(x, y)), numbers) - - ``` - - -
View Examples - -```py - -lcm(12, 7) # 84 -lcm([1, 3, 4], 5) # 60 - -``` -
- -
:arrow_up: Back to top - -### max_n - -Returns the `n` maximum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in descending order). - -Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order and then use `list.reverse()` reverse it to make it descending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array - -```py -from copy import deepcopy - - -def max_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() - numbers.reverse() - return numbers[:n] - - ``` - -
View Examples - -```py - -max_n([1, 2, 3]) # [3] -max_n([1, 2, 3], 2) # [3,2] - -``` -
- -
:arrow_up: Back to top - -### min_n - -Returns the `n` minimum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in ascending order). - -Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array - -```py -from copy import deepcopy - - -def min_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() - return numbers[:n] - - ``` - -
View Examples - -```py - -min_n([1, 2, 3]) # [1] -min_n([1, 2, 3], 2) # [1,2] - -``` -
- -
:arrow_up: Back to top - -## :books: List - -### chunk - -Chunks an array into smaller lists of a specified size. - -Uses `range` to create a list of desired size. Then use `map` on this list and fill it with splices of `arr`. - -```py -from math import ceil - - -def chunk(arr, size): - return list( - map(lambda x: arr[x * size:x * size + size], - list(range(0, ceil(len(arr) / size))))) - - ``` - -
View Examples - -```py - -chunk([1,2,3,4,5],2) # [[1,2],[3,4],5] - -``` -
- -
:arrow_up: Back to top - -### compact - -Removes falsey values from a list. - -Use `filter()` to filter out falsey values (False, None, 0, and ""). - -```py -def compact(arr): - return list(filter(lambda x: bool(x), arr)) - - ``` - -
View Examples - -```py - -compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ] - -``` -
- -
:arrow_up: Back to top - -### count_by - -:information_source: Already implemented via `collections.Counter` - -Groups the elements of a list based on the given function and returns the count of elements in each group. - -Use `map()` to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs. - -```py -def count_by(arr, fn=lambda x: x): - key = {} - for el in map(fn, arr): - key[el] = 0 if not el in key else key[el] - key[el] += 1 - return key - - ``` - -
View Examples - -```py - -from math import floor -count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2} -count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1} - -``` -
- -
:arrow_up: Back to top - -### count_occurences - -:information_source: Already implemented via `list.count()`. - -Counts the occurrences of a value in an list. - -Uses the `reduce` functin from built-in module `functools` to increment a counter each time you encounter the specific value inside the list. - -```py -def count_occurences(arr, val): - return reduce( - (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), - arr) - - ``` - -
View Examples - -```py - -count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3 - -``` -
- -
:arrow_up: Back to top - -### deep_flatten - -Deep flattens a list. - -Use recursion. Use `list.extend()` with an empty array (`result`) and the spread function to flatten a list. Recursively flatten each element that is a list. - -```py -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def deep_flatten(arr): - result = [] - result.extend( - spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) - return result - - ``` - -
View Examples - -```py - -deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5] - -``` -
- -
:arrow_up: Back to top - -### difference - -Returns the difference between two arrays. - -Create a `set` from `b`, then use list comprehension to only keep values not contained in `b` - -```py -def difference(a, b): - b = set(b) - return [item for item in a if item not in b] - - ``` -
View Examples - -```py - -difference([1, 2, 3], [1, 2, 4]) # [3] - -``` -
- -
:arrow_up: Back to top - -### difference_by - -Returns the difference between two list, after applying the provided function to each list element of both. - -Create a `set` by applying `fn` to each element in `b`, then use list comprehension in combination with fn on a to only keep values not contained in the previously created `set`. - -```py -def difference_by(a, b, fn): - b = set(map(fn, b)) - return [item for item in a if fn(item) not in b] - - ``` - -
View Examples - -```py - -from math import floor -difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2] -difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ] - -``` -
- -
:arrow_up: Back to top - -### shuffle - -:information_source: The same algorithm is already implemented via `random.shuffle`. - -Randomizes the order of the values of an list, returning a new list. - -Uses the [Fisher-Yates algorithm](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) to reorder the elements of the list. - -```py -from copy import deepcopy -from random import randint - - -def shuffle(arr): - temp_arr = deepcopy(arr) - m = len(temp_arr) - while (m): - m -= 1 - i = randint(0, m) - temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] - return temp_arr - - ``` - -
View Examples - -```py - -foo = [1,2,3] -shuffle(foo) # [2,3,1] , foo = [1,2,3] - -``` -
- -
:arrow_up: Back to top - -### spread - -Implements javascript's `[].concat(...arr)`. Flattens the list(non-deep) and returns an list. - -```py -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - ``` - - -
View Examples - -```py - -spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9] - -``` -
- -
:arrow_up: Back to top - -### zip - -:information_source: Already implemented via `itertools.zip_longest()` - -Creates a list of elements, grouped based on the position in the original lists. - -Use `max` combined with `list comprehension` to get the length of the longest list in the arguments. Loops for `max_length` times grouping elements. If lengths of `lists` vary `fill_value` is used. By default `fill_value` is `None`. - -```py -def zip(*args, fillvalue=None): - max_length = max([len(arr) for arr in args]) - result = [] - for i in range(max_length): - result.append([ - args[k][i] if i < len(args[k]) else None for k in range(len(args)) - ]) - return result - - ``` - -
View Examples - -```py - -zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]] -zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]] -zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]] - -``` -
- -
:arrow_up: Back to top - -## :scroll: String - -### byte_size - -Returns the length of a string in bytes. - -`utf-8` encodes a given string and find its length. - -```py -def byte_size(string): - return(len(string.encode('utf-8'))) - - ``` - -
View Examples - -```py - -byte_size('😀') # 4 -byte_size('Hello World') # 11 - -``` -
- -
:arrow_up: Back to top - -### capitalize - -Capitalizes the first letter of a string. - -Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `lower_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. - -```py -def capitalize(string, lower_rest=False): - return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:]) - - ``` - -
View Examples - -```py - -capitalize('fooBar') # 'FooBar' -capitalize('fooBar', True) # 'Foobar' - -``` -
- -
:arrow_up: Back to top - -### capitalize_every_word - -Capitalizes the first letter of every word in a string. - -Uses `str.title` to capitalize first letter of evry word in the string. - -```py -def capitalize_every_word(string): - return string.title() - - ``` - -
View Examples - -```py - -capitalize_every_word('hello world!') # 'Hello World!' - -``` -
- -
:arrow_up: Back to top - -### count_vowels - -Retuns `number` of vowels in provided `string`. - -Use a regular expression to count the number of vowels `(A, E, I, O, U)` in a string. - -```py -import re - - -def count_vowels(str): - return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE))) - - ``` - -
View Examples - -```py - -count_vowels('foobar') # 3 -count_vowels('gym') # 0 - -``` -
- -
:arrow_up: Back to top - -### decapitalize - -Decapitalizes the first letter of a string. - -Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `upper_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. - -```py -def decapitalize(string, upper_rest=False): - return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:]) - - ``` - -
View Examples - -```py - -decapitalize('FooBar') # 'fooBar' -decapitalize('FooBar', True) # 'fOOBAR' - -``` -
- -
:arrow_up: Back to top - -### is_lower_case - -Checks if a string is lower case. - -Convert the given string to lower case, using `str.lower()` method and compare it to the original. - -```py -def is_lower_case(str): - return str == str.lower() - - ``` - -
View Examples - -```py - -is_lower_case('abc') # True -is_lower_case('a3@$') # True -is_lower_case('Ab4') # False - -``` -
- -
:arrow_up: Back to top - -### is_upper_case - -Checks if a string is upper case. - -Convert the given string to upper case, using `str.upper()` method and compare it to the original. - -```py -def is_upper_case(str): - return str == str.upper() - - ``` - -
View Examples - -```py - -is_upper_case('ABC') # True -is_upper_case('a3@$') # True -is_upper_case('aB4') # False - -``` -
- -
:arrow_up: Back to top - -### palindrome - -Returns `True` if the given string is a palindrome, `False` otherwise. - -Convert string `str.lower()` and use `re.sub` to remove non-alphanumeric characters from it. Then compare the new string to the reversed. - -```py -def palindrome(string): - from re import sub - s = sub('[\W_]', '', string.lower()) - return s == s[::-1] - - ``` -
View Examples - -```py - -palindrome('taco cat') # True - -``` -
- -
:arrow_up: Back to top - - -## Credits - -*Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* - - - -## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_large) +![Logo](/icon.png) + +# 30-seconds-of-python-code +[![License](https://img.shields.io/aur/license/yaourt.svg)](https://github.com/kriadmin/30-seconds-of-python-code/blob/master/LICENSE) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-python-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Travis Build](https://travis-ci.org/kriadmin/30-seconds-of-python-code.svg?branch=master)](https://travis-ci.org/kriadmin/30-seconds-of-python-code) [![Insight.io](https://img.shields.io/badge/insight.io-Ready-brightgreen.svg)](https://insight.io/github.com/kriadmin/30-seconds-of-python-code/tree/master/?source=0) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_shield) + +>Python implementation of 30-seconds-of-code. + +**Note**:- This is in no way affiliated with the original [30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code/). + + +## Table of Contents +### :heavy_division_sign: Math + +
View contents
+ +### :books: List + +
View contents
+ +### :scroll: String + +
View contents
+ +
+ +## :heavy_division_sign: Math + +### average + +:information_source: Already implemented via `statistics.mean`. `statistics.mean` takes an array as an argument whereas this function takes variadic arguments. + +Returns the average of two or more numbers. + +Takes the sum of all the `args` and divides it by `len(args)`. The secind argument `0.0` in sum is to handle floating point division in `python2`. + +```py +def average(*args): + return sum(args, 0.0) / len(args) + + ``` + +
View Examples + +```py + +average(*[1, 2, 3]) # 2.0 +average(1, 2, 3) # 2.0 + +``` +
+ +
:arrow_up: Back to top + +### factorial + +Calculates the factorial of a number. + +Use recursion. If `num` is less than or equal to `1`, return `1`. Otherwise, return the product of `num` and the factorial of `num - 1`. Throws an exception if `num` is a negative or a floating point number. + +```py +def factorial(num): + if not ((num >= 0) & (num % 1 == 0)): + raise Exception( + f"Number( {num} ) can't be floating point or negative ") + return 1 if num == 0 else num * factorial(num - 1) + + ``` +
View Examples + +```py + +factorial(6) # 720 + +``` +
+ +
:arrow_up: Back to top + +### gcd + +:information_source: `math.gcd` works with only two numbers + +Calculates the greatest common divisor between two or more numbers/lists. + +The `helperGcdfunction` uses recursion. Base case is when `y` equals `0`. In this case, return `x`. Otherwise, return the GCD of `y` and the remainder of the division `x/y`. + +Uses the reduce function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. + +```py +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def gcd(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + + return reduce((lambda x, y: _gcd(x, y)), numbers) + + ``` + + +
View Examples + +```py + +gcd(8,36) # 4 + +``` +
+ +
:arrow_up: Back to top + +### lcm + +Returns the least common multiple of two or more numbers. + +Use the `greatest common divisor (GCD)` formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. The GCD formula uses recursion. + +Uses `reduce` function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. + +```py +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def lcm(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + + def _lcm(x, y): + return x * y / _gcd(x, y) + + return reduce((lambda x, y: _lcm(x, y)), numbers) + + ``` + + +
View Examples + +```py + +lcm(12, 7) # 84 +lcm([1, 3, 4], 5) # 60 + +``` +
+ +
:arrow_up: Back to top + +### max_n + +Returns the `n` maximum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in descending order). + +Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order and then use `list.reverse()` reverse it to make it descending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array + +```py +from copy import deepcopy + + +def max_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() + numbers.reverse() + return numbers[:n] + + ``` + +
View Examples + +```py + +max_n([1, 2, 3]) # [3] +max_n([1, 2, 3], 2) # [3,2] + +``` +
+ +
:arrow_up: Back to top + +### min_n + +Returns the `n` minimum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in ascending order). + +Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array + +```py +from copy import deepcopy + + +def min_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() + return numbers[:n] + + ``` + +
View Examples + +```py + +min_n([1, 2, 3]) # [1] +min_n([1, 2, 3], 2) # [1,2] + +``` +
+ +
:arrow_up: Back to top + +## :books: List + +### chunk + +Chunks an array into smaller lists of a specified size. + +Uses `range` to create a list of desired size. Then use `map` on this list and fill it with splices of `arr`. + +```py +from math import ceil + + +def chunk(arr, size): + return list( + map(lambda x: arr[x * size:x * size + size], + list(range(0, ceil(len(arr) / size))))) + + ``` + +
View Examples + +```py + +chunk([1,2,3,4,5],2) # [[1,2],[3,4],5] + +``` +
+ +
:arrow_up: Back to top + +### compact + +Removes falsey values from a list. + +Use `filter()` to filter out falsey values (False, None, 0, and ""). + +```py +def compact(arr): + return list(filter(lambda x: bool(x), arr)) + + ``` + +
View Examples + +```py + +compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ] + +``` +
+ +
:arrow_up: Back to top + +### count_by + +:information_source: Already implemented via `collections.Counter` + +Groups the elements of a list based on the given function and returns the count of elements in each group. + +Use `map()` to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs. + +```py +def count_by(arr, fn=lambda x: x): + key = {} + for el in map(fn, arr): + key[el] = 0 if not el in key else key[el] + key[el] += 1 + return key + + ``` + +
View Examples + +```py + +from math import floor +count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2} +count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1} + +``` +
+ +
:arrow_up: Back to top + +### count_occurences + +:information_source: Already implemented via `list.count()`. + +Counts the occurrences of a value in an list. + +Uses the `reduce` functin from built-in module `functools` to increment a counter each time you encounter the specific value inside the list. + +```py +def count_occurences(arr, val): + return reduce( + (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), + arr) + + ``` + +
View Examples + +```py + +count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3 + +``` +
+ +
:arrow_up: Back to top + +### deep_flatten + +Deep flattens a list. + +Use recursion. Use `list.extend()` with an empty array (`result`) and the spread function to flatten a list. Recursively flatten each element that is a list. + +```py +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def deep_flatten(arr): + result = [] + result.extend( + spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) + return result + + ``` + +
View Examples + +```py + +deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5] + +``` +
+ +
:arrow_up: Back to top + +### difference + +Returns the difference between two arrays. + +Create a `set` from `b`, then use list comprehension to only keep values not contained in `b` + +```py +def difference(a, b): + b = set(b) + return [item for item in a if item not in b] + + ``` +
View Examples + +```py + +difference([1, 2, 3], [1, 2, 4]) # [3] + +``` +
+ +
:arrow_up: Back to top + +### difference_by + +Returns the difference between two list, after applying the provided function to each list element of both. + +Create a `set` by applying `fn` to each element in `b`, then use list comprehension in combination with fn on a to only keep values not contained in the previously created `set`. + +```py +def difference_by(a, b, fn): + b = set(map(fn, b)) + return [item for item in a if fn(item) not in b] + + ``` + +
View Examples + +```py + +from math import floor +difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2] +difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ] + +``` +
+ +
:arrow_up: Back to top + +### shuffle + +:information_source: The same algorithm is already implemented via `random.shuffle`. + +Randomizes the order of the values of an list, returning a new list. + +Uses the [Fisher-Yates algorithm](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) to reorder the elements of the list. + +```py +from copy import deepcopy +from random import randint + + +def shuffle(arr): + temp_arr = deepcopy(arr) + m = len(temp_arr) + while (m): + m -= 1 + i = randint(0, m) + temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] + return temp_arr + + ``` + +
View Examples + +```py + +foo = [1,2,3] +shuffle(foo) # [2,3,1] , foo = [1,2,3] + +``` +
+ +
:arrow_up: Back to top + +### spread + +Implements javascript's `[].concat(...arr)`. Flattens the list(non-deep) and returns an list. + +```py +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + ``` + + +
View Examples + +```py + +spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9] + +``` +
+ +
:arrow_up: Back to top + +### zip + +:information_source: Already implemented via `itertools.zip_longest()` + +Creates a list of elements, grouped based on the position in the original lists. + +Use `max` combined with `list comprehension` to get the length of the longest list in the arguments. Loops for `max_length` times grouping elements. If lengths of `lists` vary `fill_value` is used. By default `fill_value` is `None`. + +```py +def zip(*args, fillvalue=None): + max_length = max([len(arr) for arr in args]) + result = [] + for i in range(max_length): + result.append([ + args[k][i] if i < len(args[k]) else None for k in range(len(args)) + ]) + return result + + ``` + +
View Examples + +```py + +zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]] +zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]] +zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]] + +``` +
+ +
:arrow_up: Back to top + +## :scroll: String + +### byte_size + +Returns the length of a string in bytes. + +`utf-8` encodes a given string and find its length. + +```py +def byte_size(string): + return(len(string.encode('utf-8'))) + + ``` + +
View Examples + +```py + +byte_size('😀') # 4 +byte_size('Hello World') # 11 + +``` +
+ +
:arrow_up: Back to top + +### capitalize + +Capitalizes the first letter of a string. + +Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `lower_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. + +```py +def capitalize(string, lower_rest=False): + return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:]) + + ``` + +
View Examples + +```py + +capitalize('fooBar') # 'FooBar' +capitalize('fooBar', True) # 'Foobar' + +``` +
+ +
:arrow_up: Back to top + +### capitalize_every_word + +Capitalizes the first letter of every word in a string. + +Uses `str.title` to capitalize first letter of evry word in the string. + +```py +def capitalize_every_word(string): + return string.title() + + ``` + +
View Examples + +```py + +capitalize_every_word('hello world!') # 'Hello World!' + +``` +
+ +
:arrow_up: Back to top + +### count_vowels + +Retuns `number` of vowels in provided `string`. + +Use a regular expression to count the number of vowels `(A, E, I, O, U)` in a string. + +```py +import re + + +def count_vowels(str): + return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE))) + + ``` + +
View Examples + +```py + +count_vowels('foobar') # 3 +count_vowels('gym') # 0 + +``` +
+ +
:arrow_up: Back to top + +### decapitalize + +Decapitalizes the first letter of a string. + +Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `upper_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. + +```py +def decapitalize(string, upper_rest=False): + return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:]) + + ``` + +
View Examples + +```py + +decapitalize('FooBar') # 'fooBar' +decapitalize('FooBar', True) # 'fOOBAR' + +``` +
+ +
:arrow_up: Back to top + +### is_lower_case + +Checks if a string is lower case. + +Convert the given string to lower case, using `str.lower()` method and compare it to the original. + +```py +def is_lower_case(str): + return str == str.lower() + + ``` + +
View Examples + +```py + +is_lower_case('abc') # True +is_lower_case('a3@$') # True +is_lower_case('Ab4') # False + +``` +
+ +
:arrow_up: Back to top + +### is_upper_case + +Checks if a string is upper case. + +Convert the given string to upper case, using `str.upper()` method and compare it to the original. + +```py +def is_upper_case(str): + return str == str.upper() + + ``` + +
View Examples + +```py + +is_upper_case('ABC') # True +is_upper_case('a3@$') # True +is_upper_case('aB4') # False + +``` +
+ +
:arrow_up: Back to top + +### palindrome + +Returns `True` if the given string is a palindrome, `False` otherwise. + +Convert string `str.lower()` and use `re.sub` to remove non-alphanumeric characters from it. Then compare the new string to the reversed. + +```py +def palindrome(string): + from re import sub + s = sub('[\W_]', '', string.lower()) + return s == s[::-1] + + ``` +
View Examples + +```py + +palindrome('taco cat') # True + +``` +
+ +
:arrow_up: Back to top + + +## Credits + +*Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* + + + +## License +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_large) diff --git a/config.ini b/config.ini index e8cde1dd7..0806a1204 100644 --- a/config.ini +++ b/config.ini @@ -1,2 +1,2 @@ -[tape] +[tape] python_files=*.test.py \ No newline at end of file diff --git a/contributor_database b/contributor_database new file mode 100644 index 000000000..17e428769 --- /dev/null +++ b/contributor_database @@ -0,0 +1,24 @@ +average:[Rohit Tanwar](@kriadmin) +chunk:[Rohit Tanwar](@kriadmin) +compact:[Rohit Tanwar](@kriadmin) +count_occurences:[Rohit Tanwar](@kriadmin) +count_vowels:[Rohit Tanwar](@kriadmin) +deep_flatten:[Rohit Tanwar](@kriadmin) +difference:[Rohit Tanwar](@kriadmin) +factorial:[Rohit Tanwar](@kriadmin) +gcd:[Rohit Tanwar](@kriadmin) +lcm:[Rohit Tanwar](@kriadmin) +max_n:[Rohit Tanwar](@kriadmin) +min_n:[Rohit Tanwar](@kriadmin) +shuffle:[Rohit Tanwar](@kriadmin) +spread:[Rohit Tanwar](@kriadmin) +zip:[Rohit Tanwar](@kriadmin) +byte_size:[Rohit Tanwar](@kriadmin) +capitalize:[Rohit Tanwar](@kriadmin) +capitalize_every_word:[Rohit Tanwar](@kriadmin) +decapitalize:[Rohit Tanwar](@kriadmin) +palindrome:[Rohit Tanwar](@kriadmin) +is_upper_case:[Rohit Tanwar](@kriadmin) +is_lower_case:[Rohit Tanwar](@kriadmin) +count_by:[Rohit Tanwar](@kriadmin) +difference_by:[Rohit Tanwar](@kriadmin) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c7b95a8e8..725cc5010 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,16 @@ -autopep8==1.3.3 -cffi==1.11.4 -click==6.7 -emoji==0.4.5 -Flask==0.12.2 -Flask-OAuth==0.12 -gunicorn==19.7.1 -httplib2==0.10.3 -itsdangerous==0.24 -Jinja2==2.10 -MarkupSafe==1.0 -misaka==2.1.0 -mistune==0.8.3 -oauth2==1.9.0.post1 -pycparser==2.18 +autopep8==1.3.3 +cffi==1.11.4 +click==6.7 +emoji==0.4.5 +Flask==0.12.2 +Flask-OAuth==0.12 +gunicorn==19.7.1 +httplib2==0.10.3 +itsdangerous==0.24 +Jinja2==2.10 +MarkupSafe==1.0 +misaka==2.1.0 +mistune==0.8.3 +oauth2==1.9.0.post1 +pycparser==2.18 Werkzeug==0.14.1 \ No newline at end of file diff --git a/scripts/lint.py b/scripts/lint.py index 4b255cdd9..aa1bfd992 100644 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -1,18 +1,18 @@ -import autopep8 -import re -import os -import sys -print(sys.version) -files = os.listdir('snippets') -codeRe = "```\s*python([\s\S]*?)```" -for file in files: - someFile = open("snippets/" + file) - fileData = someFile.read() - someFile.close() - originalCode = re.search(codeRe,fileData).group(0) - #print(re.split(codeRe,fileData)[0]) - formatedCode = '\n'+autopep8.fix_code(re.split(codeRe,fileData)[1]).strip()+'\n' - fileToSave = fileData.replace(originalCode,('```python'+formatedCode+'```')) - someFile = open("snippets/"+file,'w') - someFile.write(fileToSave) +import autopep8 +import re +import os +import sys +print(sys.version) +files = os.listdir('snippets') +codeRe = "```\s*python([\s\S]*?)```" +for file in files: + someFile = open("snippets/" + file) + fileData = someFile.read() + someFile.close() + originalCode = re.search(codeRe,fileData).group(0) + #print(re.split(codeRe,fileData)[0]) + formatedCode = '\n'+autopep8.fix_code(re.split(codeRe,fileData)[1]).strip()+'\n' + fileToSave = fileData.replace(originalCode,('```python'+formatedCode+'```')) + someFile = open("snippets/"+file,'w') + someFile.write(fileToSave) someFile.close() \ No newline at end of file diff --git a/scripts/readme.py b/scripts/readme.py index 584337e10..190a54eb8 100644 --- a/scripts/readme.py +++ b/scripts/readme.py @@ -1,51 +1,51 @@ -import re -codeRe = "```\s*python([\s\S]*?)```" -def title_case(str): - return str[:1].upper() + str[1:].lower() -EMOJIS = { - 'adapter': ':electric_plug:', - 'list': ':books:', - 'browser': ':globe_with_meridians:', - 'date': ':stopwatch:', - 'function': ':control_knobs:', - 'logic': ':crystal_ball:', - 'math': ':heavy_division_sign:', - 'media': ':tv:', - 'node': ':package:', - 'object': 'card_file_box', - 'string': ':scroll:', - 'type': ':page_with_curl:', - 'utility': ':wrench:' -} -def tagger(): - tag_data = open('tag_database').read() - tag_dict = {} - tag_list = tag_data.split('\n') - for tag in tag_list: - category = tag.split(':')[1] - snippet = tag.split(':')[0] - if category in tag_dict: - tag_dict[category].append(snippet) - else: - tag_dict[category] = [snippet] - return tag_dict - -start = open("static-parts/readme-start.md").read() + '\n\n' -end = open("static-parts/readme-end.md").read() -toAppend = '' -tag_dict = tagger() -toAppend += '## Table of Contents \n' -for category in tag_dict: - toAppend = toAppend + '### ' + EMOJIS[category] + ' ' + title_case(category) +'\n\n
View contents
    ' - for snippet in sorted(tag_dict[category]): - toAppend += f'
  • {snippet}
  • \n' - toAppend += '
\n\n' -toAppend += '
\n\n' -for category in tag_dict: - toAppend = toAppend + '## ' + EMOJIS[category] + ' ' + title_case(category) +'\n\n' - for snippet in sorted(tag_dict[category]): - someFile = open("snippets/" + snippet + '.md') - fileData = someFile.read() - codeParts = re.split(codeRe,fileData) - toAppend += codeParts[0] + '```py{codeParts[1]} \n ```'.format(codeParts= codeParts) +codeParts[2] + '
View Examples\n\n```py\n{codeParts[3]}\n```\n
\n\n
:arrow_up: Back to top\n '.format(codeParts=codeParts) + '\n' +import re +codeRe = "```\s*python([\s\S]*?)```" +def title_case(str): + return str[:1].upper() + str[1:].lower() +EMOJIS = { + 'adapter': ':electric_plug:', + 'list': ':books:', + 'browser': ':globe_with_meridians:', + 'date': ':stopwatch:', + 'function': ':control_knobs:', + 'logic': ':crystal_ball:', + 'math': ':heavy_division_sign:', + 'media': ':tv:', + 'node': ':package:', + 'object': 'card_file_box', + 'string': ':scroll:', + 'type': ':page_with_curl:', + 'utility': ':wrench:' +} +def tagger(): + tag_data = open('tag_database').read() + tag_dict = {} + tag_list = tag_data.split('\n') + for tag in tag_list: + category = tag.split(':')[1] + snippet = tag.split(':')[0] + if category in tag_dict: + tag_dict[category].append(snippet) + else: + tag_dict[category] = [snippet] + return tag_dict + +start = open("static-parts/readme-start.md").read() + '\n\n' +end = open("static-parts/readme-end.md").read() +toAppend = '' +tag_dict = tagger() +toAppend += '## Table of Contents \n' +for category in tag_dict: + toAppend = toAppend + '### ' + EMOJIS[category] + ' ' + title_case(category) +'\n\n
View contents
    ' + for snippet in sorted(tag_dict[category]): + toAppend += f'
  • {snippet}
  • \n' + toAppend += '
\n\n' +toAppend += '
\n\n' +for category in tag_dict: + toAppend = toAppend + '## ' + EMOJIS[category] + ' ' + title_case(category) +'\n\n' + for snippet in sorted(tag_dict[category]): + someFile = open("snippets/" + snippet + '.md') + fileData = someFile.read() + codeParts = re.split(codeRe,fileData) + toAppend += codeParts[0] + '```py{codeParts[1]} \n ```'.format(codeParts= codeParts) +codeParts[2] + '
View Examples\n\n```py\n{codeParts[3]}\n```\n
\n\n
:arrow_up: Back to top\n '.format(codeParts=codeParts) + '\n' open("README.md",'w').write(start+toAppend+'\n'+end) \ No newline at end of file diff --git a/scripts/tdd.py b/scripts/tdd.py index d3c647d3e..f090ada64 100644 --- a/scripts/tdd.py +++ b/scripts/tdd.py @@ -1,27 +1,27 @@ -import os,re - -codeRe = "```\s*python([\s\S]*?)```" - -snippets = [string.replace('.md','') for string in os.listdir('snippets')] - -for snippet in snippets: - os.makedirs('test/' + snippet,exist_ok=True) - with open(f'snippets/{snippet}.md','r') as f: - content = f.read() - code = re.search(codeRe,content).group(1).strip() - file_to_write_to = open(f'test/{snippet}/{snippet}.py','w') - file_to_write_to.write(code) - file_to_write_to.close() - if not os.path.isfile(f'test/{snippet}/{snippet}.test.py'): - test_file = open(f'test/{snippet}/{snippet}.test.py','w') - test_file.write(f''' -import types,functools -from pytape import test -from {snippet} import {snippet} -def {snippet}_test(t): - t.true(isinstance({snippet}, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'{snippet} is a function') -test('Testing {snippet}',{snippet}_test) - '''.strip()) - test_file.close() - else: +import os,re + +codeRe = "```\s*python([\s\S]*?)```" + +snippets = [string.replace('.md','') for string in os.listdir('snippets')] + +for snippet in snippets: + os.makedirs('test/' + snippet,exist_ok=True) + with open(f'snippets/{snippet}.md','r') as f: + content = f.read() + code = re.search(codeRe,content).group(1).strip() + file_to_write_to = open(f'test/{snippet}/{snippet}.py','w') + file_to_write_to.write(code) + file_to_write_to.close() + if not os.path.isfile(f'test/{snippet}/{snippet}.test.py'): + test_file = open(f'test/{snippet}/{snippet}.test.py','w') + test_file.write(f''' +import types,functools +from pytape import test +from {snippet} import {snippet} +def {snippet}_test(t): + t.true(isinstance({snippet}, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'{snippet} is a function') +test('Testing {snippet}',{snippet}_test) + '''.strip()) + test_file.close() + else: pass \ No newline at end of file diff --git a/snippet_template.md b/snippet_template.md index f1cf31008..e22cbb072 100644 --- a/snippet_template.md +++ b/snippet_template.md @@ -1,15 +1,15 @@ -### function_name - -Describe briefly what the function does - -Explain your method and the functions used. - -``` python -def function_name(args): - # code - return 0 -``` - -``` python -function_name(val) # result -``` +### function_name + +Describe briefly what the function does + +Explain your method and the functions used. + +``` python +def function_name(args): + # code + return 0 +``` + +``` python +function_name(val) # result +``` diff --git a/snippets/average.md b/snippets/average.md index 746f6f746..0adee30a0 100644 --- a/snippets/average.md +++ b/snippets/average.md @@ -1,17 +1,17 @@ -### average - -:information_source: Already implemented via `statistics.mean`. `statistics.mean` takes an array as an argument whereas this function takes variadic arguments. - -Returns the average of two or more numbers. - -Takes the sum of all the `args` and divides it by `len(args)`. The secind argument `0.0` in sum is to handle floating point division in `python2`. - -```python -def average(*args): - return sum(args, 0.0) / len(args) -``` - -``` python -average(*[1, 2, 3]) # 2.0 -average(1, 2, 3) # 2.0 +### average + +:information_source: Already implemented via `statistics.mean`. `statistics.mean` takes an array as an argument whereas this function takes variadic arguments. + +Returns the average of two or more numbers. + +Takes the sum of all the `args` and divides it by `len(args)`. The secind argument `0.0` in sum is to handle floating point division in `python2`. + +```python +def average(*args): + return sum(args, 0.0) / len(args) +``` + +``` python +average(*[1, 2, 3]) # 2.0 +average(1, 2, 3) # 2.0 ``` \ No newline at end of file diff --git a/snippets/byte_size.md b/snippets/byte_size.md index faa8ba5fd..885bb35e1 100644 --- a/snippets/byte_size.md +++ b/snippets/byte_size.md @@ -1,15 +1,15 @@ -### byte_size - -Returns the length of a string in bytes. - -`utf-8` encodes a given string and find its length. - -```python -def byte_size(string): - return(len(string.encode('utf-8'))) -``` - -```python -byte_size('😀') # 4 -byte_size('Hello World') # 11 +### byte_size + +Returns the length of a string in bytes. + +`utf-8` encodes a given string and find its length. + +```python +def byte_size(string): + return(len(string.encode('utf-8'))) +``` + +```python +byte_size('😀') # 4 +byte_size('Hello World') # 11 ``` \ No newline at end of file diff --git a/snippets/capitalize.md b/snippets/capitalize.md index 61f1b3294..f7de127c7 100644 --- a/snippets/capitalize.md +++ b/snippets/capitalize.md @@ -1,15 +1,15 @@ -### capitalize - -Capitalizes the first letter of a string. - -Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `lower_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. - -```python -def capitalize(string, lower_rest=False): - return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:]) -``` - -```python -capitalize('fooBar') # 'FooBar' -capitalize('fooBar', True) # 'Foobar' +### capitalize + +Capitalizes the first letter of a string. + +Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `lower_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. + +```python +def capitalize(string, lower_rest=False): + return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:]) +``` + +```python +capitalize('fooBar') # 'FooBar' +capitalize('fooBar', True) # 'Foobar' ``` \ No newline at end of file diff --git a/snippets/capitalize_every_word.md b/snippets/capitalize_every_word.md index ba0c8f273..3e676437f 100644 --- a/snippets/capitalize_every_word.md +++ b/snippets/capitalize_every_word.md @@ -1,14 +1,14 @@ -### capitalize_every_word - -Capitalizes the first letter of every word in a string. - -Uses `str.title` to capitalize first letter of evry word in the string. - -```python -def capitalize_every_word(string): - return string.title() -``` - -```python -capitalize_every_word('hello world!') # 'Hello World!' +### capitalize_every_word + +Capitalizes the first letter of every word in a string. + +Uses `str.title` to capitalize first letter of evry word in the string. + +```python +def capitalize_every_word(string): + return string.title() +``` + +```python +capitalize_every_word('hello world!') # 'Hello World!' ``` \ No newline at end of file diff --git a/snippets/chunk.md b/snippets/chunk.md index d6dc58060..7678a16e2 100644 --- a/snippets/chunk.md +++ b/snippets/chunk.md @@ -1,19 +1,19 @@ -### chunk - -Chunks an array into smaller lists of a specified size. - -Uses `range` to create a list of desired size. Then use `map` on this list and fill it with splices of `arr`. - -```python -from math import ceil - - -def chunk(arr, size): - return list( - map(lambda x: arr[x * size:x * size + size], - list(range(0, ceil(len(arr) / size))))) -``` - -``` python -chunk([1,2,3,4,5],2) # [[1,2],[3,4],5] -``` +### chunk + +Chunks an array into smaller lists of a specified size. + +Uses `range` to create a list of desired size. Then use `map` on this list and fill it with splices of `arr`. + +```python +from math import ceil + + +def chunk(arr, size): + return list( + map(lambda x: arr[x * size:x * size + size], + list(range(0, ceil(len(arr) / size))))) +``` + +``` python +chunk([1,2,3,4,5],2) # [[1,2],[3,4],5] +``` diff --git a/snippets/compact.md b/snippets/compact.md index 51f14918e..75b9e10f6 100644 --- a/snippets/compact.md +++ b/snippets/compact.md @@ -1,14 +1,14 @@ -### compact - -Removes falsey values from a list. - -Use `filter()` to filter out falsey values (False, None, 0, and ""). - -```python -def compact(arr): - return list(filter(lambda x: bool(x), arr)) -``` - -``` python -compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ] +### compact + +Removes falsey values from a list. + +Use `filter()` to filter out falsey values (False, None, 0, and ""). + +```python +def compact(arr): + return list(filter(lambda x: bool(x), arr)) +``` + +``` python +compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ] ``` \ No newline at end of file diff --git a/snippets/count_by.md b/snippets/count_by.md index c3e67488a..2a395292d 100644 --- a/snippets/count_by.md +++ b/snippets/count_by.md @@ -1,22 +1,22 @@ -### count_by - -:information_source: Already implemented via `collections.Counter` - -Groups the elements of a list based on the given function and returns the count of elements in each group. - -Use `map()` to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs. - -```python -def count_by(arr, fn=lambda x: x): - key = {} - for el in map(fn, arr): - key[el] = 0 if not el in key else key[el] - key[el] += 1 - return key -``` - -``` python -from math import floor -count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2} -count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1} +### count_by + +:information_source: Already implemented via `collections.Counter` + +Groups the elements of a list based on the given function and returns the count of elements in each group. + +Use `map()` to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs. + +```python +def count_by(arr, fn=lambda x: x): + key = {} + for el in map(fn, arr): + key[el] = 0 if not el in key else key[el] + key[el] += 1 + return key +``` + +``` python +from math import floor +count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2} +count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1} ``` \ No newline at end of file diff --git a/snippets/count_occurences.md b/snippets/count_occurences.md index 82dc746d7..0d3726e5c 100644 --- a/snippets/count_occurences.md +++ b/snippets/count_occurences.md @@ -1,18 +1,18 @@ -### count_occurences - -:information_source: Already implemented via `list.count()`. - -Counts the occurrences of a value in an list. - -Uses the `reduce` functin from built-in module `functools` to increment a counter each time you encounter the specific value inside the list. - -```python -def count_occurences(arr, val): - return reduce( - (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), - arr) -``` - -```python -count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3 +### count_occurences + +:information_source: Already implemented via `list.count()`. + +Counts the occurrences of a value in an list. + +Uses the `reduce` functin from built-in module `functools` to increment a counter each time you encounter the specific value inside the list. + +```python +def count_occurences(arr, val): + return reduce( + (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), + arr) +``` + +```python +count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3 ``` \ No newline at end of file diff --git a/snippets/count_vowels.md b/snippets/count_vowels.md index 256009312..2550cae19 100644 --- a/snippets/count_vowels.md +++ b/snippets/count_vowels.md @@ -1,18 +1,18 @@ -### count_vowels - -Retuns `number` of vowels in provided `string`. - -Use a regular expression to count the number of vowels `(A, E, I, O, U)` in a string. - -```python -import re - - -def count_vowels(str): - return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE))) -``` - -``` python -count_vowels('foobar') # 3 -count_vowels('gym') # 0 -``` +### count_vowels + +Retuns `number` of vowels in provided `string`. + +Use a regular expression to count the number of vowels `(A, E, I, O, U)` in a string. + +```python +import re + + +def count_vowels(str): + return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE))) +``` + +``` python +count_vowels('foobar') # 3 +count_vowels('gym') # 0 +``` diff --git a/snippets/decapitalize.md b/snippets/decapitalize.md index 9667c5ccf..2a41484bd 100644 --- a/snippets/decapitalize.md +++ b/snippets/decapitalize.md @@ -1,15 +1,15 @@ -### decapitalize - -Decapitalizes the first letter of a string. - -Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `upper_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. - -```python -def decapitalize(string, upper_rest=False): - return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:]) -``` - -```python -decapitalize('FooBar') # 'fooBar' -decapitalize('FooBar', True) # 'fOOBAR' +### decapitalize + +Decapitalizes the first letter of a string. + +Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the `upper_rest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. + +```python +def decapitalize(string, upper_rest=False): + return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:]) +``` + +```python +decapitalize('FooBar') # 'fooBar' +decapitalize('FooBar', True) # 'fOOBAR' ``` \ No newline at end of file diff --git a/snippets/deep_flatten.md b/snippets/deep_flatten.md index 3da31478d..dc8f35c18 100644 --- a/snippets/deep_flatten.md +++ b/snippets/deep_flatten.md @@ -1,27 +1,27 @@ -### deep_flatten - -Deep flattens a list. - -Use recursion. Use `list.extend()` with an empty array (`result`) and the spread function to flatten a list. Recursively flatten each element that is a list. - -```python -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def deep_flatten(arr): - result = [] - result.extend( - spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) - return result -``` - -```python -deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5] -``` +### deep_flatten + +Deep flattens a list. + +Use recursion. Use `list.extend()` with an empty array (`result`) and the spread function to flatten a list. Recursively flatten each element that is a list. + +```python +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def deep_flatten(arr): + result = [] + result.extend( + spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) + return result +``` + +```python +deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5] +``` diff --git a/snippets/difference.md b/snippets/difference.md index e8efec4d7..dedb95263 100644 --- a/snippets/difference.md +++ b/snippets/difference.md @@ -1,14 +1,14 @@ -### difference - -Returns the difference between two arrays. - -Create a `set` from `b`, then use list comprehension to only keep values not contained in `b` - -```python -def difference(a, b): - b = set(b) - return [item for item in a if item not in b] -``` -``` python -difference([1, 2, 3], [1, 2, 4]) # [3] +### difference + +Returns the difference between two arrays. + +Create a `set` from `b`, then use list comprehension to only keep values not contained in `b` + +```python +def difference(a, b): + b = set(b) + return [item for item in a if item not in b] +``` +``` python +difference([1, 2, 3], [1, 2, 4]) # [3] ``` \ No newline at end of file diff --git a/snippets/difference_by.md b/snippets/difference_by.md index 5fcd004a2..a7801bfc9 100644 --- a/snippets/difference_by.md +++ b/snippets/difference_by.md @@ -1,17 +1,17 @@ -### difference_by - -Returns the difference between two list, after applying the provided function to each list element of both. - -Create a `set` by applying `fn` to each element in `b`, then use list comprehension in combination with fn on a to only keep values not contained in the previously created `set`. - -```python -def difference_by(a, b, fn): - b = set(map(fn, b)) - return [item for item in a if fn(item) not in b] -``` - -```python -from math import floor -difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2] -difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ] +### difference_by + +Returns the difference between two list, after applying the provided function to each list element of both. + +Create a `set` by applying `fn` to each element in `b`, then use list comprehension in combination with fn on a to only keep values not contained in the previously created `set`. + +```python +def difference_by(a, b, fn): + b = set(map(fn, b)) + return [item for item in a if fn(item) not in b] +``` + +```python +from math import floor +difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2] +difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ] ``` \ No newline at end of file diff --git a/snippets/factorial.md b/snippets/factorial.md index 2a303a11c..e7d3d6e81 100644 --- a/snippets/factorial.md +++ b/snippets/factorial.md @@ -1,16 +1,16 @@ -### factorial - -Calculates the factorial of a number. - -Use recursion. If `num` is less than or equal to `1`, return `1`. Otherwise, return the product of `num` and the factorial of `num - 1`. Throws an exception if `num` is a negative or a floating point number. - -```python -def factorial(num): - if not ((num >= 0) & (num % 1 == 0)): - raise Exception( - f"Number( {num} ) can't be floating point or negative ") - return 1 if num == 0 else num * factorial(num - 1) -``` -``` python -factorial(6) # 720 -``` +### factorial + +Calculates the factorial of a number. + +Use recursion. If `num` is less than or equal to `1`, return `1`. Otherwise, return the product of `num` and the factorial of `num - 1`. Throws an exception if `num` is a negative or a floating point number. + +```python +def factorial(num): + if not ((num >= 0) & (num % 1 == 0)): + raise Exception( + f"Number( {num} ) can't be floating point or negative ") + return 1 if num == 0 else num * factorial(num - 1) +``` +``` python +factorial(6) # 720 +``` diff --git a/snippets/gcd.md b/snippets/gcd.md index 5922b24b5..cca70cb41 100644 --- a/snippets/gcd.md +++ b/snippets/gcd.md @@ -1,38 +1,38 @@ -### gcd - -:information_source: `math.gcd` works with only two numbers - -Calculates the greatest common divisor between two or more numbers/lists. - -The `helperGcdfunction` uses recursion. Base case is when `y` equals `0`. In this case, return `x`. Otherwise, return the GCD of `y` and the remainder of the division `x/y`. - -Uses the reduce function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. - -```python -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def gcd(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - - return reduce((lambda x, y: _gcd(x, y)), numbers) -``` - - -``` python -gcd(8,36) # 4 +### gcd + +:information_source: `math.gcd` works with only two numbers + +Calculates the greatest common divisor between two or more numbers/lists. + +The `helperGcdfunction` uses recursion. Base case is when `y` equals `0`. In this case, return `x`. Otherwise, return the GCD of `y` and the remainder of the division `x/y`. + +Uses the reduce function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. + +```python +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def gcd(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + + return reduce((lambda x, y: _gcd(x, y)), numbers) +``` + + +``` python +gcd(8,36) # 4 ``` \ No newline at end of file diff --git a/snippets/is_lower_case.md b/snippets/is_lower_case.md index e760674db..a702252a0 100644 --- a/snippets/is_lower_case.md +++ b/snippets/is_lower_case.md @@ -1,16 +1,16 @@ -### is_lower_case - -Checks if a string is lower case. - -Convert the given string to lower case, using `str.lower()` method and compare it to the original. - -```python -def is_lower_case(str): - return str == str.lower() -``` - -```python -is_lower_case('abc') # True -is_lower_case('a3@$') # True -is_lower_case('Ab4') # False +### is_lower_case + +Checks if a string is lower case. + +Convert the given string to lower case, using `str.lower()` method and compare it to the original. + +```python +def is_lower_case(str): + return str == str.lower() +``` + +```python +is_lower_case('abc') # True +is_lower_case('a3@$') # True +is_lower_case('Ab4') # False ``` \ No newline at end of file diff --git a/snippets/is_upper_case.md b/snippets/is_upper_case.md index af1f35d55..0e26509b6 100644 --- a/snippets/is_upper_case.md +++ b/snippets/is_upper_case.md @@ -1,16 +1,16 @@ -### is_upper_case - -Checks if a string is upper case. - -Convert the given string to upper case, using `str.upper()` method and compare it to the original. - -```python -def is_upper_case(str): - return str == str.upper() -``` - -```python -is_upper_case('ABC') # True -is_upper_case('a3@$') # True -is_upper_case('aB4') # False +### is_upper_case + +Checks if a string is upper case. + +Convert the given string to upper case, using `str.upper()` method and compare it to the original. + +```python +def is_upper_case(str): + return str == str.upper() +``` + +```python +is_upper_case('ABC') # True +is_upper_case('a3@$') # True +is_upper_case('aB4') # False ``` \ No newline at end of file diff --git a/snippets/lcm.md b/snippets/lcm.md index 7400a6d4c..59b75c08f 100644 --- a/snippets/lcm.md +++ b/snippets/lcm.md @@ -1,40 +1,40 @@ -### lcm - -Returns the least common multiple of two or more numbers. - -Use the `greatest common divisor (GCD)` formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. The GCD formula uses recursion. - -Uses `reduce` function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. - -```python -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def lcm(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - - def _lcm(x, y): - return x * y / _gcd(x, y) - - return reduce((lambda x, y: _lcm(x, y)), numbers) -``` - - -``` python -lcm(12, 7) # 84 -lcm([1, 3, 4], 5) # 60 +### lcm + +Returns the least common multiple of two or more numbers. + +Use the `greatest common divisor (GCD)` formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. The GCD formula uses recursion. + +Uses `reduce` function from the inbuilt module `functools`. Also defines a method `spread` for javascript like spreading of lists. + +```python +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def lcm(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + + def _lcm(x, y): + return x * y / _gcd(x, y) + + return reduce((lambda x, y: _lcm(x, y)), numbers) +``` + + +``` python +lcm(12, 7) # 84 +lcm([1, 3, 4], 5) # 60 ``` \ No newline at end of file diff --git a/snippets/max_n.md b/snippets/max_n.md index 05953faeb..cab451b17 100644 --- a/snippets/max_n.md +++ b/snippets/max_n.md @@ -1,21 +1,21 @@ -### max_n - -Returns the `n` maximum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in descending order). - -Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order and then use `list.reverse()` reverse it to make it descending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array - -```python -from copy import deepcopy - - -def max_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() - numbers.reverse() - return numbers[:n] -``` - -```python -max_n([1, 2, 3]) # [3] -max_n([1, 2, 3], 2) # [3,2] +### max_n + +Returns the `n` maximum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in descending order). + +Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order and then use `list.reverse()` reverse it to make it descending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array + +```python +from copy import deepcopy + + +def max_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() + numbers.reverse() + return numbers[:n] +``` + +```python +max_n([1, 2, 3]) # [3] +max_n([1, 2, 3], 2) # [3,2] ``` \ No newline at end of file diff --git a/snippets/min_n.md b/snippets/min_n.md index 36a436d10..ee57f05c2 100644 --- a/snippets/min_n.md +++ b/snippets/min_n.md @@ -1,20 +1,20 @@ -### min_n - -Returns the `n` minimum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in ascending order). - -Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array - -```python -from copy import deepcopy - - -def min_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() - return numbers[:n] -``` - -```python -min_n([1, 2, 3]) # [1] -min_n([1, 2, 3], 2) # [1,2] +### min_n + +Returns the `n` minimum elements from the provided list. If `n` is greater than or equal to the provided list's length, then return the original list(sorted in ascending order). + +Use `list.sort()` combined with the `deepcopy` function from the inbuilt `copy` module to create a shallow clone of the list and sort it in ascending order. Use `[:n]` to get the specified number of elements. Omit the second argument, `n`, to get a one-element array + +```python +from copy import deepcopy + + +def min_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() + return numbers[:n] +``` + +```python +min_n([1, 2, 3]) # [1] +min_n([1, 2, 3], 2) # [1,2] ``` \ No newline at end of file diff --git a/snippets/palindrome.md b/snippets/palindrome.md index 4764aaf3a..20efc8259 100644 --- a/snippets/palindrome.md +++ b/snippets/palindrome.md @@ -1,15 +1,15 @@ -### palindrome - -Returns `True` if the given string is a palindrome, `False` otherwise. - -Convert string `str.lower()` and use `re.sub` to remove non-alphanumeric characters from it. Then compare the new string to the reversed. - -```python -def palindrome(string): - from re import sub - s = sub('[\W_]', '', string.lower()) - return s == s[::-1] -``` -```python -palindrome('taco cat') # True +### palindrome + +Returns `True` if the given string is a palindrome, `False` otherwise. + +Convert string `str.lower()` and use `re.sub` to remove non-alphanumeric characters from it. Then compare the new string to the reversed. + +```python +def palindrome(string): + from re import sub + s = sub('[\W_]', '', string.lower()) + return s == s[::-1] +``` +```python +palindrome('taco cat') # True ``` \ No newline at end of file diff --git a/snippets/shuffle.md b/snippets/shuffle.md index 536591f1e..4d27274b7 100644 --- a/snippets/shuffle.md +++ b/snippets/shuffle.md @@ -1,27 +1,27 @@ -### shuffle - -:information_source: The same algorithm is already implemented via `random.shuffle`. - -Randomizes the order of the values of an list, returning a new list. - -Uses the [Fisher-Yates algorithm](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) to reorder the elements of the list. - -```python -from copy import deepcopy -from random import randint - - -def shuffle(arr): - temp_arr = deepcopy(arr) - m = len(temp_arr) - while (m): - m -= 1 - i = randint(0, m) - temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] - return temp_arr -``` - -``` python -foo = [1,2,3] -shuffle(foo) # [2,3,1] , foo = [1,2,3] +### shuffle + +:information_source: The same algorithm is already implemented via `random.shuffle`. + +Randomizes the order of the values of an list, returning a new list. + +Uses the [Fisher-Yates algorithm](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) to reorder the elements of the list. + +```python +from copy import deepcopy +from random import randint + + +def shuffle(arr): + temp_arr = deepcopy(arr) + m = len(temp_arr) + while (m): + m -= 1 + i = randint(0, m) + temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] + return temp_arr +``` + +``` python +foo = [1,2,3] +shuffle(foo) # [2,3,1] , foo = [1,2,3] ``` \ No newline at end of file diff --git a/snippets/spread.md b/snippets/spread.md index c37fae703..65e0becd3 100644 --- a/snippets/spread.md +++ b/snippets/spread.md @@ -1,19 +1,19 @@ -### spread - -Implements javascript's `[].concat(...arr)`. Flattens the list(non-deep) and returns an list. - -```python -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret -``` - - -```python -spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9] +### spread + +Implements javascript's `[].concat(...arr)`. Flattens the list(non-deep) and returns an list. + +```python +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret +``` + + +```python +spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9] ``` \ No newline at end of file diff --git a/snippets/zip.md b/snippets/zip.md index c36700aab..f10ced8d4 100644 --- a/snippets/zip.md +++ b/snippets/zip.md @@ -1,24 +1,24 @@ -### zip - -:information_source: Already implemented via `itertools.zip_longest()` - -Creates a list of elements, grouped based on the position in the original lists. - -Use `max` combined with `list comprehension` to get the length of the longest list in the arguments. Loops for `max_length` times grouping elements. If lengths of `lists` vary `fill_value` is used. By default `fill_value` is `None`. - -```python -def zip(*args, fillvalue=None): - max_length = max([len(arr) for arr in args]) - result = [] - for i in range(max_length): - result.append([ - args[k][i] if i < len(args[k]) else None for k in range(len(args)) - ]) - return result -``` - -``` python -zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]] -zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]] -zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]] +### zip + +:information_source: Already implemented via `itertools.zip_longest()` + +Creates a list of elements, grouped based on the position in the original lists. + +Use `max` combined with `list comprehension` to get the length of the longest list in the arguments. Loops for `max_length` times grouping elements. If lengths of `lists` vary `fill_value` is used. By default `fill_value` is `None`. + +```python +def zip(*args, fillvalue=None): + max_length = max([len(arr) for arr in args]) + result = [] + for i in range(max_length): + result.append([ + args[k][i] if i < len(args[k]) else None for k in range(len(args)) + ]) + return result +``` + +``` python +zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]] +zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]] +zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]] ``` \ No newline at end of file diff --git a/static-parts/readme-end.md b/static-parts/readme-end.md index 85537e0f6..b707a250f 100644 --- a/static-parts/readme-end.md +++ b/static-parts/readme-end.md @@ -1,8 +1,8 @@ -## Credits - -*Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* - - - -## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_large) +## Credits + +*Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* + + + +## License +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_large) diff --git a/static-parts/readme-start.md b/static-parts/readme-start.md index e6236041f..5a6b0cd06 100644 --- a/static-parts/readme-start.md +++ b/static-parts/readme-start.md @@ -1,9 +1,9 @@ -![Logo](/icon.png) - -# 30-seconds-of-python-code -[![License](https://img.shields.io/aur/license/yaourt.svg)](https://github.com/kriadmin/30-seconds-of-python-code/blob/master/LICENSE) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-python-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Travis Build](https://travis-ci.org/kriadmin/30-seconds-of-python-code.svg?branch=master)](https://travis-ci.org/kriadmin/30-seconds-of-python-code) [![Insight.io](https://img.shields.io/badge/insight.io-Ready-brightgreen.svg)](https://insight.io/github.com/kriadmin/30-seconds-of-python-code/tree/master/?source=0) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_shield) - ->Python implementation of 30-seconds-of-code. - -**Note**:- This is in no way affiliated with the original [30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code/). +![Logo](/icon.png) + +# 30-seconds-of-python-code +[![License](https://img.shields.io/aur/license/yaourt.svg)](https://github.com/kriadmin/30-seconds-of-python-code/blob/master/LICENSE) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-python-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Travis Build](https://travis-ci.org/kriadmin/30-seconds-of-python-code.svg?branch=master)](https://travis-ci.org/kriadmin/30-seconds-of-python-code) [![Insight.io](https://img.shields.io/badge/insight.io-Ready-brightgreen.svg)](https://insight.io/github.com/kriadmin/30-seconds-of-python-code/tree/master/?source=0) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkriadmin%2F30-seconds-of-python-code?ref=badge_shield) + +>Python implementation of 30-seconds-of-code. + +**Note**:- This is in no way affiliated with the original [30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code/). diff --git a/tag_database b/tag_database index c1b7f4491..f8be5804e 100644 --- a/tag_database +++ b/tag_database @@ -1,24 +1,24 @@ -average:math -chunk:list -compact:list -count_occurences:list -count_vowels:string -deep_flatten:list -difference:list -factorial:math -gcd:math -lcm:math -max_n:math -min_n:math -shuffle:list -spread:list -zip:list -byte_size:string -capitalize:string -capitalize_every_word:string -decapitalize:string -palindrome:string -is_upper_case:string -is_lower_case:string -count_by:list +average:math +chunk:list +compact:list +count_occurences:list +count_vowels:string +deep_flatten:list +difference:list +factorial:math +gcd:math +lcm:math +max_n:math +min_n:math +shuffle:list +spread:list +zip:list +byte_size:string +capitalize:string +capitalize_every_word:string +decapitalize:string +palindrome:string +is_upper_case:string +is_lower_case:string +count_by:list difference_by:list \ No newline at end of file diff --git a/test/average/average.py b/test/average/average.py index 1ff6e2ef9..64087c958 100644 --- a/test/average/average.py +++ b/test/average/average.py @@ -1,2 +1,2 @@ -def average(*args): +def average(*args): return sum(args, 0.0) / len(args) \ No newline at end of file diff --git a/test/average/average.test.py b/test/average/average.test.py index bc715b99c..040e8c52c 100644 --- a/test/average/average.test.py +++ b/test/average/average.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from average import average -def average_test(t): - t.true(isinstance(average, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'average is a function') +import types,functools +from pytape import test +from average import average +def average_test(t): + t.true(isinstance(average, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'average is a function') test('Testing average',average_test) \ No newline at end of file diff --git a/test/byte_size/byte_size.py b/test/byte_size/byte_size.py index 5050bb37d..fdb82b196 100644 --- a/test/byte_size/byte_size.py +++ b/test/byte_size/byte_size.py @@ -1,2 +1,2 @@ -def byte_size(string): +def byte_size(string): return(len(string.encode('utf-8'))) \ No newline at end of file diff --git a/test/byte_size/byte_size.test.py b/test/byte_size/byte_size.test.py index 6cea1e5f0..a58402a3b 100644 --- a/test/byte_size/byte_size.test.py +++ b/test/byte_size/byte_size.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from byte_size import byte_size -def byte_size_test(t): - t.true(isinstance(byte_size, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'byte_size is a function') +import types,functools +from pytape import test +from byte_size import byte_size +def byte_size_test(t): + t.true(isinstance(byte_size, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'byte_size is a function') test('Testing byte_size',byte_size_test) \ No newline at end of file diff --git a/test/capitalize/capitalize.py b/test/capitalize/capitalize.py index 0eb21baa1..737f60a11 100644 --- a/test/capitalize/capitalize.py +++ b/test/capitalize/capitalize.py @@ -1,2 +1,2 @@ -def capitalize(string, lower_rest=False): +def capitalize(string, lower_rest=False): return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:]) \ No newline at end of file diff --git a/test/capitalize/capitalize.test.py b/test/capitalize/capitalize.test.py index 13badb810..08566fa1d 100644 --- a/test/capitalize/capitalize.test.py +++ b/test/capitalize/capitalize.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from capitalize import capitalize -def capitalize_test(t): - t.true(isinstance(capitalize, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'capitalize is a function') +import types,functools +from pytape import test +from capitalize import capitalize +def capitalize_test(t): + t.true(isinstance(capitalize, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'capitalize is a function') test('Testing capitalize',capitalize_test) \ No newline at end of file diff --git a/test/capitalize_every_word/capitalize_every_word.py b/test/capitalize_every_word/capitalize_every_word.py index 7f7d7bf5a..554cc5068 100644 --- a/test/capitalize_every_word/capitalize_every_word.py +++ b/test/capitalize_every_word/capitalize_every_word.py @@ -1,2 +1,2 @@ -def capitalize_every_word(string): +def capitalize_every_word(string): return string.title() \ No newline at end of file diff --git a/test/capitalize_every_word/capitalize_every_word.test.py b/test/capitalize_every_word/capitalize_every_word.test.py index 36a9a381a..92147207e 100644 --- a/test/capitalize_every_word/capitalize_every_word.test.py +++ b/test/capitalize_every_word/capitalize_every_word.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from capitalize_every_word import capitalize_every_word -def capitalize_every_word_test(t): - t.true(isinstance(capitalize_every_word, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'capitalize_every_word is a function') +import types,functools +from pytape import test +from capitalize_every_word import capitalize_every_word +def capitalize_every_word_test(t): + t.true(isinstance(capitalize_every_word, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'capitalize_every_word is a function') test('Testing capitalize_every_word',capitalize_every_word_test) \ No newline at end of file diff --git a/test/chunk/chunk.py b/test/chunk/chunk.py index 6f247c2c9..a88109e26 100644 --- a/test/chunk/chunk.py +++ b/test/chunk/chunk.py @@ -1,7 +1,7 @@ -from math import ceil - - -def chunk(arr, size): - return list( - map(lambda x: arr[x * size:x * size + size], +from math import ceil + + +def chunk(arr, size): + return list( + map(lambda x: arr[x * size:x * size + size], list(range(0, ceil(len(arr) / size))))) \ No newline at end of file diff --git a/test/chunk/chunk.test.py b/test/chunk/chunk.test.py index 3af760779..ead9ead97 100644 --- a/test/chunk/chunk.test.py +++ b/test/chunk/chunk.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from chunk import chunk -def chunk_test(t): - t.true(isinstance(chunk, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'chunk is a function') +import types,functools +from pytape import test +from chunk import chunk +def chunk_test(t): + t.true(isinstance(chunk, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'chunk is a function') test('Testing chunk',chunk_test) \ No newline at end of file diff --git a/test/compact/compact.py b/test/compact/compact.py index f90cc92d7..20420541c 100644 --- a/test/compact/compact.py +++ b/test/compact/compact.py @@ -1,2 +1,2 @@ -def compact(arr): +def compact(arr): return list(filter(lambda x: bool(x), arr)) \ No newline at end of file diff --git a/test/compact/compact.test.py b/test/compact/compact.test.py index 4ff5b875f..b237572e2 100644 --- a/test/compact/compact.test.py +++ b/test/compact/compact.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from compact import compact -def compact_test(t): - t.true(isinstance(compact, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'compact is a function') +import types,functools +from pytape import test +from compact import compact +def compact_test(t): + t.true(isinstance(compact, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'compact is a function') test('Testing compact',compact_test) \ No newline at end of file diff --git a/test/count_by/count_by.py b/test/count_by/count_by.py index aae034ead..90c0fc813 100644 --- a/test/count_by/count_by.py +++ b/test/count_by/count_by.py @@ -1,6 +1,6 @@ -def count_by(arr, fn=lambda x: x): - key = {} - for el in map(fn, arr): - key[el] = 0 if not el in key else key[el] - key[el] += 1 +def count_by(arr, fn=lambda x: x): + key = {} + for el in map(fn, arr): + key[el] = 0 if not el in key else key[el] + key[el] += 1 return key \ No newline at end of file diff --git a/test/count_by/count_by.test.py b/test/count_by/count_by.test.py index 2edf9e070..624cf17c8 100644 --- a/test/count_by/count_by.test.py +++ b/test/count_by/count_by.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from count_by import count_by -def count_by_test(t): - t.true(isinstance(count_by, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_by is a function') +import types,functools +from pytape import test +from count_by import count_by +def count_by_test(t): + t.true(isinstance(count_by, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_by is a function') test('Testing count_by',count_by_test) \ No newline at end of file diff --git a/test/count_occurences/count_occurences.py b/test/count_occurences/count_occurences.py index 161f8f86f..e98edff74 100644 --- a/test/count_occurences/count_occurences.py +++ b/test/count_occurences/count_occurences.py @@ -1,4 +1,4 @@ -def count_occurences(arr, val): - return reduce( - (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), +def count_occurences(arr, val): + return reduce( + (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), arr) \ No newline at end of file diff --git a/test/count_occurences/count_occurences.test.py b/test/count_occurences/count_occurences.test.py index 73b902c2c..d452604bf 100644 --- a/test/count_occurences/count_occurences.test.py +++ b/test/count_occurences/count_occurences.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from count_occurences import count_occurences -def count_occurences_test(t): - t.true(isinstance(count_occurences, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_occurences is a function') +import types,functools +from pytape import test +from count_occurences import count_occurences +def count_occurences_test(t): + t.true(isinstance(count_occurences, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_occurences is a function') test('Testing count_occurences',count_occurences_test) \ No newline at end of file diff --git a/test/count_vowels/count_vowels.py b/test/count_vowels/count_vowels.py index 05217ac13..04c7fa737 100644 --- a/test/count_vowels/count_vowels.py +++ b/test/count_vowels/count_vowels.py @@ -1,5 +1,5 @@ -import re - - -def count_vowels(str): +import re + + +def count_vowels(str): return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE))) \ No newline at end of file diff --git a/test/count_vowels/count_vowels.test.py b/test/count_vowels/count_vowels.test.py index b32d9ccd4..d27c1bf2f 100644 --- a/test/count_vowels/count_vowels.test.py +++ b/test/count_vowels/count_vowels.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from count_vowels import count_vowels -def count_vowels_test(t): - t.true(isinstance(count_vowels, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_vowels is a function') +import types,functools +from pytape import test +from count_vowels import count_vowels +def count_vowels_test(t): + t.true(isinstance(count_vowels, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'count_vowels is a function') test('Testing count_vowels',count_vowels_test) \ No newline at end of file diff --git a/test/decapitalize/decapitalize.py b/test/decapitalize/decapitalize.py index 4518a6599..ed4ffd6c9 100644 --- a/test/decapitalize/decapitalize.py +++ b/test/decapitalize/decapitalize.py @@ -1,2 +1,2 @@ -def decapitalize(string, upper_rest=False): +def decapitalize(string, upper_rest=False): return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:]) \ No newline at end of file diff --git a/test/decapitalize/decapitalize.test.py b/test/decapitalize/decapitalize.test.py index f6a3cbed5..60959dc16 100644 --- a/test/decapitalize/decapitalize.test.py +++ b/test/decapitalize/decapitalize.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from decapitalize import decapitalize -def decapitalize_test(t): - t.true(isinstance(decapitalize, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'decapitalize is a function') +import types,functools +from pytape import test +from decapitalize import decapitalize +def decapitalize_test(t): + t.true(isinstance(decapitalize, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'decapitalize is a function') test('Testing decapitalize',decapitalize_test) \ No newline at end of file diff --git a/test/deep_flatten/deep_flatten.py b/test/deep_flatten/deep_flatten.py index 355991028..2a6c2095e 100644 --- a/test/deep_flatten/deep_flatten.py +++ b/test/deep_flatten/deep_flatten.py @@ -1,15 +1,15 @@ -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def deep_flatten(arr): - result = [] - result.extend( - spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def deep_flatten(arr): + result = [] + result.extend( + spread(list(map(lambda x: deep(x) if type(x) == list else x, arr)))) return result \ No newline at end of file diff --git a/test/deep_flatten/deep_flatten.test.py b/test/deep_flatten/deep_flatten.test.py index 5ea80d419..cb8b13cd6 100644 --- a/test/deep_flatten/deep_flatten.test.py +++ b/test/deep_flatten/deep_flatten.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from deep_flatten import deep_flatten -def deep_flatten_test(t): - t.true(isinstance(deep_flatten, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'deep_flatten is a function') +import types,functools +from pytape import test +from deep_flatten import deep_flatten +def deep_flatten_test(t): + t.true(isinstance(deep_flatten, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'deep_flatten is a function') test('Testing deep_flatten',deep_flatten_test) \ No newline at end of file diff --git a/test/difference/difference.py b/test/difference/difference.py index b375d7748..87a05ff45 100644 --- a/test/difference/difference.py +++ b/test/difference/difference.py @@ -1,3 +1,3 @@ -def difference(a, b): - b = set(b) +def difference(a, b): + b = set(b) return [item for item in a if item not in b] \ No newline at end of file diff --git a/test/difference/difference.test.py b/test/difference/difference.test.py index e82e3e54a..1172c07b4 100644 --- a/test/difference/difference.test.py +++ b/test/difference/difference.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from difference import difference -def difference_test(t): - t.true(isinstance(difference, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'difference is a function') +import types,functools +from pytape import test +from difference import difference +def difference_test(t): + t.true(isinstance(difference, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'difference is a function') test('Testing difference',difference_test) \ No newline at end of file diff --git a/test/difference_by/difference_by.py b/test/difference_by/difference_by.py index fb639d430..f2fe98623 100644 --- a/test/difference_by/difference_by.py +++ b/test/difference_by/difference_by.py @@ -1,3 +1,3 @@ -def difference_by(a, b, fn): - b = set(map(fn, b)) +def difference_by(a, b, fn): + b = set(map(fn, b)) return [item for item in a if fn(item) not in b] \ No newline at end of file diff --git a/test/difference_by/difference_by.test.py b/test/difference_by/difference_by.test.py index 7b702ba2d..31e000f4e 100644 --- a/test/difference_by/difference_by.test.py +++ b/test/difference_by/difference_by.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from difference_by import difference_by -def difference_by_test(t): - t.true(isinstance(difference_by, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'difference_by is a function') +import types,functools +from pytape import test +from difference_by import difference_by +def difference_by_test(t): + t.true(isinstance(difference_by, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'difference_by is a function') test('Testing difference_by',difference_by_test) \ No newline at end of file diff --git a/test/factorial/factorial.py b/test/factorial/factorial.py index 999f1fb52..49fba02ba 100644 --- a/test/factorial/factorial.py +++ b/test/factorial/factorial.py @@ -1,5 +1,5 @@ -def factorial(num): - if not ((num >= 0) & (num % 1 == 0)): - raise Exception( - f"Number( {num} ) can't be floating point or negative ") +def factorial(num): + if not ((num >= 0) & (num % 1 == 0)): + raise Exception( + f"Number( {num} ) can't be floating point or negative ") return 1 if num == 0 else num * factorial(num - 1) \ No newline at end of file diff --git a/test/factorial/factorial.test.py b/test/factorial/factorial.test.py index 94acd8d60..de1d46372 100644 --- a/test/factorial/factorial.test.py +++ b/test/factorial/factorial.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from factorial import factorial -def factorial_test(t): - t.true(isinstance(factorial, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'factorial is a function') +import types,functools +from pytape import test +from factorial import factorial +def factorial_test(t): + t.true(isinstance(factorial, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'factorial is a function') test('Testing factorial',factorial_test) \ No newline at end of file diff --git a/test/gcd/gcd.py b/test/gcd/gcd.py index a4ad73048..fed4f0941 100644 --- a/test/gcd/gcd.py +++ b/test/gcd/gcd.py @@ -1,21 +1,21 @@ -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def gcd(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def gcd(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + return reduce((lambda x, y: _gcd(x, y)), numbers) \ No newline at end of file diff --git a/test/gcd/gcd.test.py b/test/gcd/gcd.test.py index bae75801a..5eae2d908 100644 --- a/test/gcd/gcd.test.py +++ b/test/gcd/gcd.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from gcd import gcd -def gcd_test(t): - t.true(isinstance(gcd, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'gcd is a function') +import types,functools +from pytape import test +from gcd import gcd +def gcd_test(t): + t.true(isinstance(gcd, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'gcd is a function') test('Testing gcd',gcd_test) \ No newline at end of file diff --git a/test/is_lower_case/is_lower_case.py b/test/is_lower_case/is_lower_case.py index 3b914e8b9..b7e414afd 100644 --- a/test/is_lower_case/is_lower_case.py +++ b/test/is_lower_case/is_lower_case.py @@ -1,2 +1,2 @@ -def is_lower_case(str): +def is_lower_case(str): return str == str.lower() \ No newline at end of file diff --git a/test/is_lower_case/is_lower_case.test.py b/test/is_lower_case/is_lower_case.test.py index 8952a9d06..e5de08fbd 100644 --- a/test/is_lower_case/is_lower_case.test.py +++ b/test/is_lower_case/is_lower_case.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from is_lower_case import is_lower_case -def is_lower_case_test(t): - t.true(isinstance(is_lower_case, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'is_lower_case is a function') +import types,functools +from pytape import test +from is_lower_case import is_lower_case +def is_lower_case_test(t): + t.true(isinstance(is_lower_case, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'is_lower_case is a function') test('Testing is_lower_case',is_lower_case_test) \ No newline at end of file diff --git a/test/is_upper_case/is_upper_case.py b/test/is_upper_case/is_upper_case.py index 062b4f8d2..0d59887ed 100644 --- a/test/is_upper_case/is_upper_case.py +++ b/test/is_upper_case/is_upper_case.py @@ -1,2 +1,2 @@ -def is_upper_case(str): +def is_upper_case(str): return str == str.upper() \ No newline at end of file diff --git a/test/is_upper_case/is_upper_case.test.py b/test/is_upper_case/is_upper_case.test.py index d0ddedc97..b0004171e 100644 --- a/test/is_upper_case/is_upper_case.test.py +++ b/test/is_upper_case/is_upper_case.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from is_upper_case import is_upper_case -def is_upper_case_test(t): - t.true(isinstance(is_upper_case, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'is_upper_case is a function') +import types,functools +from pytape import test +from is_upper_case import is_upper_case +def is_upper_case_test(t): + t.true(isinstance(is_upper_case, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'is_upper_case is a function') test('Testing is_upper_case',is_upper_case_test) \ No newline at end of file diff --git a/test/lcm/lcm.py b/test/lcm/lcm.py index bd6cf9111..917f638ac 100644 --- a/test/lcm/lcm.py +++ b/test/lcm/lcm.py @@ -1,24 +1,24 @@ -from functools import reduce - - -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) - return ret - - -def lcm(*args): - numbers = [] - numbers.extend(spread(list(args))) - - def _gcd(x, y): - return x if not y else gcd(y, x % y) - - def _lcm(x, y): - return x * y / _gcd(x, y) - +from functools import reduce + + +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) + return ret + + +def lcm(*args): + numbers = [] + numbers.extend(spread(list(args))) + + def _gcd(x, y): + return x if not y else gcd(y, x % y) + + def _lcm(x, y): + return x * y / _gcd(x, y) + return reduce((lambda x, y: _lcm(x, y)), numbers) \ No newline at end of file diff --git a/test/lcm/lcm.test.py b/test/lcm/lcm.test.py index e782a3cb4..29f89658a 100644 --- a/test/lcm/lcm.test.py +++ b/test/lcm/lcm.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from lcm import lcm -def lcm_test(t): - t.true(isinstance(lcm, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'lcm is a function') +import types,functools +from pytape import test +from lcm import lcm +def lcm_test(t): + t.true(isinstance(lcm, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'lcm is a function') test('Testing lcm',lcm_test) \ No newline at end of file diff --git a/test/max_n/max_n.py b/test/max_n/max_n.py index 70006802c..a50b47bb6 100644 --- a/test/max_n/max_n.py +++ b/test/max_n/max_n.py @@ -1,8 +1,8 @@ -from copy import deepcopy - - -def max_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() - numbers.reverse() +from copy import deepcopy + + +def max_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() + numbers.reverse() return numbers[:n] \ No newline at end of file diff --git a/test/max_n/max_n.test.py b/test/max_n/max_n.test.py index 1dd239b56..a85e2525a 100644 --- a/test/max_n/max_n.test.py +++ b/test/max_n/max_n.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from max_n import max_n -def max_n_test(t): - t.true(isinstance(max_n, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'max_n is a function') +import types,functools +from pytape import test +from max_n import max_n +def max_n_test(t): + t.true(isinstance(max_n, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'max_n is a function') test('Testing max_n',max_n_test) \ No newline at end of file diff --git a/test/min_n/min_n.py b/test/min_n/min_n.py index c973b3a61..0026858be 100644 --- a/test/min_n/min_n.py +++ b/test/min_n/min_n.py @@ -1,7 +1,7 @@ -from copy import deepcopy - - -def min_n(arr, n=1): - numbers = deepcopy(arr) - numbers.sort() +from copy import deepcopy + + +def min_n(arr, n=1): + numbers = deepcopy(arr) + numbers.sort() return numbers[:n] \ No newline at end of file diff --git a/test/min_n/min_n.test.py b/test/min_n/min_n.test.py index 2dccbc972..01b86f055 100644 --- a/test/min_n/min_n.test.py +++ b/test/min_n/min_n.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from min_n import min_n -def min_n_test(t): - t.true(isinstance(min_n, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'min_n is a function') +import types,functools +from pytape import test +from min_n import min_n +def min_n_test(t): + t.true(isinstance(min_n, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'min_n is a function') test('Testing min_n',min_n_test) \ No newline at end of file diff --git a/test/palindrome/palindrome.py b/test/palindrome/palindrome.py index f7b5165e7..73679f3e7 100644 --- a/test/palindrome/palindrome.py +++ b/test/palindrome/palindrome.py @@ -1,4 +1,4 @@ -def palindrome(string): - from re import sub - s = sub('[\W_]', '', string.lower()) +def palindrome(string): + from re import sub + s = sub('[\W_]', '', string.lower()) return s == s[::-1] \ No newline at end of file diff --git a/test/palindrome/palindrome.test.py b/test/palindrome/palindrome.test.py index 3e432312f..c2fcc8f90 100644 --- a/test/palindrome/palindrome.test.py +++ b/test/palindrome/palindrome.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from palindrome import palindrome -def palindrome_test(t): - t.true(isinstance(palindrome, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'palindrome is a function') +import types,functools +from pytape import test +from palindrome import palindrome +def palindrome_test(t): + t.true(isinstance(palindrome, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'palindrome is a function') test('Testing palindrome',palindrome_test) \ No newline at end of file diff --git a/test/shuffle/shuffle.py b/test/shuffle/shuffle.py index 2d16df93f..120264534 100644 --- a/test/shuffle/shuffle.py +++ b/test/shuffle/shuffle.py @@ -1,12 +1,12 @@ -from copy import deepcopy -from random import randint - - -def shuffle(arr): - temp_arr = deepcopy(arr) - m = len(temp_arr) - while (m): - m -= 1 - i = randint(0, m) - temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] +from copy import deepcopy +from random import randint + + +def shuffle(arr): + temp_arr = deepcopy(arr) + m = len(temp_arr) + while (m): + m -= 1 + i = randint(0, m) + temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] return temp_arr \ No newline at end of file diff --git a/test/shuffle/shuffle.test.py b/test/shuffle/shuffle.test.py index 71ca7f80f..d8f48caf2 100644 --- a/test/shuffle/shuffle.test.py +++ b/test/shuffle/shuffle.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from shuffle import shuffle -def shuffle_test(t): - t.true(isinstance(shuffle, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'shuffle is a function') +import types,functools +from pytape import test +from shuffle import shuffle +def shuffle_test(t): + t.true(isinstance(shuffle, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'shuffle is a function') test('Testing shuffle',shuffle_test) \ No newline at end of file diff --git a/test/spread/spread.py b/test/spread/spread.py index 02baa7f82..0efae561c 100644 --- a/test/spread/spread.py +++ b/test/spread/spread.py @@ -1,8 +1,8 @@ -def spread(arg): - ret = [] - for i in arg: - if isinstance(i, list): - ret.extend(i) - else: - ret.append(i) +def spread(arg): + ret = [] + for i in arg: + if isinstance(i, list): + ret.extend(i) + else: + ret.append(i) return ret \ No newline at end of file diff --git a/test/spread/spread.test.py b/test/spread/spread.test.py index 36779af5a..8e222caae 100644 --- a/test/spread/spread.test.py +++ b/test/spread/spread.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from spread import spread -def spread_test(t): - t.true(isinstance(spread, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'spread is a function') +import types,functools +from pytape import test +from spread import spread +def spread_test(t): + t.true(isinstance(spread, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'spread is a function') test('Testing spread',spread_test) \ No newline at end of file diff --git a/test/zip/zip.py b/test/zip/zip.py index ef9aa5593..ed2680f60 100644 --- a/test/zip/zip.py +++ b/test/zip/zip.py @@ -1,8 +1,8 @@ -def zip(*args, fillvalue=None): - max_length = max([len(arr) for arr in args]) - result = [] - for i in range(max_length): - result.append([ - args[k][i] if i < len(args[k]) else None for k in range(len(args)) - ]) +def zip(*args, fillvalue=None): + max_length = max([len(arr) for arr in args]) + result = [] + for i in range(max_length): + result.append([ + args[k][i] if i < len(args[k]) else None for k in range(len(args)) + ]) return result \ No newline at end of file diff --git a/test/zip/zip.test.py b/test/zip/zip.test.py index 4dbe4f005..81d595bac 100644 --- a/test/zip/zip.test.py +++ b/test/zip/zip.test.py @@ -1,6 +1,6 @@ -import types,functools -from pytape import test -from zip import zip -def zip_test(t): - t.true(isinstance(zip, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'zip is a function') +import types,functools +from pytape import test +from zip import zip +def zip_test(t): + t.true(isinstance(zip, (types.BuiltinFunctionType, types.FunctionType, functools.partial)),'zip is a function') test('Testing zip',zip_test) \ No newline at end of file diff --git a/website/app/__init__.py b/website/app/__init__.py index d6e6d4a08..e1e924e5b 100644 --- a/website/app/__init__.py +++ b/website/app/__init__.py @@ -1,8 +1,8 @@ -from flask import Flask - -app = Flask(__name__) - -app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 -app.secret_key = 'thedarklordisgreat' - +from flask import Flask + +app = Flask(__name__) + +app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 +app.secret_key = 'thedarklordisgreat' + from app import routes,vote \ No newline at end of file diff --git a/website/app/etc/hosts b/website/app/etc/hosts index 3abd760ec..62a8cca88 100644 --- a/website/app/etc/hosts +++ b/website/app/etc/hosts @@ -1,2 +1,2 @@ -127.0.0.1 localwebsite +127.0.0.1 localwebsite 127.0.0.1 blog.localwebsite \ No newline at end of file diff --git a/website/app/routes.py b/website/app/routes.py index 91cb59e0c..44bc4f1a0 100644 --- a/website/app/routes.py +++ b/website/app/routes.py @@ -1,23 +1,23 @@ -from flask import render_template, redirect ,request, url_for -from app import app, vote, vote_data - -@app.route('/') -@app.route('/index') -@app.route('/index/') -def index(): - return render_template('index.html',vote={}) -''' -For future when we have logins -@app.route('/',methods=['POST']) -@app.route('/index',methods=['POST']) -@app.route('/index/',methods=['POST']) -def post(): - try: - vote.vote(request.form['submit']) - except Exception as e: - return render_template('index.html', vote=vote_data.vote_data(),err_400=True,message=e) - return redirect(f"/#{request.form['submit']}",code=302) -''' - - - +from flask import render_template, redirect ,request, url_for +from app import app, vote, vote_data + +@app.route('/') +@app.route('/index') +@app.route('/index/') +def index(): + return render_template('index.html',vote={}) +''' +For future when we have logins +@app.route('/',methods=['POST']) +@app.route('/index',methods=['POST']) +@app.route('/index/',methods=['POST']) +def post(): + try: + vote.vote(request.form['submit']) + except Exception as e: + return render_template('index.html', vote=vote_data.vote_data(),err_400=True,message=e) + return redirect(f"/#{request.form['submit']}",code=302) +''' + + + diff --git a/website/app/snippets b/website/app/snippets index 28ea1fabc..09c52e118 100644 --- a/website/app/snippets +++ b/website/app/snippets @@ -1,8 +1,8 @@ -count_vowels -byte_size -capitalize -capitalize_every_word -decapitalize -palindrome -is_upper_case +count_vowels +byte_size +capitalize +capitalize_every_word +decapitalize +palindrome +is_upper_case is_lower_case \ No newline at end of file diff --git a/website/app/static/css/prism.css b/website/app/static/css/prism.css index d56b7e094..2a173aeee 100644 --- a/website/app/static/css/prism.css +++ b/website/app/static/css/prism.css @@ -1,1229 +1,1229 @@ -:root { - --f-col:#111; - --f-col2:#444; - --b-col:#f8f8f8; - --b-col2:#f0f0f0; - --blq-col:#f57c00; - --pre-col:#1565c0; - --br-col:#aaa; - --br-col2:#ddd; - --h-ratio:1.19; - --u-m:.5rem; - --u-p:.5rem; - --u-br-r:.125rem; - --a-l-col:#0277bd; - --a-v-col:#01579b - } - html { - font-size:16px - } - a,b,del,em,i,ins,q,span,strong,u { - font-size:1em - } - html,* { - font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",Helvetica,sans-serif; - line-height:1.5; - -webkit-text-size-adjust:100% - } - * { - font-size:1rem - } - body { - margin:0; - color:var(--f-col); - background:var(--b-col) - } - details { - display:block - } - summary { - display:list-item - } - abbr[title] { - border-bottom:none; - text-decoration:underline dotted - } - input { - overflow:visible - } - img { - max-width:100%; - height:auto - } - h1,h2,h3,h4,h5,h6 { - line-height:1.2; - margin:calc(1.5 * var(--u-m)) var(--u-m); - font-weight:500 - } - h1 small,h2 small,h3 small,h4 small,h5 small,h6 small { - color:var(--f-col2); - display:block; - margin-top:-.25rem - } - h1 { - font-size:calc(1rem * var(--h-ratio) * var(--h-ratio) * var(--h-ratio) * var(--h-ratio)) - } - h2 { - font-size:calc(1rem * var(--h-ratio) * var(--h-ratio) * var(--h-ratio)) - } - h3 { - font-size:calc(1rem * var(--h-ratio) * var(--h-ratio)) - } - h4 { - font-size:calc(1rem * var(--h-ratio)) - } - h5 { - font-size:1rem - } - h6 { - font-size:calc(1rem/ var(--h-ratio)) - } - p { - margin:var(--u-m) - } - ol,ul { - margin:var(--u-m); - padding-left:calc(2 * var(--u-m)) - } - b,strong { - font-weight:700 - } - hr { - box-sizing:content-box; - border:0; - line-height:1.25em; - margin:var(--u-m); - height:.0625rem; - background:linear-gradient(to right,transparent,var(--br-col) 20%,var(--br-col) 80%,transparent) - } - blockquote { - display:block; - position:relative; - font-style:italic; - color:var(--f-col2); - margin:var(--u-m); - padding:calc(3 * var(--u-p)); - border:.0625rem solid var(--br-col2); - border-left:.375rem solid var(--blq-col); - border-radius:0 var(--u-br-r) var(--u-br-r) 0 - } - blockquote:before { - position:absolute; - top:calc(0rem - var(--u-p)); - left:0; - font-family:sans-serif; - font-size:3rem; - font-weight:700; - content:"\201c"; - color:var(--blq-col) - } - blockquote[cite]:after { - font-style:normal; - font-size:.75em; - font-weight:700; - content:"\a— " attr(cite); - white-space:pre - } - code,kbd,pre,samp { - font-family:Menlo,Consolas,monospace; - font-size:.85em - } - code { - background:var(--b-col2); - border-radius:var(--u-br-r); - padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) - } - kbd { - background:var(--f-col); - color:var(--b-col); - border-radius:var(--u-br-r); - padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) - } - pre { - overflow:auto; - background:var(--b-col2); - padding:calc(1.5 * var(--u-p)); - margin:var(--u-m); - border:.0625rem solid var(--br-col2); - border-left:.25rem solid var(--pre-col); - border-radius:0 var(--u-br-r) var(--u-br-r) 0 - } - sup,sub,code,kbd { - line-height:0; - position:relative; - vertical-align:baseline - } - small,sup,sub,figcaption { - font-size:.75em - } - sup { - top:-.5em - } - sub { - bottom:-.25em - } - figure { - margin:var(--u-m) - } - figcaption { - color:var(--f-col2) - } - a { - text-decoration:none - } - a:link { - color:var(--a-l-col) - } - a:visited { - color:var(--a-v-col) - } - a:hover,a:focus { - text-decoration:underline - } - .container { - margin:0 auto; - padding:0 calc(1.5 * var(--u-p)) - } - .row { - box-sizing:border-box; - display:flex; - flex:0 1 auto; - flex-flow:row wrap - } - .col-sm,[class^='col-sm-'],[class^='col-sm-o-'] { - flex:0 0 auto; - padding:0 calc(var(--u-p)/ 2) - } - .col-sm { - max-width:100%; - flex-grow:1; - flex-basis:0 - } - .col-sm-1 { - max-width:8.33333%; - flex-basis:8.33333% - } - .col-sm-o-0 { - margin-left:0 - } - .col-sm-2 { - max-width:16.66667%; - flex-basis:16.66667% - } - .col-sm-o-1 { - margin-left:8.33333% - } - .col-sm-3 { - max-width:25%; - flex-basis:25% - } - .col-sm-o-2 { - margin-left:16.66667% - } - .col-sm-4 { - max-width:33.33333%; - flex-basis:33.33333% - } - .col-sm-o-3 { - margin-left:25% - } - .col-sm-5 { - max-width:41.66667%; - flex-basis:41.66667% - } - .col-sm-o-4 { - margin-left:33.33333% - } - .col-sm-6 { - max-width:50%; - flex-basis:50% - } - .col-sm-o-5 { - margin-left:41.66667% - } - .col-sm-7 { - max-width:58.33333%; - flex-basis:58.33333% - } - .col-sm-o-6 { - margin-left:50% - } - .col-sm-8 { - max-width:66.66667%; - flex-basis:66.66667% - } - .col-sm-o-7 { - margin-left:58.33333% - } - .col-sm-9 { - max-width:75%; - flex-basis:75% - } - .col-sm-o-8 { - margin-left:66.66667% - } - .col-sm-10 { - max-width:83.33333%; - flex-basis:83.33333% - } - .col-sm-o-9 { - margin-left:75% - } - .col-sm-11 { - max-width:91.66667%; - flex-basis:91.66667% - } - .col-sm-o-10 { - margin-left:83.33333% - } - .col-sm-12 { - max-width:100%; - flex-basis:100% - } - .col-sm-o-11 { - margin-left:91.66667% - } - .col-sm-n { - order:initial - } - .col-sm-f { - order:-999 - } - .col-sm-l { - order:999 - } - @media screen and (min-width: 768px) { - .col-md,[class^='col-md-'],[class^='col-md-o-'] { - flex:0 0 auto; - padding:0 calc(var(--u-p)/ 2) - } - .col-md { - max-width:100%; - flex-grow:1; - flex-basis:0 - } - .col-md-1 { - max-width:8.33333%; - flex-basis:8.33333% - } - .col-md-o-0 { - margin-left:0 - } - .col-md-2 { - max-width:16.66667%; - flex-basis:16.66667% - } - .col-md-o-1 { - margin-left:8.33333% - } - .col-md-3 { - max-width:25%; - flex-basis:25% - } - .col-md-o-2 { - margin-left:16.66667% - } - .col-md-4 { - max-width:33.33333%; - flex-basis:33.33333% - } - .col-md-o-3 { - margin-left:25% - } - .col-md-5 { - max-width:41.66667%; - flex-basis:41.66667% - } - .col-md-o-4 { - margin-left:33.33333% - } - .col-md-6 { - max-width:50%; - flex-basis:50% - } - .col-md-o-5 { - margin-left:41.66667% - } - .col-md-7 { - max-width:58.33333%; - flex-basis:58.33333% - } - .col-md-o-6 { - margin-left:50% - } - .col-md-8 { - max-width:66.66667%; - flex-basis:66.66667% - } - .col-md-o-7 { - margin-left:58.33333% - } - .col-md-9 { - max-width:75%; - flex-basis:75% - } - .col-md-o-8 { - margin-left:66.66667% - } - .col-md-10 { - max-width:83.33333%; - flex-basis:83.33333% - } - .col-md-o-9 { - margin-left:75% - } - .col-md-11 { - max-width:91.66667%; - flex-basis:91.66667% - } - .col-md-o-10 { - margin-left:83.33333% - } - .col-md-12 { - max-width:100%; - flex-basis:100% - } - .col-md-o-11 { - margin-left:91.66667% - } - .col-md-n { - order:initial - } - .col-md-f { - order:-999 - } - .col-md-l { - order:999 - } - } - @media screen and (min-width: 1280px) { - .col-lg,[class^='col-lg-'],[class^='col-lg-o-'] { - flex:0 0 auto; - padding:0 calc(var(--u-p)/ 2) - } - .col-lg { - max-width:100%; - flex-grow:1; - flex-basis:0 - } - .col-lg-1 { - max-width:8.33333%; - flex-basis:8.33333% - } - .col-lg-o-0 { - margin-left:0 - } - .col-lg-2 { - max-width:16.66667%; - flex-basis:16.66667% - } - .col-lg-o-1 { - margin-left:8.33333% - } - .col-lg-3 { - max-width:25%; - flex-basis:25% - } - .col-lg-o-2 { - margin-left:16.66667% - } - .col-lg-4 { - max-width:33.33333%; - flex-basis:33.33333% - } - .col-lg-o-3 { - margin-left:25% - } - .col-lg-5 { - max-width:41.66667%; - flex-basis:41.66667% - } - .col-lg-o-4 { - margin-left:33.33333% - } - .col-lg-6 { - max-width:50%; - flex-basis:50% - } - .col-lg-o-5 { - margin-left:41.66667% - } - .col-lg-7 { - max-width:58.33333%; - flex-basis:58.33333% - } - .col-lg-o-6 { - margin-left:50% - } - .col-lg-8 { - max-width:66.66667%; - flex-basis:66.66667% - } - .col-lg-o-7 { - margin-left:58.33333% - } - .col-lg-9 { - max-width:75%; - flex-basis:75% - } - .col-lg-o-8 { - margin-left:66.66667% - } - .col-lg-10 { - max-width:83.33333%; - flex-basis:83.33333% - } - .col-lg-o-9 { - margin-left:75% - } - .col-lg-11 { - max-width:91.66667%; - flex-basis:91.66667% - } - .col-lg-o-10 { - margin-left:83.33333% - } - .col-lg-12 { - max-width:100%; - flex-basis:100% - } - .col-lg-o-11 { - margin-left:91.66667% - } - .col-lg-n { - order:initial - } - .col-lg-f { - order:-999 - } - .col-lg-l { - order:999 - } - } - :root { - --cd-b-col:#f8f8f8; - --cd-f-col:#111; - --cd-br-col:#ddd - } - .card { - display:flex; - flex-direction:column; - justify-content:space-between; - align-self:center; - position:relative; - width:100%; - background:var(--cd-b-col); - color:var(--cd-f-col); - border:.0625rem solid var(--cd-br-col); - border-radius:var(--u-br-r); - margin:var(--u-m); - overflow:hidden - } - @media screen and (min-width: 320px) { - .card { - max-width:320px - } - } - .card>.section { - background:var(--cd-b-col); - color:var(--cd-f-col); - box-sizing:border-box; - margin:0; - border:0; - border-radius:0; - border-bottom:.0625rem solid var(--cd-br-col); - padding:var(--u-p); - width:100% - } - .card>.section.media { - height:200px; - padding:0; - -o-object-fit:cover; - object-fit:cover - } - .card>.section:last-child { - border-bottom:0 - } - .card.fluid { - max-width:100%; - width:auto - } - .card>.section.double-padded { - padding:calc(1.5 * var(--u-p)) - } - .card { - box-shadow:0 1.25rem 2.5rem -0.625rem rgba(0,32,64,0.1) - } - .card>h3.section.double-padded { - padding:calc(3 * var(--u-p)) - } - .card>.section.double-padded>p { - margin:var(--u-m) calc(var(--u-m)/ 2) - } - .card+.card { - margin-top:calc(5 * var(--u-m)) - } - :root { - --frm-b-col:#f0f0f0; - --frm-f-col:#111; - --frm-br-col:#ddd; - --in-b-col:#f8f8f8; - --in-f-col:#111; - --in-br-col:#ddd; - --in-fc-col:#0288d1; - --in-inv-col:#d32f2f; - --btn-b-col:#e2e2e2; - --btn-h-b-col:#dcdcdc; - --btn-f-col:#212121; - --btn-br-col:transparent; - --btn-h-br-col:transparent; - --btn-grp-br-col:rgba(124,124,124,0.54) - } - form { - background:var(--frm-b-col); - color:var(--frm-f-col); - border:.0625rem solid var(--frm-br-col); - border-radius:var(--u-br-r); - margin:var(--u-m); - padding:calc(2 * var(--u-p)) var(--u-p) - } - fieldset { - border:.0625rem solid var(--frm-br-col); - border-radius:var(--u-br-r); - margin:calc(var(--u-m)/ 4); - padding:var(--u-p) - } - legend { - box-sizing:border-box; - display:table; - max-width:100%; - white-space:normal; - font-weight:700; - padding:calc(var(--u-p)/ 2) - } - label { - padding:calc(var(--u-p)/ 2) var(--u-p) - } - .input-group { - display:inline-block - } - [type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button { - height:auto - } - [type="search"] { - -webkit-appearance:textfield; - outline-offset:-2px - } - [type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration { - -webkit-appearance:none - } - input:not([type]),[type="text"],[type="email"],[type="number"],[type="search"],[type="password"],[type="url"],[type="tel"],[type="checkbox"],[type="radio"],textarea,select { - box-sizing:border-box; - background:var(--in-b-col); - color:var(--in-f-col); - border:.0625rem solid var(--in-br-col); - border-radius:var(--u-br-r); - margin:calc(var(--u-m)/ 2); - padding:var(--u-p) calc(1.5 * var(--u-p)) - } - input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus,textarea:hover,textarea:focus,select:hover,select:focus { - border-color:var(--in-fc-col); - box-shadow:none - } - input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid,textarea:invalid,textarea:focus:invalid,select:invalid,select:focus:invalid { - border-color:var(--in-inv-col); - box-shadow:none - } - input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly],textarea[readonly],select[readonly] { - background:var(--b-col2) - } - select { - max-width:100% - } - option { - overflow:hidden; - text-overflow:ellipsis - } - [type="checkbox"],[type="radio"] { - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - position:relative; - height:calc(1rem + var(--u-p) / 2); - width:calc(1rem + var(--u-p) / 2); - vertical-align:text-bottom; - padding:0; - flex-basis:calc(1rem + var(--u-p) / 2)!important; - flex-grow:0!important - } - [type="checkbox"]:checked:before,[type="radio"]:checked:before { - position:absolute - } - [type="checkbox"]:checked:before { - content:'\2713'; - font-family:sans-serif; - font-size:calc(1rem + var(--u-p) / 2); - top:calc(0rem - var(--u-p)); - left:calc(var(--u-p)/ 4) - } - [type="radio"] { - border-radius:100% - } - [type="radio"]:checked:before { - border-radius:100%; - content:''; - top:calc(.0625rem + var(--u-p) / 2); - left:calc(.0625rem + var(--u-p) / 2); - background:var(--in-f-col); - width:0.5rem; - height:0.5rem - } - :placeholder-shown { - color:var(--in-f-col) - } - ::-ms-placeholder { - color:var(--in-f-col); - opacity:0.54 - } - button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner { - border-style:none; - padding:0 - } - button,html [type="button"],[type="reset"],[type="submit"] { - -webkit-appearance:button - } - button { - overflow:visible; - text-transform:none - } - button,[type="button"],[type="submit"],[type="reset"],a.button,label.button,.button,a[role="button"],label[role="button"],[role="button"] { - display:inline-block; - background:var(--btn-b-col); - color:var(--btn-f-col); - border:.0625rem solid var(--btn-br-col); - border-radius:var(--u-br-r); - padding:var(--u-p) calc(1.5 * var(--u-p)); - margin:var(--u-m); - text-decoration:none; - cursor:pointer; - transition:background 0.3s - } - button:hover,button:focus,[type="button"]:hover,[type="button"]:focus,[type="submit"]:hover,[type="submit"]:focus,[type="reset"]:hover,[type="reset"]:focus,a.button:hover,a.button:focus,label.button:hover,label.button:focus,.button:hover,.button:focus,a[role="button"]:hover,a[role="button"]:focus,label[role="button"]:hover,label[role="button"]:focus,[role="button"]:hover,[role="button"]:focus { - background:var(--btn-h-b-col); - border-color:var(--btn-h-br-col) - } - input:disabled,input[disabled],textarea:disabled,textarea[disabled],select:disabled,select[disabled],button:disabled,button[disabled],.button:disabled,.button[disabled],[role="button"]:disabled,[role="button"][disabled] { - cursor:not-allowed; - opacity:.75 - } - .button-group { - display:flex; - border:.0625rem solid var(--btn-grp-br-col); - border-radius:var(--u-br-r); - margin:var(--u-m) - } - .button-group>button,.button-group [type="button"],.button-group>[type="submit"],.button-group>[type="reset"],.button-group>.button,.button-group>[role="button"] { - margin:0; - max-width:100%; - flex:1 1 auto; - text-align:center; - border:0; - border-radius:0; - box-shadow:none - } - .button-group>:not(:first-child) { - border-left:.0625rem solid var(--btn-grp-br-col) - } - @media screen and (max-width: 767px) { - .button-group { - flex-direction:column - } - .button-group>:not(:first-child) { - border:0; - border-top:.0625rem solid var(--btn-grp-br-col) - } - } - button.primary,[type="button"].primary,[type="submit"].primary,[type="reset"].primary,.button.primary,[role="button"].primary { - --btn-b-col:#1976d2; - --btn-f-col:#f8f8f8 - } - button.primary:hover,button.primary:focus,[type="button"].primary:hover,[type="button"].primary:focus,[type="submit"].primary:hover,[type="submit"].primary:focus,[type="reset"].primary:hover,[type="reset"].primary:focus,.button.primary:hover,.button.primary:focus,[role="button"].primary:hover,[role="button"].primary:focus { - --btn-h-b-col:#1565c0 - } - :root { - --hd-b-col:#f8f8f8; - --hd-hv-b-col:#f0f0f0; - --hd-f-col:#444; - --hd-br-col:#ddd; - --nv-b-col:#f8f8f8; - --nv-hv-b-col:#f0f0f0; - --nv-f-col:#444; - --nv-br-col:#ddd; - --nv-ln-col:#0277bd; - --ft-f-col:#444; - --ft-b-col:#f8f8f8; - --ft-br-col:#ddd; - --ft-ln-col:#0277bd; - --dr-b-col:#f8f8f8; - --dr-hv-b-col:#f0f0f0; - --dr-br-col:#ddd; - --dr-cl-col:#444 - } - header { - height:3.1875rem; - background:var(--hd-b-col); - color:var(--hd-f-col); - border-bottom:.0625rem solid var(--hd-br-col); - padding:calc(var(--u-p)/ 4) 0; - white-space:nowrap; - overflow-x:auto; - overflow-y:hidden - } - header.row { - box-sizing:content-box - } - header .logo { - color:var(--hd-f-col); - font-size:1.75rem; - padding:var(--u-p) calc(2 * var(--u-p)); - text-decoration:none - } - header button,header [type="button"],header .button,header [role="button"] { - box-sizing:border-box; - position:relative; - top:calc(0rem - var(--u-p) / 4); - height:calc(3.1875rem + var(--u-p) / 2); - background:var(--hd-b-col); - line-height:calc(3.1875rem - var(--u-p) * 1.5); - text-align:center; - color:var(--hd-f-col); - border:0; - border-radius:0; - margin:0; - text-transform:uppercase - } - header button:hover,header button:focus,header [type="button"]:hover,header [type="button"]:focus,header .button:hover,header .button:focus,header [role="button"]:hover,header [role="button"]:focus { - background:var(--hd-hv-b-col) - } - nav { - background:var(--nv-b-col); - color:var(--nv-f-col); - border:.0625rem solid var(--nv-br-col); - border-radius:var(--u-br-r); - margin:var(--u-m) - } - nav * { - padding:var(--u-p) calc(1.5 * var(--u-p)) - } - nav a,nav a:visited { - display:block; - color:var(--nv-ln-col); - border-radius:var(--u-br-r); - transition:background 0.3s - } - nav a:hover,nav a:focus,nav a:visited:hover,nav a:visited:focus { - text-decoration:none; - background:var(--nv-hv-b-col) - } - nav .sublink-1 { - position:relative; - margin-left:calc(2 * var(--u-p)) - } - nav .sublink-1:before { - position:absolute; - left:calc(var(--u-p) - 1 * var(--u-p)); - top:-.0625rem; - content:''; - height:100%; - border:.0625rem solid var(--nv-br-col); - border-left:0 - } - footer { - background:var(--ft-b-col); - color:var(--ft-f-col); - border-top:.0625rem solid var(--ft-br-col); - padding:calc(2 * var(--u-p)) var(--u-p); - font-size:.875rem - } - footer a,footer a:visited { - color:var(--ft-ln-col) - } - header.sticky { - position:-webkit-sticky; - position:sticky; - z-index:1101; - top:0 - } - footer.sticky { - position:-webkit-sticky; - position:sticky; - z-index:1101; - bottom:0 - } - .drawer-toggle:before { - display:inline-block; - position:relative; - vertical-align:bottom; - content:'\00a0\2261\00a0'; - font-family:sans-serif; - font-size:1.5em - } - @media screen and (min-width: 768px) { - .drawer-toggle:not(.persistent) { - display:none - } - } - [type="checkbox"].drawer { - height:1px; - width:1px; - margin:-1px; - overflow:hidden; - position:absolute; - clip:rect(0 0 0 0); - -webkit-clip-path:inset(100%); - clip-path:inset(100%) - } - [type="checkbox"].drawer+* { - display:block; - box-sizing:border-box; - position:fixed; - top:0; - width:320px; - height:100vh; - overflow-y:auto; - background:var(--dr-b-col); - border:.0625rem solid var(--dr-br-col); - border-radius:0; - margin:0; - z-index:1110; - left:-320px; - transition:left 0.3s - } - [type="checkbox"].drawer+* .drawer-close { - position:absolute; - top:var(--u-m); - right:var(--u-m); - z-index:1111; - width:2rem; - height:2rem; - border-radius:var(--u-br-r); - padding:var(--u-p); - margin:0; - cursor:pointer; - transition:background 0.3s - } - [type="checkbox"].drawer+* .drawer-close:before { - display:block; - content:'\00D7'; - color:var(--dr-cl-col); - position:relative; - font-family:sans-serif; - font-size:2rem; - line-height:1; - text-align:center - } - [type="checkbox"].drawer+* .drawer-close:hover,[type="checkbox"].drawer+* .drawer-close:focus { - background:var(--dr-hv-b-col) - } - @media screen and (max-width: 320px) { - [type="checkbox"].drawer+* { - width:100% - } - } - [type="checkbox"].drawer:checked+* { - left:0 - } - @media screen and (min-width: 768px) { - [type="checkbox"].drawer:not(.persistent)+* { - position:static; - height:100%; - z-index:1100 - } - [type="checkbox"].drawer:not(.persistent)+* .drawer-close { - display:none - } - } - :root { - --mrk-b-col:#424242; - --mrk-f-col:#fafafa - } - mark { - background:var(--mrk-b-col); - color:var(--mrk-f-col); - font-size:.5em; - line-height:1em; - border-radius:var(--u-br-r); - padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) - } - mark.inline-block { - display:inline-block; - font-size:1em; - line-height:1.5; - padding:calc(var(--u-p)/ 2) var(--u-p) - } - :root { - --tst-b-col:#212121; - --tst-f-col:#fafafa - } - .toast { - position:fixed; - bottom:calc(var(--u-m) * 3); - left:50%; - transform:translate(-50%,-50%); - z-index:1111; - color:var(--tst-f-col); - background:var(--tst-b-col); - border-radius:calc(var(--u-br-r) * 16); - padding:var(--u-p) calc(var(--u-p) * 3) - } - .toast { - bottom:calc(var(--u-m)/ 2); - opacity:1; - transition:opacity 0.3s ease-in-out - } - mark { - position:relative; - top:-0.25rem; - left:0.25rem - } - mark.secondary { - --mrk-b-col:#d32f2f - } - mark.tertiary { - --mrk-b-col:#308732 - } - mark.tag { - padding:calc(var(--u-p)/2) var(--u-p); - border-radius:1em - } - code,pre,kbd,code *,pre *,kbd *,code[class*="language-"],pre[class*="language-"] { - font-family:Menlo,Consolas,monospace!important - } - pre { - border:0.0625rem solid var(--br-col2); - border-radius:var(--u-br-r) - } - .group { - position:relative; - margin-top:2em; - margin-bottom:1em - } - .search { - font-size:0.875rem; - margin-top:-0.1em; - display:block; - width:100%; - border:none; - border-bottom:.0625rem solid var(--nv-ln-col) - } - .search:focus { - outline:none - } - label#search-label { - color:var(--nv-ln-col); - font-size:1.125rem; - font-weight:400; - position:absolute; - left:0.3125rem; - top:0.625rem - } - .search:focus~label#search-label,.search:valid~label#search-label { - top:-1.25rem; - font-size:0.875rem; - color:var(--nv-ln-col) - } - label#menu-toggle { - width:3.4375rem - } - header h1.logo { - margin-top:-0.8rem; - text-align:center - } - header h1.logo a { - text-decoration:none; - color:#111 - } - header #title { - position:relative; - top:-1rem - } - @media screen and (max-width: 500px) { - header #title { - font-size:1rem; - display:block - } - } - header h1 small { - display:block; - font-size:0.875rem; - color:#888; - margin-top:-0.8rem - } - @media screen and (max-width: 768px) { - header h1 small { - font-size:0.75rem - } - } - @media screen and (max-width: 600px) { - header h1 small { - font-size:0.625rem - } - } - @media screen and (max-width: 500px) { - header h1 small { - font-size:0.5rem; - margin-top:-1.2rem - } - } - label#menu-toggle { - position:absolute; - left:0.5rem; - top:0.5rem; - width:3.4375rem - } - main { - padding:0 - } - :root { - --clps-lbl-b-col:#e8e8e8; - --clps-lbl-f-col:#212121; - --clps-lbl-h-b-col:#f0f0f0; - --clps-sel-lbl-b-col:#ececec; - --clps-br-col:#ddd; - --clps-cnt-b-col:#fafafa; - --clps-sel-lbl-br-col:#0277bd - } - label.collapse { - width:100%; - display:inline-block; - cursor:pointer; - box-sizing:border-box; - transition:background 0.3s; - color:var(--clps-lbl-f-col); - background:var(--clps-lbl-b-col); - border:.0625rem solid var(--clps-br-col); - padding:calc(1.5 * var(--u-p)); - border-radius:var(--u-br-r) - } - label.collapse:hover,label.collapse:focus { - background:var(--clps-lbl-h-b-col) - } - label.collapse+pre { - box-sizing:border-box; - height:0; - max-height:1px; - overflow:auto; - margin:0; - border:0; - padding:0; - transition:max-height 0.3s - } - label.collapse.toggled { - background:var(--clps-sel-lbl-b-col); - border-bottom-color:var(--clps-sel-lbl-br-col); - border-bottom-left-radius:0; - border-bottom-right-radius:0 - } - label.collapse.toggled+pre { - border-top-left-radius:0; - border-top-right-radius:0; - position:relative; - width:100%; - height:auto; - border:.0625rem solid var(--clps-br-col); - border-top:0; - padding:calc(2 * var(--u-p)); - max-height:400px - } - button.primary.clipboard-copy { - width:100%; - margin-left:0 - } - button.primary.clipboard-copy>img { - vertical-align:bottom - } - code[class*="language-"],pre[class*="language-"] { - color:#222; - text-align:left; - white-space:pre; - word-spacing:normal; - word-break:normal; - word-wrap:normal; - line-height:1.8; - -moz-tab-size:2; - -o-tab-size:2; - tab-size:2; - -webkit-hypens:none; - -moz-hyphens:none; - -ms-hyphens:none; - hyphens:none - } - pre[class*="language-"] { - padding:calc(2 * var(--u-p)); - overflow:auto; - margin:var(--u-m) 0 - } - pre[class*="language-"]::-moz-selection,pre[class*="language-"] ::-moz-selection,code[class*="language-"]::-moz-selection,code[class*="language-"] ::-moz-selection { - background:#b3d4fc - } - pre[class*="language-"]::selection,pre[class*="language-"] ::selection,code[class*="language-"]::selection,code[class*="language-"] ::selection { - background:#b3d4fc - } - :not(pre)>code[class*="language-"] { - padding:.1em; - border-radius:.3em; - white-space:normal - } - .token.comment,.token.prolog,.token.doctype,.token.cdata { - color:#7a8490 - } - .token.punctuation { - color:#666 - } - .namespace { - opacity:.7 - } - .token.property,.token.tag,.token.boolean,.token.constant,.token.symbol,.token.deleted,.token.function { - color:#005cc5 - } - .token.number,.token.class-name { - color:#832ed2 - } - .token.selector,.token.attr-name,.token.string,.token.char,.token.builtin,.token.inserted { - color:#067e36 - } - .token.operator,.token.entity,.token.url,.language-css .token.string,.style .token.string,.token.atrule,.token.attr-value,.token.keyword { - color:#d73a49 - } - .token.regex { - color:#097cab - } - .token.important,.token.variable { - color:#e90 - } - .token.important,.token.bold { - font-weight:bold - } - .token.italic { - font-style:italic - } - .token.entity { - cursor:help - } - button.scroll-to-top { - border-radius:100%; - font-size:1.5rem; - line-height:1; - box-sizing:border-box; - width:2.75rem; - height:2.75rem; - position:fixed; - bottom:1rem; - right:2rem; - background:var(--b-col); - box-shadow:0 0.25rem 0.25rem 0 rgba(0,0,0,0.125),0 0.125rem 0.125rem -0.125rem rgba(0,0,0,0.25) - } - button.scroll-to-top:hover,button.scroll-to-top:focus { - background:var(--b-col2) - } +:root { + --f-col:#111; + --f-col2:#444; + --b-col:#f8f8f8; + --b-col2:#f0f0f0; + --blq-col:#f57c00; + --pre-col:#1565c0; + --br-col:#aaa; + --br-col2:#ddd; + --h-ratio:1.19; + --u-m:.5rem; + --u-p:.5rem; + --u-br-r:.125rem; + --a-l-col:#0277bd; + --a-v-col:#01579b + } + html { + font-size:16px + } + a,b,del,em,i,ins,q,span,strong,u { + font-size:1em + } + html,* { + font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",Helvetica,sans-serif; + line-height:1.5; + -webkit-text-size-adjust:100% + } + * { + font-size:1rem + } + body { + margin:0; + color:var(--f-col); + background:var(--b-col) + } + details { + display:block + } + summary { + display:list-item + } + abbr[title] { + border-bottom:none; + text-decoration:underline dotted + } + input { + overflow:visible + } + img { + max-width:100%; + height:auto + } + h1,h2,h3,h4,h5,h6 { + line-height:1.2; + margin:calc(1.5 * var(--u-m)) var(--u-m); + font-weight:500 + } + h1 small,h2 small,h3 small,h4 small,h5 small,h6 small { + color:var(--f-col2); + display:block; + margin-top:-.25rem + } + h1 { + font-size:calc(1rem * var(--h-ratio) * var(--h-ratio) * var(--h-ratio) * var(--h-ratio)) + } + h2 { + font-size:calc(1rem * var(--h-ratio) * var(--h-ratio) * var(--h-ratio)) + } + h3 { + font-size:calc(1rem * var(--h-ratio) * var(--h-ratio)) + } + h4 { + font-size:calc(1rem * var(--h-ratio)) + } + h5 { + font-size:1rem + } + h6 { + font-size:calc(1rem/ var(--h-ratio)) + } + p { + margin:var(--u-m) + } + ol,ul { + margin:var(--u-m); + padding-left:calc(2 * var(--u-m)) + } + b,strong { + font-weight:700 + } + hr { + box-sizing:content-box; + border:0; + line-height:1.25em; + margin:var(--u-m); + height:.0625rem; + background:linear-gradient(to right,transparent,var(--br-col) 20%,var(--br-col) 80%,transparent) + } + blockquote { + display:block; + position:relative; + font-style:italic; + color:var(--f-col2); + margin:var(--u-m); + padding:calc(3 * var(--u-p)); + border:.0625rem solid var(--br-col2); + border-left:.375rem solid var(--blq-col); + border-radius:0 var(--u-br-r) var(--u-br-r) 0 + } + blockquote:before { + position:absolute; + top:calc(0rem - var(--u-p)); + left:0; + font-family:sans-serif; + font-size:3rem; + font-weight:700; + content:"\201c"; + color:var(--blq-col) + } + blockquote[cite]:after { + font-style:normal; + font-size:.75em; + font-weight:700; + content:"\a— " attr(cite); + white-space:pre + } + code,kbd,pre,samp { + font-family:Menlo,Consolas,monospace; + font-size:.85em + } + code { + background:var(--b-col2); + border-radius:var(--u-br-r); + padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) + } + kbd { + background:var(--f-col); + color:var(--b-col); + border-radius:var(--u-br-r); + padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) + } + pre { + overflow:auto; + background:var(--b-col2); + padding:calc(1.5 * var(--u-p)); + margin:var(--u-m); + border:.0625rem solid var(--br-col2); + border-left:.25rem solid var(--pre-col); + border-radius:0 var(--u-br-r) var(--u-br-r) 0 + } + sup,sub,code,kbd { + line-height:0; + position:relative; + vertical-align:baseline + } + small,sup,sub,figcaption { + font-size:.75em + } + sup { + top:-.5em + } + sub { + bottom:-.25em + } + figure { + margin:var(--u-m) + } + figcaption { + color:var(--f-col2) + } + a { + text-decoration:none + } + a:link { + color:var(--a-l-col) + } + a:visited { + color:var(--a-v-col) + } + a:hover,a:focus { + text-decoration:underline + } + .container { + margin:0 auto; + padding:0 calc(1.5 * var(--u-p)) + } + .row { + box-sizing:border-box; + display:flex; + flex:0 1 auto; + flex-flow:row wrap + } + .col-sm,[class^='col-sm-'],[class^='col-sm-o-'] { + flex:0 0 auto; + padding:0 calc(var(--u-p)/ 2) + } + .col-sm { + max-width:100%; + flex-grow:1; + flex-basis:0 + } + .col-sm-1 { + max-width:8.33333%; + flex-basis:8.33333% + } + .col-sm-o-0 { + margin-left:0 + } + .col-sm-2 { + max-width:16.66667%; + flex-basis:16.66667% + } + .col-sm-o-1 { + margin-left:8.33333% + } + .col-sm-3 { + max-width:25%; + flex-basis:25% + } + .col-sm-o-2 { + margin-left:16.66667% + } + .col-sm-4 { + max-width:33.33333%; + flex-basis:33.33333% + } + .col-sm-o-3 { + margin-left:25% + } + .col-sm-5 { + max-width:41.66667%; + flex-basis:41.66667% + } + .col-sm-o-4 { + margin-left:33.33333% + } + .col-sm-6 { + max-width:50%; + flex-basis:50% + } + .col-sm-o-5 { + margin-left:41.66667% + } + .col-sm-7 { + max-width:58.33333%; + flex-basis:58.33333% + } + .col-sm-o-6 { + margin-left:50% + } + .col-sm-8 { + max-width:66.66667%; + flex-basis:66.66667% + } + .col-sm-o-7 { + margin-left:58.33333% + } + .col-sm-9 { + max-width:75%; + flex-basis:75% + } + .col-sm-o-8 { + margin-left:66.66667% + } + .col-sm-10 { + max-width:83.33333%; + flex-basis:83.33333% + } + .col-sm-o-9 { + margin-left:75% + } + .col-sm-11 { + max-width:91.66667%; + flex-basis:91.66667% + } + .col-sm-o-10 { + margin-left:83.33333% + } + .col-sm-12 { + max-width:100%; + flex-basis:100% + } + .col-sm-o-11 { + margin-left:91.66667% + } + .col-sm-n { + order:initial + } + .col-sm-f { + order:-999 + } + .col-sm-l { + order:999 + } + @media screen and (min-width: 768px) { + .col-md,[class^='col-md-'],[class^='col-md-o-'] { + flex:0 0 auto; + padding:0 calc(var(--u-p)/ 2) + } + .col-md { + max-width:100%; + flex-grow:1; + flex-basis:0 + } + .col-md-1 { + max-width:8.33333%; + flex-basis:8.33333% + } + .col-md-o-0 { + margin-left:0 + } + .col-md-2 { + max-width:16.66667%; + flex-basis:16.66667% + } + .col-md-o-1 { + margin-left:8.33333% + } + .col-md-3 { + max-width:25%; + flex-basis:25% + } + .col-md-o-2 { + margin-left:16.66667% + } + .col-md-4 { + max-width:33.33333%; + flex-basis:33.33333% + } + .col-md-o-3 { + margin-left:25% + } + .col-md-5 { + max-width:41.66667%; + flex-basis:41.66667% + } + .col-md-o-4 { + margin-left:33.33333% + } + .col-md-6 { + max-width:50%; + flex-basis:50% + } + .col-md-o-5 { + margin-left:41.66667% + } + .col-md-7 { + max-width:58.33333%; + flex-basis:58.33333% + } + .col-md-o-6 { + margin-left:50% + } + .col-md-8 { + max-width:66.66667%; + flex-basis:66.66667% + } + .col-md-o-7 { + margin-left:58.33333% + } + .col-md-9 { + max-width:75%; + flex-basis:75% + } + .col-md-o-8 { + margin-left:66.66667% + } + .col-md-10 { + max-width:83.33333%; + flex-basis:83.33333% + } + .col-md-o-9 { + margin-left:75% + } + .col-md-11 { + max-width:91.66667%; + flex-basis:91.66667% + } + .col-md-o-10 { + margin-left:83.33333% + } + .col-md-12 { + max-width:100%; + flex-basis:100% + } + .col-md-o-11 { + margin-left:91.66667% + } + .col-md-n { + order:initial + } + .col-md-f { + order:-999 + } + .col-md-l { + order:999 + } + } + @media screen and (min-width: 1280px) { + .col-lg,[class^='col-lg-'],[class^='col-lg-o-'] { + flex:0 0 auto; + padding:0 calc(var(--u-p)/ 2) + } + .col-lg { + max-width:100%; + flex-grow:1; + flex-basis:0 + } + .col-lg-1 { + max-width:8.33333%; + flex-basis:8.33333% + } + .col-lg-o-0 { + margin-left:0 + } + .col-lg-2 { + max-width:16.66667%; + flex-basis:16.66667% + } + .col-lg-o-1 { + margin-left:8.33333% + } + .col-lg-3 { + max-width:25%; + flex-basis:25% + } + .col-lg-o-2 { + margin-left:16.66667% + } + .col-lg-4 { + max-width:33.33333%; + flex-basis:33.33333% + } + .col-lg-o-3 { + margin-left:25% + } + .col-lg-5 { + max-width:41.66667%; + flex-basis:41.66667% + } + .col-lg-o-4 { + margin-left:33.33333% + } + .col-lg-6 { + max-width:50%; + flex-basis:50% + } + .col-lg-o-5 { + margin-left:41.66667% + } + .col-lg-7 { + max-width:58.33333%; + flex-basis:58.33333% + } + .col-lg-o-6 { + margin-left:50% + } + .col-lg-8 { + max-width:66.66667%; + flex-basis:66.66667% + } + .col-lg-o-7 { + margin-left:58.33333% + } + .col-lg-9 { + max-width:75%; + flex-basis:75% + } + .col-lg-o-8 { + margin-left:66.66667% + } + .col-lg-10 { + max-width:83.33333%; + flex-basis:83.33333% + } + .col-lg-o-9 { + margin-left:75% + } + .col-lg-11 { + max-width:91.66667%; + flex-basis:91.66667% + } + .col-lg-o-10 { + margin-left:83.33333% + } + .col-lg-12 { + max-width:100%; + flex-basis:100% + } + .col-lg-o-11 { + margin-left:91.66667% + } + .col-lg-n { + order:initial + } + .col-lg-f { + order:-999 + } + .col-lg-l { + order:999 + } + } + :root { + --cd-b-col:#f8f8f8; + --cd-f-col:#111; + --cd-br-col:#ddd + } + .card { + display:flex; + flex-direction:column; + justify-content:space-between; + align-self:center; + position:relative; + width:100%; + background:var(--cd-b-col); + color:var(--cd-f-col); + border:.0625rem solid var(--cd-br-col); + border-radius:var(--u-br-r); + margin:var(--u-m); + overflow:hidden + } + @media screen and (min-width: 320px) { + .card { + max-width:320px + } + } + .card>.section { + background:var(--cd-b-col); + color:var(--cd-f-col); + box-sizing:border-box; + margin:0; + border:0; + border-radius:0; + border-bottom:.0625rem solid var(--cd-br-col); + padding:var(--u-p); + width:100% + } + .card>.section.media { + height:200px; + padding:0; + -o-object-fit:cover; + object-fit:cover + } + .card>.section:last-child { + border-bottom:0 + } + .card.fluid { + max-width:100%; + width:auto + } + .card>.section.double-padded { + padding:calc(1.5 * var(--u-p)) + } + .card { + box-shadow:0 1.25rem 2.5rem -0.625rem rgba(0,32,64,0.1) + } + .card>h3.section.double-padded { + padding:calc(3 * var(--u-p)) + } + .card>.section.double-padded>p { + margin:var(--u-m) calc(var(--u-m)/ 2) + } + .card+.card { + margin-top:calc(5 * var(--u-m)) + } + :root { + --frm-b-col:#f0f0f0; + --frm-f-col:#111; + --frm-br-col:#ddd; + --in-b-col:#f8f8f8; + --in-f-col:#111; + --in-br-col:#ddd; + --in-fc-col:#0288d1; + --in-inv-col:#d32f2f; + --btn-b-col:#e2e2e2; + --btn-h-b-col:#dcdcdc; + --btn-f-col:#212121; + --btn-br-col:transparent; + --btn-h-br-col:transparent; + --btn-grp-br-col:rgba(124,124,124,0.54) + } + form { + background:var(--frm-b-col); + color:var(--frm-f-col); + border:.0625rem solid var(--frm-br-col); + border-radius:var(--u-br-r); + margin:var(--u-m); + padding:calc(2 * var(--u-p)) var(--u-p) + } + fieldset { + border:.0625rem solid var(--frm-br-col); + border-radius:var(--u-br-r); + margin:calc(var(--u-m)/ 4); + padding:var(--u-p) + } + legend { + box-sizing:border-box; + display:table; + max-width:100%; + white-space:normal; + font-weight:700; + padding:calc(var(--u-p)/ 2) + } + label { + padding:calc(var(--u-p)/ 2) var(--u-p) + } + .input-group { + display:inline-block + } + [type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button { + height:auto + } + [type="search"] { + -webkit-appearance:textfield; + outline-offset:-2px + } + [type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration { + -webkit-appearance:none + } + input:not([type]),[type="text"],[type="email"],[type="number"],[type="search"],[type="password"],[type="url"],[type="tel"],[type="checkbox"],[type="radio"],textarea,select { + box-sizing:border-box; + background:var(--in-b-col); + color:var(--in-f-col); + border:.0625rem solid var(--in-br-col); + border-radius:var(--u-br-r); + margin:calc(var(--u-m)/ 2); + padding:var(--u-p) calc(1.5 * var(--u-p)) + } + input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus,textarea:hover,textarea:focus,select:hover,select:focus { + border-color:var(--in-fc-col); + box-shadow:none + } + input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid,textarea:invalid,textarea:focus:invalid,select:invalid,select:focus:invalid { + border-color:var(--in-inv-col); + box-shadow:none + } + input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly],textarea[readonly],select[readonly] { + background:var(--b-col2) + } + select { + max-width:100% + } + option { + overflow:hidden; + text-overflow:ellipsis + } + [type="checkbox"],[type="radio"] { + -webkit-appearance:none; + -moz-appearance:none; + appearance:none; + position:relative; + height:calc(1rem + var(--u-p) / 2); + width:calc(1rem + var(--u-p) / 2); + vertical-align:text-bottom; + padding:0; + flex-basis:calc(1rem + var(--u-p) / 2)!important; + flex-grow:0!important + } + [type="checkbox"]:checked:before,[type="radio"]:checked:before { + position:absolute + } + [type="checkbox"]:checked:before { + content:'\2713'; + font-family:sans-serif; + font-size:calc(1rem + var(--u-p) / 2); + top:calc(0rem - var(--u-p)); + left:calc(var(--u-p)/ 4) + } + [type="radio"] { + border-radius:100% + } + [type="radio"]:checked:before { + border-radius:100%; + content:''; + top:calc(.0625rem + var(--u-p) / 2); + left:calc(.0625rem + var(--u-p) / 2); + background:var(--in-f-col); + width:0.5rem; + height:0.5rem + } + :placeholder-shown { + color:var(--in-f-col) + } + ::-ms-placeholder { + color:var(--in-f-col); + opacity:0.54 + } + button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner { + border-style:none; + padding:0 + } + button,html [type="button"],[type="reset"],[type="submit"] { + -webkit-appearance:button + } + button { + overflow:visible; + text-transform:none + } + button,[type="button"],[type="submit"],[type="reset"],a.button,label.button,.button,a[role="button"],label[role="button"],[role="button"] { + display:inline-block; + background:var(--btn-b-col); + color:var(--btn-f-col); + border:.0625rem solid var(--btn-br-col); + border-radius:var(--u-br-r); + padding:var(--u-p) calc(1.5 * var(--u-p)); + margin:var(--u-m); + text-decoration:none; + cursor:pointer; + transition:background 0.3s + } + button:hover,button:focus,[type="button"]:hover,[type="button"]:focus,[type="submit"]:hover,[type="submit"]:focus,[type="reset"]:hover,[type="reset"]:focus,a.button:hover,a.button:focus,label.button:hover,label.button:focus,.button:hover,.button:focus,a[role="button"]:hover,a[role="button"]:focus,label[role="button"]:hover,label[role="button"]:focus,[role="button"]:hover,[role="button"]:focus { + background:var(--btn-h-b-col); + border-color:var(--btn-h-br-col) + } + input:disabled,input[disabled],textarea:disabled,textarea[disabled],select:disabled,select[disabled],button:disabled,button[disabled],.button:disabled,.button[disabled],[role="button"]:disabled,[role="button"][disabled] { + cursor:not-allowed; + opacity:.75 + } + .button-group { + display:flex; + border:.0625rem solid var(--btn-grp-br-col); + border-radius:var(--u-br-r); + margin:var(--u-m) + } + .button-group>button,.button-group [type="button"],.button-group>[type="submit"],.button-group>[type="reset"],.button-group>.button,.button-group>[role="button"] { + margin:0; + max-width:100%; + flex:1 1 auto; + text-align:center; + border:0; + border-radius:0; + box-shadow:none + } + .button-group>:not(:first-child) { + border-left:.0625rem solid var(--btn-grp-br-col) + } + @media screen and (max-width: 767px) { + .button-group { + flex-direction:column + } + .button-group>:not(:first-child) { + border:0; + border-top:.0625rem solid var(--btn-grp-br-col) + } + } + button.primary,[type="button"].primary,[type="submit"].primary,[type="reset"].primary,.button.primary,[role="button"].primary { + --btn-b-col:#1976d2; + --btn-f-col:#f8f8f8 + } + button.primary:hover,button.primary:focus,[type="button"].primary:hover,[type="button"].primary:focus,[type="submit"].primary:hover,[type="submit"].primary:focus,[type="reset"].primary:hover,[type="reset"].primary:focus,.button.primary:hover,.button.primary:focus,[role="button"].primary:hover,[role="button"].primary:focus { + --btn-h-b-col:#1565c0 + } + :root { + --hd-b-col:#f8f8f8; + --hd-hv-b-col:#f0f0f0; + --hd-f-col:#444; + --hd-br-col:#ddd; + --nv-b-col:#f8f8f8; + --nv-hv-b-col:#f0f0f0; + --nv-f-col:#444; + --nv-br-col:#ddd; + --nv-ln-col:#0277bd; + --ft-f-col:#444; + --ft-b-col:#f8f8f8; + --ft-br-col:#ddd; + --ft-ln-col:#0277bd; + --dr-b-col:#f8f8f8; + --dr-hv-b-col:#f0f0f0; + --dr-br-col:#ddd; + --dr-cl-col:#444 + } + header { + height:3.1875rem; + background:var(--hd-b-col); + color:var(--hd-f-col); + border-bottom:.0625rem solid var(--hd-br-col); + padding:calc(var(--u-p)/ 4) 0; + white-space:nowrap; + overflow-x:auto; + overflow-y:hidden + } + header.row { + box-sizing:content-box + } + header .logo { + color:var(--hd-f-col); + font-size:1.75rem; + padding:var(--u-p) calc(2 * var(--u-p)); + text-decoration:none + } + header button,header [type="button"],header .button,header [role="button"] { + box-sizing:border-box; + position:relative; + top:calc(0rem - var(--u-p) / 4); + height:calc(3.1875rem + var(--u-p) / 2); + background:var(--hd-b-col); + line-height:calc(3.1875rem - var(--u-p) * 1.5); + text-align:center; + color:var(--hd-f-col); + border:0; + border-radius:0; + margin:0; + text-transform:uppercase + } + header button:hover,header button:focus,header [type="button"]:hover,header [type="button"]:focus,header .button:hover,header .button:focus,header [role="button"]:hover,header [role="button"]:focus { + background:var(--hd-hv-b-col) + } + nav { + background:var(--nv-b-col); + color:var(--nv-f-col); + border:.0625rem solid var(--nv-br-col); + border-radius:var(--u-br-r); + margin:var(--u-m) + } + nav * { + padding:var(--u-p) calc(1.5 * var(--u-p)) + } + nav a,nav a:visited { + display:block; + color:var(--nv-ln-col); + border-radius:var(--u-br-r); + transition:background 0.3s + } + nav a:hover,nav a:focus,nav a:visited:hover,nav a:visited:focus { + text-decoration:none; + background:var(--nv-hv-b-col) + } + nav .sublink-1 { + position:relative; + margin-left:calc(2 * var(--u-p)) + } + nav .sublink-1:before { + position:absolute; + left:calc(var(--u-p) - 1 * var(--u-p)); + top:-.0625rem; + content:''; + height:100%; + border:.0625rem solid var(--nv-br-col); + border-left:0 + } + footer { + background:var(--ft-b-col); + color:var(--ft-f-col); + border-top:.0625rem solid var(--ft-br-col); + padding:calc(2 * var(--u-p)) var(--u-p); + font-size:.875rem + } + footer a,footer a:visited { + color:var(--ft-ln-col) + } + header.sticky { + position:-webkit-sticky; + position:sticky; + z-index:1101; + top:0 + } + footer.sticky { + position:-webkit-sticky; + position:sticky; + z-index:1101; + bottom:0 + } + .drawer-toggle:before { + display:inline-block; + position:relative; + vertical-align:bottom; + content:'\00a0\2261\00a0'; + font-family:sans-serif; + font-size:1.5em + } + @media screen and (min-width: 768px) { + .drawer-toggle:not(.persistent) { + display:none + } + } + [type="checkbox"].drawer { + height:1px; + width:1px; + margin:-1px; + overflow:hidden; + position:absolute; + clip:rect(0 0 0 0); + -webkit-clip-path:inset(100%); + clip-path:inset(100%) + } + [type="checkbox"].drawer+* { + display:block; + box-sizing:border-box; + position:fixed; + top:0; + width:320px; + height:100vh; + overflow-y:auto; + background:var(--dr-b-col); + border:.0625rem solid var(--dr-br-col); + border-radius:0; + margin:0; + z-index:1110; + left:-320px; + transition:left 0.3s + } + [type="checkbox"].drawer+* .drawer-close { + position:absolute; + top:var(--u-m); + right:var(--u-m); + z-index:1111; + width:2rem; + height:2rem; + border-radius:var(--u-br-r); + padding:var(--u-p); + margin:0; + cursor:pointer; + transition:background 0.3s + } + [type="checkbox"].drawer+* .drawer-close:before { + display:block; + content:'\00D7'; + color:var(--dr-cl-col); + position:relative; + font-family:sans-serif; + font-size:2rem; + line-height:1; + text-align:center + } + [type="checkbox"].drawer+* .drawer-close:hover,[type="checkbox"].drawer+* .drawer-close:focus { + background:var(--dr-hv-b-col) + } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer+* { + width:100% + } + } + [type="checkbox"].drawer:checked+* { + left:0 + } + @media screen and (min-width: 768px) { + [type="checkbox"].drawer:not(.persistent)+* { + position:static; + height:100%; + z-index:1100 + } + [type="checkbox"].drawer:not(.persistent)+* .drawer-close { + display:none + } + } + :root { + --mrk-b-col:#424242; + --mrk-f-col:#fafafa + } + mark { + background:var(--mrk-b-col); + color:var(--mrk-f-col); + font-size:.5em; + line-height:1em; + border-radius:var(--u-br-r); + padding:calc(var(--u-p)/ 4) calc(var(--u-p)/ 2) + } + mark.inline-block { + display:inline-block; + font-size:1em; + line-height:1.5; + padding:calc(var(--u-p)/ 2) var(--u-p) + } + :root { + --tst-b-col:#212121; + --tst-f-col:#fafafa + } + .toast { + position:fixed; + bottom:calc(var(--u-m) * 3); + left:50%; + transform:translate(-50%,-50%); + z-index:1111; + color:var(--tst-f-col); + background:var(--tst-b-col); + border-radius:calc(var(--u-br-r) * 16); + padding:var(--u-p) calc(var(--u-p) * 3) + } + .toast { + bottom:calc(var(--u-m)/ 2); + opacity:1; + transition:opacity 0.3s ease-in-out + } + mark { + position:relative; + top:-0.25rem; + left:0.25rem + } + mark.secondary { + --mrk-b-col:#d32f2f + } + mark.tertiary { + --mrk-b-col:#308732 + } + mark.tag { + padding:calc(var(--u-p)/2) var(--u-p); + border-radius:1em + } + code,pre,kbd,code *,pre *,kbd *,code[class*="language-"],pre[class*="language-"] { + font-family:Menlo,Consolas,monospace!important + } + pre { + border:0.0625rem solid var(--br-col2); + border-radius:var(--u-br-r) + } + .group { + position:relative; + margin-top:2em; + margin-bottom:1em + } + .search { + font-size:0.875rem; + margin-top:-0.1em; + display:block; + width:100%; + border:none; + border-bottom:.0625rem solid var(--nv-ln-col) + } + .search:focus { + outline:none + } + label#search-label { + color:var(--nv-ln-col); + font-size:1.125rem; + font-weight:400; + position:absolute; + left:0.3125rem; + top:0.625rem + } + .search:focus~label#search-label,.search:valid~label#search-label { + top:-1.25rem; + font-size:0.875rem; + color:var(--nv-ln-col) + } + label#menu-toggle { + width:3.4375rem + } + header h1.logo { + margin-top:-0.8rem; + text-align:center + } + header h1.logo a { + text-decoration:none; + color:#111 + } + header #title { + position:relative; + top:-1rem + } + @media screen and (max-width: 500px) { + header #title { + font-size:1rem; + display:block + } + } + header h1 small { + display:block; + font-size:0.875rem; + color:#888; + margin-top:-0.8rem + } + @media screen and (max-width: 768px) { + header h1 small { + font-size:0.75rem + } + } + @media screen and (max-width: 600px) { + header h1 small { + font-size:0.625rem + } + } + @media screen and (max-width: 500px) { + header h1 small { + font-size:0.5rem; + margin-top:-1.2rem + } + } + label#menu-toggle { + position:absolute; + left:0.5rem; + top:0.5rem; + width:3.4375rem + } + main { + padding:0 + } + :root { + --clps-lbl-b-col:#e8e8e8; + --clps-lbl-f-col:#212121; + --clps-lbl-h-b-col:#f0f0f0; + --clps-sel-lbl-b-col:#ececec; + --clps-br-col:#ddd; + --clps-cnt-b-col:#fafafa; + --clps-sel-lbl-br-col:#0277bd + } + label.collapse { + width:100%; + display:inline-block; + cursor:pointer; + box-sizing:border-box; + transition:background 0.3s; + color:var(--clps-lbl-f-col); + background:var(--clps-lbl-b-col); + border:.0625rem solid var(--clps-br-col); + padding:calc(1.5 * var(--u-p)); + border-radius:var(--u-br-r) + } + label.collapse:hover,label.collapse:focus { + background:var(--clps-lbl-h-b-col) + } + label.collapse+pre { + box-sizing:border-box; + height:0; + max-height:1px; + overflow:auto; + margin:0; + border:0; + padding:0; + transition:max-height 0.3s + } + label.collapse.toggled { + background:var(--clps-sel-lbl-b-col); + border-bottom-color:var(--clps-sel-lbl-br-col); + border-bottom-left-radius:0; + border-bottom-right-radius:0 + } + label.collapse.toggled+pre { + border-top-left-radius:0; + border-top-right-radius:0; + position:relative; + width:100%; + height:auto; + border:.0625rem solid var(--clps-br-col); + border-top:0; + padding:calc(2 * var(--u-p)); + max-height:400px + } + button.primary.clipboard-copy { + width:100%; + margin-left:0 + } + button.primary.clipboard-copy>img { + vertical-align:bottom + } + code[class*="language-"],pre[class*="language-"] { + color:#222; + text-align:left; + white-space:pre; + word-spacing:normal; + word-break:normal; + word-wrap:normal; + line-height:1.8; + -moz-tab-size:2; + -o-tab-size:2; + tab-size:2; + -webkit-hypens:none; + -moz-hyphens:none; + -ms-hyphens:none; + hyphens:none + } + pre[class*="language-"] { + padding:calc(2 * var(--u-p)); + overflow:auto; + margin:var(--u-m) 0 + } + pre[class*="language-"]::-moz-selection,pre[class*="language-"] ::-moz-selection,code[class*="language-"]::-moz-selection,code[class*="language-"] ::-moz-selection { + background:#b3d4fc + } + pre[class*="language-"]::selection,pre[class*="language-"] ::selection,code[class*="language-"]::selection,code[class*="language-"] ::selection { + background:#b3d4fc + } + :not(pre)>code[class*="language-"] { + padding:.1em; + border-radius:.3em; + white-space:normal + } + .token.comment,.token.prolog,.token.doctype,.token.cdata { + color:#7a8490 + } + .token.punctuation { + color:#666 + } + .namespace { + opacity:.7 + } + .token.property,.token.tag,.token.boolean,.token.constant,.token.symbol,.token.deleted,.token.function { + color:#005cc5 + } + .token.number,.token.class-name { + color:#832ed2 + } + .token.selector,.token.attr-name,.token.string,.token.char,.token.builtin,.token.inserted { + color:#067e36 + } + .token.operator,.token.entity,.token.url,.language-css .token.string,.style .token.string,.token.atrule,.token.attr-value,.token.keyword { + color:#d73a49 + } + .token.regex { + color:#097cab + } + .token.important,.token.variable { + color:#e90 + } + .token.important,.token.bold { + font-weight:bold + } + .token.italic { + font-style:italic + } + .token.entity { + cursor:help + } + button.scroll-to-top { + border-radius:100%; + font-size:1.5rem; + line-height:1; + box-sizing:border-box; + width:2.75rem; + height:2.75rem; + position:fixed; + bottom:1rem; + right:2rem; + background:var(--b-col); + box-shadow:0 0.25rem 0.25rem 0 rgba(0,0,0,0.125),0 0.125rem 0.125rem -0.125rem rgba(0,0,0,0.25) + } + button.scroll-to-top:hover,button.scroll-to-top:focus { + background:var(--b-col2) + } \ No newline at end of file diff --git a/website/app/templates/base.html b/website/app/templates/base.html index 7400ebdff..9f96496f3 100644 --- a/website/app/templates/base.html +++ b/website/app/templates/base.html @@ -1,74 +1,74 @@ - - - - - -30 seconds of python code - - - - {% if err_400 %} -
{{ message }}
- {% endif %} -

logo 30 seconds of python code Python Implementation of 30 seconds of code

- {% block content %}{% endblock %} - - - - + + + + + +30 seconds of python code + + + + {% if err_400 %} +
{{ message }}
+ {% endif %} +

logo 30 seconds of python code Python Implementation of 30 seconds of code

+ {% block content %}{% endblock %} + + + + diff --git a/website/app/templates/index.html b/website/app/templates/index.html index cb6798bbb..88cc3da1a 100644 --- a/website/app/templates/index.html +++ b/website/app/templates/index.html @@ -1,379 +1,379 @@ -{% extends "base.html" %} - -{% block content %}

Math

average

-

Already implemented via statistics.mean. statistics.mean takes an array as an argument whereas this function takes variadic arguments.

-

Returns the average of two or more numbers.

-

Takes the sum of all the args and divides it by len(args). The secind argument 0.0 in sum is to handle floating point division in python2.

- -
def average(*args):
-    return sum(args, 0.0) / len(args)
- -
average(*[1, 2, 3]) # 2.0
-average(1, 2, 3) # 2.0
-
- -

factorial

-

Calculates the factorial of a number.

-

Use recursion. If num is less than or equal to 1, return 1. Otherwise, return the product of num and the factorial of num - 1. Throws an exception if num is a negative or a floating point number.

- -
def factorial(num):
-    if not ((num >= 0) & (num % 1 == 0)):
-        raise Exception(
-            f"Number( {num} ) can't be floating point or negative ")
-    return 1 if num == 0 else num * factorial(num - 1)
- -
factorial(6) # 720
-
- -

gcd

-

math.gcd works with only two numbers

-

Calculates the greatest common divisor between two or more numbers/lists.

-

The helperGcdfunction uses recursion. Base case is when y equals 0. In this case, return x. Otherwise, return the GCD of y and the remainder of the division x/y.

-

Uses the reduce function from the inbuilt module functools. Also defines a method spread for javascript like spreading of lists.

- -
from functools import reduce
-
-
-def spread(arg):
-    ret = []
-    for i in arg:
-        if isinstance(i, list):
-            ret.extend(i)
-        else:
-            ret.append(i)
-    return ret
-
-
-def gcd(*args):
-    numbers = []
-    numbers.extend(spread(list(args)))
-
-    def _gcd(x, y):
-        return x if not y else gcd(y, x % y)
-
-    return reduce((lambda x, y: _gcd(x, y)), numbers)
- -
gcd(8,36) # 4
-
- -

lcm

-

Returns the least common multiple of two or more numbers.

-

Use the greatest common divisor (GCD) formula and the fact that lcm(x,y) = x * y / gcd(x,y) to determine the least common multiple. The GCD formula uses recursion.

-

Uses reduce function from the inbuilt module functools. Also defines a method spread for javascript like spreading of lists.

- -
from functools import reduce
-
-
-def spread(arg):
-    ret = []
-    for i in arg:
-        if isinstance(i, list):
-            ret.extend(i)
-        else:
-            ret.append(i)
-    return ret
-
-
-def lcm(*args):
-    numbers = []
-    numbers.extend(spread(list(args)))
-
-    def _gcd(x, y):
-        return x if not y else gcd(y, x % y)
-
-    def _lcm(x, y):
-        return x * y / _gcd(x, y)
-
-    return reduce((lambda x, y: _lcm(x, y)), numbers)
- -
lcm(12, 7) # 84
-lcm([1, 3, 4], 5) # 60
-
- -

max_n

-

Returns the n maximum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list(sorted in descending order).

-

Use list.sort() combined with the deepcopy function from the inbuilt copy module to create a shallow clone of the list and sort it in ascending order and then use list.reverse() reverse it to make it descending order. Use [:n] to get the specified number of elements. Omit the second argument, n, to get a one-element array

- -
from copy import deepcopy
-
-
-def max_n(arr, n=1):
-    numbers = deepcopy(arr)
-    numbers.sort()
-    numbers.reverse()
-    return numbers[:n]
- -
max_n([1, 2, 3]) # [3]
-max_n([1, 2, 3], 2) # [3,2]
-
- -

min_n

-

Returns the n minimum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list(sorted in ascending order).

-

Use list.sort() combined with the deepcopy function from the inbuilt copy module to create a shallow clone of the list and sort it in ascending order. Use [:n] to get the specified number of elements. Omit the second argument, n, to get a one-element array

- -
from copy import deepcopy
-
-
-def min_n(arr, n=1):
-    numbers = deepcopy(arr)
-    numbers.sort()
-    return numbers[:n]
- -
min_n([1, 2, 3]) # [1]
-min_n([1, 2, 3], 2) # [1,2]
-
- -

List

chunk

-

Chunks an array into smaller lists of a specified size.

-

Uses range to create a list of desired size. Then use map on this list and fill it with splices of arr.

- -
from math import ceil
-
-
-def chunk(arr, size):
-    return list(
-        map(lambda x: arr[x * size:x * size + size],
-            list(range(0, ceil(len(arr) / size)))))
- -
chunk([1,2,3,4,5],2) # [[1,2],[3,4],5]
-
- -

compact

-

Removes falsey values from a list.

-

Use filter() to filter out falsey values (False, None, 0, and "").

- -
def compact(arr):
-    return list(filter(lambda x: bool(x), arr))
- -
compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ]
-
- -

count_occurences

-

Already implemented via list.count().

-

Counts the occurrences of a value in an list.

-

Uses the reduce functin from built-in module functools to increment a counter each time you encounter the specific value inside the list.

- -
def count_occurences(arr, val):
-    return reduce(
-        (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0),
-        arr)
- -
count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3
-
- -

deep_flatten

-

Deep flattens a list.

-

Use recursion. Use list.extend() with an empty array (result) and the spread function to flatten a list. Recursively flatten each element that is a list.

- -
def spread(arg):
-    ret = []
-    for i in arg:
-        if isinstance(i, list):
-            ret.extend(i)
-        else:
-            ret.append(i)
-    return ret
-
-
-def deep_flatten(arr):
-    result = []
-    result.extend(
-        spread(list(map(lambda x: deep(x) if type(x) == list else x, arr))))
-    return result
- -
deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5]
-
- -

difference

-

Returns the difference between two arrays.

-

Create a set from b, then use list comprehension to only keep values not contained in b

- -
def difference(a, b):
-    b = set(b)
-    return [item for item in a if item not in b]
- -
difference([1, 2, 3], [1, 2, 4]) # [3]
-
- -

shuffle

-

The same algorithm is already implemented via random.shuffle.

-

Randomizes the order of the values of an list, returning a new list.

-

Uses the Fisher-Yates algorithm to reorder the elements of the list.

- -
from copy import deepcopy
-from random import randint
-
-
-def shuffle(arr):
-    temp_arr = deepcopy(arr)
-    m = len(temp_arr)
-    while (m):
-        m -= 1
-        i = randint(0, m)
-        temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m]
-    return temp_arr
- -
foo = [1,2,3]
-shuffle(foo) # [2,3,1] , foo = [1,2,3]
-
- -

spread

-

Implements javascript's [].concat(...arr). Flattens the list(non-deep) and returns an list.

- -
def spread(arg):
-    ret = []
-    for i in arg:
-        if isinstance(i, list):
-            ret.extend(i)
-        else:
-            ret.append(i)
-    return ret
- -
spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9]
-
- -

zip

-

Already implemented via itertools.zip_longest()

-

Creates a list of elements, grouped based on the position in the original lists.

-

Use max combined with list comprehension to get the length of the longest list in the arguments. Loops for max_length times grouping elements. If lengths of lists vary fill_value is used. By default fill_value is None.

- -
def zip(*args, fillvalue=None):
-    max_length = max([len(arr) for arr in args])
-    result = []
-    for i in range(max_length):
-        result.append([
-            args[k][i] if i < len(args[k]) else None for k in range(len(args))
-        ])
-    return result
- -
zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]]
-zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]]
-zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]]
-
- -

count_by

-

Already implemented via collections.Counter

-

Groups the elements of a list based on the given function and returns the count of elements in each group.

-

Use map() to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs.

- -
def count_by(arr, fn=lambda x: x):
-    key = {}
-    for el in map(fn, arr):
-        key[el] = 0 if not el in key else key[el]
-        key[el] += 1
-    return key
- -
from math import floor
-count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2}
-count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1}
-
- -

difference_by

-

Returns the difference between two list, after applying the provided function to each list element of both.

-

Create a set by applying fn to each element in b, then use list comprehension in combination with fn on a to only keep values not contained in the previously created set.

- -
def difference_by(a, b, fn):
-    b = set(map(fn, b))
-    return [item for item in a if fn(item) not in b]
- -
from math import floor
-difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2]
-difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ]
-
- -

String

count_vowels

-

Retuns number of vowels in provided string.

-

Use a regular expression to count the number of vowels (A, E, I, O, U) in a string.

- -
import re
-
-
-def count_vowels(str):
-    return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE)))
- -
count_vowels('foobar') # 3
-count_vowels('gym') # 0
-
- -

byte_size

-

Returns the length of a string in bytes.

-

utf-8 encodes a given string and find its length.

- -
def byte_size(string):
-    return(len(string.encode('utf-8')))
- -
byte_size('😀') # 4
-byte_size('Hello World') # 11
-
- -

capitalize

-

Capitalizes the first letter of a string.

-

Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the lower_rest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

- -
def capitalize(string, lower_rest=False):
-    return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:])
- -
capitalize('fooBar') # 'FooBar'
-capitalize('fooBar', True) # 'Foobar'
-
- -

capitalize_every_word

-

Capitalizes the first letter of every word in a string.

-

Uses str.title to capitalize first letter of evry word in the string.

- -
def capitalize_every_word(string):
-    return string.title()
- -
capitalize_every_word('hello world!') # 'Hello World!'
-
- -

decapitalize

-

Decapitalizes the first letter of a string.

-

Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the upper_rest parameter to keep the rest of the string intact, or set it to true to convert to uppercase.

- -
def decapitalize(string, upper_rest=False):
-    return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:])
- -
decapitalize('FooBar') # 'fooBar'
-decapitalize('FooBar', True) # 'fOOBAR'
-
- -

palindrome

-

Returns True if the given string is a palindrome, False otherwise.

-

Convert string str.lower() and use re.sub to remove non-alphanumeric characters from it. Then compare the new string to the reversed.

- -
def palindrome(string):
-    from re import sub
-    s = sub('[\W_]', '', string.lower())
-    return s == s[::-1]
- -
palindrome('taco cat') # True
-
- -

is_upper_case

-

Checks if a string is upper case.

-

Convert the given string to upper case, using str.upper() method and compare it to the original.

- -
def is_upper_case(str):
-    return str == str.upper()
- -
is_upper_case('ABC') # True
-is_upper_case('a3@$') # True
-is_upper_case('aB4') # False
-
- -

is_lower_case

-

Checks if a string is lower case.

-

Convert the given string to lower case, using str.lower() method and compare it to the original.

- -
def is_lower_case(str):
-    return str == str.lower()
- -
is_lower_case('abc') # True
-is_lower_case('a3@$') # True
-is_lower_case('Ab4') # False
-
- -
- +{% extends "base.html" %} + +{% block content %}

Math

average

+

Already implemented via statistics.mean. statistics.mean takes an array as an argument whereas this function takes variadic arguments.

+

Returns the average of two or more numbers.

+

Takes the sum of all the args and divides it by len(args). The secind argument 0.0 in sum is to handle floating point division in python2.

+ +
def average(*args):
+    return sum(args, 0.0) / len(args)
+ +
average(*[1, 2, 3]) # 2.0
+average(1, 2, 3) # 2.0
+
+ +

factorial

+

Calculates the factorial of a number.

+

Use recursion. If num is less than or equal to 1, return 1. Otherwise, return the product of num and the factorial of num - 1. Throws an exception if num is a negative or a floating point number.

+ +
def factorial(num):
+    if not ((num >= 0) & (num % 1 == 0)):
+        raise Exception(
+            f"Number( {num} ) can't be floating point or negative ")
+    return 1 if num == 0 else num * factorial(num - 1)
+ +
factorial(6) # 720
+
+ +

gcd

+

math.gcd works with only two numbers

+

Calculates the greatest common divisor between two or more numbers/lists.

+

The helperGcdfunction uses recursion. Base case is when y equals 0. In this case, return x. Otherwise, return the GCD of y and the remainder of the division x/y.

+

Uses the reduce function from the inbuilt module functools. Also defines a method spread for javascript like spreading of lists.

+ +
from functools import reduce
+
+
+def spread(arg):
+    ret = []
+    for i in arg:
+        if isinstance(i, list):
+            ret.extend(i)
+        else:
+            ret.append(i)
+    return ret
+
+
+def gcd(*args):
+    numbers = []
+    numbers.extend(spread(list(args)))
+
+    def _gcd(x, y):
+        return x if not y else gcd(y, x % y)
+
+    return reduce((lambda x, y: _gcd(x, y)), numbers)
+ +
gcd(8,36) # 4
+
+ +

lcm

+

Returns the least common multiple of two or more numbers.

+

Use the greatest common divisor (GCD) formula and the fact that lcm(x,y) = x * y / gcd(x,y) to determine the least common multiple. The GCD formula uses recursion.

+

Uses reduce function from the inbuilt module functools. Also defines a method spread for javascript like spreading of lists.

+ +
from functools import reduce
+
+
+def spread(arg):
+    ret = []
+    for i in arg:
+        if isinstance(i, list):
+            ret.extend(i)
+        else:
+            ret.append(i)
+    return ret
+
+
+def lcm(*args):
+    numbers = []
+    numbers.extend(spread(list(args)))
+
+    def _gcd(x, y):
+        return x if not y else gcd(y, x % y)
+
+    def _lcm(x, y):
+        return x * y / _gcd(x, y)
+
+    return reduce((lambda x, y: _lcm(x, y)), numbers)
+ +
lcm(12, 7) # 84
+lcm([1, 3, 4], 5) # 60
+
+ +

max_n

+

Returns the n maximum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list(sorted in descending order).

+

Use list.sort() combined with the deepcopy function from the inbuilt copy module to create a shallow clone of the list and sort it in ascending order and then use list.reverse() reverse it to make it descending order. Use [:n] to get the specified number of elements. Omit the second argument, n, to get a one-element array

+ +
from copy import deepcopy
+
+
+def max_n(arr, n=1):
+    numbers = deepcopy(arr)
+    numbers.sort()
+    numbers.reverse()
+    return numbers[:n]
+ +
max_n([1, 2, 3]) # [3]
+max_n([1, 2, 3], 2) # [3,2]
+
+ +

min_n

+

Returns the n minimum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list(sorted in ascending order).

+

Use list.sort() combined with the deepcopy function from the inbuilt copy module to create a shallow clone of the list and sort it in ascending order. Use [:n] to get the specified number of elements. Omit the second argument, n, to get a one-element array

+ +
from copy import deepcopy
+
+
+def min_n(arr, n=1):
+    numbers = deepcopy(arr)
+    numbers.sort()
+    return numbers[:n]
+ +
min_n([1, 2, 3]) # [1]
+min_n([1, 2, 3], 2) # [1,2]
+
+ +

List

chunk

+

Chunks an array into smaller lists of a specified size.

+

Uses range to create a list of desired size. Then use map on this list and fill it with splices of arr.

+ +
from math import ceil
+
+
+def chunk(arr, size):
+    return list(
+        map(lambda x: arr[x * size:x * size + size],
+            list(range(0, ceil(len(arr) / size)))))
+ +
chunk([1,2,3,4,5],2) # [[1,2],[3,4],5]
+
+ +

compact

+

Removes falsey values from a list.

+

Use filter() to filter out falsey values (False, None, 0, and "").

+ +
def compact(arr):
+    return list(filter(lambda x: bool(x), arr))
+ +
compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ]
+
+ +

count_occurences

+

Already implemented via list.count().

+

Counts the occurrences of a value in an list.

+

Uses the reduce functin from built-in module functools to increment a counter each time you encounter the specific value inside the list.

+ +
def count_occurences(arr, val):
+    return reduce(
+        (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0),
+        arr)
+ +
count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3
+
+ +

deep_flatten

+

Deep flattens a list.

+

Use recursion. Use list.extend() with an empty array (result) and the spread function to flatten a list. Recursively flatten each element that is a list.

+ +
def spread(arg):
+    ret = []
+    for i in arg:
+        if isinstance(i, list):
+            ret.extend(i)
+        else:
+            ret.append(i)
+    return ret
+
+
+def deep_flatten(arr):
+    result = []
+    result.extend(
+        spread(list(map(lambda x: deep(x) if type(x) == list else x, arr))))
+    return result
+ +
deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5]
+
+ +

difference

+

Returns the difference between two arrays.

+

Create a set from b, then use list comprehension to only keep values not contained in b

+ +
def difference(a, b):
+    b = set(b)
+    return [item for item in a if item not in b]
+ +
difference([1, 2, 3], [1, 2, 4]) # [3]
+
+ +

shuffle

+

The same algorithm is already implemented via random.shuffle.

+

Randomizes the order of the values of an list, returning a new list.

+

Uses the Fisher-Yates algorithm to reorder the elements of the list.

+ +
from copy import deepcopy
+from random import randint
+
+
+def shuffle(arr):
+    temp_arr = deepcopy(arr)
+    m = len(temp_arr)
+    while (m):
+        m -= 1
+        i = randint(0, m)
+        temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m]
+    return temp_arr
+ +
foo = [1,2,3]
+shuffle(foo) # [2,3,1] , foo = [1,2,3]
+
+ +

spread

+

Implements javascript's [].concat(...arr). Flattens the list(non-deep) and returns an list.

+ +
def spread(arg):
+    ret = []
+    for i in arg:
+        if isinstance(i, list):
+            ret.extend(i)
+        else:
+            ret.append(i)
+    return ret
+ +
spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9]
+
+ +

zip

+

Already implemented via itertools.zip_longest()

+

Creates a list of elements, grouped based on the position in the original lists.

+

Use max combined with list comprehension to get the length of the longest list in the arguments. Loops for max_length times grouping elements. If lengths of lists vary fill_value is used. By default fill_value is None.

+ +
def zip(*args, fillvalue=None):
+    max_length = max([len(arr) for arr in args])
+    result = []
+    for i in range(max_length):
+        result.append([
+            args[k][i] if i < len(args[k]) else None for k in range(len(args))
+        ])
+    return result
+ +
zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]]
+zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]]
+zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]]
+
+ +

count_by

+

Already implemented via collections.Counter

+

Groups the elements of a list based on the given function and returns the count of elements in each group.

+

Use map() to map the values of the list using the given function. Iterate over the map and increase the the elements count each time it occurs.

+ +
def count_by(arr, fn=lambda x: x):
+    key = {}
+    for el in map(fn, arr):
+        key[el] = 0 if not el in key else key[el]
+        key[el] += 1
+    return key
+ +
from math import floor
+count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2}
+count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1}
+
+ +

difference_by

+

Returns the difference between two list, after applying the provided function to each list element of both.

+

Create a set by applying fn to each element in b, then use list comprehension in combination with fn on a to only keep values not contained in the previously created set.

+ +
def difference_by(a, b, fn):
+    b = set(map(fn, b))
+    return [item for item in a if fn(item) not in b]
+ +
from math import floor
+difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2]
+difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ]
+
+ +

String

count_vowels

+

Retuns number of vowels in provided string.

+

Use a regular expression to count the number of vowels (A, E, I, O, U) in a string.

+ +
import re
+
+
+def count_vowels(str):
+    return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE)))
+ +
count_vowels('foobar') # 3
+count_vowels('gym') # 0
+
+ +

byte_size

+

Returns the length of a string in bytes.

+

utf-8 encodes a given string and find its length.

+ +
def byte_size(string):
+    return(len(string.encode('utf-8')))
+ +
byte_size('😀') # 4
+byte_size('Hello World') # 11
+
+ +

capitalize

+

Capitalizes the first letter of a string.

+

Capitalizes the fist letter of the sring and then adds it with rest of the string. Omit the lower_rest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

+ +
def capitalize(string, lower_rest=False):
+    return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:])
+ +
capitalize('fooBar') # 'FooBar'
+capitalize('fooBar', True) # 'Foobar'
+
+ +

capitalize_every_word

+

Capitalizes the first letter of every word in a string.

+

Uses str.title to capitalize first letter of evry word in the string.

+ +
def capitalize_every_word(string):
+    return string.title()
+ +
capitalize_every_word('hello world!') # 'Hello World!'
+
+ +

decapitalize

+

Decapitalizes the first letter of a string.

+

Decapitalizes the fist letter of the sring and then adds it with rest of the string. Omit the upper_rest parameter to keep the rest of the string intact, or set it to true to convert to uppercase.

+ +
def decapitalize(string, upper_rest=False):
+    return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:])
+ +
decapitalize('FooBar') # 'fooBar'
+decapitalize('FooBar', True) # 'fOOBAR'
+
+ +

palindrome

+

Returns True if the given string is a palindrome, False otherwise.

+

Convert string str.lower() and use re.sub to remove non-alphanumeric characters from it. Then compare the new string to the reversed.

+ +
def palindrome(string):
+    from re import sub
+    s = sub('[\W_]', '', string.lower())
+    return s == s[::-1]
+ +
palindrome('taco cat') # True
+
+ +

is_upper_case

+

Checks if a string is upper case.

+

Convert the given string to upper case, using str.upper() method and compare it to the original.

+ +
def is_upper_case(str):
+    return str == str.upper()
+ +
is_upper_case('ABC') # True
+is_upper_case('a3@$') # True
+is_upper_case('aB4') # False
+
+ +

is_lower_case

+

Checks if a string is lower case.

+

Convert the given string to lower case, using str.lower() method and compare it to the original.

+ +
def is_lower_case(str):
+    return str == str.lower()
+ +
is_lower_case('abc') # True
+is_lower_case('a3@$') # True
+is_lower_case('Ab4') # False
+
+ +
+
{% endblock %} \ No newline at end of file diff --git a/website/app/vote.py b/website/app/vote.py index 631017dbd..7132c5487 100644 --- a/website/app/vote.py +++ b/website/app/vote.py @@ -1,16 +1,16 @@ -import json - - -def vote(snippet): - snippets = open('website/app/snippets').read().split('\n') - with open('website/app/votes.json', 'r') as f: - if snippet in snippets: - data = json.load(f) - try: - data[snippet] - except KeyError: - data[snippet] = 0 - data[snippet] += 1 - open('website/app/votes.json','w').write(str(data).replace("'",'"')) - else: - raise Exception(f'{snippet} does not exists ') +import json + + +def vote(snippet): + snippets = open('website/app/snippets').read().split('\n') + with open('website/app/votes.json', 'r') as f: + if snippet in snippets: + data = json.load(f) + try: + data[snippet] + except KeyError: + data[snippet] = 0 + data[snippet] += 1 + open('website/app/votes.json','w').write(str(data).replace("'",'"')) + else: + raise Exception(f'{snippet} does not exists ') diff --git a/website/app/vote_data.py b/website/app/vote_data.py index e36806df4..64b01507a 100644 --- a/website/app/vote_data.py +++ b/website/app/vote_data.py @@ -1,16 +1,16 @@ -import json - -def vote_data(): - f = open('website/app/snippets') - snippets = f.read().split('\n') - f.close() - - f = open('website/app/votes.json') - votes_data = json.load(f) - votes = {} - for snippet in snippets: - try: - votes[snippet] = votes_data[snippet] - except KeyError: - votes[snippet] = 0 - return votes +import json + +def vote_data(): + f = open('website/app/snippets') + snippets = f.read().split('\n') + f.close() + + f = open('website/app/votes.json') + votes_data = json.load(f) + votes = {} + for snippet in snippets: + try: + votes[snippet] = votes_data[snippet] + except KeyError: + votes[snippet] = 0 + return votes diff --git a/website/etc/hosts b/website/etc/hosts index 3abd760ec..62a8cca88 100644 --- a/website/etc/hosts +++ b/website/etc/hosts @@ -1,2 +1,2 @@ -127.0.0.1 localwebsite +127.0.0.1 localwebsite 127.0.0.1 blog.localwebsite \ No newline at end of file diff --git a/website/index.html b/website/index.html index b580d1bf5..cac34cd3f 100644 --- a/website/index.html +++ b/website/index.html @@ -1,10 +1,10 @@ - - - - - -
def Hello_World(val):
-    print(f'Hello {val}')
-    wow!
-
- + + + + + +
def Hello_World(val):
+    print(f'Hello {val}')
+    wow!
+
+ diff --git a/website/main.py b/website/main.py index b113d5919..ea6bf0897 100644 --- a/website/main.py +++ b/website/main.py @@ -1,69 +1,69 @@ -import os -import re - -import emoji -import mistune - -codeRe = "```\s*python([\s\S]*?)```" -def tagger(): - tag_data = open('tag_database').read() - tag_dict = {} - tag_list = tag_data.split('\n') - for tag in tag_list: - category = tag.split(':')[1] - snippet = tag.split(':')[0] - if category in tag_dict: - tag_dict[category].append(snippet) - else: - tag_dict[category] = [snippet] - return tag_dict - -class MyRenderer(mistune.Renderer): - def block_code(self, code, lang): - if not lang: - return f'\n
{mistune.escape(code.strip())}
\n' - else: - return f'\n
{mistune.escape(code.strip())}
\n' - - -renderer = MyRenderer() -md = mistune.Markdown(renderer=renderer,escape=True) -def title_case(str): - return str[:1].upper() + str[1:].lower() - -rendered = '' - -tag_dict = tagger() - -for category in tag_dict: - rendered += f'

{title_case(category)}

' - snippets = tag_dict[category] - for file in snippets: - content = open('snippets/'+file+'.md').read() - content = re.sub(':(\S+):',r':\1:',content) - codeParts = re.split(codeRe,content) - codeParts[3] = f'\n\n\n\n```python\n{codeParts[3].strip()}\n```\n' - content = codeParts[0] + '``` python' + codeParts[1] + '```' + codeParts[2] + codeParts[3] - content = f'
{emoji.emojize(md.render(content),use_aliases=True)}
'+'\n\n' - rendered += re.sub('

(\S+)

',r'

\1

',content) + '
' - rendered = re.sub('

(\S+)

',r'

\1

',rendered) -nav_string = '' -start = '''{% extends "base.html" %} - -{% block content %}''' - -end = '{% endblock %}' - -footer = ''' - - ''' -rendered = f'
{nav_string}
' + rendered + f'{footer}
' -rendered = re.sub('','',rendered) -open('website/app/templates/index.html','w',encoding='utf-8').write(start + rendered + end) -snippets = [snippet.replace('.md','') for snippet in snippets] -open('website/app/snippets','w').write('\n'.join(snippets)) +import os +import re + +import emoji +import mistune + +codeRe = "```\s*python([\s\S]*?)```" +def tagger(): + tag_data = open('tag_database').read() + tag_dict = {} + tag_list = tag_data.split('\n') + for tag in tag_list: + category = tag.split(':')[1] + snippet = tag.split(':')[0] + if category in tag_dict: + tag_dict[category].append(snippet) + else: + tag_dict[category] = [snippet] + return tag_dict + +class MyRenderer(mistune.Renderer): + def block_code(self, code, lang): + if not lang: + return f'\n
{mistune.escape(code.strip())}
\n' + else: + return f'\n
{mistune.escape(code.strip())}
\n' + + +renderer = MyRenderer() +md = mistune.Markdown(renderer=renderer,escape=True) +def title_case(str): + return str[:1].upper() + str[1:].lower() + +rendered = '' + +tag_dict = tagger() + +for category in tag_dict: + rendered += f'

{title_case(category)}

' + snippets = tag_dict[category] + for file in snippets: + content = open('snippets/'+file+'.md').read() + content = re.sub(':(\S+):',r':\1:',content) + codeParts = re.split(codeRe,content) + codeParts[3] = f'\n\n\n\n```python\n{codeParts[3].strip()}\n```\n' + content = codeParts[0] + '``` python' + codeParts[1] + '```' + codeParts[2] + codeParts[3] + content = f'
{emoji.emojize(md.render(content),use_aliases=True)}
'+'\n\n' + rendered += re.sub('

(\S+)

',r'

\1

',content) + '
' + rendered = re.sub('

(\S+)

',r'

\1

',rendered) +nav_string = '' +start = '''{% extends "base.html" %} + +{% block content %}''' + +end = '{% endblock %}' + +footer = ''' + + ''' +rendered = f'
{nav_string}
' + rendered + f'{footer}
' +rendered = re.sub('','',rendered) +open('website/app/templates/index.html','w',encoding='utf-8').write(start + rendered + end) +snippets = [snippet.replace('.md','') for snippet in snippets] +open('website/app/snippets','w').write('\n'.join(snippets)) diff --git a/website/requirements.txt b/website/requirements.txt index 260f44905..6a8c00455 100644 --- a/website/requirements.txt +++ b/website/requirements.txt @@ -1,15 +1,15 @@ -cffi==1.11.4 -click==6.7 -emoji==0.4.5 -Flask==0.12.2 -Flask-OAuth==0.12 -gunicorn==19.7.1 -httplib2==0.10.3 -itsdangerous==0.24 -Jinja2==2.10 -MarkupSafe==1.0 -misaka==2.1.0 -mistune==0.8.3 -oauth2==1.9.0.post1 -pycparser==2.18 +cffi==1.11.4 +click==6.7 +emoji==0.4.5 +Flask==0.12.2 +Flask-OAuth==0.12 +gunicorn==19.7.1 +httplib2==0.10.3 +itsdangerous==0.24 +Jinja2==2.10 +MarkupSafe==1.0 +misaka==2.1.0 +mistune==0.8.3 +oauth2==1.9.0.post1 +pycparser==2.18 Werkzeug==0.14.1 \ No newline at end of file diff --git a/website/run.py b/website/run.py index 714d5bd3f..9d4666819 100644 --- a/website/run.py +++ b/website/run.py @@ -1,6 +1,6 @@ -from app import app - -if __name__ == '__main__': - app.jinja_env.auto_reload = True - app.config['TEMPLATES_AUTO_RELOAD'] = True +from app import app + +if __name__ == '__main__': + app.jinja_env.auto_reload = True + app.config['TEMPLATES_AUTO_RELOAD'] = True app.run(debug=True, host='0.0.0.0',port=80) \ No newline at end of file diff --git a/website/web/Lib/site-packages/Flask-0.12.2.dist-info/RECORD b/website/web/Lib/site-packages/Flask-0.12.2.dist-info/RECORD index 750e2fad0..69d2b278a 100644 --- a/website/web/Lib/site-packages/Flask-0.12.2.dist-info/RECORD +++ b/website/web/Lib/site-packages/Flask-0.12.2.dist-info/RECORD @@ -1,52 +1,52 @@ -Flask-0.12.2.dist-info/DESCRIPTION.rst,sha256=DmJm8IBlBjl3wkm0Ly23jYvWbvK_mCuE5oUseYCijbI,810 -Flask-0.12.2.dist-info/LICENSE.txt,sha256=hLgKluMRHSnxG-L0EmrqjmKgG5cHlff6pIh3rCNINeI,1582 -Flask-0.12.2.dist-info/METADATA,sha256=OgSkJQ_kmrz4qEkS-OzYtL75uZmXAThymkOcGR4kXRQ,1948 -Flask-0.12.2.dist-info/RECORD,, -Flask-0.12.2.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 -Flask-0.12.2.dist-info/entry_points.txt,sha256=jzk2Wy2h30uEcqqzd4CVnlzsMXB-vaD5GXjuPMXmTmI,60 -Flask-0.12.2.dist-info/metadata.json,sha256=By8kZ1vY9lLEAGnRiWNBhudqKvLPo0HkZVXTYECyPKk,1389 -Flask-0.12.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 -flask/__init__.py,sha256=sHdK1v6WRbVmCN0fEv990EE7rOT2UlamQkSof2d0Dt0,1673 -flask/__main__.py,sha256=cldbNi5zpjE68XzIWI8uYHNWwBHHVJmwtlXWk6P4CO4,291 -flask/_compat.py,sha256=VlfjUuLjufsTHJIjr_ZsnnOesSbAXIslBBgRe5tfOok,2802 -flask/app.py,sha256=6DPjtb5jUJWgL5fXksG5boA49EB3l-k9pWyftitbNNk,83169 -flask/blueprints.py,sha256=6HVasMcPcaq7tk36kCrgX4bnhTkky4G5WIWCyyJL8HY,16872 -flask/cli.py,sha256=2NXEdCOu5-4ymklxX4Lf6bjb-89I4VHYeP6xScR3i8E,18328 -flask/config.py,sha256=Ym5Jenyu6zAZ1fdVLeKekY9-EsKmq8183qnRgauwCMY,9905 -flask/ctx.py,sha256=UPA0YwoIlHP0txOGanC9lQLSGv6eCqV5Fmw2cVJRmgQ,14739 -flask/debughelpers.py,sha256=z-uQavKIymOZl0WQDLXsnacA00ERIlCx3S3Tnb_OYsE,6024 -flask/exthook.py,sha256=SvXs5jwpcOjogwJ7SNquiWTxowoN1-MHFoqAejWnk2o,5762 -flask/globals.py,sha256=I3m_4RssLhWW1R11zuEI8oFryHUHX3NQwjMkGXOZzg8,1645 -flask/helpers.py,sha256=KrsQ2Yo3lOVHvBTgQCLvpubgmTOpQdTTyiCOOYlwDuQ,38452 -flask/json.py,sha256=1zPM-NPLiWoOfGd0P14FxnEkeKtjtUZxMC9pyYyDBYI,9183 -flask/logging.py,sha256=UG-77jPkRClk9w1B-_ArjjXPuj9AmZz9mG0IRGvptW0,2751 -flask/sessions.py,sha256=QBKXVYKJ-HKbx9m6Yb5yan_EPq84a5yevVLgAzNKFQY,14394 -flask/signals.py,sha256=MfZk5qTRj_R_O3aGYlTEnx2g3SvlZncz8Ii73eKK59g,2209 -flask/templating.py,sha256=u7FbN6j56H_q6CrdJJyJ6gZtqaMa0vh1_GP12gEHRQQ,4912 -flask/testing.py,sha256=II8EO_NjOT1LvL8Hh_SdIFL_BdlwVPcB9yot5pbltxE,5630 -flask/views.py,sha256=6OPv7gwu3h14JhqpeeMRWwrxoGHsUr4_nOGSyTRAxAI,5630 -flask/wrappers.py,sha256=1S_5mmuA1Tlx7D9lXV6xMblrg-PdAauNWahe-henMEE,7612 -flask/ext/__init__.py,sha256=UEezCApsG4ZJWqwUnX9YmWcNN4OVENgph_9L05n0eOM,842 -../../Scripts/flask.exe,sha256=WiosIiBPkig5ooCR_yaHUrP5WMPviLDqJxogDFixmOY,98150 -Flask-0.12.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -flask/ext/__pycache__/__init__.cpython-36.pyc,, -flask/__pycache__/app.cpython-36.pyc,, -flask/__pycache__/blueprints.cpython-36.pyc,, -flask/__pycache__/cli.cpython-36.pyc,, -flask/__pycache__/config.cpython-36.pyc,, -flask/__pycache__/ctx.cpython-36.pyc,, -flask/__pycache__/debughelpers.cpython-36.pyc,, -flask/__pycache__/exthook.cpython-36.pyc,, -flask/__pycache__/globals.cpython-36.pyc,, -flask/__pycache__/helpers.cpython-36.pyc,, -flask/__pycache__/json.cpython-36.pyc,, -flask/__pycache__/logging.cpython-36.pyc,, -flask/__pycache__/sessions.cpython-36.pyc,, -flask/__pycache__/signals.cpython-36.pyc,, -flask/__pycache__/templating.cpython-36.pyc,, -flask/__pycache__/testing.cpython-36.pyc,, -flask/__pycache__/views.cpython-36.pyc,, -flask/__pycache__/wrappers.cpython-36.pyc,, -flask/__pycache__/_compat.cpython-36.pyc,, -flask/__pycache__/__init__.cpython-36.pyc,, -flask/__pycache__/__main__.cpython-36.pyc,, +Flask-0.12.2.dist-info/DESCRIPTION.rst,sha256=DmJm8IBlBjl3wkm0Ly23jYvWbvK_mCuE5oUseYCijbI,810 +Flask-0.12.2.dist-info/LICENSE.txt,sha256=hLgKluMRHSnxG-L0EmrqjmKgG5cHlff6pIh3rCNINeI,1582 +Flask-0.12.2.dist-info/METADATA,sha256=OgSkJQ_kmrz4qEkS-OzYtL75uZmXAThymkOcGR4kXRQ,1948 +Flask-0.12.2.dist-info/RECORD,, +Flask-0.12.2.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +Flask-0.12.2.dist-info/entry_points.txt,sha256=jzk2Wy2h30uEcqqzd4CVnlzsMXB-vaD5GXjuPMXmTmI,60 +Flask-0.12.2.dist-info/metadata.json,sha256=By8kZ1vY9lLEAGnRiWNBhudqKvLPo0HkZVXTYECyPKk,1389 +Flask-0.12.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=sHdK1v6WRbVmCN0fEv990EE7rOT2UlamQkSof2d0Dt0,1673 +flask/__main__.py,sha256=cldbNi5zpjE68XzIWI8uYHNWwBHHVJmwtlXWk6P4CO4,291 +flask/_compat.py,sha256=VlfjUuLjufsTHJIjr_ZsnnOesSbAXIslBBgRe5tfOok,2802 +flask/app.py,sha256=6DPjtb5jUJWgL5fXksG5boA49EB3l-k9pWyftitbNNk,83169 +flask/blueprints.py,sha256=6HVasMcPcaq7tk36kCrgX4bnhTkky4G5WIWCyyJL8HY,16872 +flask/cli.py,sha256=2NXEdCOu5-4ymklxX4Lf6bjb-89I4VHYeP6xScR3i8E,18328 +flask/config.py,sha256=Ym5Jenyu6zAZ1fdVLeKekY9-EsKmq8183qnRgauwCMY,9905 +flask/ctx.py,sha256=UPA0YwoIlHP0txOGanC9lQLSGv6eCqV5Fmw2cVJRmgQ,14739 +flask/debughelpers.py,sha256=z-uQavKIymOZl0WQDLXsnacA00ERIlCx3S3Tnb_OYsE,6024 +flask/exthook.py,sha256=SvXs5jwpcOjogwJ7SNquiWTxowoN1-MHFoqAejWnk2o,5762 +flask/globals.py,sha256=I3m_4RssLhWW1R11zuEI8oFryHUHX3NQwjMkGXOZzg8,1645 +flask/helpers.py,sha256=KrsQ2Yo3lOVHvBTgQCLvpubgmTOpQdTTyiCOOYlwDuQ,38452 +flask/json.py,sha256=1zPM-NPLiWoOfGd0P14FxnEkeKtjtUZxMC9pyYyDBYI,9183 +flask/logging.py,sha256=UG-77jPkRClk9w1B-_ArjjXPuj9AmZz9mG0IRGvptW0,2751 +flask/sessions.py,sha256=QBKXVYKJ-HKbx9m6Yb5yan_EPq84a5yevVLgAzNKFQY,14394 +flask/signals.py,sha256=MfZk5qTRj_R_O3aGYlTEnx2g3SvlZncz8Ii73eKK59g,2209 +flask/templating.py,sha256=u7FbN6j56H_q6CrdJJyJ6gZtqaMa0vh1_GP12gEHRQQ,4912 +flask/testing.py,sha256=II8EO_NjOT1LvL8Hh_SdIFL_BdlwVPcB9yot5pbltxE,5630 +flask/views.py,sha256=6OPv7gwu3h14JhqpeeMRWwrxoGHsUr4_nOGSyTRAxAI,5630 +flask/wrappers.py,sha256=1S_5mmuA1Tlx7D9lXV6xMblrg-PdAauNWahe-henMEE,7612 +flask/ext/__init__.py,sha256=UEezCApsG4ZJWqwUnX9YmWcNN4OVENgph_9L05n0eOM,842 +../../Scripts/flask.exe,sha256=WiosIiBPkig5ooCR_yaHUrP5WMPviLDqJxogDFixmOY,98150 +Flask-0.12.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask/ext/__pycache__/__init__.cpython-36.pyc,, +flask/__pycache__/app.cpython-36.pyc,, +flask/__pycache__/blueprints.cpython-36.pyc,, +flask/__pycache__/cli.cpython-36.pyc,, +flask/__pycache__/config.cpython-36.pyc,, +flask/__pycache__/ctx.cpython-36.pyc,, +flask/__pycache__/debughelpers.cpython-36.pyc,, +flask/__pycache__/exthook.cpython-36.pyc,, +flask/__pycache__/globals.cpython-36.pyc,, +flask/__pycache__/helpers.cpython-36.pyc,, +flask/__pycache__/json.cpython-36.pyc,, +flask/__pycache__/logging.cpython-36.pyc,, +flask/__pycache__/sessions.cpython-36.pyc,, +flask/__pycache__/signals.cpython-36.pyc,, +flask/__pycache__/templating.cpython-36.pyc,, +flask/__pycache__/testing.cpython-36.pyc,, +flask/__pycache__/views.cpython-36.pyc,, +flask/__pycache__/wrappers.cpython-36.pyc,, +flask/__pycache__/_compat.cpython-36.pyc,, +flask/__pycache__/__init__.cpython-36.pyc,, +flask/__pycache__/__main__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/PKG-INFO index c7e3f5907..63db21e96 100644 --- a/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/PKG-INFO @@ -1,30 +1,30 @@ -Metadata-Version: 1.1 -Name: Flask-OAuth -Version: 0.12 -Summary: Adds OAuth support to Flask -Home-page: http://github.com/mitsuhiko/flask-oauth -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -License: BSD -Description: - Flask-OAuth - ----------- - - Adds OAuth support to Flask. - - Links - ````` - - * `documentation `_ - * `development version - `_ - -Platform: any -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules +Metadata-Version: 1.1 +Name: Flask-OAuth +Version: 0.12 +Summary: Adds OAuth support to Flask +Home-page: http://github.com/mitsuhiko/flask-oauth +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Description: + Flask-OAuth + ----------- + + Adds OAuth support to Flask. + + Links + ````` + + * `documentation `_ + * `development version + `_ + +Platform: any +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/installed-files.txt index a20164513..57bfb769b 100644 --- a/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/Flask_OAuth-0.12-py3.6.egg-info/installed-files.txt @@ -1,8 +1,8 @@ -..\flask_oauth.py -..\__pycache__\flask_oauth.cpython-36.pyc -dependency_links.txt -not-zip-safe -PKG-INFO -requires.txt -SOURCES.txt -top_level.txt +..\flask_oauth.py +..\__pycache__\flask_oauth.cpython-36.pyc +dependency_links.txt +not-zip-safe +PKG-INFO +requires.txt +SOURCES.txt +top_level.txt diff --git a/website/web/Lib/site-packages/Jinja2-2.10.dist-info/LICENSE.txt b/website/web/Lib/site-packages/Jinja2-2.10.dist-info/LICENSE.txt index 31bf900e5..10145a264 100644 --- a/website/web/Lib/site-packages/Jinja2-2.10.dist-info/LICENSE.txt +++ b/website/web/Lib/site-packages/Jinja2-2.10.dist-info/LICENSE.txt @@ -1,31 +1,31 @@ -Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details. - -Some rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/website/web/Lib/site-packages/Jinja2-2.10.dist-info/RECORD b/website/web/Lib/site-packages/Jinja2-2.10.dist-info/RECORD index 4bef2c1d5..a1ec831ea 100644 --- a/website/web/Lib/site-packages/Jinja2-2.10.dist-info/RECORD +++ b/website/web/Lib/site-packages/Jinja2-2.10.dist-info/RECORD @@ -1,63 +1,63 @@ -Jinja2-2.10.dist-info/DESCRIPTION.rst,sha256=b5ckFDoM7vVtz_mAsJD4OPteFKCqE7beu353g4COoYI,978 -Jinja2-2.10.dist-info/LICENSE.txt,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554 -Jinja2-2.10.dist-info/METADATA,sha256=18EgU8zR6-av-0-5y_gXebzK4GnBB_76lALUsl-6QHM,2258 -Jinja2-2.10.dist-info/RECORD,, -Jinja2-2.10.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110 -Jinja2-2.10.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72 -Jinja2-2.10.dist-info/metadata.json,sha256=NPUJ9TMBxVQAv_kTJzvU8HwmP-4XZvbK9mz6_4YUVl4,1473 -Jinja2-2.10.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 -jinja2/__init__.py,sha256=xJHjaMoy51_KXn1wf0cysH6tUUifUxZCwSOfcJGEYZw,2614 -jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596 -jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726 -jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144 -jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878 -jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794 -jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386 -jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626 -jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045 -jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400 -jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849 -jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428 -jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500 -jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528 -jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197 -jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559 -jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382 -jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340 -jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308 -jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853 -jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722 -jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875 -jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755 -jinja2/sandbox.py,sha256=TVyZHlNqqTzsv9fv2NvJNmSdWRHTguhyMHdxjWms32U,16708 -jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237 -jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629 -jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316 -Jinja2-2.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -jinja2/__pycache__/asyncfilters.cpython-36.pyc,, -jinja2/__pycache__/asyncsupport.cpython-36.pyc,, -jinja2/__pycache__/bccache.cpython-36.pyc,, -jinja2/__pycache__/compiler.cpython-36.pyc,, -jinja2/__pycache__/constants.cpython-36.pyc,, -jinja2/__pycache__/debug.cpython-36.pyc,, -jinja2/__pycache__/defaults.cpython-36.pyc,, -jinja2/__pycache__/environment.cpython-36.pyc,, -jinja2/__pycache__/exceptions.cpython-36.pyc,, -jinja2/__pycache__/ext.cpython-36.pyc,, -jinja2/__pycache__/filters.cpython-36.pyc,, -jinja2/__pycache__/idtracking.cpython-36.pyc,, -jinja2/__pycache__/lexer.cpython-36.pyc,, -jinja2/__pycache__/loaders.cpython-36.pyc,, -jinja2/__pycache__/meta.cpython-36.pyc,, -jinja2/__pycache__/nativetypes.cpython-36.pyc,, -jinja2/__pycache__/nodes.cpython-36.pyc,, -jinja2/__pycache__/optimizer.cpython-36.pyc,, -jinja2/__pycache__/parser.cpython-36.pyc,, -jinja2/__pycache__/runtime.cpython-36.pyc,, -jinja2/__pycache__/sandbox.cpython-36.pyc,, -jinja2/__pycache__/tests.cpython-36.pyc,, -jinja2/__pycache__/utils.cpython-36.pyc,, -jinja2/__pycache__/visitor.cpython-36.pyc,, -jinja2/__pycache__/_compat.cpython-36.pyc,, -jinja2/__pycache__/_identifier.cpython-36.pyc,, -jinja2/__pycache__/__init__.cpython-36.pyc,, +Jinja2-2.10.dist-info/DESCRIPTION.rst,sha256=b5ckFDoM7vVtz_mAsJD4OPteFKCqE7beu353g4COoYI,978 +Jinja2-2.10.dist-info/LICENSE.txt,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554 +Jinja2-2.10.dist-info/METADATA,sha256=18EgU8zR6-av-0-5y_gXebzK4GnBB_76lALUsl-6QHM,2258 +Jinja2-2.10.dist-info/RECORD,, +Jinja2-2.10.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110 +Jinja2-2.10.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72 +Jinja2-2.10.dist-info/metadata.json,sha256=NPUJ9TMBxVQAv_kTJzvU8HwmP-4XZvbK9mz6_4YUVl4,1473 +Jinja2-2.10.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=xJHjaMoy51_KXn1wf0cysH6tUUifUxZCwSOfcJGEYZw,2614 +jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596 +jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726 +jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144 +jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878 +jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794 +jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386 +jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626 +jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045 +jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400 +jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849 +jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428 +jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500 +jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528 +jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197 +jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559 +jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382 +jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340 +jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308 +jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853 +jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722 +jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875 +jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755 +jinja2/sandbox.py,sha256=TVyZHlNqqTzsv9fv2NvJNmSdWRHTguhyMHdxjWms32U,16708 +jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237 +jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629 +jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316 +Jinja2-2.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2/__pycache__/asyncfilters.cpython-36.pyc,, +jinja2/__pycache__/asyncsupport.cpython-36.pyc,, +jinja2/__pycache__/bccache.cpython-36.pyc,, +jinja2/__pycache__/compiler.cpython-36.pyc,, +jinja2/__pycache__/constants.cpython-36.pyc,, +jinja2/__pycache__/debug.cpython-36.pyc,, +jinja2/__pycache__/defaults.cpython-36.pyc,, +jinja2/__pycache__/environment.cpython-36.pyc,, +jinja2/__pycache__/exceptions.cpython-36.pyc,, +jinja2/__pycache__/ext.cpython-36.pyc,, +jinja2/__pycache__/filters.cpython-36.pyc,, +jinja2/__pycache__/idtracking.cpython-36.pyc,, +jinja2/__pycache__/lexer.cpython-36.pyc,, +jinja2/__pycache__/loaders.cpython-36.pyc,, +jinja2/__pycache__/meta.cpython-36.pyc,, +jinja2/__pycache__/nativetypes.cpython-36.pyc,, +jinja2/__pycache__/nodes.cpython-36.pyc,, +jinja2/__pycache__/optimizer.cpython-36.pyc,, +jinja2/__pycache__/parser.cpython-36.pyc,, +jinja2/__pycache__/runtime.cpython-36.pyc,, +jinja2/__pycache__/sandbox.cpython-36.pyc,, +jinja2/__pycache__/tests.cpython-36.pyc,, +jinja2/__pycache__/utils.cpython-36.pyc,, +jinja2/__pycache__/visitor.cpython-36.pyc,, +jinja2/__pycache__/_compat.cpython-36.pyc,, +jinja2/__pycache__/_identifier.cpython-36.pyc,, +jinja2/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/PKG-INFO index 6f2568f66..ad3a5a4ab 100644 --- a/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/PKG-INFO @@ -1,133 +1,133 @@ -Metadata-Version: 1.1 -Name: MarkupSafe -Version: 1.0 -Summary: Implements a XML/HTML/XHTML Markup safe string for Python -Home-page: http://github.com/pallets/markupsafe -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -License: BSD -Description: MarkupSafe - ========== - - Implements a unicode subclass that supports HTML strings: - - .. code-block:: python - - >>> from markupsafe import Markup, escape - >>> escape("") - Markup(u'<script>alert(document.cookie);</script>') - >>> tmpl = Markup("%s") - >>> tmpl % "Peter > Lustig" - Markup(u'Peter > Lustig') - - If you want to make an object unicode that is not yet unicode - but don't want to lose the taint information, you can use the - ``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which - is a different name for the same function). - - .. code-block:: python - - >>> from markupsafe import soft_unicode - >>> soft_unicode(42) - u'42' - >>> soft_unicode(Markup('foo')) - Markup(u'foo') - - HTML Representations - -------------------- - - Objects can customize their HTML markup equivalent by overriding - the ``__html__`` function: - - .. code-block:: python - - >>> class Foo(object): - ... def __html__(self): - ... return 'Nice' - ... - >>> escape(Foo()) - Markup(u'Nice') - >>> Markup(Foo()) - Markup(u'Nice') - - Silent Escapes - -------------- - - Since MarkupSafe 0.10 there is now also a separate escape function - called ``escape_silent`` that returns an empty string for ``None`` for - consistency with other systems that return empty strings for ``None`` - when escaping (for instance Pylons' webhelpers). - - If you also want to use this for the escape method of the Markup - object, you can create your own subclass that does that: - - .. code-block:: python - - from markupsafe import Markup, escape_silent as escape - - class SilentMarkup(Markup): - __slots__ = () - - @classmethod - def escape(cls, s): - return cls(escape(s)) - - New-Style String Formatting - --------------------------- - - Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and - 3.x are now fully supported. Previously the escape behavior of those - functions was spotty at best. The new implementations operates under the - following algorithm: - - 1. if an object has an ``__html_format__`` method it is called as - replacement for ``__format__`` with the format specifier. It either - has to return a string or markup object. - 2. if an object has an ``__html__`` method it is called. - 3. otherwise the default format system of Python kicks in and the result - is HTML escaped. - - Here is how you can implement your own formatting: - - .. code-block:: python - - class User(object): - - def __init__(self, id, username): - self.id = id - self.username = username - - def __html_format__(self, format_spec): - if format_spec == 'link': - return Markup('{1}').format( - self.id, - self.__html__(), - ) - elif format_spec: - raise ValueError('Invalid format spec') - return self.__html__() - - def __html__(self): - return Markup('{0}').format(self.username) - - And to format that user: - - .. code-block:: python - - >>> user = User(1, 'foo') - >>> Markup('

User: {0:link}').format(user) - Markup(u'

User: foo') - - Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. - -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML +Metadata-Version: 1.1 +Name: MarkupSafe +Version: 1.0 +Summary: Implements a XML/HTML/XHTML Markup safe string for Python +Home-page: http://github.com/pallets/markupsafe +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Description: MarkupSafe + ========== + + Implements a unicode subclass that supports HTML strings: + + .. code-block:: python + + >>> from markupsafe import Markup, escape + >>> escape("") + Markup(u'<script>alert(document.cookie);</script>') + >>> tmpl = Markup("%s") + >>> tmpl % "Peter > Lustig" + Markup(u'Peter > Lustig') + + If you want to make an object unicode that is not yet unicode + but don't want to lose the taint information, you can use the + ``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which + is a different name for the same function). + + .. code-block:: python + + >>> from markupsafe import soft_unicode + >>> soft_unicode(42) + u'42' + >>> soft_unicode(Markup('foo')) + Markup(u'foo') + + HTML Representations + -------------------- + + Objects can customize their HTML markup equivalent by overriding + the ``__html__`` function: + + .. code-block:: python + + >>> class Foo(object): + ... def __html__(self): + ... return 'Nice' + ... + >>> escape(Foo()) + Markup(u'Nice') + >>> Markup(Foo()) + Markup(u'Nice') + + Silent Escapes + -------------- + + Since MarkupSafe 0.10 there is now also a separate escape function + called ``escape_silent`` that returns an empty string for ``None`` for + consistency with other systems that return empty strings for ``None`` + when escaping (for instance Pylons' webhelpers). + + If you also want to use this for the escape method of the Markup + object, you can create your own subclass that does that: + + .. code-block:: python + + from markupsafe import Markup, escape_silent as escape + + class SilentMarkup(Markup): + __slots__ = () + + @classmethod + def escape(cls, s): + return cls(escape(s)) + + New-Style String Formatting + --------------------------- + + Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and + 3.x are now fully supported. Previously the escape behavior of those + functions was spotty at best. The new implementations operates under the + following algorithm: + + 1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. + 2. if an object has an ``__html__`` method it is called. + 3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + + Here is how you can implement your own formatting: + + .. code-block:: python + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + + And to format that user: + + .. code-block:: python + + >>> user = User(1, 'foo') + >>> Markup('

User: {0:link}').format(user) + Markup(u'

User: foo') + + Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. + +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML diff --git a/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/installed-files.txt index 6cdf040ee..22e67eaa9 100644 --- a/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/MarkupSafe-1.0-py3.6.egg-info/installed-files.txt @@ -1,15 +1,15 @@ -..\markupsafe\_compat.py -..\markupsafe\_constants.py -..\markupsafe\_native.py -..\markupsafe\__init__.py -..\markupsafe\_speedups.c -..\markupsafe\__pycache__\_compat.cpython-36.pyc -..\markupsafe\__pycache__\_constants.cpython-36.pyc -..\markupsafe\__pycache__\_native.cpython-36.pyc -..\markupsafe\__pycache__\__init__.cpython-36.pyc -..\markupsafe\_speedups.cp36-win_amd64.pyd -dependency_links.txt -not-zip-safe -PKG-INFO -SOURCES.txt -top_level.txt +..\markupsafe\_compat.py +..\markupsafe\_constants.py +..\markupsafe\_native.py +..\markupsafe\__init__.py +..\markupsafe\_speedups.c +..\markupsafe\__pycache__\_compat.cpython-36.pyc +..\markupsafe\__pycache__\_constants.cpython-36.pyc +..\markupsafe\__pycache__\_native.cpython-36.pyc +..\markupsafe\__pycache__\__init__.cpython-36.pyc +..\markupsafe\_speedups.cp36-win_amd64.pyd +dependency_links.txt +not-zip-safe +PKG-INFO +SOURCES.txt +top_level.txt diff --git a/website/web/Lib/site-packages/Werkzeug-0.14.1.dist-info/RECORD b/website/web/Lib/site-packages/Werkzeug-0.14.1.dist-info/RECORD index 357d9b772..421652cd0 100644 --- a/website/web/Lib/site-packages/Werkzeug-0.14.1.dist-info/RECORD +++ b/website/web/Lib/site-packages/Werkzeug-0.14.1.dist-info/RECORD @@ -1,97 +1,97 @@ -Werkzeug-0.14.1.dist-info/DESCRIPTION.rst,sha256=rOCN36jwsWtWsTpqPG96z7FMilB5qI1CIARSKRuUmz8,2452 -Werkzeug-0.14.1.dist-info/LICENSE.txt,sha256=xndz_dD4m269AF9l_Xbl5V3tM1N3C1LoZC2PEPxWO-8,1534 -Werkzeug-0.14.1.dist-info/METADATA,sha256=FbfadrPdJNUWAxMOKxGUtHe5R3IDSBKYYmAz3FvI3uY,3872 -Werkzeug-0.14.1.dist-info/RECORD,, -Werkzeug-0.14.1.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 -Werkzeug-0.14.1.dist-info/metadata.json,sha256=4489UTt6HBp2NQil95-pBkjU4Je93SMHvMxZ_rjOpqA,1452 -Werkzeug-0.14.1.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 -werkzeug/__init__.py,sha256=NR0d4n_-U9BLVKlOISean3zUt2vBwhvK-AZE6M0sC0k,6842 -werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311 -werkzeug/_internal.py,sha256=GhEyGMlsSz_tYjsDWO9TG35VN7304MM8gjKDrXLEdVc,13873 -werkzeug/_reloader.py,sha256=AyPphcOHPbu6qzW0UbrVvTDJdre5WgpxbhIJN_TqzUc,9264 -werkzeug/datastructures.py,sha256=3IgNKNqrz-ZjmAG7y3YgEYK-enDiMT_b652PsypWcYg,90080 -werkzeug/exceptions.py,sha256=3wp95Hqj9FqV8MdikV99JRcHse_fSMn27V8tgP5Hw2c,20505 -werkzeug/filesystem.py,sha256=hHWeWo_gqLMzTRfYt8-7n2wWcWUNTnDyudQDLOBEICE,2175 -werkzeug/formparser.py,sha256=mUuCwjzjb8_E4RzrAT2AioLuZSYpqR1KXTK6LScRYzA,21722 -werkzeug/http.py,sha256=RQg4MJuhRv2isNRiEh__Phh09ebpfT3Kuu_GfrZ54_c,40079 -werkzeug/local.py,sha256=QdQhWV5L8p1Y1CJ1CDStwxaUs24SuN5aebHwjVD08C8,14553 -werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519 -werkzeug/routing.py,sha256=2JVtdSgxKGeANy4Z_FP-dKESvKtkYGCZ1J2fARCLGCY,67214 -werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365 -werkzeug/security.py,sha256=0m107exslz4QJLWQCpfQJ04z3re4eGHVggRvrQVAdWc,9193 -werkzeug/serving.py,sha256=A0flnIJHufdn2QJ9oeuHfrXwP3LzP8fn3rNW6hbxKUg,31926 -werkzeug/test.py,sha256=XmECSmnpASiYQTct4oMiWr0LT5jHWCtKqnpYKZd2ui8,36100 -werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396 -werkzeug/urls.py,sha256=dUeLg2IeTm0WLmSvFeD4hBZWGdOs-uHudR5-t8n9zPo,36771 -werkzeug/useragents.py,sha256=BhYMf4cBTHyN4U0WsQedePIocmNlH_34C-UwqSThGCc,5865 -werkzeug/utils.py,sha256=BrY1j0DHQ8RTb0K1StIobKuMJhN9SQQkWEARbrh2qpk,22972 -werkzeug/websocket.py,sha256=PpSeDxXD_0UsPAa5hQhQNM6mxibeUgn8lA8eRqiS0vM,11344 -werkzeug/wrappers.py,sha256=kbyL_aFjxELwPgMwfNCYjKu-CR6kNkh-oO8wv3GXbk8,84511 -werkzeug/wsgi.py,sha256=1Nob-aeChWQf7MsiicO8RZt6J90iRzEcik44ev9Qu8s,49347 -werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623 -werkzeug/contrib/atom.py,sha256=qqfJcfIn2RYY-3hO3Oz0aLq9YuNubcPQ_KZcNsDwVJo,15575 -werkzeug/contrib/cache.py,sha256=xBImHNj09BmX_7kC5NUCx8f_l4L8_O7zi0jCL21UZKE,32163 -werkzeug/contrib/fixers.py,sha256=gR06T-w71ur-tHQ_31kP_4jpOncPJ4Wc1dOqTvYusr8,10179 -werkzeug/contrib/iterio.py,sha256=RlqDvGhz0RneTpzE8dVc-yWCUv4nkPl1jEc_EDp2fH0,10814 -werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564 -werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334 -werkzeug/contrib/lint.py,sha256=Mj9NeUN7s4zIUWeQOAVjrmtZIcl3Mm2yDe9BSIr9YGE,12558 -werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151 -werkzeug/contrib/securecookie.py,sha256=uWMyHDHY3lkeBRiCSayGqWkAIy4a7xAbSE_Hln9ecqc,12196 -werkzeug/contrib/sessions.py,sha256=39LVNvLbm5JWpbxM79WC2l87MJFbqeISARjwYbkJatw,12577 -werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453 -werkzeug/contrib/wrappers.py,sha256=v7OYlz7wQtDlS9fey75UiRZ1IkUWqCpzbhsLy4k14Hw,10398 -werkzeug/debug/__init__.py,sha256=uSn9BqCZ5E3ySgpoZtundpROGsn-uYvZtSFiTfAX24M,17452 -werkzeug/debug/console.py,sha256=n3-dsKk1TsjnN-u4ZgmuWCU_HO0qw5IA7ttjhyyMM6I,5607 -werkzeug/debug/repr.py,sha256=bKqstDYGfECpeLerd48s_hxuqK4b6UWnjMu3d_DHO8I,9340 -werkzeug/debug/tbtools.py,sha256=rBudXCmkVdAKIcdhxANxgf09g6kQjJWW9_5bjSpr4OY,18451 -werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 -werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 -werkzeug/debug/shared/debugger.js,sha256=PKPVYuyO4SX1hkqLOwCLvmIEO5154WatFYaXE-zIfKI,6264 -werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 -werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 -werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 -werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 -werkzeug/debug/shared/style.css,sha256=IEO0PC2pWmh2aEyGCaN--txuWsRCliuhlbEhPDFwh0A,6270 -werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 -Werkzeug-0.14.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -werkzeug/contrib/__pycache__/atom.cpython-36.pyc,, -werkzeug/contrib/__pycache__/cache.cpython-36.pyc,, -werkzeug/contrib/__pycache__/fixers.cpython-36.pyc,, -werkzeug/contrib/__pycache__/iterio.cpython-36.pyc,, -werkzeug/contrib/__pycache__/jsrouting.cpython-36.pyc,, -werkzeug/contrib/__pycache__/limiter.cpython-36.pyc,, -werkzeug/contrib/__pycache__/lint.cpython-36.pyc,, -werkzeug/contrib/__pycache__/profiler.cpython-36.pyc,, -werkzeug/contrib/__pycache__/securecookie.cpython-36.pyc,, -werkzeug/contrib/__pycache__/sessions.cpython-36.pyc,, -werkzeug/contrib/__pycache__/testtools.cpython-36.pyc,, -werkzeug/contrib/__pycache__/wrappers.cpython-36.pyc,, -werkzeug/contrib/__pycache__/__init__.cpython-36.pyc,, -werkzeug/debug/__pycache__/console.cpython-36.pyc,, -werkzeug/debug/__pycache__/repr.cpython-36.pyc,, -werkzeug/debug/__pycache__/tbtools.cpython-36.pyc,, -werkzeug/debug/__pycache__/__init__.cpython-36.pyc,, -werkzeug/__pycache__/datastructures.cpython-36.pyc,, -werkzeug/__pycache__/exceptions.cpython-36.pyc,, -werkzeug/__pycache__/filesystem.cpython-36.pyc,, -werkzeug/__pycache__/formparser.cpython-36.pyc,, -werkzeug/__pycache__/http.cpython-36.pyc,, -werkzeug/__pycache__/local.cpython-36.pyc,, -werkzeug/__pycache__/posixemulation.cpython-36.pyc,, -werkzeug/__pycache__/routing.cpython-36.pyc,, -werkzeug/__pycache__/script.cpython-36.pyc,, -werkzeug/__pycache__/security.cpython-36.pyc,, -werkzeug/__pycache__/serving.cpython-36.pyc,, -werkzeug/__pycache__/test.cpython-36.pyc,, -werkzeug/__pycache__/testapp.cpython-36.pyc,, -werkzeug/__pycache__/urls.cpython-36.pyc,, -werkzeug/__pycache__/useragents.cpython-36.pyc,, -werkzeug/__pycache__/utils.cpython-36.pyc,, -werkzeug/__pycache__/websocket.cpython-36.pyc,, -werkzeug/__pycache__/wrappers.cpython-36.pyc,, -werkzeug/__pycache__/wsgi.cpython-36.pyc,, -werkzeug/__pycache__/_compat.cpython-36.pyc,, -werkzeug/__pycache__/_internal.cpython-36.pyc,, -werkzeug/__pycache__/_reloader.cpython-36.pyc,, -werkzeug/__pycache__/__init__.cpython-36.pyc,, +Werkzeug-0.14.1.dist-info/DESCRIPTION.rst,sha256=rOCN36jwsWtWsTpqPG96z7FMilB5qI1CIARSKRuUmz8,2452 +Werkzeug-0.14.1.dist-info/LICENSE.txt,sha256=xndz_dD4m269AF9l_Xbl5V3tM1N3C1LoZC2PEPxWO-8,1534 +Werkzeug-0.14.1.dist-info/METADATA,sha256=FbfadrPdJNUWAxMOKxGUtHe5R3IDSBKYYmAz3FvI3uY,3872 +Werkzeug-0.14.1.dist-info/RECORD,, +Werkzeug-0.14.1.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 +Werkzeug-0.14.1.dist-info/metadata.json,sha256=4489UTt6HBp2NQil95-pBkjU4Je93SMHvMxZ_rjOpqA,1452 +Werkzeug-0.14.1.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 +werkzeug/__init__.py,sha256=NR0d4n_-U9BLVKlOISean3zUt2vBwhvK-AZE6M0sC0k,6842 +werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311 +werkzeug/_internal.py,sha256=GhEyGMlsSz_tYjsDWO9TG35VN7304MM8gjKDrXLEdVc,13873 +werkzeug/_reloader.py,sha256=AyPphcOHPbu6qzW0UbrVvTDJdre5WgpxbhIJN_TqzUc,9264 +werkzeug/datastructures.py,sha256=3IgNKNqrz-ZjmAG7y3YgEYK-enDiMT_b652PsypWcYg,90080 +werkzeug/exceptions.py,sha256=3wp95Hqj9FqV8MdikV99JRcHse_fSMn27V8tgP5Hw2c,20505 +werkzeug/filesystem.py,sha256=hHWeWo_gqLMzTRfYt8-7n2wWcWUNTnDyudQDLOBEICE,2175 +werkzeug/formparser.py,sha256=mUuCwjzjb8_E4RzrAT2AioLuZSYpqR1KXTK6LScRYzA,21722 +werkzeug/http.py,sha256=RQg4MJuhRv2isNRiEh__Phh09ebpfT3Kuu_GfrZ54_c,40079 +werkzeug/local.py,sha256=QdQhWV5L8p1Y1CJ1CDStwxaUs24SuN5aebHwjVD08C8,14553 +werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519 +werkzeug/routing.py,sha256=2JVtdSgxKGeANy4Z_FP-dKESvKtkYGCZ1J2fARCLGCY,67214 +werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365 +werkzeug/security.py,sha256=0m107exslz4QJLWQCpfQJ04z3re4eGHVggRvrQVAdWc,9193 +werkzeug/serving.py,sha256=A0flnIJHufdn2QJ9oeuHfrXwP3LzP8fn3rNW6hbxKUg,31926 +werkzeug/test.py,sha256=XmECSmnpASiYQTct4oMiWr0LT5jHWCtKqnpYKZd2ui8,36100 +werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396 +werkzeug/urls.py,sha256=dUeLg2IeTm0WLmSvFeD4hBZWGdOs-uHudR5-t8n9zPo,36771 +werkzeug/useragents.py,sha256=BhYMf4cBTHyN4U0WsQedePIocmNlH_34C-UwqSThGCc,5865 +werkzeug/utils.py,sha256=BrY1j0DHQ8RTb0K1StIobKuMJhN9SQQkWEARbrh2qpk,22972 +werkzeug/websocket.py,sha256=PpSeDxXD_0UsPAa5hQhQNM6mxibeUgn8lA8eRqiS0vM,11344 +werkzeug/wrappers.py,sha256=kbyL_aFjxELwPgMwfNCYjKu-CR6kNkh-oO8wv3GXbk8,84511 +werkzeug/wsgi.py,sha256=1Nob-aeChWQf7MsiicO8RZt6J90iRzEcik44ev9Qu8s,49347 +werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623 +werkzeug/contrib/atom.py,sha256=qqfJcfIn2RYY-3hO3Oz0aLq9YuNubcPQ_KZcNsDwVJo,15575 +werkzeug/contrib/cache.py,sha256=xBImHNj09BmX_7kC5NUCx8f_l4L8_O7zi0jCL21UZKE,32163 +werkzeug/contrib/fixers.py,sha256=gR06T-w71ur-tHQ_31kP_4jpOncPJ4Wc1dOqTvYusr8,10179 +werkzeug/contrib/iterio.py,sha256=RlqDvGhz0RneTpzE8dVc-yWCUv4nkPl1jEc_EDp2fH0,10814 +werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564 +werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334 +werkzeug/contrib/lint.py,sha256=Mj9NeUN7s4zIUWeQOAVjrmtZIcl3Mm2yDe9BSIr9YGE,12558 +werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151 +werkzeug/contrib/securecookie.py,sha256=uWMyHDHY3lkeBRiCSayGqWkAIy4a7xAbSE_Hln9ecqc,12196 +werkzeug/contrib/sessions.py,sha256=39LVNvLbm5JWpbxM79WC2l87MJFbqeISARjwYbkJatw,12577 +werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453 +werkzeug/contrib/wrappers.py,sha256=v7OYlz7wQtDlS9fey75UiRZ1IkUWqCpzbhsLy4k14Hw,10398 +werkzeug/debug/__init__.py,sha256=uSn9BqCZ5E3ySgpoZtundpROGsn-uYvZtSFiTfAX24M,17452 +werkzeug/debug/console.py,sha256=n3-dsKk1TsjnN-u4ZgmuWCU_HO0qw5IA7ttjhyyMM6I,5607 +werkzeug/debug/repr.py,sha256=bKqstDYGfECpeLerd48s_hxuqK4b6UWnjMu3d_DHO8I,9340 +werkzeug/debug/tbtools.py,sha256=rBudXCmkVdAKIcdhxANxgf09g6kQjJWW9_5bjSpr4OY,18451 +werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/debugger.js,sha256=PKPVYuyO4SX1hkqLOwCLvmIEO5154WatFYaXE-zIfKI,6264 +werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 +werkzeug/debug/shared/style.css,sha256=IEO0PC2pWmh2aEyGCaN--txuWsRCliuhlbEhPDFwh0A,6270 +werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 +Werkzeug-0.14.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +werkzeug/contrib/__pycache__/atom.cpython-36.pyc,, +werkzeug/contrib/__pycache__/cache.cpython-36.pyc,, +werkzeug/contrib/__pycache__/fixers.cpython-36.pyc,, +werkzeug/contrib/__pycache__/iterio.cpython-36.pyc,, +werkzeug/contrib/__pycache__/jsrouting.cpython-36.pyc,, +werkzeug/contrib/__pycache__/limiter.cpython-36.pyc,, +werkzeug/contrib/__pycache__/lint.cpython-36.pyc,, +werkzeug/contrib/__pycache__/profiler.cpython-36.pyc,, +werkzeug/contrib/__pycache__/securecookie.cpython-36.pyc,, +werkzeug/contrib/__pycache__/sessions.cpython-36.pyc,, +werkzeug/contrib/__pycache__/testtools.cpython-36.pyc,, +werkzeug/contrib/__pycache__/wrappers.cpython-36.pyc,, +werkzeug/contrib/__pycache__/__init__.cpython-36.pyc,, +werkzeug/debug/__pycache__/console.cpython-36.pyc,, +werkzeug/debug/__pycache__/repr.cpython-36.pyc,, +werkzeug/debug/__pycache__/tbtools.cpython-36.pyc,, +werkzeug/debug/__pycache__/__init__.cpython-36.pyc,, +werkzeug/__pycache__/datastructures.cpython-36.pyc,, +werkzeug/__pycache__/exceptions.cpython-36.pyc,, +werkzeug/__pycache__/filesystem.cpython-36.pyc,, +werkzeug/__pycache__/formparser.cpython-36.pyc,, +werkzeug/__pycache__/http.cpython-36.pyc,, +werkzeug/__pycache__/local.cpython-36.pyc,, +werkzeug/__pycache__/posixemulation.cpython-36.pyc,, +werkzeug/__pycache__/routing.cpython-36.pyc,, +werkzeug/__pycache__/script.cpython-36.pyc,, +werkzeug/__pycache__/security.cpython-36.pyc,, +werkzeug/__pycache__/serving.cpython-36.pyc,, +werkzeug/__pycache__/test.cpython-36.pyc,, +werkzeug/__pycache__/testapp.cpython-36.pyc,, +werkzeug/__pycache__/urls.cpython-36.pyc,, +werkzeug/__pycache__/useragents.cpython-36.pyc,, +werkzeug/__pycache__/utils.cpython-36.pyc,, +werkzeug/__pycache__/websocket.cpython-36.pyc,, +werkzeug/__pycache__/wrappers.cpython-36.pyc,, +werkzeug/__pycache__/wsgi.cpython-36.pyc,, +werkzeug/__pycache__/_compat.cpython-36.pyc,, +werkzeug/__pycache__/_internal.cpython-36.pyc,, +werkzeug/__pycache__/_reloader.cpython-36.pyc,, +werkzeug/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/cffi-1.11.4.dist-info/RECORD b/website/web/Lib/site-packages/cffi-1.11.4.dist-info/RECORD index 54d4939de..01d1c5060 100644 --- a/website/web/Lib/site-packages/cffi-1.11.4.dist-info/RECORD +++ b/website/web/Lib/site-packages/cffi-1.11.4.dist-info/RECORD @@ -1,43 +1,43 @@ -_cffi_backend.cp36-win_amd64.pyd,sha256=likuFoX9C7Qi1bfHpJJHzKgOXmWFdXIN1IbPCbmO7bc,170496 -cffi/__init__.py,sha256=mewOsqyqnxYpvL3XfQFIRYyxcoW2ic60hMResP7gdJM,479 -cffi/_cffi_errors.h,sha256=NLNuKgpRUJ4x0ku4pi-Pe1vT1mzovxBTeHjPZTxCB7U,3804 -cffi/_cffi_include.h,sha256=JuFfmwpRE65vym3Nxr9vDMOIEuv21tXdarkL1l2WNms,12149 -cffi/_embedding.h,sha256=iSs9APxG4SDy_ahlyV1s46_lvWdVBxnuOwaEBN5jOUg,17643 -cffi/api.py,sha256=eUXlc8fTxiS3PjpfBU3sMi8gVgeG4yIsPA6teyNWehI,40221 -cffi/backend_ctypes.py,sha256=XxMfz3Kn_QZhvLLqNXmIL_Z9M8CGlGAa1YWtH6k8wYQ,42086 -cffi/cffi_opcode.py,sha256=v9RdD_ovA8rCtqsC95Ivki5V667rAOhGgs3fb2q9xpM,5724 -cffi/commontypes.py,sha256=QS4uxCDI7JhtTyjh1hlnCA-gynmaszWxJaRRLGkJa1A,2689 -cffi/cparser.py,sha256=R0_gdB8vL1YNf-W5G_5KvV1pOTnZwvuLeioaDvODI6c,39250 -cffi/error.py,sha256=L_J76qbh6LSxH4A64muOUwJKL6zVHC32E3gG1ntUM-A,666 -cffi/ffiplatform.py,sha256=HMXqR8ks2wtdsNxGaWpQ_PyqIvtiuos_vf1qKCy-cwg,4046 -cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 -cffi/model.py,sha256=-ZXCFO_EPbX3zN3ecx4H2rR0MZZA16ZwldDuv3CzJXU,21495 -cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 -cffi/recompiler.py,sha256=4qpl0bOTaegsWJbaCvjtRh4q6KH5hWZurnKK1YGEeRk,63092 -cffi/setuptools_ext.py,sha256=6K2HJn-qNTQL-FvILZCH0T90MR6FVelFClL4f8ZCWaQ,7682 -cffi/vengine_cpy.py,sha256=hdyjjZNijLrg_uGMnnFyC-7GG_LxWtwB8BlS2vvVDQ0,41470 -cffi/vengine_gen.py,sha256=Zkq0-EdeZwn6qUvf_CI8iUEs2UxVIvDmKCH1j0-y0GI,26676 -cffi/verifier.py,sha256=J9Enz2rbJb9CHPqWlWQ5uQESoyr0uc7MNWugchjXBv4,11207 -cffi-1.11.4.dist-info/DESCRIPTION.rst,sha256=9ijQLbcqTWNF-iV0RznFiBeBCNrjArA0P-eutKUPw98,220 -cffi-1.11.4.dist-info/METADATA,sha256=uiGWsWy8zEb_-R4-vMutpELIrBKsvCV-_soHfZNjUaw,1174 -cffi-1.11.4.dist-info/RECORD,, -cffi-1.11.4.dist-info/WHEEL,sha256=3o6dJ54ci-MtRFdJCPkLCK5G-vO7QSv3lIQ-NrhglGk,106 -cffi-1.11.4.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76 -cffi-1.11.4.dist-info/metadata.json,sha256=8S4WNSCRPXo6P__ARsF2aUGV0Drrh82dQQxr9Xsj9vw,1192 -cffi-1.11.4.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 -cffi-1.11.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -cffi/__pycache__/api.cpython-36.pyc,, -cffi/__pycache__/backend_ctypes.cpython-36.pyc,, -cffi/__pycache__/cffi_opcode.cpython-36.pyc,, -cffi/__pycache__/commontypes.cpython-36.pyc,, -cffi/__pycache__/cparser.cpython-36.pyc,, -cffi/__pycache__/error.cpython-36.pyc,, -cffi/__pycache__/ffiplatform.cpython-36.pyc,, -cffi/__pycache__/lock.cpython-36.pyc,, -cffi/__pycache__/model.cpython-36.pyc,, -cffi/__pycache__/recompiler.cpython-36.pyc,, -cffi/__pycache__/setuptools_ext.cpython-36.pyc,, -cffi/__pycache__/vengine_cpy.cpython-36.pyc,, -cffi/__pycache__/vengine_gen.cpython-36.pyc,, -cffi/__pycache__/verifier.cpython-36.pyc,, -cffi/__pycache__/__init__.cpython-36.pyc,, +_cffi_backend.cp36-win_amd64.pyd,sha256=likuFoX9C7Qi1bfHpJJHzKgOXmWFdXIN1IbPCbmO7bc,170496 +cffi/__init__.py,sha256=mewOsqyqnxYpvL3XfQFIRYyxcoW2ic60hMResP7gdJM,479 +cffi/_cffi_errors.h,sha256=NLNuKgpRUJ4x0ku4pi-Pe1vT1mzovxBTeHjPZTxCB7U,3804 +cffi/_cffi_include.h,sha256=JuFfmwpRE65vym3Nxr9vDMOIEuv21tXdarkL1l2WNms,12149 +cffi/_embedding.h,sha256=iSs9APxG4SDy_ahlyV1s46_lvWdVBxnuOwaEBN5jOUg,17643 +cffi/api.py,sha256=eUXlc8fTxiS3PjpfBU3sMi8gVgeG4yIsPA6teyNWehI,40221 +cffi/backend_ctypes.py,sha256=XxMfz3Kn_QZhvLLqNXmIL_Z9M8CGlGAa1YWtH6k8wYQ,42086 +cffi/cffi_opcode.py,sha256=v9RdD_ovA8rCtqsC95Ivki5V667rAOhGgs3fb2q9xpM,5724 +cffi/commontypes.py,sha256=QS4uxCDI7JhtTyjh1hlnCA-gynmaszWxJaRRLGkJa1A,2689 +cffi/cparser.py,sha256=R0_gdB8vL1YNf-W5G_5KvV1pOTnZwvuLeioaDvODI6c,39250 +cffi/error.py,sha256=L_J76qbh6LSxH4A64muOUwJKL6zVHC32E3gG1ntUM-A,666 +cffi/ffiplatform.py,sha256=HMXqR8ks2wtdsNxGaWpQ_PyqIvtiuos_vf1qKCy-cwg,4046 +cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 +cffi/model.py,sha256=-ZXCFO_EPbX3zN3ecx4H2rR0MZZA16ZwldDuv3CzJXU,21495 +cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 +cffi/recompiler.py,sha256=4qpl0bOTaegsWJbaCvjtRh4q6KH5hWZurnKK1YGEeRk,63092 +cffi/setuptools_ext.py,sha256=6K2HJn-qNTQL-FvILZCH0T90MR6FVelFClL4f8ZCWaQ,7682 +cffi/vengine_cpy.py,sha256=hdyjjZNijLrg_uGMnnFyC-7GG_LxWtwB8BlS2vvVDQ0,41470 +cffi/vengine_gen.py,sha256=Zkq0-EdeZwn6qUvf_CI8iUEs2UxVIvDmKCH1j0-y0GI,26676 +cffi/verifier.py,sha256=J9Enz2rbJb9CHPqWlWQ5uQESoyr0uc7MNWugchjXBv4,11207 +cffi-1.11.4.dist-info/DESCRIPTION.rst,sha256=9ijQLbcqTWNF-iV0RznFiBeBCNrjArA0P-eutKUPw98,220 +cffi-1.11.4.dist-info/METADATA,sha256=uiGWsWy8zEb_-R4-vMutpELIrBKsvCV-_soHfZNjUaw,1174 +cffi-1.11.4.dist-info/RECORD,, +cffi-1.11.4.dist-info/WHEEL,sha256=3o6dJ54ci-MtRFdJCPkLCK5G-vO7QSv3lIQ-NrhglGk,106 +cffi-1.11.4.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76 +cffi-1.11.4.dist-info/metadata.json,sha256=8S4WNSCRPXo6P__ARsF2aUGV0Drrh82dQQxr9Xsj9vw,1192 +cffi-1.11.4.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 +cffi-1.11.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cffi/__pycache__/api.cpython-36.pyc,, +cffi/__pycache__/backend_ctypes.cpython-36.pyc,, +cffi/__pycache__/cffi_opcode.cpython-36.pyc,, +cffi/__pycache__/commontypes.cpython-36.pyc,, +cffi/__pycache__/cparser.cpython-36.pyc,, +cffi/__pycache__/error.cpython-36.pyc,, +cffi/__pycache__/ffiplatform.cpython-36.pyc,, +cffi/__pycache__/lock.cpython-36.pyc,, +cffi/__pycache__/model.cpython-36.pyc,, +cffi/__pycache__/recompiler.cpython-36.pyc,, +cffi/__pycache__/setuptools_ext.cpython-36.pyc,, +cffi/__pycache__/vengine_cpy.cpython-36.pyc,, +cffi/__pycache__/vengine_gen.cpython-36.pyc,, +cffi/__pycache__/verifier.cpython-36.pyc,, +cffi/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/cffi-1.11.4.dist-info/WHEEL b/website/web/Lib/site-packages/cffi-1.11.4.dist-info/WHEEL index 2be04293c..938a5223f 100644 --- a/website/web/Lib/site-packages/cffi-1.11.4.dist-info/WHEEL +++ b/website/web/Lib/site-packages/cffi-1.11.4.dist-info/WHEEL @@ -1,5 +1,5 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.30.0) -Root-Is-Purelib: false -Tag: cp36-cp36m-win_amd64 - +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0) +Root-Is-Purelib: false +Tag: cp36-cp36m-win_amd64 + diff --git a/website/web/Lib/site-packages/click-6.7.dist-info/RECORD b/website/web/Lib/site-packages/click-6.7.dist-info/RECORD index 6eaa8b20b..017e58d38 100644 --- a/website/web/Lib/site-packages/click-6.7.dist-info/RECORD +++ b/website/web/Lib/site-packages/click-6.7.dist-info/RECORD @@ -1,41 +1,41 @@ -click/__init__.py,sha256=k8R00cFKWI8dhDVKQeLBlAdNh1CxerMEDRiGnr32gdw,2858 -click/_bashcomplete.py,sha256=82rMiibtEurdwBq60NHXVCBuGXJHDpblFO9o2YxJDF0,2423 -click/_compat.py,sha256=j59MpzxYGE-fTGj0A5sg8UI8GhHod1XMojiCA0jvbL0,21011 -click/_termui_impl.py,sha256=Ol1JJhvBRw3l8j1WIU0tOWjQtxxmwGE44lFDbzDqzoA,16395 -click/_textwrap.py,sha256=gwS4m7bdQiJnzaDG8osFcRb-5vn4t4l2qSCy-5csCEc,1198 -click/_unicodefun.py,sha256=A3UOzJw6lEZyol2SBg3fNXgweTutaOzkJ61OB7vik3Y,4204 -click/_winconsole.py,sha256=MzG46DEYPoRyx4SO7EIhFuFZHESgooAfJLIukbB6p5c,7790 -click/core.py,sha256=M0nJ6Kkye7XZXYG7HCbkJWSfy14WHV6bQmGLACrOhKw,70254 -click/decorators.py,sha256=y7CX2needh8iRWafj-QS_hGQFsN24eyXAhx5Y2ATwas,10941 -click/exceptions.py,sha256=rOa0pP3PbSy0_AAPOW9irBEM8AJ3BySN-4z2VUwFVo4,6788 -click/formatting.py,sha256=eh-cypTUAhpI3HD-K4ZpR3vCiURIO62xXvKkR3tNUTM,8889 -click/globals.py,sha256=PAgnKvGxq4YuEIldw3lgYOGBLYwsyxnm1IByBX3BFXo,1515 -click/parser.py,sha256=i01xgYuIA6AwQWEXjshwHSwnTR3gUep4FxJIfyW4ta4,15510 -click/termui.py,sha256=Bp99MSWQtyoWe1_7HggDmA77n--3KLxu7NsZMFMaCUo,21008 -click/testing.py,sha256=kJ9mjtJgwNAlkgKcFf9-ISxufmaPDbbuOHVC9WIvKdY,11002 -click/types.py,sha256=ZGb2lmFs5Vwd9loTRIMbGcqhPVOql8mGoBhWBRT6V4E,18864 -click/utils.py,sha256=1jalPlkUU28JReTEQeeSFtbJd-SirYWBNfjtELBKzT4,14916 -click-6.7.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 -click-6.7.dist-info/METADATA,sha256=l6lAyogIUXiHKUK_rWguef-EMcvO5C6bXzFCNCcblbQ,424 -click-6.7.dist-info/RECORD,, -click-6.7.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113 -click-6.7.dist-info/metadata.json,sha256=qg0uO6amNHkIkOxnmWX7Xa_DNQMQ62Q6drivuP9Gh1c,571 -click-6.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 -click-6.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click/__pycache__/core.cpython-36.pyc,, -click/__pycache__/decorators.cpython-36.pyc,, -click/__pycache__/exceptions.cpython-36.pyc,, -click/__pycache__/formatting.cpython-36.pyc,, -click/__pycache__/globals.cpython-36.pyc,, -click/__pycache__/parser.cpython-36.pyc,, -click/__pycache__/termui.cpython-36.pyc,, -click/__pycache__/testing.cpython-36.pyc,, -click/__pycache__/types.cpython-36.pyc,, -click/__pycache__/utils.cpython-36.pyc,, -click/__pycache__/_bashcomplete.cpython-36.pyc,, -click/__pycache__/_compat.cpython-36.pyc,, -click/__pycache__/_termui_impl.cpython-36.pyc,, -click/__pycache__/_textwrap.cpython-36.pyc,, -click/__pycache__/_unicodefun.cpython-36.pyc,, -click/__pycache__/_winconsole.cpython-36.pyc,, -click/__pycache__/__init__.cpython-36.pyc,, +click/__init__.py,sha256=k8R00cFKWI8dhDVKQeLBlAdNh1CxerMEDRiGnr32gdw,2858 +click/_bashcomplete.py,sha256=82rMiibtEurdwBq60NHXVCBuGXJHDpblFO9o2YxJDF0,2423 +click/_compat.py,sha256=j59MpzxYGE-fTGj0A5sg8UI8GhHod1XMojiCA0jvbL0,21011 +click/_termui_impl.py,sha256=Ol1JJhvBRw3l8j1WIU0tOWjQtxxmwGE44lFDbzDqzoA,16395 +click/_textwrap.py,sha256=gwS4m7bdQiJnzaDG8osFcRb-5vn4t4l2qSCy-5csCEc,1198 +click/_unicodefun.py,sha256=A3UOzJw6lEZyol2SBg3fNXgweTutaOzkJ61OB7vik3Y,4204 +click/_winconsole.py,sha256=MzG46DEYPoRyx4SO7EIhFuFZHESgooAfJLIukbB6p5c,7790 +click/core.py,sha256=M0nJ6Kkye7XZXYG7HCbkJWSfy14WHV6bQmGLACrOhKw,70254 +click/decorators.py,sha256=y7CX2needh8iRWafj-QS_hGQFsN24eyXAhx5Y2ATwas,10941 +click/exceptions.py,sha256=rOa0pP3PbSy0_AAPOW9irBEM8AJ3BySN-4z2VUwFVo4,6788 +click/formatting.py,sha256=eh-cypTUAhpI3HD-K4ZpR3vCiURIO62xXvKkR3tNUTM,8889 +click/globals.py,sha256=PAgnKvGxq4YuEIldw3lgYOGBLYwsyxnm1IByBX3BFXo,1515 +click/parser.py,sha256=i01xgYuIA6AwQWEXjshwHSwnTR3gUep4FxJIfyW4ta4,15510 +click/termui.py,sha256=Bp99MSWQtyoWe1_7HggDmA77n--3KLxu7NsZMFMaCUo,21008 +click/testing.py,sha256=kJ9mjtJgwNAlkgKcFf9-ISxufmaPDbbuOHVC9WIvKdY,11002 +click/types.py,sha256=ZGb2lmFs5Vwd9loTRIMbGcqhPVOql8mGoBhWBRT6V4E,18864 +click/utils.py,sha256=1jalPlkUU28JReTEQeeSFtbJd-SirYWBNfjtELBKzT4,14916 +click-6.7.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 +click-6.7.dist-info/METADATA,sha256=l6lAyogIUXiHKUK_rWguef-EMcvO5C6bXzFCNCcblbQ,424 +click-6.7.dist-info/RECORD,, +click-6.7.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113 +click-6.7.dist-info/metadata.json,sha256=qg0uO6amNHkIkOxnmWX7Xa_DNQMQ62Q6drivuP9Gh1c,571 +click-6.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click-6.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click/__pycache__/core.cpython-36.pyc,, +click/__pycache__/decorators.cpython-36.pyc,, +click/__pycache__/exceptions.cpython-36.pyc,, +click/__pycache__/formatting.cpython-36.pyc,, +click/__pycache__/globals.cpython-36.pyc,, +click/__pycache__/parser.cpython-36.pyc,, +click/__pycache__/termui.cpython-36.pyc,, +click/__pycache__/testing.cpython-36.pyc,, +click/__pycache__/types.cpython-36.pyc,, +click/__pycache__/utils.cpython-36.pyc,, +click/__pycache__/_bashcomplete.cpython-36.pyc,, +click/__pycache__/_compat.cpython-36.pyc,, +click/__pycache__/_termui_impl.cpython-36.pyc,, +click/__pycache__/_textwrap.cpython-36.pyc,, +click/__pycache__/_unicodefun.cpython-36.pyc,, +click/__pycache__/_winconsole.cpython-36.pyc,, +click/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/PKG-INFO index 3fa645523..3893027ae 100644 --- a/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/PKG-INFO @@ -1,102 +1,102 @@ -Metadata-Version: 1.1 -Name: emoji -Version: 0.4.5 -Summary: Emoji for Python -Home-page: https://github.com/carpedm20/emoji/ -Author: Taehoon Kim and Kevin Wurster -Author-email: carpedm20@gmail.com and wursterk@gmail.com -License: New BSD -Description: Emoji - ===== - - Emoji for Python. This project was inspired by `kyokomi `__. - - - Example - ------- - - The entire set of Emoji codes as defined by the `unicode consortium `__ - is supported in addition to a bunch of `aliases `__. By - default only the official list is enabled but doing ``emoji.emojize(use_aliases=True)`` enables - both the full list and aliases. - - .. code-block:: python - - >> import emoji - >> print(emoji.emojize('Python is :thumbs_up_sign:')) - Python is 👍 - >> print(emoji.emojize('Python is :thumbsup:', use_aliases=True)) - Python is 👍 - - - Installation - ------------ - - Via pip: - - .. code-block:: console - - $ pip install emoji --upgrade - - From master branch: - - .. code-block:: console - - $ git clone https://github.com/carpedm20/emoji.git - $ cd emoji - $ python setup.py install - - - Developing - ---------- - - .. code-block:: console - - $ git clone https://github.com/carpedm20/emoji.git - $ cd emoji - $ pip install -e .\[dev\] - $ nosetests - - The ``utils/get-codes-from-unicode-consortium.py`` may help when updating - ``unicode_codes.py`` but is not guaranteed to work. Generally speaking it - scrapes a table on the Unicode Consortium's website with - `BeautifulSoup `_ and prints the - contents to ``stdout`` in a more useful format. - - - Link - ---- - - `Emoji Cheat Sheet `__ - - `Official unicode list `__ - - - Authors - ------- - - Taehoon Kim / `@carpedm20 `__ - - Kevin Wurster / `@geowurster `__ -Keywords: emoji -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Multimedia :: Graphics :: Presentation -Classifier: Topic :: Software Development :: Libraries :: Python Modules +Metadata-Version: 1.1 +Name: emoji +Version: 0.4.5 +Summary: Emoji for Python +Home-page: https://github.com/carpedm20/emoji/ +Author: Taehoon Kim and Kevin Wurster +Author-email: carpedm20@gmail.com and wursterk@gmail.com +License: New BSD +Description: Emoji + ===== + + Emoji for Python. This project was inspired by `kyokomi `__. + + + Example + ------- + + The entire set of Emoji codes as defined by the `unicode consortium `__ + is supported in addition to a bunch of `aliases `__. By + default only the official list is enabled but doing ``emoji.emojize(use_aliases=True)`` enables + both the full list and aliases. + + .. code-block:: python + + >> import emoji + >> print(emoji.emojize('Python is :thumbs_up_sign:')) + Python is 👍 + >> print(emoji.emojize('Python is :thumbsup:', use_aliases=True)) + Python is 👍 + + + Installation + ------------ + + Via pip: + + .. code-block:: console + + $ pip install emoji --upgrade + + From master branch: + + .. code-block:: console + + $ git clone https://github.com/carpedm20/emoji.git + $ cd emoji + $ python setup.py install + + + Developing + ---------- + + .. code-block:: console + + $ git clone https://github.com/carpedm20/emoji.git + $ cd emoji + $ pip install -e .\[dev\] + $ nosetests + + The ``utils/get-codes-from-unicode-consortium.py`` may help when updating + ``unicode_codes.py`` but is not guaranteed to work. Generally speaking it + scrapes a table on the Unicode Consortium's website with + `BeautifulSoup `_ and prints the + contents to ``stdout`` in a more useful format. + + + Link + ---- + + `Emoji Cheat Sheet `__ + + `Official unicode list `__ + + + Authors + ------- + + Taehoon Kim / `@carpedm20 `__ + + Kevin Wurster / `@geowurster `__ +Keywords: emoji +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Multimedia :: Graphics :: Presentation +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/installed-files.txt index 57da17a55..09a795385 100644 --- a/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/emoji-0.4.5-py3.6.egg-info/installed-files.txt @@ -1,12 +1,12 @@ -..\emoji\core.py -..\emoji\unicode_codes.py -..\emoji\__init__.py -..\emoji\__pycache__\core.cpython-36.pyc -..\emoji\__pycache__\unicode_codes.cpython-36.pyc -..\emoji\__pycache__\__init__.cpython-36.pyc -dependency_links.txt -PKG-INFO -requires.txt -SOURCES.txt -top_level.txt -zip-safe +..\emoji\core.py +..\emoji\unicode_codes.py +..\emoji\__init__.py +..\emoji\__pycache__\core.cpython-36.pyc +..\emoji\__pycache__\unicode_codes.cpython-36.pyc +..\emoji\__pycache__\__init__.cpython-36.pyc +dependency_links.txt +PKG-INFO +requires.txt +SOURCES.txt +top_level.txt +zip-safe diff --git a/website/web/Lib/site-packages/gunicorn-19.7.1.dist-info/RECORD b/website/web/Lib/site-packages/gunicorn-19.7.1.dist-info/RECORD index 6c52af41a..c95178988 100644 --- a/website/web/Lib/site-packages/gunicorn-19.7.1.dist-info/RECORD +++ b/website/web/Lib/site-packages/gunicorn-19.7.1.dist-info/RECORD @@ -1,91 +1,91 @@ -gunicorn/__init__.py,sha256=VmHJyCtQGzIz9zMteqz5Qr4o3fa7FcbLESpc2_oJUs4,255 -gunicorn/_compat.py,sha256=IgADLDObcvKcQWExjqm4XgWNULhwigfBC7u8td-xNqQ,8719 -gunicorn/arbiter.py,sha256=z9p8_U7OSWdpauM4gVNTMde9HLSLFy8sqHetJpYg1BU,19974 -gunicorn/argparse_compat.py,sha256=gsHDGwo4BSJWHdiaEXy0Emr96NKC0LDYmK5nB7PE8Qc,87791 -gunicorn/config.py,sha256=Ue3dRcICKLLBd6kKEi_SNVY6vrPz9dLaXDCM3qtT1XU,50464 -gunicorn/debug.py,sha256=9z2i59LfELYi3VvbwyrIKezYrQuowVAsWfSLZI75TDI,2303 -gunicorn/errors.py,sha256=CNtO7hfBdqJADoEyPGME2kTW8QcxlUWmmA1NfOEJvSQ,632 -gunicorn/glogging.py,sha256=Yfhr6K-qUkPm7yWU-pBsFXMr2rz5A0X1VQXizkepIQM,14782 -gunicorn/pidfile.py,sha256=_69tsfF1aHklrMrJe2sHERovMduRByVTv99my7yQ874,2357 -gunicorn/reloader.py,sha256=IHtXLjFxQxSTmFRnc3UehBbjAkQsg2uiZA87iresCYM,3598 -gunicorn/selectors.py,sha256=14_UESrpE3AQKXWKeeAUG9vBTzJ0yTYDGtEo6xOtlDY,18997 -gunicorn/six.py,sha256=6N-6RCENPfBtMpN5UmgDfDKmJebbbuPu_Dk3Zf8ngww,27344 -gunicorn/sock.py,sha256=dgCYctz6vbQQs6NoXvcBxMCwnpHXVKQQ1R4MIE7pD0o,5985 -gunicorn/systemd.py,sha256=ffhv17cdv-hDeFAJi1eAVtJskkVciV6cQU75Q2oplqg,1362 -gunicorn/util.py,sha256=vPrXejIi4wHUdH-bhX6ditV9KnCc3cwbqeniL1I1QdM,15749 -gunicorn/app/__init__.py,sha256=GuqstqdkizeV4HRbd8aGMBn0Q8IDOyRU1wMMNqNe5GY,127 -gunicorn/app/base.py,sha256=yw8Vt8Ddvz024rYGTJG5vQW6Cs47GhwDIcsiE5jsgfo,6120 -gunicorn/app/pasterapp.py,sha256=05rRnbj_UC-vpvUoSrihe7XewtVXt7kEuHpo0ztXHW8,6124 -gunicorn/app/wsgiapp.py,sha256=he4kEYCYMOvB9X1DohXXZ7V3E7q3J--k2C1KeiyzoDo,2178 -gunicorn/http/__init__.py,sha256=b4TF3x5F0VYOPTOeNYwRGR1EYHBaPMhZRMoNeuD5-n0,277 -gunicorn/http/_sendfile.py,sha256=Eqd-s3HlvLuyfGjqaH_Jk72cAtEV8hQv5tb1M1AqcBU,2217 -gunicorn/http/body.py,sha256=SbFMqhFR_V1AKg1Bm0grZL5gmhJu2zf_8Xz2Kaj-mao,7355 -gunicorn/http/errors.py,sha256=57KmM6CA7UldH7ZfYRSF8drsh95iI5sVoTEHoQrlcSI,2446 -gunicorn/http/message.py,sha256=qUqTbGzTrGpdcez_99id0DNxiiABje4sQwfLvQMpXx8,11320 -gunicorn/http/parser.py,sha256=IRMvp0veP4wL8Z4vgNV72CPydCNPdNNIy9u-DlDvvSo,1294 -gunicorn/http/unreader.py,sha256=1D9E3QD8BBkCrJ4BvIDUdZngT4n7Q1H-X-GLqF19iT4,2024 -gunicorn/http/wsgi.py,sha256=3AuCEeD2QwsosLZf3XTCCyHHFHqzUU_6KiOY1gCFUPA,13173 -gunicorn/instrument/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -gunicorn/instrument/statsd.py,sha256=GjiYfNYwfOc8f0lhGbaF_NSxj4DI8O4RwSr6CTp7Ee0,4462 -gunicorn/workers/__init__.py,sha256=Z57G1WjnZDCG52C8PgiXF4mKRKqlv81b2GHkhOJiO6A,774 -gunicorn/workers/_gaiohttp.py,sha256=CFKiyLNqWqemhDvDovb-JqMRTMNz50gZUwwOpIjrpHw,5071 -gunicorn/workers/async.py,sha256=54VkS3S_wrFD7v3jInhFfkeBhaPnV5UN-cu-i5MoXkc,5575 -gunicorn/workers/base.py,sha256=u-Jg3bqNzQSwZdMVYWhOmOmSYZ8eTzCkyWluJyx5nq0,8842 -gunicorn/workers/gaiohttp.py,sha256=GIkR9AnyaZ8b1Pt7It35iIK6EPwe2JSUgt55u7nw9qo,500 -gunicorn/workers/geventlet.py,sha256=FWlx3tuNe5r4xzEVLo9Kq8kgI39X7ZyU7fgz94jInZY,4084 -gunicorn/workers/ggevent.py,sha256=we70lCiiyHwaW75kqM40KOsX7FKyZiRvjT2EPROKt5c,6838 -gunicorn/workers/gthread.py,sha256=fz_1hsQWhxYKpJDWi30hwnXn0HR8S_pQisKTwSxbkC4,12108 -gunicorn/workers/gtornado.py,sha256=s0wW09nLj5sWmCuTjlO6XK_r3th7l2gudMlAJ_v4CIU,4380 -gunicorn/workers/sync.py,sha256=_vd1JATNLG4MgJppNJG5KWBIzLGYqRzhEAQVz9H11LI,7153 -gunicorn/workers/workertmp.py,sha256=6QINPBrriLvezgkC_hclOOeXLi_owMt_SOA5KPEIN-A,1459 -gunicorn-19.7.1.dist-info/DESCRIPTION.rst,sha256=gCCsiCS_cxp9BYBUISH3yQgOJ7Qwf1doRlU848N7V9A,1398 -gunicorn-19.7.1.dist-info/LICENSE.txt,sha256=_RuA_evOQZ7h84E6s5Kb4vcfyQnSWRfqGGkltuDng2A,1136 -gunicorn-19.7.1.dist-info/METADATA,sha256=m6Nip9TLNboEu6VWR_dMTlhyWB-zgqJ_UipUWec5gsA,2714 -gunicorn-19.7.1.dist-info/RECORD,, -gunicorn-19.7.1.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 -gunicorn-19.7.1.dist-info/entry_points.txt,sha256=XeFINKRdSUKwJwaVSolO24PuV_YeO71IMF-rOra5JO8,184 -gunicorn-19.7.1.dist-info/metadata.json,sha256=pnwtIEmGk3PCJ2KXBlAeY48xpJqPWE8nqA5z4UUgQ0g,1747 -gunicorn-19.7.1.dist-info/top_level.txt,sha256=cdMaa2yhxb8do-WioY9qRHUCfwf55YztjwQCncaInoE,9 -../../Scripts/gunicorn.exe,sha256=Agw_UJkjn3-HlQe28HjmOE80Yxafz1ejm5HfdqviPVc,98159 -../../Scripts/gunicorn_paster.exe,sha256=zXB8gCVboTSrZ_w4tasc7SgnnQCBWZMVfmXqdnlHdSU,98161 -gunicorn-19.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -gunicorn/app/__pycache__/base.cpython-36.pyc,, -gunicorn/app/__pycache__/pasterapp.cpython-36.pyc,, -gunicorn/app/__pycache__/wsgiapp.cpython-36.pyc,, -gunicorn/app/__pycache__/__init__.cpython-36.pyc,, -gunicorn/http/__pycache__/body.cpython-36.pyc,, -gunicorn/http/__pycache__/errors.cpython-36.pyc,, -gunicorn/http/__pycache__/message.cpython-36.pyc,, -gunicorn/http/__pycache__/parser.cpython-36.pyc,, -gunicorn/http/__pycache__/unreader.cpython-36.pyc,, -gunicorn/http/__pycache__/wsgi.cpython-36.pyc,, -gunicorn/http/__pycache__/_sendfile.cpython-36.pyc,, -gunicorn/http/__pycache__/__init__.cpython-36.pyc,, -gunicorn/instrument/__pycache__/statsd.cpython-36.pyc,, -gunicorn/instrument/__pycache__/__init__.cpython-36.pyc,, -gunicorn/workers/__pycache__/async.cpython-36.pyc,, -gunicorn/workers/__pycache__/base.cpython-36.pyc,, -gunicorn/workers/__pycache__/gaiohttp.cpython-36.pyc,, -gunicorn/workers/__pycache__/geventlet.cpython-36.pyc,, -gunicorn/workers/__pycache__/ggevent.cpython-36.pyc,, -gunicorn/workers/__pycache__/gthread.cpython-36.pyc,, -gunicorn/workers/__pycache__/gtornado.cpython-36.pyc,, -gunicorn/workers/__pycache__/sync.cpython-36.pyc,, -gunicorn/workers/__pycache__/workertmp.cpython-36.pyc,, -gunicorn/workers/__pycache__/_gaiohttp.cpython-36.pyc,, -gunicorn/workers/__pycache__/__init__.cpython-36.pyc,, -gunicorn/__pycache__/arbiter.cpython-36.pyc,, -gunicorn/__pycache__/argparse_compat.cpython-36.pyc,, -gunicorn/__pycache__/config.cpython-36.pyc,, -gunicorn/__pycache__/debug.cpython-36.pyc,, -gunicorn/__pycache__/errors.cpython-36.pyc,, -gunicorn/__pycache__/glogging.cpython-36.pyc,, -gunicorn/__pycache__/pidfile.cpython-36.pyc,, -gunicorn/__pycache__/reloader.cpython-36.pyc,, -gunicorn/__pycache__/selectors.cpython-36.pyc,, -gunicorn/__pycache__/six.cpython-36.pyc,, -gunicorn/__pycache__/sock.cpython-36.pyc,, -gunicorn/__pycache__/systemd.cpython-36.pyc,, -gunicorn/__pycache__/util.cpython-36.pyc,, -gunicorn/__pycache__/_compat.cpython-36.pyc,, -gunicorn/__pycache__/__init__.cpython-36.pyc,, +gunicorn/__init__.py,sha256=VmHJyCtQGzIz9zMteqz5Qr4o3fa7FcbLESpc2_oJUs4,255 +gunicorn/_compat.py,sha256=IgADLDObcvKcQWExjqm4XgWNULhwigfBC7u8td-xNqQ,8719 +gunicorn/arbiter.py,sha256=z9p8_U7OSWdpauM4gVNTMde9HLSLFy8sqHetJpYg1BU,19974 +gunicorn/argparse_compat.py,sha256=gsHDGwo4BSJWHdiaEXy0Emr96NKC0LDYmK5nB7PE8Qc,87791 +gunicorn/config.py,sha256=Ue3dRcICKLLBd6kKEi_SNVY6vrPz9dLaXDCM3qtT1XU,50464 +gunicorn/debug.py,sha256=9z2i59LfELYi3VvbwyrIKezYrQuowVAsWfSLZI75TDI,2303 +gunicorn/errors.py,sha256=CNtO7hfBdqJADoEyPGME2kTW8QcxlUWmmA1NfOEJvSQ,632 +gunicorn/glogging.py,sha256=Yfhr6K-qUkPm7yWU-pBsFXMr2rz5A0X1VQXizkepIQM,14782 +gunicorn/pidfile.py,sha256=_69tsfF1aHklrMrJe2sHERovMduRByVTv99my7yQ874,2357 +gunicorn/reloader.py,sha256=IHtXLjFxQxSTmFRnc3UehBbjAkQsg2uiZA87iresCYM,3598 +gunicorn/selectors.py,sha256=14_UESrpE3AQKXWKeeAUG9vBTzJ0yTYDGtEo6xOtlDY,18997 +gunicorn/six.py,sha256=6N-6RCENPfBtMpN5UmgDfDKmJebbbuPu_Dk3Zf8ngww,27344 +gunicorn/sock.py,sha256=dgCYctz6vbQQs6NoXvcBxMCwnpHXVKQQ1R4MIE7pD0o,5985 +gunicorn/systemd.py,sha256=ffhv17cdv-hDeFAJi1eAVtJskkVciV6cQU75Q2oplqg,1362 +gunicorn/util.py,sha256=vPrXejIi4wHUdH-bhX6ditV9KnCc3cwbqeniL1I1QdM,15749 +gunicorn/app/__init__.py,sha256=GuqstqdkizeV4HRbd8aGMBn0Q8IDOyRU1wMMNqNe5GY,127 +gunicorn/app/base.py,sha256=yw8Vt8Ddvz024rYGTJG5vQW6Cs47GhwDIcsiE5jsgfo,6120 +gunicorn/app/pasterapp.py,sha256=05rRnbj_UC-vpvUoSrihe7XewtVXt7kEuHpo0ztXHW8,6124 +gunicorn/app/wsgiapp.py,sha256=he4kEYCYMOvB9X1DohXXZ7V3E7q3J--k2C1KeiyzoDo,2178 +gunicorn/http/__init__.py,sha256=b4TF3x5F0VYOPTOeNYwRGR1EYHBaPMhZRMoNeuD5-n0,277 +gunicorn/http/_sendfile.py,sha256=Eqd-s3HlvLuyfGjqaH_Jk72cAtEV8hQv5tb1M1AqcBU,2217 +gunicorn/http/body.py,sha256=SbFMqhFR_V1AKg1Bm0grZL5gmhJu2zf_8Xz2Kaj-mao,7355 +gunicorn/http/errors.py,sha256=57KmM6CA7UldH7ZfYRSF8drsh95iI5sVoTEHoQrlcSI,2446 +gunicorn/http/message.py,sha256=qUqTbGzTrGpdcez_99id0DNxiiABje4sQwfLvQMpXx8,11320 +gunicorn/http/parser.py,sha256=IRMvp0veP4wL8Z4vgNV72CPydCNPdNNIy9u-DlDvvSo,1294 +gunicorn/http/unreader.py,sha256=1D9E3QD8BBkCrJ4BvIDUdZngT4n7Q1H-X-GLqF19iT4,2024 +gunicorn/http/wsgi.py,sha256=3AuCEeD2QwsosLZf3XTCCyHHFHqzUU_6KiOY1gCFUPA,13173 +gunicorn/instrument/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +gunicorn/instrument/statsd.py,sha256=GjiYfNYwfOc8f0lhGbaF_NSxj4DI8O4RwSr6CTp7Ee0,4462 +gunicorn/workers/__init__.py,sha256=Z57G1WjnZDCG52C8PgiXF4mKRKqlv81b2GHkhOJiO6A,774 +gunicorn/workers/_gaiohttp.py,sha256=CFKiyLNqWqemhDvDovb-JqMRTMNz50gZUwwOpIjrpHw,5071 +gunicorn/workers/async.py,sha256=54VkS3S_wrFD7v3jInhFfkeBhaPnV5UN-cu-i5MoXkc,5575 +gunicorn/workers/base.py,sha256=u-Jg3bqNzQSwZdMVYWhOmOmSYZ8eTzCkyWluJyx5nq0,8842 +gunicorn/workers/gaiohttp.py,sha256=GIkR9AnyaZ8b1Pt7It35iIK6EPwe2JSUgt55u7nw9qo,500 +gunicorn/workers/geventlet.py,sha256=FWlx3tuNe5r4xzEVLo9Kq8kgI39X7ZyU7fgz94jInZY,4084 +gunicorn/workers/ggevent.py,sha256=we70lCiiyHwaW75kqM40KOsX7FKyZiRvjT2EPROKt5c,6838 +gunicorn/workers/gthread.py,sha256=fz_1hsQWhxYKpJDWi30hwnXn0HR8S_pQisKTwSxbkC4,12108 +gunicorn/workers/gtornado.py,sha256=s0wW09nLj5sWmCuTjlO6XK_r3th7l2gudMlAJ_v4CIU,4380 +gunicorn/workers/sync.py,sha256=_vd1JATNLG4MgJppNJG5KWBIzLGYqRzhEAQVz9H11LI,7153 +gunicorn/workers/workertmp.py,sha256=6QINPBrriLvezgkC_hclOOeXLi_owMt_SOA5KPEIN-A,1459 +gunicorn-19.7.1.dist-info/DESCRIPTION.rst,sha256=gCCsiCS_cxp9BYBUISH3yQgOJ7Qwf1doRlU848N7V9A,1398 +gunicorn-19.7.1.dist-info/LICENSE.txt,sha256=_RuA_evOQZ7h84E6s5Kb4vcfyQnSWRfqGGkltuDng2A,1136 +gunicorn-19.7.1.dist-info/METADATA,sha256=m6Nip9TLNboEu6VWR_dMTlhyWB-zgqJ_UipUWec5gsA,2714 +gunicorn-19.7.1.dist-info/RECORD,, +gunicorn-19.7.1.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +gunicorn-19.7.1.dist-info/entry_points.txt,sha256=XeFINKRdSUKwJwaVSolO24PuV_YeO71IMF-rOra5JO8,184 +gunicorn-19.7.1.dist-info/metadata.json,sha256=pnwtIEmGk3PCJ2KXBlAeY48xpJqPWE8nqA5z4UUgQ0g,1747 +gunicorn-19.7.1.dist-info/top_level.txt,sha256=cdMaa2yhxb8do-WioY9qRHUCfwf55YztjwQCncaInoE,9 +../../Scripts/gunicorn.exe,sha256=Agw_UJkjn3-HlQe28HjmOE80Yxafz1ejm5HfdqviPVc,98159 +../../Scripts/gunicorn_paster.exe,sha256=zXB8gCVboTSrZ_w4tasc7SgnnQCBWZMVfmXqdnlHdSU,98161 +gunicorn-19.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +gunicorn/app/__pycache__/base.cpython-36.pyc,, +gunicorn/app/__pycache__/pasterapp.cpython-36.pyc,, +gunicorn/app/__pycache__/wsgiapp.cpython-36.pyc,, +gunicorn/app/__pycache__/__init__.cpython-36.pyc,, +gunicorn/http/__pycache__/body.cpython-36.pyc,, +gunicorn/http/__pycache__/errors.cpython-36.pyc,, +gunicorn/http/__pycache__/message.cpython-36.pyc,, +gunicorn/http/__pycache__/parser.cpython-36.pyc,, +gunicorn/http/__pycache__/unreader.cpython-36.pyc,, +gunicorn/http/__pycache__/wsgi.cpython-36.pyc,, +gunicorn/http/__pycache__/_sendfile.cpython-36.pyc,, +gunicorn/http/__pycache__/__init__.cpython-36.pyc,, +gunicorn/instrument/__pycache__/statsd.cpython-36.pyc,, +gunicorn/instrument/__pycache__/__init__.cpython-36.pyc,, +gunicorn/workers/__pycache__/async.cpython-36.pyc,, +gunicorn/workers/__pycache__/base.cpython-36.pyc,, +gunicorn/workers/__pycache__/gaiohttp.cpython-36.pyc,, +gunicorn/workers/__pycache__/geventlet.cpython-36.pyc,, +gunicorn/workers/__pycache__/ggevent.cpython-36.pyc,, +gunicorn/workers/__pycache__/gthread.cpython-36.pyc,, +gunicorn/workers/__pycache__/gtornado.cpython-36.pyc,, +gunicorn/workers/__pycache__/sync.cpython-36.pyc,, +gunicorn/workers/__pycache__/workertmp.cpython-36.pyc,, +gunicorn/workers/__pycache__/_gaiohttp.cpython-36.pyc,, +gunicorn/workers/__pycache__/__init__.cpython-36.pyc,, +gunicorn/__pycache__/arbiter.cpython-36.pyc,, +gunicorn/__pycache__/argparse_compat.cpython-36.pyc,, +gunicorn/__pycache__/config.cpython-36.pyc,, +gunicorn/__pycache__/debug.cpython-36.pyc,, +gunicorn/__pycache__/errors.cpython-36.pyc,, +gunicorn/__pycache__/glogging.cpython-36.pyc,, +gunicorn/__pycache__/pidfile.cpython-36.pyc,, +gunicorn/__pycache__/reloader.cpython-36.pyc,, +gunicorn/__pycache__/selectors.cpython-36.pyc,, +gunicorn/__pycache__/six.cpython-36.pyc,, +gunicorn/__pycache__/sock.cpython-36.pyc,, +gunicorn/__pycache__/systemd.cpython-36.pyc,, +gunicorn/__pycache__/util.cpython-36.pyc,, +gunicorn/__pycache__/_compat.cpython-36.pyc,, +gunicorn/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/PKG-INFO index 7c3e4d779..e94d55db6 100644 --- a/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/PKG-INFO @@ -1,63 +1,63 @@ -Metadata-Version: 1.1 -Name: httplib2 -Version: 0.10.3 -Summary: A comprehensive HTTP client library. -Home-page: https://github.com/httplib2/httplib2 -Author: Joe Gregorio -Author-email: joe@bitworking.org -License: MIT -Description: - - A comprehensive HTTP client library, ``httplib2`` supports many features left out of other HTTP libraries. - - **HTTP and HTTPS** - HTTPS support is only available if the socket module was compiled with SSL support. - - - **Keep-Alive** - Supports HTTP 1.1 Keep-Alive, keeping the socket open and performing multiple requests over the same connection if possible. - - - **Authentication** - The following three types of HTTP Authentication are supported. These can be used over both HTTP and HTTPS. - - * Digest - * Basic - * WSSE - - **Caching** - The module can optionally operate with a private cache that understands the Cache-Control: - header and uses both the ETag and Last-Modified cache validators. Both file system - and memcached based caches are supported. - - - **All Methods** - The module can handle any HTTP request method, not just GET and POST. - - - **Redirects** - Automatically follows 3XX redirects on GETs. - - - **Compression** - Handles both 'deflate' and 'gzip' types of compression. - - - **Lost update support** - Automatically adds back ETags into PUT requests to resources we have already cached. This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout - - - **Unit Tested** - A large and growing set of unit tests. - - -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Topic :: Software Development :: Libraries +Metadata-Version: 1.1 +Name: httplib2 +Version: 0.10.3 +Summary: A comprehensive HTTP client library. +Home-page: https://github.com/httplib2/httplib2 +Author: Joe Gregorio +Author-email: joe@bitworking.org +License: MIT +Description: + + A comprehensive HTTP client library, ``httplib2`` supports many features left out of other HTTP libraries. + + **HTTP and HTTPS** + HTTPS support is only available if the socket module was compiled with SSL support. + + + **Keep-Alive** + Supports HTTP 1.1 Keep-Alive, keeping the socket open and performing multiple requests over the same connection if possible. + + + **Authentication** + The following three types of HTTP Authentication are supported. These can be used over both HTTP and HTTPS. + + * Digest + * Basic + * WSSE + + **Caching** + The module can optionally operate with a private cache that understands the Cache-Control: + header and uses both the ETag and Last-Modified cache validators. Both file system + and memcached based caches are supported. + + + **All Methods** + The module can handle any HTTP request method, not just GET and POST. + + + **Redirects** + Automatically follows 3XX redirects on GETs. + + + **Compression** + Handles both 'deflate' and 'gzip' types of compression. + + + **Lost update support** + Automatically adds back ETags into PUT requests to resources we have already cached. This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout + + + **Unit Tested** + A large and growing set of unit tests. + + +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Software Development :: Libraries diff --git a/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/installed-files.txt index cd83fba2e..0351c52a6 100644 --- a/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/httplib2-0.10.3-py3.6.egg-info/installed-files.txt @@ -1,9 +1,9 @@ -..\httplib2\iri2uri.py -..\httplib2\__init__.py -..\httplib2\cacerts.txt -..\httplib2\__pycache__\iri2uri.cpython-36.pyc -..\httplib2\__pycache__\__init__.cpython-36.pyc -dependency_links.txt -PKG-INFO -SOURCES.txt -top_level.txt +..\httplib2\iri2uri.py +..\httplib2\__init__.py +..\httplib2\cacerts.txt +..\httplib2\__pycache__\iri2uri.cpython-36.pyc +..\httplib2\__pycache__\__init__.cpython-36.pyc +dependency_links.txt +PKG-INFO +SOURCES.txt +top_level.txt diff --git a/website/web/Lib/site-packages/httplib2/iri2uri.py b/website/web/Lib/site-packages/httplib2/iri2uri.py index 711377c0f..98985f846 100644 --- a/website/web/Lib/site-packages/httplib2/iri2uri.py +++ b/website/web/Lib/site-packages/httplib2/iri2uri.py @@ -1,110 +1,110 @@ -""" -iri2uri - -Converts an IRI to a URI. - -""" -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = [] -__version__ = "1.0.0" -__license__ = "MIT" -__history__ = """ -""" - -import urllib.parse - - -# Convert an IRI to a URI following the rules in RFC 3987 -# -# The characters we need to enocde and escape are defined in the spec: -# -# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD -# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF -# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD -# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD -# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD -# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD -# / %xD0000-DFFFD / %xE1000-EFFFD - -escape_range = [ - (0xA0, 0xD7FF), - (0xE000, 0xF8FF), - (0xF900, 0xFDCF), - (0xFDF0, 0xFFEF), - (0x10000, 0x1FFFD), - (0x20000, 0x2FFFD), - (0x30000, 0x3FFFD), - (0x40000, 0x4FFFD), - (0x50000, 0x5FFFD), - (0x60000, 0x6FFFD), - (0x70000, 0x7FFFD), - (0x80000, 0x8FFFD), - (0x90000, 0x9FFFD), - (0xA0000, 0xAFFFD), - (0xB0000, 0xBFFFD), - (0xC0000, 0xCFFFD), - (0xD0000, 0xDFFFD), - (0xE1000, 0xEFFFD), - (0xF0000, 0xFFFFD), - (0x100000, 0x10FFFD), -] - -def encode(c): - retval = c - i = ord(c) - for low, high in escape_range: - if i < low: - break - if i >= low and i <= high: - retval = "".join(["%%%2X" % o for o in c.encode('utf-8')]) - break - return retval - - -def iri2uri(uri): - """Convert an IRI to a URI. Note that IRIs must be - passed in a unicode strings. That is, do not utf-8 encode - the IRI before passing it into the function.""" - if isinstance(uri ,str): - (scheme, authority, path, query, fragment) = urllib.parse.urlsplit(uri) - authority = authority.encode('idna').decode('utf-8') - # For each character in 'ucschar' or 'iprivate' - # 1. encode as utf-8 - # 2. then %-encode each octet of that utf-8 - uri = urllib.parse.urlunsplit((scheme, authority, path, query, fragment)) - uri = "".join([encode(c) for c in uri]) - return uri - -if __name__ == "__main__": - import unittest - - class Test(unittest.TestCase): - - def test_uris(self): - """Test that URIs are invariant under the transformation.""" - invariant = [ - "ftp://ftp.is.co.za/rfc/rfc1808.txt", - "http://www.ietf.org/rfc/rfc2396.txt", - "ldap://[2001:db8::7]/c=GB?objectClass?one", - "mailto:John.Doe@example.com", - "news:comp.infosystems.www.servers.unix", - "tel:+1-816-555-1212", - "telnet://192.0.2.16:80/", - "urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] - for uri in invariant: - self.assertEqual(uri, iri2uri(uri)) - - def test_iri(self): - """ Test that the right type of escaping is done for each part of the URI.""" - self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri("http://\N{COMET}.com/\N{COMET}")) - self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri("http://bitworking.org/?fred=\N{COMET}")) - self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri("http://bitworking.org/#\N{COMET}")) - self.assertEqual("#%E2%98%84", iri2uri("#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) - self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) - - unittest.main() - - +""" +iri2uri + +Converts an IRI to a URI. + +""" +__author__ = "Joe Gregorio (joe@bitworking.org)" +__copyright__ = "Copyright 2006, Joe Gregorio" +__contributors__ = [] +__version__ = "1.0.0" +__license__ = "MIT" +__history__ = """ +""" + +import urllib.parse + + +# Convert an IRI to a URI following the rules in RFC 3987 +# +# The characters we need to enocde and escape are defined in the spec: +# +# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD +# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF +# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD +# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD +# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD +# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD +# / %xD0000-DFFFD / %xE1000-EFFFD + +escape_range = [ + (0xA0, 0xD7FF), + (0xE000, 0xF8FF), + (0xF900, 0xFDCF), + (0xFDF0, 0xFFEF), + (0x10000, 0x1FFFD), + (0x20000, 0x2FFFD), + (0x30000, 0x3FFFD), + (0x40000, 0x4FFFD), + (0x50000, 0x5FFFD), + (0x60000, 0x6FFFD), + (0x70000, 0x7FFFD), + (0x80000, 0x8FFFD), + (0x90000, 0x9FFFD), + (0xA0000, 0xAFFFD), + (0xB0000, 0xBFFFD), + (0xC0000, 0xCFFFD), + (0xD0000, 0xDFFFD), + (0xE1000, 0xEFFFD), + (0xF0000, 0xFFFFD), + (0x100000, 0x10FFFD), +] + +def encode(c): + retval = c + i = ord(c) + for low, high in escape_range: + if i < low: + break + if i >= low and i <= high: + retval = "".join(["%%%2X" % o for o in c.encode('utf-8')]) + break + return retval + + +def iri2uri(uri): + """Convert an IRI to a URI. Note that IRIs must be + passed in a unicode strings. That is, do not utf-8 encode + the IRI before passing it into the function.""" + if isinstance(uri ,str): + (scheme, authority, path, query, fragment) = urllib.parse.urlsplit(uri) + authority = authority.encode('idna').decode('utf-8') + # For each character in 'ucschar' or 'iprivate' + # 1. encode as utf-8 + # 2. then %-encode each octet of that utf-8 + uri = urllib.parse.urlunsplit((scheme, authority, path, query, fragment)) + uri = "".join([encode(c) for c in uri]) + return uri + +if __name__ == "__main__": + import unittest + + class Test(unittest.TestCase): + + def test_uris(self): + """Test that URIs are invariant under the transformation.""" + invariant = [ + "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "http://www.ietf.org/rfc/rfc2396.txt", + "ldap://[2001:db8::7]/c=GB?objectClass?one", + "mailto:John.Doe@example.com", + "news:comp.infosystems.www.servers.unix", + "tel:+1-816-555-1212", + "telnet://192.0.2.16:80/", + "urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] + for uri in invariant: + self.assertEqual(uri, iri2uri(uri)) + + def test_iri(self): + """ Test that the right type of escaping is done for each part of the URI.""" + self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri("http://\N{COMET}.com/\N{COMET}")) + self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri("http://bitworking.org/?fred=\N{COMET}")) + self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri("http://bitworking.org/#\N{COMET}")) + self.assertEqual("#%E2%98%84", iri2uri("#\N{COMET}")) + self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) + self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) + self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) + + unittest.main() + + diff --git a/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/PKG-INFO index c46c6623c..b0d59f7db 100644 --- a/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/PKG-INFO @@ -1,13 +1,13 @@ -Metadata-Version: 1.1 -Name: itsdangerous -Version: 0.24 -Summary: Various helpers to pass trusted data to untrusted environments and back. -Home-page: http://github.com/mitsuhiko/itsdangerous -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN -Classifier: License :: OSI Approved :: BSD License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 +Metadata-Version: 1.1 +Name: itsdangerous +Version: 0.24 +Summary: Various helpers to pass trusted data to untrusted environments and back. +Home-page: http://github.com/mitsuhiko/itsdangerous +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 diff --git a/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/installed-files.txt index 8c277b821..3f6b765c1 100644 --- a/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/itsdangerous-0.24-py3.6.egg-info/installed-files.txt @@ -1,7 +1,7 @@ -..\itsdangerous.py -..\__pycache__\itsdangerous.cpython-36.pyc -dependency_links.txt -not-zip-safe -PKG-INFO -SOURCES.txt -top_level.txt +..\itsdangerous.py +..\__pycache__\itsdangerous.cpython-36.pyc +dependency_links.txt +not-zip-safe +PKG-INFO +SOURCES.txt +top_level.txt diff --git a/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/PKG-INFO index b9548af20..eb73b225e 100644 --- a/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/PKG-INFO @@ -1,80 +1,80 @@ -Metadata-Version: 1.1 -Name: misaka -Version: 2.1.0 -Summary: A CFFI binding for Hoedown, a markdown parsing library. -Home-page: https://github.com/FSX/misaka -Author: Frank Smit -Author-email: frank@61924.nl -License: MIT -Description: Misaka - ====== - - .. image:: https://img.shields.io/pypi/v/misaka.svg - :target: https://pypi.python.org/pypi/misaka - - .. image:: https://img.shields.io/pypi/dm/misaka.svg - :target: https://pypi.python.org/pypi/misaka - - .. image:: https://img.shields.io/travis/FSX/misaka.svg - :target: https://travis-ci.org/FSX/misaka - - A CFFI binding for Hoedown_ (version 3), a markdown parsing library. - - Documentation can be found at: http://misaka.61924.nl/ - - .. _Hoedown: https://github.com/hoedown/hoedown - - - Installation - ------------ - - Misaka has been tested on CPython 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6. It needs - CFFI 1.0 or newer, because of this it will not work on PyPy 2.5 and older. - - With pip:: - - pip install misaka - - Or manually:: - - python setup.py install - - - Example - ------- - - Very simple example: - - .. code:: python - - import misaka as m - print m.html('some other text') - - Or: - - .. code:: python - - from misaka import Markdown, HtmlRenderer - - rndr = HtmlRenderer() - md = Markdown(rndr) - - print(md('some text')) - -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: C -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Text Processing :: Markup -Classifier: Topic :: Text Processing :: Markup :: HTML -Classifier: Topic :: Utilities +Metadata-Version: 1.1 +Name: misaka +Version: 2.1.0 +Summary: A CFFI binding for Hoedown, a markdown parsing library. +Home-page: https://github.com/FSX/misaka +Author: Frank Smit +Author-email: frank@61924.nl +License: MIT +Description: Misaka + ====== + + .. image:: https://img.shields.io/pypi/v/misaka.svg + :target: https://pypi.python.org/pypi/misaka + + .. image:: https://img.shields.io/pypi/dm/misaka.svg + :target: https://pypi.python.org/pypi/misaka + + .. image:: https://img.shields.io/travis/FSX/misaka.svg + :target: https://travis-ci.org/FSX/misaka + + A CFFI binding for Hoedown_ (version 3), a markdown parsing library. + + Documentation can be found at: http://misaka.61924.nl/ + + .. _Hoedown: https://github.com/hoedown/hoedown + + + Installation + ------------ + + Misaka has been tested on CPython 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6. It needs + CFFI 1.0 or newer, because of this it will not work on PyPy 2.5 and older. + + With pip:: + + pip install misaka + + Or manually:: + + python setup.py install + + + Example + ------- + + Very simple example: + + .. code:: python + + import misaka as m + print m.html('some other text') + + Or: + + .. code:: python + + from misaka import Markdown, HtmlRenderer + + rndr = HtmlRenderer() + md = Markdown(rndr) + + print(md('some text')) + +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: C +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Text Processing :: Markup +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Topic :: Utilities diff --git a/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/installed-files.txt index 5af9f660e..5318748d6 100644 --- a/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/misaka-2.1.0-py3.6.egg-info/installed-files.txt @@ -1,17 +1,17 @@ -..\misaka\api.py -..\misaka\callbacks.py -..\misaka\constants.py -..\misaka\utils.py -..\misaka\__init__.py -..\misaka\__pycache__\api.cpython-36.pyc -..\misaka\__pycache__\callbacks.cpython-36.pyc -..\misaka\__pycache__\constants.cpython-36.pyc -..\misaka\__pycache__\utils.cpython-36.pyc -..\misaka\__pycache__\__init__.cpython-36.pyc -..\misaka\_hoedown.cp36-win_amd64.pyd -dependency_links.txt -PKG-INFO -requires.txt -SOURCES.txt -top_level.txt -..\..\..\Scripts\misaka +..\misaka\api.py +..\misaka\callbacks.py +..\misaka\constants.py +..\misaka\utils.py +..\misaka\__init__.py +..\misaka\__pycache__\api.cpython-36.pyc +..\misaka\__pycache__\callbacks.cpython-36.pyc +..\misaka\__pycache__\constants.cpython-36.pyc +..\misaka\__pycache__\utils.cpython-36.pyc +..\misaka\__pycache__\__init__.cpython-36.pyc +..\misaka\_hoedown.cp36-win_amd64.pyd +dependency_links.txt +PKG-INFO +requires.txt +SOURCES.txt +top_level.txt +..\..\..\Scripts\misaka diff --git a/website/web/Lib/site-packages/mistune-0.8.3.dist-info/RECORD b/website/web/Lib/site-packages/mistune-0.8.3.dist-info/RECORD index e53cfef3b..4ff8dc032 100644 --- a/website/web/Lib/site-packages/mistune-0.8.3.dist-info/RECORD +++ b/website/web/Lib/site-packages/mistune-0.8.3.dist-info/RECORD @@ -1,9 +1,9 @@ -mistune.py,sha256=1CU_A107jEtx78PjEtq6c4ZHtKdDonRSJODPtwIReVc,35484 -mistune-0.8.3.dist-info/DESCRIPTION.rst,sha256=LXWyD6Z969DW5qPJD4-qHY5oWDYyCxHNXJ2vG38fkEM,7429 -mistune-0.8.3.dist-info/METADATA,sha256=OnZC85NWWVxlA7nUM4n9v1nvrvRJeNrv7ka48UTJBy4,8424 -mistune-0.8.3.dist-info/RECORD,, -mistune-0.8.3.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110 -mistune-0.8.3.dist-info/metadata.json,sha256=tDAIopDKqeftHxW4qCwuZFOiiiL1qaLzTI0QAimIHO4,1143 -mistune-0.8.3.dist-info/top_level.txt,sha256=tjJTM65kAdwKAJ2mA769tnDGYYlfR8pqRsobKjVEfcg,8 -mistune-0.8.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -__pycache__/mistune.cpython-36.pyc,, +mistune.py,sha256=1CU_A107jEtx78PjEtq6c4ZHtKdDonRSJODPtwIReVc,35484 +mistune-0.8.3.dist-info/DESCRIPTION.rst,sha256=LXWyD6Z969DW5qPJD4-qHY5oWDYyCxHNXJ2vG38fkEM,7429 +mistune-0.8.3.dist-info/METADATA,sha256=OnZC85NWWVxlA7nUM4n9v1nvrvRJeNrv7ka48UTJBy4,8424 +mistune-0.8.3.dist-info/RECORD,, +mistune-0.8.3.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110 +mistune-0.8.3.dist-info/metadata.json,sha256=tDAIopDKqeftHxW4qCwuZFOiiiL1qaLzTI0QAimIHO4,1143 +mistune-0.8.3.dist-info/top_level.txt,sha256=tjJTM65kAdwKAJ2mA769tnDGYYlfR8pqRsobKjVEfcg,8 +mistune-0.8.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +__pycache__/mistune.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/oauth2-1.9.0.post1.dist-info/RECORD b/website/web/Lib/site-packages/oauth2-1.9.0.post1.dist-info/RECORD index 055f940f5..2aaa0e340 100644 --- a/website/web/Lib/site-packages/oauth2-1.9.0.post1.dist-info/RECORD +++ b/website/web/Lib/site-packages/oauth2-1.9.0.post1.dist-info/RECORD @@ -1,24 +1,24 @@ -oauth2/__init__.py,sha256=DxJ4YTfZ9XCQMh3-A3Zh0V69fFFFBaTsYAt8kpHooqE,29729 -oauth2/_compat.py,sha256=wpUO9GeOrsVHTC76Mi8p0aJ5Yqo7VkR5jvRt_QM5-u8,1434 -oauth2/_version.py,sha256=1HZjwFhqb8hgqQgaJOYJWBCbN3ZzWMqZoS6Zyjr3d2Q,482 -oauth2/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -oauth2/clients/imap.py,sha256=QDs1eTgihbnLZbrtTha7SIJjCz0YLDPCv739Jh5P-8w,1685 -oauth2/clients/smtp.py,sha256=uBP2F2Wd437sQNM6zEOKbwgjyMBVvy3A5e6UmID6VKI,1680 -oauth2-1.9.0.post1.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 -oauth2-1.9.0.post1.dist-info/METADATA,sha256=quJ9-Fv7dgNRc6e4IqyaTe_0oThuNXnMASpDdWkt9vI,846 -oauth2-1.9.0.post1.dist-info/metadata.json,sha256=d6c2-KFOi2StY-06wtCj1jxux1kkJ7dM3fNTHhV128A,1038 -oauth2-1.9.0.post1.dist-info/RECORD,, -oauth2-1.9.0.post1.dist-info/top_level.txt,sha256=KVK4-5idrV0LQsjpZgNoeKX2LJOKBG0DCDUUT1Xtog0,13 -oauth2-1.9.0.post1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 -oauth2-1.9.0.post1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 -tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -tests/test_oauth.py,sha256=o51AMNepXmA_Cue7HG4oVPw9ThDEsW3ioDRSvHKKuLo,64525 -oauth2-1.9.0.post1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -oauth2/clients/__pycache__/imap.cpython-36.pyc,, -oauth2/clients/__pycache__/smtp.cpython-36.pyc,, -oauth2/clients/__pycache__/__init__.cpython-36.pyc,, -oauth2/__pycache__/_compat.cpython-36.pyc,, -oauth2/__pycache__/_version.cpython-36.pyc,, -oauth2/__pycache__/__init__.cpython-36.pyc,, -tests/__pycache__/test_oauth.cpython-36.pyc,, -tests/__pycache__/__init__.cpython-36.pyc,, +oauth2/__init__.py,sha256=DxJ4YTfZ9XCQMh3-A3Zh0V69fFFFBaTsYAt8kpHooqE,29729 +oauth2/_compat.py,sha256=wpUO9GeOrsVHTC76Mi8p0aJ5Yqo7VkR5jvRt_QM5-u8,1434 +oauth2/_version.py,sha256=1HZjwFhqb8hgqQgaJOYJWBCbN3ZzWMqZoS6Zyjr3d2Q,482 +oauth2/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +oauth2/clients/imap.py,sha256=QDs1eTgihbnLZbrtTha7SIJjCz0YLDPCv739Jh5P-8w,1685 +oauth2/clients/smtp.py,sha256=uBP2F2Wd437sQNM6zEOKbwgjyMBVvy3A5e6UmID6VKI,1680 +oauth2-1.9.0.post1.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 +oauth2-1.9.0.post1.dist-info/METADATA,sha256=quJ9-Fv7dgNRc6e4IqyaTe_0oThuNXnMASpDdWkt9vI,846 +oauth2-1.9.0.post1.dist-info/metadata.json,sha256=d6c2-KFOi2StY-06wtCj1jxux1kkJ7dM3fNTHhV128A,1038 +oauth2-1.9.0.post1.dist-info/RECORD,, +oauth2-1.9.0.post1.dist-info/top_level.txt,sha256=KVK4-5idrV0LQsjpZgNoeKX2LJOKBG0DCDUUT1Xtog0,13 +oauth2-1.9.0.post1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 +oauth2-1.9.0.post1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +tests/test_oauth.py,sha256=o51AMNepXmA_Cue7HG4oVPw9ThDEsW3ioDRSvHKKuLo,64525 +oauth2-1.9.0.post1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +oauth2/clients/__pycache__/imap.cpython-36.pyc,, +oauth2/clients/__pycache__/smtp.cpython-36.pyc,, +oauth2/clients/__pycache__/__init__.cpython-36.pyc,, +oauth2/__pycache__/_compat.cpython-36.pyc,, +oauth2/__pycache__/_version.cpython-36.pyc,, +oauth2/__pycache__/__init__.cpython-36.pyc,, +tests/__pycache__/test_oauth.cpython-36.pyc,, +tests/__pycache__/__init__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/pip-9.0.1.dist-info/RECORD b/website/web/Lib/site-packages/pip-9.0.1.dist-info/RECORD index 7a7a33ee6..d8a93e7a7 100644 --- a/website/web/Lib/site-packages/pip-9.0.1.dist-info/RECORD +++ b/website/web/Lib/site-packages/pip-9.0.1.dist-info/RECORD @@ -1,501 +1,501 @@ -pip/__init__.py,sha256=00QWSreEBjb8Y8sPs8HeqgLXSB-3UrONJxo4J5APxEc,11348 -pip/__main__.py,sha256=V6Kh-IEDEFpt1cahRE6MajUF_14qJR_Qsvn4MjWZXzE,584 -pip/basecommand.py,sha256=TTlmZesQ4Vuxcto2KqwZGmgmN5ioHEl_DeFev9ie_SA,11910 -pip/baseparser.py,sha256=AKMOeF3fTrRroiv0DmTQbdiLW0DQux2KqGC_dJJB9d0,10465 -pip/cmdoptions.py,sha256=8JCcF2kKAF2cFnV77oW-3DsHJifr9jF2WuChzzwgcwg,16474 -pip/download.py,sha256=rA0wbmqC2n9ejX481YJSidmKgQqQDjdaxkHkHlAN68k,32171 -pip/exceptions.py,sha256=BvqH-Jw3tP2b-2IJ2kjrQemOAPMqKrQMLRIZHZQpJXk,8121 -pip/index.py,sha256=L6UhtAEZc2qw7BqfQrkPQcw2gCgEw3GukLRSA95BNyI,39950 -pip/locations.py,sha256=9rJRlgonC6QC2zGDIn_7mXaoZ9_tF_IHM2BQhWVRgbo,5626 -pip/pep425tags.py,sha256=q3kec4f6NHszuGYIhGIbVvs896D06uJAnKFgJ_wce44,10980 -pip/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 -pip/wheel.py,sha256=QSWmGs2ui-n4UMWm0JUY6aMCcwNKungVzbWsxI9KlJQ,32010 -pip/_vendor/__init__.py,sha256=WaaSJ3roSSJ_Uv4yKAxlGohKEH9YUA3aIh1Xg2IjfgU,4670 -pip/_vendor/appdirs.py,sha256=-9UOIZy62ahCQVY9-b7Nn6_5_4Y6ooHnv72tM8iHi9Y,22368 -pip/_vendor/distro.py,sha256=A4Douw9pcqdYxDTp5b-OR02fxVXnfWs-wC1wA89rhRk,38349 -pip/_vendor/ipaddress.py,sha256=wimbqcE7rwwETlucn8A_4Qd_-NKXPOBcNxJHarUoXng,80176 -pip/_vendor/ordereddict.py,sha256=4KsFuc6V8IgHROCHUu-4vCrr21ZPPea7Z0cvX9AjQ7w,4094 -pip/_vendor/pyparsing.py,sha256=7vAuUVbh6txUKQR2IzJ8_9DKmD5vtm5MDssWkI0ka8o,224171 -pip/_vendor/re-vendor.py,sha256=PcdZ40d0ohMsdJmA4t0AeAWbPXi1tFsvAwA5KE5FGeY,773 -pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 -pip/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -pip/_vendor/cachecontrol/__init__.py,sha256=UPyFlz0dIjxusu5ITig9UDFJdSY5LTwijhldn0AfyzU,302 -pip/_vendor/cachecontrol/_cmd.py,sha256=MPxZfZd2LKDzVrs55X3wA1rsI2YuP8evLZSwQj0dIk0,1320 -pip/_vendor/cachecontrol/adapter.py,sha256=RaGYyRA-RA1J0AnE67GzEYFPBu4YH4EQUvQqTKa57iM,4608 -pip/_vendor/cachecontrol/cache.py,sha256=xtl-V-pr9KSt9VvFDRCB9yrHPEvqvbk-5M1vAInZb5k,790 -pip/_vendor/cachecontrol/compat.py,sha256=uyovOpd1ehI3J1XeBqJvcsIp6fvkjBpoQmu_0J2st8c,416 -pip/_vendor/cachecontrol/controller.py,sha256=elDsLcaYA15ncodRmHnWQp6ekU_ocEGtDeGLbsnTjzo,13024 -pip/_vendor/cachecontrol/filewrapper.py,sha256=_K8cStmXqD33m15PfsQ8rlpo6FfXjVbKmjvLXyICRgI,2531 -pip/_vendor/cachecontrol/heuristics.py,sha256=WtJrVsyWjpP9WoUiDVdTZZRNBCz5ZVptaQpYnqofDQU,4141 -pip/_vendor/cachecontrol/serialize.py,sha256=XM6elG9DSNexwaOCgMjUtfrHHW5NAB6TSbIf3x235xs,6536 -pip/_vendor/cachecontrol/wrapper.py,sha256=Kqyu_3TW_54XDudha4-HF21vyEOAJ4ZnRXFysTiLmXA,498 -pip/_vendor/cachecontrol/caches/__init__.py,sha256=uWnUtyMvHY_LULaL_4_IR1F_xPgK5zHfJyRnBq4DnPE,369 -pip/_vendor/cachecontrol/caches/file_cache.py,sha256=FsDug3bwUAQ3okjjfGzxlDaBf2fwVSn1iBKMTL6SyGU,3532 -pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=XywqxkS9MkCaflTOY_wjrE02neKdywB9YwlOBbP7Ywc,973 -pip/_vendor/colorama/__init__.py,sha256=9xByrTvk9upkL5NGV5It2Eje4-kzNLwa_1lGPWpXoNU,240 -pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 -pip/_vendor/colorama/ansitowin32.py,sha256=gJZB35Lbdjatykd2zrUUnokMzkvcFgscyn_tNxxMFHA,9668 -pip/_vendor/colorama/initialise.py,sha256=cHqVJtb82OG7HUCxvQ2joG7N_CoxbIKbI_fgryZkj20,1917 -pip/_vendor/colorama/win32.py,sha256=_SCEoTK_GA2tU1nhbayKKac-v9Jn98lCPIFOeFMGCHQ,5365 -pip/_vendor/colorama/winterm.py,sha256=V7U7ojwG1q4n6PKripjEvW_htYQi5ueXSM3LUUoqqDY,6290 -pip/_vendor/distlib/__init__.py,sha256=-aUeNNCfiIG_1Tqf19BH0xLNuBKGX1I7lNhcLYgFUEA,581 -pip/_vendor/distlib/compat.py,sha256=FzKlP9dNUMH-j_1LCVnjgx6KgUbpnRjTjYkTkDYRPlI,40801 -pip/_vendor/distlib/database.py,sha256=jniJmYk0Mj2t6gZYbnn68TvQwnVZ0kXyeuf_3AxFclk,49672 -pip/_vendor/distlib/index.py,sha256=Cw8gxFq_7xXvdgExL3efjLAY3EAPDMSL3VA42RkbQBs,21085 -pip/_vendor/distlib/locators.py,sha256=hD_Hm3aSL9DklY9Cxyct2n_74gZ0xNFFGB5L7M6ds14,51013 -pip/_vendor/distlib/manifest.py,sha256=3qEuZhHlDbvyYZ1BZbdapDAivgMgUwWpZ00cmXqcn18,14810 -pip/_vendor/distlib/markers.py,sha256=iRrVWwpyVwjkKJSX8NEQ92_MRMwpROcfNGKCD-Ch1QM,6282 -pip/_vendor/distlib/metadata.py,sha256=hUsf7Qh2Ae4CCkL33qK8ppwC8ZTzT7ep6Hj9RKpijKU,38833 -pip/_vendor/distlib/resources.py,sha256=VFBVbFqLVqDBSQDXcFQHrX1KEcuoDxTK699Ydi_beyc,10766 -pip/_vendor/distlib/scripts.py,sha256=xpehNfISGPTNxQZu02K9Rw2QbNx_2Q4emePv3W5X0iw,15224 -pip/_vendor/distlib/t32.exe,sha256=cp0UAUDDr1tGAx8adlKxWbCHIa-oB3bxev5zYzgAr8E,89088 -pip/_vendor/distlib/t64.exe,sha256=FiljDPcX9qvoe9FYE_9pNEHqbqMnhcCOuI_oLJ4F9F8,97792 -pip/_vendor/distlib/util.py,sha256=E2wU-RZShPMFUMJr9kPmemTULinM4qDzosNPihCuKE0,52991 -pip/_vendor/distlib/version.py,sha256=CgghOUylxGD7dEA2S3MvWjx7mY_2bWsluF0Of3Yxl4Y,23711 -pip/_vendor/distlib/w32.exe,sha256=LItrBJesEqt2QTQuB-yha2YbMegURHmHmdSxhjBqmnc,85504 -pip/_vendor/distlib/w64.exe,sha256=n_PioBC7ltz7sAk1WLbLzZJgS4R2axSy_0HPf8ZCsEg,94208 -pip/_vendor/distlib/wheel.py,sha256=UP53cKxOM5r7bHSS-n5prF6hwJEVsMW9ZNJutOuC26c,39115 -pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 -pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 -pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 -pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 -pip/_vendor/distlib/_backport/sysconfig.py,sha256=eSEyJg7jxF_eHlHG8IOtl93kb07UoMIRp1wYsPeGi9k,26955 -pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 -pip/_vendor/html5lib/__init__.py,sha256=JsIwmFldk-9raBadPSTS74JrfmJvozc-3aekMi7Hr9s,780 -pip/_vendor/html5lib/_ihatexml.py,sha256=tzXygYmisUmiEUt2v7E1Ab50AKQsrD-SglPRnY75vME,16705 -pip/_vendor/html5lib/_inputstream.py,sha256=C4lX5gUBwebOWy41hYP2ZBpkPVNvxk_hZBm3OVyPZM4,32532 -pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 -pip/_vendor/html5lib/_utils.py,sha256=bS6THVlL8ZyTcI6CIxiM6xxuHsE8i1j5Ogd3Ha1G84U,4096 -pip/_vendor/html5lib/constants.py,sha256=Dfc1Fv3_9frktgWjg4tbj-CjMMp02Ko9qMe4il1BVdo,83387 -pip/_vendor/html5lib/html5parser.py,sha256=Dmlu9hlq5w_id6mBZyY_sE5LukIACgvG4kpgIsded8Q,117170 -pip/_vendor/html5lib/serializer.py,sha256=Urrsa0cPPLqNX-UbJWS2gUhs_06qVbNxZvUnrmGZK6E,14177 -pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 -pip/_vendor/html5lib/_trie/_base.py,sha256=6P_AcIoGjtwB2qAlhV8H4VP-ztQxoXFGwt4NyMqG_Kw,979 -pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 -pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 -pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=DXv-P2vdQ5F3OTWM6QZ6KhyDlAWm90pbfrD1Bk9D_l0,621 -pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 -pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=2Q_JnMscn_tNbV_qpgYN_5M3PnBGfmuvECMKDExHUcY,2742 -pip/_vendor/html5lib/filters/lint.py,sha256=qf5cLrT6xXd8V7GH1R_3lKxIjuJSfpbWTpSwaglYdDw,3365 -pip/_vendor/html5lib/filters/optionaltags.py,sha256=EHig4kM-QiLjuxVJ3FAAFNy-10k4aV6HJbQzHKZ_3u8,10534 -pip/_vendor/html5lib/filters/sanitizer.py,sha256=7PqJrhm6mo3JvaHk2IQW7i74Or7Qtd-FV8UftJIyDys,25112 -pip/_vendor/html5lib/filters/whitespace.py,sha256=KPt067nYTqqi8KLTClyynn4eVzNDC_-MApXNVHRXVX0,1139 -pip/_vendor/html5lib/treeadapters/__init__.py,sha256=l3LcqMSEyoh99Jh_eWjGexHnIvKhLAXoP-LDz88whuM,208 -pip/_vendor/html5lib/treeadapters/genshi.py,sha256=6VIuHDNoExv1JWv3ePj6V5CM-tcyiUSWe5_Hd2ejbwY,1555 -pip/_vendor/html5lib/treeadapters/sax.py,sha256=3of4vvaUYIAic7pngebwJV24hpOS7Zg9ggJa_WQegy4,1661 -pip/_vendor/html5lib/treebuilders/__init__.py,sha256=UlB4orkTgZhFIKQdXrtiWn9cpKSsuhnOQOIHeD0Fv4k,3406 -pip/_vendor/html5lib/treebuilders/base.py,sha256=4vdjm_Z2f_GTQBwKnWlrzVcctTb-K5sfN8pXDaWODiA,13942 -pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 -pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 -pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=CEgwHMIQZvIDFAqct4kqPkVtyKIm9efHFq_VeExEPCA,14161 -pip/_vendor/html5lib/treewalkers/__init__.py,sha256=CFpUOCfLuhAgVJ8NYk9wviCu1khYnv7XRStvyzU1Fws,5544 -pip/_vendor/html5lib/treewalkers/base.py,sha256=ei-2cFbNFd0gRjyaFmxnxZGLNID4o0bHFCH9bMyZ5Bk,4939 -pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 -pip/_vendor/html5lib/treewalkers/etree.py,sha256=8jVLEY2FjgN4RFugwhAh44l9ScVYoDStQFCnlPwvafI,4684 -pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 -pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 -pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 -pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 -pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 -pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 -pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 -pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 -pip/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 -pip/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 -pip/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 -pip/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 -pip/_vendor/packaging/markers.py,sha256=mtg2nphJE1oQO39g1DgsdPsMO-guBBClpR-AEYFrbMg,8230 -pip/_vendor/packaging/requirements.py,sha256=SD7dVJGjdPUqtoHb47qwK6wWJTQd-ZXWjxpJg83UcBA,4327 -pip/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 -pip/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 -pip/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 -pip/_vendor/pkg_resources/__init__.py,sha256=CcwuHtCBZn9OTkmgF9cFpadIAMhlrnZTVKTOo4V2p58,103230 -pip/_vendor/progress/__init__.py,sha256=Wn1074LUDZovd4zfoVYojnPBgOc6ctHbQX7rp_p8lRA,3023 -pip/_vendor/progress/bar.py,sha256=YNPJeRrwYVKFO2nyaEwsQjYByamMWTgJMvQO1NpD-AY,2685 -pip/_vendor/progress/counter.py,sha256=kEqA8jWEdwrc6P_9VaRx7bjOHwk9gxl-Q9oVbQ08v5c,1502 -pip/_vendor/progress/helpers.py,sha256=FehfwZTv-5cCfsbcMlvlUkm3xZ0cRhsev6XVpmeTF4c,2854 -pip/_vendor/progress/spinner.py,sha256=iCVtUQbaJUFHTjn1ZLPQLPYeao4lC9aXAa_HxIeUK6k,1314 -pip/_vendor/requests/__init__.py,sha256=Cde-qxOWcslaEcPvKAJQPFbY8_va8PMbU7Rssr7vViI,2326 -pip/_vendor/requests/adapters.py,sha256=DJdgax91PyS2s6_oZPELbuLWNlM2xGguNu62sqcOUik,19740 -pip/_vendor/requests/api.py,sha256=PgminOpD8hLLKLNs0RWLKr1HpNc4Qxr_6uen8q2c9CI,5794 -pip/_vendor/requests/auth.py,sha256=eBLtJlcTZxRG7xKXCvGQBLO9a-PxFgMf2qTUbtZwMJM,8175 -pip/_vendor/requests/cacert.pem,sha256=5xzWFRrSP0ZsXiW6emg8UQ_w497lT4qWCv32OO8R1ME,344712 -pip/_vendor/requests/certs.py,sha256=Aa-oStu9f2lVi8VM9Aw1xaAtTIz7bhu5CGKNPEW1waM,625 -pip/_vendor/requests/compat.py,sha256=0cgWB43LEX5OrX1O4k-bPbFlIbWXgEd412DSDJtF1Y8,1687 -pip/_vendor/requests/cookies.py,sha256=awMI0hm3SKheMEDTqO8AIadc2XmnCGKPCTNw_4hlM3Q,18208 -pip/_vendor/requests/exceptions.py,sha256=x-MGvDASYKSstuCNYTA5IT_EAcxTp5knE3WPMrgkrlI,2860 -pip/_vendor/requests/hooks.py,sha256=HXAHoC1FNTFRZX6-lNdvPM7Tst4kvGwYTN-AOKRxoRU,767 -pip/_vendor/requests/models.py,sha256=YHuL2khGDFxeWc-NMJIcfFqvYJ0dKs1mXfj1Fuff1J8,30532 -pip/_vendor/requests/sessions.py,sha256=H7HpKRLKeu1MSH5W1-PI2GMCFLN4bz5i3OFqjjgzE5k,25609 -pip/_vendor/requests/status_codes.py,sha256=uwVHcMPkHV3FElDLlnDTH3KULZIAGxaovbBxrjWm8N0,3316 -pip/_vendor/requests/structures.py,sha256=yexCvWbX40M6E8mLQOpAGZZ-ZoAnyaT2dni-Bp-b42g,3012 -pip/_vendor/requests/utils.py,sha256=9d3jqnA8avsF9N1QPmsk2pJgo2pxuExrN2hoIhtLggY,24163 -pip/_vendor/requests/packages/__init__.py,sha256=CVheqNRcXIkAi5037RhxeqbAqd0QhrK1o9R9kS2xvuI,1384 -pip/_vendor/requests/packages/chardet/__init__.py,sha256=XuTKCYOR7JwsoHxqZTYH86LVyMDbDI3s1s0W_qoGEBM,1295 -pip/_vendor/requests/packages/chardet/big5freq.py,sha256=D8oTdz-GM7Jg8TsaWJDm65vM_OLHC3xub6qUJ3rOgsQ,82594 -pip/_vendor/requests/packages/chardet/big5prober.py,sha256=XX96C--6WKYW36mL-z7pJSAtc169Z8ZImByCP4pEN9A,1684 -pip/_vendor/requests/packages/chardet/chardetect.py,sha256=f4299UZG6uWd3i3r_N0OdrFj2sA9JFI54PAmDLAFmWA,2504 -pip/_vendor/requests/packages/chardet/chardistribution.py,sha256=cUARQFr1oTLXeJCDQrDRkUP778AvSMzhSCnG8VLCV58,9226 -pip/_vendor/requests/packages/chardet/charsetgroupprober.py,sha256=0lKk7VE516fgMw119tNefFqLOxKfIE9WfdkpIT69OKU,3791 -pip/_vendor/requests/packages/chardet/charsetprober.py,sha256=Z48o2KiOj23FNqYH8FqzhH5m1qdm3rI8DcTm2Yqtklg,1902 -pip/_vendor/requests/packages/chardet/codingstatemachine.py,sha256=E85rYhHVMw9xDEJVgiQhp0OnLGr6i2r8_7QOWMKTH08,2318 -pip/_vendor/requests/packages/chardet/compat.py,sha256=5mm6yrHwef1JEG5OxkPJlSq5lkjLVpEGh3iPgFBkpkM,1157 -pip/_vendor/requests/packages/chardet/constants.py,sha256=-UnY8U7EP7z9fTyd09yq35BEkSFEAUAiv9ohd1DW1s4,1335 -pip/_vendor/requests/packages/chardet/cp949prober.py,sha256=FMvdLyB7fejPXRsTbca7LK1P3RUvvssmjUNyaEfz8zY,1782 -pip/_vendor/requests/packages/chardet/escprober.py,sha256=q5TcQKeVq31WxrW7Sv8yjpZkjEoaHO8S92EJZ9hodys,3187 -pip/_vendor/requests/packages/chardet/escsm.py,sha256=7iljEKN8lXTh8JFXPUSwlibMno6R6ksq4evLxbkzfro,7839 -pip/_vendor/requests/packages/chardet/eucjpprober.py,sha256=5IpfSEjAb7h3hcGMd6dkU80O900C2N6xku28rdYFKuc,3678 -pip/_vendor/requests/packages/chardet/euckrfreq.py,sha256=T5saK5mImySG5ygQPtsp6o2uKulouCwYm2ElOyFkJqU,45978 -pip/_vendor/requests/packages/chardet/euckrprober.py,sha256=Wo7dnZ5Erw_nB4H-m5alMiOxOuJUmGHlwCSaGqExDZA,1675 -pip/_vendor/requests/packages/chardet/euctwfreq.py,sha256=G_I0BW9i1w0ONeeUwIYqV7_U09buIHdqh-wNHVaql7I,34872 -pip/_vendor/requests/packages/chardet/euctwprober.py,sha256=upS2P6GuT5ujOxXYw-RJLcT7A4PTuo27KGUKU4UZpIQ,1676 -pip/_vendor/requests/packages/chardet/gb2312freq.py,sha256=M2gFdo_qQ_BslStEchrPW5CrPEZEacC0uyDLw4ok-kY,36011 -pip/_vendor/requests/packages/chardet/gb2312prober.py,sha256=VWnjoRa83Y6V6oczMaxyUr0uy48iCnC2nzk9zfEIRHc,1681 -pip/_vendor/requests/packages/chardet/hebrewprober.py,sha256=8pdoUfsVXf_L4BnJde_BewS6H2yInV5688eu0nFhLHY,13359 -pip/_vendor/requests/packages/chardet/jisfreq.py,sha256=ZcL4R5ekHHbP2KCYGakVMBsiKqZZZAABzhwi-uRkOps,47315 -pip/_vendor/requests/packages/chardet/jpcntx.py,sha256=yftmp0QaF6RJO5SJs8I7LU5AF4rwP23ebeCQL4BM1OY,19348 -pip/_vendor/requests/packages/chardet/langbulgarianmodel.py,sha256=ZyPsA796MSVhYdfWhMCgKWckupAKAnKqWcE3Cl3ej6o,12784 -pip/_vendor/requests/packages/chardet/langcyrillicmodel.py,sha256=fkcd5OvogUp-GrNDWAZPgkYsSRCD2omotAEvqjlmLKE,17725 -pip/_vendor/requests/packages/chardet/langgreekmodel.py,sha256=QHMy31CH_ot67UCtmurCEKqKx2WwoaKrw2YCYYBK2Lw,12628 -pip/_vendor/requests/packages/chardet/langhebrewmodel.py,sha256=4ASl5vzKJPng4H278VHKtRYC03TpQpenlHTcsmZH1rE,11318 -pip/_vendor/requests/packages/chardet/langhungarianmodel.py,sha256=SXwuUzh49_cBeMXhshRHdrhlkz0T8_pZWV_pdqBKNFk,12536 -pip/_vendor/requests/packages/chardet/langthaimodel.py,sha256=-k7djh3dGKngAGnt3WfuoJN7acDcWcmHAPojhaUd7q4,11275 -pip/_vendor/requests/packages/chardet/latin1prober.py,sha256=238JHOxH8aRudJY2NmeSv5s7i0Qe3GuklIU3HlYybvg,5232 -pip/_vendor/requests/packages/chardet/mbcharsetprober.py,sha256=9rOCjDVsmSMp6e7q2syqak22j7lrbUZhJhMee2gbVL0,3268 -pip/_vendor/requests/packages/chardet/mbcsgroupprober.py,sha256=SHRzNPLpDXfMJLA8phCHVU0WgqbgDCNxDQMolGX_7yk,1967 -pip/_vendor/requests/packages/chardet/mbcssm.py,sha256=IKwJXyxu34n6NojmxVxC60MLFtJKm-hIfxaFEnb3uBA,19590 -pip/_vendor/requests/packages/chardet/sbcharsetprober.py,sha256=Xq0lODqJnDgxglBiQI4BqTFiPbn63-0a5XNA5-hVu7U,4793 -pip/_vendor/requests/packages/chardet/sbcsgroupprober.py,sha256=8hLyH8RAG-aohBo7o_KciWVgRo42ZE_zEtuNG1JMRYI,3291 -pip/_vendor/requests/packages/chardet/sjisprober.py,sha256=UYOmiMDzttYIkSDoOB08UEagivJpUXz4tuWiWzTiOr8,3764 -pip/_vendor/requests/packages/chardet/universaldetector.py,sha256=h-E2x6XSCzlNjycYWG0Fe4Cf1SGdaIzUNu2HCphpMZA,6840 -pip/_vendor/requests/packages/chardet/utf8prober.py,sha256=7tdNZGrJY7jZUBD483GGMkiP0Tx8Fp-cGvWHoAsilHg,2652 -pip/_vendor/requests/packages/urllib3/__init__.py,sha256=EF9pbHgMzqQek2Y6EZ82A8B6wETFeW7bK0K-HoZ3Ffo,2852 -pip/_vendor/requests/packages/urllib3/_collections.py,sha256=RP-cHyTx4AgYwvoETK8q1IVRbWFJnE0VV692ZHSbU68,10553 -pip/_vendor/requests/packages/urllib3/connection.py,sha256=QCmkelYgtbc06DfJtgs22na78kRTLCTbLb-OSWLbt-A,11617 -pip/_vendor/requests/packages/urllib3/connectionpool.py,sha256=fls19n1Y4jnwOBsZz_9F01i08xH2gZXEIyyDmWd-mKU,33591 -pip/_vendor/requests/packages/urllib3/exceptions.py,sha256=zGjhZCR1wefEnCN5b7WouQ3UhXesJ2bRKYIeWusaFJs,5599 -pip/_vendor/requests/packages/urllib3/fields.py,sha256=WUMvCLvnw7XemBq6AmCgNPJwyIJL_vWaMHaA2FLlscM,5931 -pip/_vendor/requests/packages/urllib3/filepost.py,sha256=NvLlFsdt8ih_Q4S2ekQF3CJG0nOXs32YI-G04_AdT2g,2320 -pip/_vendor/requests/packages/urllib3/poolmanager.py,sha256=9Uf0fUk0aR_s1auXgwceoN2gbaIQ08lrum_cGEA9-_U,13092 -pip/_vendor/requests/packages/urllib3/request.py,sha256=jET7OvA3FSjxABBRGhCyMdPvM9XuJA6df9gRhkJiJiY,5988 -pip/_vendor/requests/packages/urllib3/response.py,sha256=wxJSV_6pyh6Cgx7XFVGpNhpZCbh4eL7lCSFaU4ixXXc,18615 -pip/_vendor/requests/packages/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/requests/packages/urllib3/contrib/appengine.py,sha256=NdN_xOgDLMadUPe_dN3wdan_DH9-fxVNqFgq19tbqQs,7937 -pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py,sha256=r-vMDMXAGbix9a7-IhbKVTATmAst-5g4hKYOLf8Kd5M,4531 -pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py,sha256=JsdAh0gL4XvQzhOEBRoFtJN91qLf1LFIDEFZs95445I,11778 -pip/_vendor/requests/packages/urllib3/contrib/socks.py,sha256=uPHtE6R8uyUbD9R8l2wO80c87WDGZ9rou3kNOwV74eA,5668 -pip/_vendor/requests/packages/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 -pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 -pip/_vendor/requests/packages/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py,sha256=cOWMIn1orgJoA35p6pSzO_-Dc6iOX9Dhl6D2sL9b_2o,460 -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=fK28k37hL7-D79v9iM2fHgNK9Q1Pw0M7qVRL4rkfFjQ,3778 -pip/_vendor/requests/packages/urllib3/util/__init__.py,sha256=n2QE9_0Bb6u8tf7LUc4qKe8V-Hz9G8lEOc9j_30Q8d0,892 -pip/_vendor/requests/packages/urllib3/util/connection.py,sha256=7B5Mmepg5Xd399VKE__VHxD2ObapYFrB3mWJ_EnIebs,4744 -pip/_vendor/requests/packages/urllib3/util/request.py,sha256=ZMDewRK-mjlK72szGIIjzYnLIn-zPP0WgJUMjKeZ6Tg,2128 -pip/_vendor/requests/packages/urllib3/util/response.py,sha256=1UFd5TIp9MyBp4xgnZoyQZscZVPPr0tWRaXNR5w_vds,2165 -pip/_vendor/requests/packages/urllib3/util/retry.py,sha256=5eA3GHR_L14qz66NU6gr-v5VbKYsvdEqOvCcsx1oLKo,10664 -pip/_vendor/requests/packages/urllib3/util/ssl_.py,sha256=7xR_jvQLTQA1U006wJ1bl2KuLGnD1qQvUcFM2uysedw,11622 -pip/_vendor/requests/packages/urllib3/util/timeout.py,sha256=ioAIYptFyBG7eU_r8_ZmO45hpj1dJE6WCvrGR9dNFjs,9596 -pip/_vendor/requests/packages/urllib3/util/url.py,sha256=EcX4ZfmgKWcqM4sY9FlC-yN4y_snuURPV0TpUPHNjnc,5879 -pip/_vendor/webencodings/__init__.py,sha256=t7rAQQxXwalY-ak9hTl73qHjhia9UH-sL-e00qQrBpo,10576 -pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 -pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 -pip/_vendor/webencodings/tests.py,sha256=7vTk7LgOJn_t1XtT_viofZlEJ7cJCzPe_hvVHOkcQl8,6562 -pip/_vendor/webencodings/x_user_defined.py,sha256=72cfPRhbfkRCGkkA8ZnvVV7UnoiLb5uPMhXwhrXiLPk,4306 -pip/commands/__init__.py,sha256=2Uq3HCdjchJD9FL1LB7rd5v6UySVAVizX0W3EX3hIoE,2244 -pip/commands/check.py,sha256=-A7GI1-WZBh9a4P6UoH_aR-J7I8Lz8ly7m3wnCjmevs,1382 -pip/commands/completion.py,sha256=kkPgVX7SUcJ_8Juw5GkgWaxHN9_45wmAr9mGs1zXEEs,2453 -pip/commands/download.py,sha256=8RuuPmSYgAq3iEDTqZY_1PDXRqREdUULHNjWJeAv7Mo,7810 -pip/commands/freeze.py,sha256=h6-yFMpjCjbNj8-gOm5UuoF6cg14N5rPV4TCi3_CeuI,2835 -pip/commands/hash.py,sha256=MCt4jEFyfoce0lVeNEz1x49uaTY-VDkKiBvvxrVcHkw,1597 -pip/commands/help.py,sha256=84HWkEdnGP_AEBHnn8gJP2Te0XTXRKFoXqXopbOZTNo,982 -pip/commands/install.py,sha256=ovG9p9n1X2NPqMgFVtSuT9kMbLAdx1r3YSSiXSvgOKI,17412 -pip/commands/list.py,sha256=93bCiFyt2Qut_YHkYHJMZHpXladmxsjS-yOtZeb3uqI,11369 -pip/commands/search.py,sha256=oTs9QNdefnrmCV_JeftG0PGiMuYVmiEDF1OUaYsmDao,4502 -pip/commands/show.py,sha256=ZYM57_7U8KP9MQIIyHKQdZxmiEZByy-DRzB697VFoTY,5891 -pip/commands/uninstall.py,sha256=tz8cXz4WdpUdnt3RvpdQwH6_SNMB50egBIZWa1dwfcc,2884 -pip/commands/wheel.py,sha256=z5SEhws2YRMb0Ml1IEkg6jFZMLRpLl86bHCrQbYt5zo,7729 -pip/compat/__init__.py,sha256=2Xs_IpsmdRgHbQgQO0c8_lPvHJnQXHyGWxPbLbYJL4c,4672 -pip/compat/dictconfig.py,sha256=dRrelPDWrceDSzFT51RTEVY2GuM7UDyc5Igh_tn4Fvk,23096 -pip/models/__init__.py,sha256=0Rs7_RA4DxeOkWT5Cq4CQzDrSEhvYcN3TH2cazr72PE,71 -pip/models/index.py,sha256=pUfbO__v3mD9j-2n_ClwPS8pVyx4l2wIwyvWt8GMCRA,487 -pip/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/operations/check.py,sha256=uwUN9cs1sPo7c0Sj6pRrSv7b22Pk29SXUImTelVchMQ,1590 -pip/operations/freeze.py,sha256=k-7w7LsM-RpPv7ERBzHiPpYkH-GuYfHLyR-Cp_1VPL0,5194 -pip/req/__init__.py,sha256=vFwZY8_Vc1WU1zFAespg1My_r_AT3n7cN0W9eX0EFqk,276 -pip/req/req_file.py,sha256=fG9MDsXUNPhmGwxUiwrIXEynyD8Q7s3L47-hLZPDXq0,11926 -pip/req/req_install.py,sha256=gYrH-lwQMmt55VVbav_EtRIPu94cQbHFHm_Kq6AeHbg,46487 -pip/req/req_set.py,sha256=jHspXqcA2FxcF05dgUIAZ5huYPv6bn0wRUX0Z7PKmaA,34462 -pip/req/req_uninstall.py,sha256=fdH2VgCjEC8NRYDS7fRu3ZJaBBUEy-N5muwxDX5MBNM,6897 -pip/utils/__init__.py,sha256=HX_wYS15oiYOz-H3qG1Kbi1CY7AGWCNK5jloiD0fauc,27187 -pip/utils/appdirs.py,sha256=kj2LK-I2fC5QnEh_A_v-ev_IQMcXaWWF5DE39sNvCLQ,8811 -pip/utils/build.py,sha256=4smLRrfSCmXmjEnVnMFh2tBEpNcSLRe6J0ejZJ-wWJE,1312 -pip/utils/deprecation.py,sha256=X_FMjtDbMJqfqEkdRrki-mYyIdPB6I6DHUTCA_ChY6M,2232 -pip/utils/encoding.py,sha256=NQxGiFS5GbeAveLZTnx92t5r0PYqvt0iRnP2u9SGG1w,971 -pip/utils/filesystem.py,sha256=ZEVBuYM3fqr2_lgOESh4Y7fPFszGD474zVm_M3Mb5Tk,899 -pip/utils/glibc.py,sha256=jcQYjt_oJLPKVZB28Kauy4Sw70zS-wawxoU1HHX36_0,2939 -pip/utils/hashes.py,sha256=oMk7cd3PbJgzpSQyXq1MytMud5f6H5Oa2YY5hYuCq6I,2866 -pip/utils/logging.py,sha256=7yWu4gZw-Qclj7X80QVdpGWkdTWGKT4LiUVKcE04pro,3327 -pip/utils/outdated.py,sha256=fNwOCL5r2EftPGhgCYGMKu032HC8cV-JAr9lp0HmToM,5455 -pip/utils/packaging.py,sha256=qhmli14odw6DIhWJgQYS2Q0RrSbr8nXNcG48f5yTRms,2080 -pip/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 -pip/utils/ui.py,sha256=pbDkSAeumZ6jdZcOJ2yAbx8iBgeP2zfpqNnLJK1gskQ,11597 -pip/vcs/__init__.py,sha256=WafFliUTHMmsSISV8PHp1M5EXDNSWyJr78zKaQmPLdY,12374 -pip/vcs/bazaar.py,sha256=tYTwc4b4off8mr0O2o8SiGejqBDJxcbDBMSMd9-ISYc,3803 -pip/vcs/git.py,sha256=5LfWryi78A-2ULjEZJvCTarJ_3l8venwXASlwm8hiug,11197 -pip/vcs/mercurial.py,sha256=xG6rDiwHCRytJEs23SIHBXl_SwQo2jkkdD_6rVVP5h4,3472 -pip/vcs/subversion.py,sha256=GAuX2Sk7IZvJyEzENKcVld_wGBrQ3fpXDlXjapZEYdI,9350 -pip-9.0.1.dist-info/DESCRIPTION.rst,sha256=Va8Wj1XBpTbVQ2Z41mZRJdALEeziiS_ZewWn1H2ecY4,1287 -pip-9.0.1.dist-info/METADATA,sha256=mvs_tLoKAbECXY_6QHiVWQsagSL-1UjolQTpScT8JSk,2529 -pip-9.0.1.dist-info/RECORD,, -pip-9.0.1.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 -pip-9.0.1.dist-info/entry_points.txt,sha256=GWc-Wb9WUKZ1EuVWNz-G0l3BeIpbNJLx0OJbZ61AAV0,68 -pip-9.0.1.dist-info/metadata.json,sha256=aqvkETDy4mHUBob-2Fn5WWlXORi_M2OSfQ2HQCUU_Fk,1565 -pip-9.0.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -../../Scripts/pip.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 -../../Scripts/pip3.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 -../../Scripts/pip3.6.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 -pip-9.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip/commands/__pycache__/check.cpython-36.pyc,, -pip/commands/__pycache__/completion.cpython-36.pyc,, -pip/commands/__pycache__/download.cpython-36.pyc,, -pip/commands/__pycache__/freeze.cpython-36.pyc,, -pip/commands/__pycache__/hash.cpython-36.pyc,, -pip/commands/__pycache__/help.cpython-36.pyc,, -pip/commands/__pycache__/install.cpython-36.pyc,, -pip/commands/__pycache__/list.cpython-36.pyc,, -pip/commands/__pycache__/search.cpython-36.pyc,, -pip/commands/__pycache__/show.cpython-36.pyc,, -pip/commands/__pycache__/uninstall.cpython-36.pyc,, -pip/commands/__pycache__/wheel.cpython-36.pyc,, -pip/commands/__pycache__/__init__.cpython-36.pyc,, -pip/compat/__pycache__/dictconfig.cpython-36.pyc,, -pip/compat/__pycache__/__init__.cpython-36.pyc,, -pip/models/__pycache__/index.cpython-36.pyc,, -pip/models/__pycache__/__init__.cpython-36.pyc,, -pip/operations/__pycache__/check.cpython-36.pyc,, -pip/operations/__pycache__/freeze.cpython-36.pyc,, -pip/operations/__pycache__/__init__.cpython-36.pyc,, -pip/req/__pycache__/req_file.cpython-36.pyc,, -pip/req/__pycache__/req_install.cpython-36.pyc,, -pip/req/__pycache__/req_set.cpython-36.pyc,, -pip/req/__pycache__/req_uninstall.cpython-36.pyc,, -pip/req/__pycache__/__init__.cpython-36.pyc,, -pip/utils/__pycache__/appdirs.cpython-36.pyc,, -pip/utils/__pycache__/build.cpython-36.pyc,, -pip/utils/__pycache__/deprecation.cpython-36.pyc,, -pip/utils/__pycache__/encoding.cpython-36.pyc,, -pip/utils/__pycache__/filesystem.cpython-36.pyc,, -pip/utils/__pycache__/glibc.cpython-36.pyc,, -pip/utils/__pycache__/hashes.cpython-36.pyc,, -pip/utils/__pycache__/logging.cpython-36.pyc,, -pip/utils/__pycache__/outdated.cpython-36.pyc,, -pip/utils/__pycache__/packaging.cpython-36.pyc,, -pip/utils/__pycache__/setuptools_build.cpython-36.pyc,, -pip/utils/__pycache__/ui.cpython-36.pyc,, -pip/utils/__pycache__/__init__.cpython-36.pyc,, -pip/vcs/__pycache__/bazaar.cpython-36.pyc,, -pip/vcs/__pycache__/git.cpython-36.pyc,, -pip/vcs/__pycache__/mercurial.cpython-36.pyc,, -pip/vcs/__pycache__/subversion.cpython-36.pyc,, -pip/vcs/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-36.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-36.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/adapter.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/cache.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/compat.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/controller.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/serialize.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-36.pyc,, -pip/_vendor/cachecontrol/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/ansi.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/ansitowin32.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/initialise.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/win32.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/winterm.cpython-36.pyc,, -pip/_vendor/colorama/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/distlib/_backport/__pycache__/misc.cpython-36.pyc,, -pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-36.pyc,, -pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-36.pyc,, -pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-36.pyc,, -pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/compat.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/database.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/index.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/locators.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/manifest.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/markers.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/metadata.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/resources.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/scripts.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/util.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/version.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/wheel.cpython-36.pyc,, -pip/_vendor/distlib/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/base.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/lint.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-36.pyc,, -pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-36.pyc,, -pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-36.pyc,, -pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-36.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-36.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-36.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-36.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-36.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-36.pyc,, -pip/_vendor/html5lib/_trie/__pycache__/py.cpython-36.pyc,, -pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-36.pyc,, -pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/constants.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/html5parser.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/serializer.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/_inputstream.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/_utils.cpython-36.pyc,, -pip/_vendor/html5lib/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/linklockfile.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/pidlockfile.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/sqlitelockfile.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/symlinklockfile.cpython-36.pyc,, -pip/_vendor/lockfile/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/markers.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/requirements.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/specifiers.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/utils.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/version.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/_compat.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/_structures.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/__about__.cpython-36.pyc,, -pip/_vendor/packaging/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/pkg_resources/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/progress/__pycache__/bar.cpython-36.pyc,, -pip/_vendor/progress/__pycache__/counter.cpython-36.pyc,, -pip/_vendor/progress/__pycache__/helpers.cpython-36.pyc,, -pip/_vendor/progress/__pycache__/spinner.cpython-36.pyc,, -pip/_vendor/progress/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/big5freq.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/big5prober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/chardetect.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/chardistribution.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/charsetgroupprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/charsetprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/codingstatemachine.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/compat.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/constants.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/cp949prober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/escprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/escsm.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/eucjpprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euckrfreq.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euckrprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euctwfreq.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euctwprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/gb2312freq.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/gb2312prober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/hebrewprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/jisfreq.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/jpcntx.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langbulgarianmodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langcyrillicmodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langgreekmodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langhebrewmodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langhungarianmodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langthaimodel.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/latin1prober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcharsetprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcsgroupprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcssm.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sbcharsetprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sbcsgroupprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sjisprober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/universaldetector.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/utf8prober.cpython-36.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/appengine.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/ntlmpool.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/pyopenssl.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/socks.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/ordered_dict.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/six.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/connection.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/request.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/response.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/retry.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/ssl_.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/timeout.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/url.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/connection.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/connectionpool.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/exceptions.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/fields.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/filepost.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/poolmanager.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/request.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/response.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/_collections.cpython-36.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/packages/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/adapters.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/api.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/auth.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/certs.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/compat.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/cookies.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/exceptions.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/hooks.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/models.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/sessions.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/status_codes.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/structures.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/utils.cpython-36.pyc,, -pip/_vendor/requests/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/webencodings/__pycache__/labels.cpython-36.pyc,, -pip/_vendor/webencodings/__pycache__/mklabels.cpython-36.pyc,, -pip/_vendor/webencodings/__pycache__/tests.cpython-36.pyc,, -pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-36.pyc,, -pip/_vendor/webencodings/__pycache__/__init__.cpython-36.pyc,, -pip/_vendor/__pycache__/appdirs.cpython-36.pyc,, -pip/_vendor/__pycache__/distro.cpython-36.pyc,, -pip/_vendor/__pycache__/ipaddress.cpython-36.pyc,, -pip/_vendor/__pycache__/ordereddict.cpython-36.pyc,, -pip/_vendor/__pycache__/pyparsing.cpython-36.pyc,, -pip/_vendor/__pycache__/re-vendor.cpython-36.pyc,, -pip/_vendor/__pycache__/retrying.cpython-36.pyc,, -pip/_vendor/__pycache__/six.cpython-36.pyc,, -pip/_vendor/__pycache__/__init__.cpython-36.pyc,, -pip/__pycache__/basecommand.cpython-36.pyc,, -pip/__pycache__/baseparser.cpython-36.pyc,, -pip/__pycache__/cmdoptions.cpython-36.pyc,, -pip/__pycache__/download.cpython-36.pyc,, -pip/__pycache__/exceptions.cpython-36.pyc,, -pip/__pycache__/index.cpython-36.pyc,, -pip/__pycache__/locations.cpython-36.pyc,, -pip/__pycache__/pep425tags.cpython-36.pyc,, -pip/__pycache__/status_codes.cpython-36.pyc,, -pip/__pycache__/wheel.cpython-36.pyc,, -pip/__pycache__/__init__.cpython-36.pyc,, -pip/__pycache__/__main__.cpython-36.pyc,, +pip/__init__.py,sha256=00QWSreEBjb8Y8sPs8HeqgLXSB-3UrONJxo4J5APxEc,11348 +pip/__main__.py,sha256=V6Kh-IEDEFpt1cahRE6MajUF_14qJR_Qsvn4MjWZXzE,584 +pip/basecommand.py,sha256=TTlmZesQ4Vuxcto2KqwZGmgmN5ioHEl_DeFev9ie_SA,11910 +pip/baseparser.py,sha256=AKMOeF3fTrRroiv0DmTQbdiLW0DQux2KqGC_dJJB9d0,10465 +pip/cmdoptions.py,sha256=8JCcF2kKAF2cFnV77oW-3DsHJifr9jF2WuChzzwgcwg,16474 +pip/download.py,sha256=rA0wbmqC2n9ejX481YJSidmKgQqQDjdaxkHkHlAN68k,32171 +pip/exceptions.py,sha256=BvqH-Jw3tP2b-2IJ2kjrQemOAPMqKrQMLRIZHZQpJXk,8121 +pip/index.py,sha256=L6UhtAEZc2qw7BqfQrkPQcw2gCgEw3GukLRSA95BNyI,39950 +pip/locations.py,sha256=9rJRlgonC6QC2zGDIn_7mXaoZ9_tF_IHM2BQhWVRgbo,5626 +pip/pep425tags.py,sha256=q3kec4f6NHszuGYIhGIbVvs896D06uJAnKFgJ_wce44,10980 +pip/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 +pip/wheel.py,sha256=QSWmGs2ui-n4UMWm0JUY6aMCcwNKungVzbWsxI9KlJQ,32010 +pip/_vendor/__init__.py,sha256=WaaSJ3roSSJ_Uv4yKAxlGohKEH9YUA3aIh1Xg2IjfgU,4670 +pip/_vendor/appdirs.py,sha256=-9UOIZy62ahCQVY9-b7Nn6_5_4Y6ooHnv72tM8iHi9Y,22368 +pip/_vendor/distro.py,sha256=A4Douw9pcqdYxDTp5b-OR02fxVXnfWs-wC1wA89rhRk,38349 +pip/_vendor/ipaddress.py,sha256=wimbqcE7rwwETlucn8A_4Qd_-NKXPOBcNxJHarUoXng,80176 +pip/_vendor/ordereddict.py,sha256=4KsFuc6V8IgHROCHUu-4vCrr21ZPPea7Z0cvX9AjQ7w,4094 +pip/_vendor/pyparsing.py,sha256=7vAuUVbh6txUKQR2IzJ8_9DKmD5vtm5MDssWkI0ka8o,224171 +pip/_vendor/re-vendor.py,sha256=PcdZ40d0ohMsdJmA4t0AeAWbPXi1tFsvAwA5KE5FGeY,773 +pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 +pip/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pip/_vendor/cachecontrol/__init__.py,sha256=UPyFlz0dIjxusu5ITig9UDFJdSY5LTwijhldn0AfyzU,302 +pip/_vendor/cachecontrol/_cmd.py,sha256=MPxZfZd2LKDzVrs55X3wA1rsI2YuP8evLZSwQj0dIk0,1320 +pip/_vendor/cachecontrol/adapter.py,sha256=RaGYyRA-RA1J0AnE67GzEYFPBu4YH4EQUvQqTKa57iM,4608 +pip/_vendor/cachecontrol/cache.py,sha256=xtl-V-pr9KSt9VvFDRCB9yrHPEvqvbk-5M1vAInZb5k,790 +pip/_vendor/cachecontrol/compat.py,sha256=uyovOpd1ehI3J1XeBqJvcsIp6fvkjBpoQmu_0J2st8c,416 +pip/_vendor/cachecontrol/controller.py,sha256=elDsLcaYA15ncodRmHnWQp6ekU_ocEGtDeGLbsnTjzo,13024 +pip/_vendor/cachecontrol/filewrapper.py,sha256=_K8cStmXqD33m15PfsQ8rlpo6FfXjVbKmjvLXyICRgI,2531 +pip/_vendor/cachecontrol/heuristics.py,sha256=WtJrVsyWjpP9WoUiDVdTZZRNBCz5ZVptaQpYnqofDQU,4141 +pip/_vendor/cachecontrol/serialize.py,sha256=XM6elG9DSNexwaOCgMjUtfrHHW5NAB6TSbIf3x235xs,6536 +pip/_vendor/cachecontrol/wrapper.py,sha256=Kqyu_3TW_54XDudha4-HF21vyEOAJ4ZnRXFysTiLmXA,498 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=uWnUtyMvHY_LULaL_4_IR1F_xPgK5zHfJyRnBq4DnPE,369 +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=FsDug3bwUAQ3okjjfGzxlDaBf2fwVSn1iBKMTL6SyGU,3532 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=XywqxkS9MkCaflTOY_wjrE02neKdywB9YwlOBbP7Ywc,973 +pip/_vendor/colorama/__init__.py,sha256=9xByrTvk9upkL5NGV5It2Eje4-kzNLwa_1lGPWpXoNU,240 +pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 +pip/_vendor/colorama/ansitowin32.py,sha256=gJZB35Lbdjatykd2zrUUnokMzkvcFgscyn_tNxxMFHA,9668 +pip/_vendor/colorama/initialise.py,sha256=cHqVJtb82OG7HUCxvQ2joG7N_CoxbIKbI_fgryZkj20,1917 +pip/_vendor/colorama/win32.py,sha256=_SCEoTK_GA2tU1nhbayKKac-v9Jn98lCPIFOeFMGCHQ,5365 +pip/_vendor/colorama/winterm.py,sha256=V7U7ojwG1q4n6PKripjEvW_htYQi5ueXSM3LUUoqqDY,6290 +pip/_vendor/distlib/__init__.py,sha256=-aUeNNCfiIG_1Tqf19BH0xLNuBKGX1I7lNhcLYgFUEA,581 +pip/_vendor/distlib/compat.py,sha256=FzKlP9dNUMH-j_1LCVnjgx6KgUbpnRjTjYkTkDYRPlI,40801 +pip/_vendor/distlib/database.py,sha256=jniJmYk0Mj2t6gZYbnn68TvQwnVZ0kXyeuf_3AxFclk,49672 +pip/_vendor/distlib/index.py,sha256=Cw8gxFq_7xXvdgExL3efjLAY3EAPDMSL3VA42RkbQBs,21085 +pip/_vendor/distlib/locators.py,sha256=hD_Hm3aSL9DklY9Cxyct2n_74gZ0xNFFGB5L7M6ds14,51013 +pip/_vendor/distlib/manifest.py,sha256=3qEuZhHlDbvyYZ1BZbdapDAivgMgUwWpZ00cmXqcn18,14810 +pip/_vendor/distlib/markers.py,sha256=iRrVWwpyVwjkKJSX8NEQ92_MRMwpROcfNGKCD-Ch1QM,6282 +pip/_vendor/distlib/metadata.py,sha256=hUsf7Qh2Ae4CCkL33qK8ppwC8ZTzT7ep6Hj9RKpijKU,38833 +pip/_vendor/distlib/resources.py,sha256=VFBVbFqLVqDBSQDXcFQHrX1KEcuoDxTK699Ydi_beyc,10766 +pip/_vendor/distlib/scripts.py,sha256=xpehNfISGPTNxQZu02K9Rw2QbNx_2Q4emePv3W5X0iw,15224 +pip/_vendor/distlib/t32.exe,sha256=cp0UAUDDr1tGAx8adlKxWbCHIa-oB3bxev5zYzgAr8E,89088 +pip/_vendor/distlib/t64.exe,sha256=FiljDPcX9qvoe9FYE_9pNEHqbqMnhcCOuI_oLJ4F9F8,97792 +pip/_vendor/distlib/util.py,sha256=E2wU-RZShPMFUMJr9kPmemTULinM4qDzosNPihCuKE0,52991 +pip/_vendor/distlib/version.py,sha256=CgghOUylxGD7dEA2S3MvWjx7mY_2bWsluF0Of3Yxl4Y,23711 +pip/_vendor/distlib/w32.exe,sha256=LItrBJesEqt2QTQuB-yha2YbMegURHmHmdSxhjBqmnc,85504 +pip/_vendor/distlib/w64.exe,sha256=n_PioBC7ltz7sAk1WLbLzZJgS4R2axSy_0HPf8ZCsEg,94208 +pip/_vendor/distlib/wheel.py,sha256=UP53cKxOM5r7bHSS-n5prF6hwJEVsMW9ZNJutOuC26c,39115 +pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 +pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 +pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 +pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 +pip/_vendor/distlib/_backport/sysconfig.py,sha256=eSEyJg7jxF_eHlHG8IOtl93kb07UoMIRp1wYsPeGi9k,26955 +pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 +pip/_vendor/html5lib/__init__.py,sha256=JsIwmFldk-9raBadPSTS74JrfmJvozc-3aekMi7Hr9s,780 +pip/_vendor/html5lib/_ihatexml.py,sha256=tzXygYmisUmiEUt2v7E1Ab50AKQsrD-SglPRnY75vME,16705 +pip/_vendor/html5lib/_inputstream.py,sha256=C4lX5gUBwebOWy41hYP2ZBpkPVNvxk_hZBm3OVyPZM4,32532 +pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 +pip/_vendor/html5lib/_utils.py,sha256=bS6THVlL8ZyTcI6CIxiM6xxuHsE8i1j5Ogd3Ha1G84U,4096 +pip/_vendor/html5lib/constants.py,sha256=Dfc1Fv3_9frktgWjg4tbj-CjMMp02Ko9qMe4il1BVdo,83387 +pip/_vendor/html5lib/html5parser.py,sha256=Dmlu9hlq5w_id6mBZyY_sE5LukIACgvG4kpgIsded8Q,117170 +pip/_vendor/html5lib/serializer.py,sha256=Urrsa0cPPLqNX-UbJWS2gUhs_06qVbNxZvUnrmGZK6E,14177 +pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 +pip/_vendor/html5lib/_trie/_base.py,sha256=6P_AcIoGjtwB2qAlhV8H4VP-ztQxoXFGwt4NyMqG_Kw,979 +pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 +pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 +pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=DXv-P2vdQ5F3OTWM6QZ6KhyDlAWm90pbfrD1Bk9D_l0,621 +pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 +pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=2Q_JnMscn_tNbV_qpgYN_5M3PnBGfmuvECMKDExHUcY,2742 +pip/_vendor/html5lib/filters/lint.py,sha256=qf5cLrT6xXd8V7GH1R_3lKxIjuJSfpbWTpSwaglYdDw,3365 +pip/_vendor/html5lib/filters/optionaltags.py,sha256=EHig4kM-QiLjuxVJ3FAAFNy-10k4aV6HJbQzHKZ_3u8,10534 +pip/_vendor/html5lib/filters/sanitizer.py,sha256=7PqJrhm6mo3JvaHk2IQW7i74Or7Qtd-FV8UftJIyDys,25112 +pip/_vendor/html5lib/filters/whitespace.py,sha256=KPt067nYTqqi8KLTClyynn4eVzNDC_-MApXNVHRXVX0,1139 +pip/_vendor/html5lib/treeadapters/__init__.py,sha256=l3LcqMSEyoh99Jh_eWjGexHnIvKhLAXoP-LDz88whuM,208 +pip/_vendor/html5lib/treeadapters/genshi.py,sha256=6VIuHDNoExv1JWv3ePj6V5CM-tcyiUSWe5_Hd2ejbwY,1555 +pip/_vendor/html5lib/treeadapters/sax.py,sha256=3of4vvaUYIAic7pngebwJV24hpOS7Zg9ggJa_WQegy4,1661 +pip/_vendor/html5lib/treebuilders/__init__.py,sha256=UlB4orkTgZhFIKQdXrtiWn9cpKSsuhnOQOIHeD0Fv4k,3406 +pip/_vendor/html5lib/treebuilders/base.py,sha256=4vdjm_Z2f_GTQBwKnWlrzVcctTb-K5sfN8pXDaWODiA,13942 +pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 +pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 +pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=CEgwHMIQZvIDFAqct4kqPkVtyKIm9efHFq_VeExEPCA,14161 +pip/_vendor/html5lib/treewalkers/__init__.py,sha256=CFpUOCfLuhAgVJ8NYk9wviCu1khYnv7XRStvyzU1Fws,5544 +pip/_vendor/html5lib/treewalkers/base.py,sha256=ei-2cFbNFd0gRjyaFmxnxZGLNID4o0bHFCH9bMyZ5Bk,4939 +pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 +pip/_vendor/html5lib/treewalkers/etree.py,sha256=8jVLEY2FjgN4RFugwhAh44l9ScVYoDStQFCnlPwvafI,4684 +pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 +pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 +pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 +pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 +pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 +pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 +pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 +pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 +pip/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +pip/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pip/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pip/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +pip/_vendor/packaging/markers.py,sha256=mtg2nphJE1oQO39g1DgsdPsMO-guBBClpR-AEYFrbMg,8230 +pip/_vendor/packaging/requirements.py,sha256=SD7dVJGjdPUqtoHb47qwK6wWJTQd-ZXWjxpJg83UcBA,4327 +pip/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +pip/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +pip/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +pip/_vendor/pkg_resources/__init__.py,sha256=CcwuHtCBZn9OTkmgF9cFpadIAMhlrnZTVKTOo4V2p58,103230 +pip/_vendor/progress/__init__.py,sha256=Wn1074LUDZovd4zfoVYojnPBgOc6ctHbQX7rp_p8lRA,3023 +pip/_vendor/progress/bar.py,sha256=YNPJeRrwYVKFO2nyaEwsQjYByamMWTgJMvQO1NpD-AY,2685 +pip/_vendor/progress/counter.py,sha256=kEqA8jWEdwrc6P_9VaRx7bjOHwk9gxl-Q9oVbQ08v5c,1502 +pip/_vendor/progress/helpers.py,sha256=FehfwZTv-5cCfsbcMlvlUkm3xZ0cRhsev6XVpmeTF4c,2854 +pip/_vendor/progress/spinner.py,sha256=iCVtUQbaJUFHTjn1ZLPQLPYeao4lC9aXAa_HxIeUK6k,1314 +pip/_vendor/requests/__init__.py,sha256=Cde-qxOWcslaEcPvKAJQPFbY8_va8PMbU7Rssr7vViI,2326 +pip/_vendor/requests/adapters.py,sha256=DJdgax91PyS2s6_oZPELbuLWNlM2xGguNu62sqcOUik,19740 +pip/_vendor/requests/api.py,sha256=PgminOpD8hLLKLNs0RWLKr1HpNc4Qxr_6uen8q2c9CI,5794 +pip/_vendor/requests/auth.py,sha256=eBLtJlcTZxRG7xKXCvGQBLO9a-PxFgMf2qTUbtZwMJM,8175 +pip/_vendor/requests/cacert.pem,sha256=5xzWFRrSP0ZsXiW6emg8UQ_w497lT4qWCv32OO8R1ME,344712 +pip/_vendor/requests/certs.py,sha256=Aa-oStu9f2lVi8VM9Aw1xaAtTIz7bhu5CGKNPEW1waM,625 +pip/_vendor/requests/compat.py,sha256=0cgWB43LEX5OrX1O4k-bPbFlIbWXgEd412DSDJtF1Y8,1687 +pip/_vendor/requests/cookies.py,sha256=awMI0hm3SKheMEDTqO8AIadc2XmnCGKPCTNw_4hlM3Q,18208 +pip/_vendor/requests/exceptions.py,sha256=x-MGvDASYKSstuCNYTA5IT_EAcxTp5knE3WPMrgkrlI,2860 +pip/_vendor/requests/hooks.py,sha256=HXAHoC1FNTFRZX6-lNdvPM7Tst4kvGwYTN-AOKRxoRU,767 +pip/_vendor/requests/models.py,sha256=YHuL2khGDFxeWc-NMJIcfFqvYJ0dKs1mXfj1Fuff1J8,30532 +pip/_vendor/requests/sessions.py,sha256=H7HpKRLKeu1MSH5W1-PI2GMCFLN4bz5i3OFqjjgzE5k,25609 +pip/_vendor/requests/status_codes.py,sha256=uwVHcMPkHV3FElDLlnDTH3KULZIAGxaovbBxrjWm8N0,3316 +pip/_vendor/requests/structures.py,sha256=yexCvWbX40M6E8mLQOpAGZZ-ZoAnyaT2dni-Bp-b42g,3012 +pip/_vendor/requests/utils.py,sha256=9d3jqnA8avsF9N1QPmsk2pJgo2pxuExrN2hoIhtLggY,24163 +pip/_vendor/requests/packages/__init__.py,sha256=CVheqNRcXIkAi5037RhxeqbAqd0QhrK1o9R9kS2xvuI,1384 +pip/_vendor/requests/packages/chardet/__init__.py,sha256=XuTKCYOR7JwsoHxqZTYH86LVyMDbDI3s1s0W_qoGEBM,1295 +pip/_vendor/requests/packages/chardet/big5freq.py,sha256=D8oTdz-GM7Jg8TsaWJDm65vM_OLHC3xub6qUJ3rOgsQ,82594 +pip/_vendor/requests/packages/chardet/big5prober.py,sha256=XX96C--6WKYW36mL-z7pJSAtc169Z8ZImByCP4pEN9A,1684 +pip/_vendor/requests/packages/chardet/chardetect.py,sha256=f4299UZG6uWd3i3r_N0OdrFj2sA9JFI54PAmDLAFmWA,2504 +pip/_vendor/requests/packages/chardet/chardistribution.py,sha256=cUARQFr1oTLXeJCDQrDRkUP778AvSMzhSCnG8VLCV58,9226 +pip/_vendor/requests/packages/chardet/charsetgroupprober.py,sha256=0lKk7VE516fgMw119tNefFqLOxKfIE9WfdkpIT69OKU,3791 +pip/_vendor/requests/packages/chardet/charsetprober.py,sha256=Z48o2KiOj23FNqYH8FqzhH5m1qdm3rI8DcTm2Yqtklg,1902 +pip/_vendor/requests/packages/chardet/codingstatemachine.py,sha256=E85rYhHVMw9xDEJVgiQhp0OnLGr6i2r8_7QOWMKTH08,2318 +pip/_vendor/requests/packages/chardet/compat.py,sha256=5mm6yrHwef1JEG5OxkPJlSq5lkjLVpEGh3iPgFBkpkM,1157 +pip/_vendor/requests/packages/chardet/constants.py,sha256=-UnY8U7EP7z9fTyd09yq35BEkSFEAUAiv9ohd1DW1s4,1335 +pip/_vendor/requests/packages/chardet/cp949prober.py,sha256=FMvdLyB7fejPXRsTbca7LK1P3RUvvssmjUNyaEfz8zY,1782 +pip/_vendor/requests/packages/chardet/escprober.py,sha256=q5TcQKeVq31WxrW7Sv8yjpZkjEoaHO8S92EJZ9hodys,3187 +pip/_vendor/requests/packages/chardet/escsm.py,sha256=7iljEKN8lXTh8JFXPUSwlibMno6R6ksq4evLxbkzfro,7839 +pip/_vendor/requests/packages/chardet/eucjpprober.py,sha256=5IpfSEjAb7h3hcGMd6dkU80O900C2N6xku28rdYFKuc,3678 +pip/_vendor/requests/packages/chardet/euckrfreq.py,sha256=T5saK5mImySG5ygQPtsp6o2uKulouCwYm2ElOyFkJqU,45978 +pip/_vendor/requests/packages/chardet/euckrprober.py,sha256=Wo7dnZ5Erw_nB4H-m5alMiOxOuJUmGHlwCSaGqExDZA,1675 +pip/_vendor/requests/packages/chardet/euctwfreq.py,sha256=G_I0BW9i1w0ONeeUwIYqV7_U09buIHdqh-wNHVaql7I,34872 +pip/_vendor/requests/packages/chardet/euctwprober.py,sha256=upS2P6GuT5ujOxXYw-RJLcT7A4PTuo27KGUKU4UZpIQ,1676 +pip/_vendor/requests/packages/chardet/gb2312freq.py,sha256=M2gFdo_qQ_BslStEchrPW5CrPEZEacC0uyDLw4ok-kY,36011 +pip/_vendor/requests/packages/chardet/gb2312prober.py,sha256=VWnjoRa83Y6V6oczMaxyUr0uy48iCnC2nzk9zfEIRHc,1681 +pip/_vendor/requests/packages/chardet/hebrewprober.py,sha256=8pdoUfsVXf_L4BnJde_BewS6H2yInV5688eu0nFhLHY,13359 +pip/_vendor/requests/packages/chardet/jisfreq.py,sha256=ZcL4R5ekHHbP2KCYGakVMBsiKqZZZAABzhwi-uRkOps,47315 +pip/_vendor/requests/packages/chardet/jpcntx.py,sha256=yftmp0QaF6RJO5SJs8I7LU5AF4rwP23ebeCQL4BM1OY,19348 +pip/_vendor/requests/packages/chardet/langbulgarianmodel.py,sha256=ZyPsA796MSVhYdfWhMCgKWckupAKAnKqWcE3Cl3ej6o,12784 +pip/_vendor/requests/packages/chardet/langcyrillicmodel.py,sha256=fkcd5OvogUp-GrNDWAZPgkYsSRCD2omotAEvqjlmLKE,17725 +pip/_vendor/requests/packages/chardet/langgreekmodel.py,sha256=QHMy31CH_ot67UCtmurCEKqKx2WwoaKrw2YCYYBK2Lw,12628 +pip/_vendor/requests/packages/chardet/langhebrewmodel.py,sha256=4ASl5vzKJPng4H278VHKtRYC03TpQpenlHTcsmZH1rE,11318 +pip/_vendor/requests/packages/chardet/langhungarianmodel.py,sha256=SXwuUzh49_cBeMXhshRHdrhlkz0T8_pZWV_pdqBKNFk,12536 +pip/_vendor/requests/packages/chardet/langthaimodel.py,sha256=-k7djh3dGKngAGnt3WfuoJN7acDcWcmHAPojhaUd7q4,11275 +pip/_vendor/requests/packages/chardet/latin1prober.py,sha256=238JHOxH8aRudJY2NmeSv5s7i0Qe3GuklIU3HlYybvg,5232 +pip/_vendor/requests/packages/chardet/mbcharsetprober.py,sha256=9rOCjDVsmSMp6e7q2syqak22j7lrbUZhJhMee2gbVL0,3268 +pip/_vendor/requests/packages/chardet/mbcsgroupprober.py,sha256=SHRzNPLpDXfMJLA8phCHVU0WgqbgDCNxDQMolGX_7yk,1967 +pip/_vendor/requests/packages/chardet/mbcssm.py,sha256=IKwJXyxu34n6NojmxVxC60MLFtJKm-hIfxaFEnb3uBA,19590 +pip/_vendor/requests/packages/chardet/sbcharsetprober.py,sha256=Xq0lODqJnDgxglBiQI4BqTFiPbn63-0a5XNA5-hVu7U,4793 +pip/_vendor/requests/packages/chardet/sbcsgroupprober.py,sha256=8hLyH8RAG-aohBo7o_KciWVgRo42ZE_zEtuNG1JMRYI,3291 +pip/_vendor/requests/packages/chardet/sjisprober.py,sha256=UYOmiMDzttYIkSDoOB08UEagivJpUXz4tuWiWzTiOr8,3764 +pip/_vendor/requests/packages/chardet/universaldetector.py,sha256=h-E2x6XSCzlNjycYWG0Fe4Cf1SGdaIzUNu2HCphpMZA,6840 +pip/_vendor/requests/packages/chardet/utf8prober.py,sha256=7tdNZGrJY7jZUBD483GGMkiP0Tx8Fp-cGvWHoAsilHg,2652 +pip/_vendor/requests/packages/urllib3/__init__.py,sha256=EF9pbHgMzqQek2Y6EZ82A8B6wETFeW7bK0K-HoZ3Ffo,2852 +pip/_vendor/requests/packages/urllib3/_collections.py,sha256=RP-cHyTx4AgYwvoETK8q1IVRbWFJnE0VV692ZHSbU68,10553 +pip/_vendor/requests/packages/urllib3/connection.py,sha256=QCmkelYgtbc06DfJtgs22na78kRTLCTbLb-OSWLbt-A,11617 +pip/_vendor/requests/packages/urllib3/connectionpool.py,sha256=fls19n1Y4jnwOBsZz_9F01i08xH2gZXEIyyDmWd-mKU,33591 +pip/_vendor/requests/packages/urllib3/exceptions.py,sha256=zGjhZCR1wefEnCN5b7WouQ3UhXesJ2bRKYIeWusaFJs,5599 +pip/_vendor/requests/packages/urllib3/fields.py,sha256=WUMvCLvnw7XemBq6AmCgNPJwyIJL_vWaMHaA2FLlscM,5931 +pip/_vendor/requests/packages/urllib3/filepost.py,sha256=NvLlFsdt8ih_Q4S2ekQF3CJG0nOXs32YI-G04_AdT2g,2320 +pip/_vendor/requests/packages/urllib3/poolmanager.py,sha256=9Uf0fUk0aR_s1auXgwceoN2gbaIQ08lrum_cGEA9-_U,13092 +pip/_vendor/requests/packages/urllib3/request.py,sha256=jET7OvA3FSjxABBRGhCyMdPvM9XuJA6df9gRhkJiJiY,5988 +pip/_vendor/requests/packages/urllib3/response.py,sha256=wxJSV_6pyh6Cgx7XFVGpNhpZCbh4eL7lCSFaU4ixXXc,18615 +pip/_vendor/requests/packages/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/requests/packages/urllib3/contrib/appengine.py,sha256=NdN_xOgDLMadUPe_dN3wdan_DH9-fxVNqFgq19tbqQs,7937 +pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py,sha256=r-vMDMXAGbix9a7-IhbKVTATmAst-5g4hKYOLf8Kd5M,4531 +pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py,sha256=JsdAh0gL4XvQzhOEBRoFtJN91qLf1LFIDEFZs95445I,11778 +pip/_vendor/requests/packages/urllib3/contrib/socks.py,sha256=uPHtE6R8uyUbD9R8l2wO80c87WDGZ9rou3kNOwV74eA,5668 +pip/_vendor/requests/packages/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 +pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 +pip/_vendor/requests/packages/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py,sha256=cOWMIn1orgJoA35p6pSzO_-Dc6iOX9Dhl6D2sL9b_2o,460 +pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=fK28k37hL7-D79v9iM2fHgNK9Q1Pw0M7qVRL4rkfFjQ,3778 +pip/_vendor/requests/packages/urllib3/util/__init__.py,sha256=n2QE9_0Bb6u8tf7LUc4qKe8V-Hz9G8lEOc9j_30Q8d0,892 +pip/_vendor/requests/packages/urllib3/util/connection.py,sha256=7B5Mmepg5Xd399VKE__VHxD2ObapYFrB3mWJ_EnIebs,4744 +pip/_vendor/requests/packages/urllib3/util/request.py,sha256=ZMDewRK-mjlK72szGIIjzYnLIn-zPP0WgJUMjKeZ6Tg,2128 +pip/_vendor/requests/packages/urllib3/util/response.py,sha256=1UFd5TIp9MyBp4xgnZoyQZscZVPPr0tWRaXNR5w_vds,2165 +pip/_vendor/requests/packages/urllib3/util/retry.py,sha256=5eA3GHR_L14qz66NU6gr-v5VbKYsvdEqOvCcsx1oLKo,10664 +pip/_vendor/requests/packages/urllib3/util/ssl_.py,sha256=7xR_jvQLTQA1U006wJ1bl2KuLGnD1qQvUcFM2uysedw,11622 +pip/_vendor/requests/packages/urllib3/util/timeout.py,sha256=ioAIYptFyBG7eU_r8_ZmO45hpj1dJE6WCvrGR9dNFjs,9596 +pip/_vendor/requests/packages/urllib3/util/url.py,sha256=EcX4ZfmgKWcqM4sY9FlC-yN4y_snuURPV0TpUPHNjnc,5879 +pip/_vendor/webencodings/__init__.py,sha256=t7rAQQxXwalY-ak9hTl73qHjhia9UH-sL-e00qQrBpo,10576 +pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 +pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 +pip/_vendor/webencodings/tests.py,sha256=7vTk7LgOJn_t1XtT_viofZlEJ7cJCzPe_hvVHOkcQl8,6562 +pip/_vendor/webencodings/x_user_defined.py,sha256=72cfPRhbfkRCGkkA8ZnvVV7UnoiLb5uPMhXwhrXiLPk,4306 +pip/commands/__init__.py,sha256=2Uq3HCdjchJD9FL1LB7rd5v6UySVAVizX0W3EX3hIoE,2244 +pip/commands/check.py,sha256=-A7GI1-WZBh9a4P6UoH_aR-J7I8Lz8ly7m3wnCjmevs,1382 +pip/commands/completion.py,sha256=kkPgVX7SUcJ_8Juw5GkgWaxHN9_45wmAr9mGs1zXEEs,2453 +pip/commands/download.py,sha256=8RuuPmSYgAq3iEDTqZY_1PDXRqREdUULHNjWJeAv7Mo,7810 +pip/commands/freeze.py,sha256=h6-yFMpjCjbNj8-gOm5UuoF6cg14N5rPV4TCi3_CeuI,2835 +pip/commands/hash.py,sha256=MCt4jEFyfoce0lVeNEz1x49uaTY-VDkKiBvvxrVcHkw,1597 +pip/commands/help.py,sha256=84HWkEdnGP_AEBHnn8gJP2Te0XTXRKFoXqXopbOZTNo,982 +pip/commands/install.py,sha256=ovG9p9n1X2NPqMgFVtSuT9kMbLAdx1r3YSSiXSvgOKI,17412 +pip/commands/list.py,sha256=93bCiFyt2Qut_YHkYHJMZHpXladmxsjS-yOtZeb3uqI,11369 +pip/commands/search.py,sha256=oTs9QNdefnrmCV_JeftG0PGiMuYVmiEDF1OUaYsmDao,4502 +pip/commands/show.py,sha256=ZYM57_7U8KP9MQIIyHKQdZxmiEZByy-DRzB697VFoTY,5891 +pip/commands/uninstall.py,sha256=tz8cXz4WdpUdnt3RvpdQwH6_SNMB50egBIZWa1dwfcc,2884 +pip/commands/wheel.py,sha256=z5SEhws2YRMb0Ml1IEkg6jFZMLRpLl86bHCrQbYt5zo,7729 +pip/compat/__init__.py,sha256=2Xs_IpsmdRgHbQgQO0c8_lPvHJnQXHyGWxPbLbYJL4c,4672 +pip/compat/dictconfig.py,sha256=dRrelPDWrceDSzFT51RTEVY2GuM7UDyc5Igh_tn4Fvk,23096 +pip/models/__init__.py,sha256=0Rs7_RA4DxeOkWT5Cq4CQzDrSEhvYcN3TH2cazr72PE,71 +pip/models/index.py,sha256=pUfbO__v3mD9j-2n_ClwPS8pVyx4l2wIwyvWt8GMCRA,487 +pip/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/operations/check.py,sha256=uwUN9cs1sPo7c0Sj6pRrSv7b22Pk29SXUImTelVchMQ,1590 +pip/operations/freeze.py,sha256=k-7w7LsM-RpPv7ERBzHiPpYkH-GuYfHLyR-Cp_1VPL0,5194 +pip/req/__init__.py,sha256=vFwZY8_Vc1WU1zFAespg1My_r_AT3n7cN0W9eX0EFqk,276 +pip/req/req_file.py,sha256=fG9MDsXUNPhmGwxUiwrIXEynyD8Q7s3L47-hLZPDXq0,11926 +pip/req/req_install.py,sha256=gYrH-lwQMmt55VVbav_EtRIPu94cQbHFHm_Kq6AeHbg,46487 +pip/req/req_set.py,sha256=jHspXqcA2FxcF05dgUIAZ5huYPv6bn0wRUX0Z7PKmaA,34462 +pip/req/req_uninstall.py,sha256=fdH2VgCjEC8NRYDS7fRu3ZJaBBUEy-N5muwxDX5MBNM,6897 +pip/utils/__init__.py,sha256=HX_wYS15oiYOz-H3qG1Kbi1CY7AGWCNK5jloiD0fauc,27187 +pip/utils/appdirs.py,sha256=kj2LK-I2fC5QnEh_A_v-ev_IQMcXaWWF5DE39sNvCLQ,8811 +pip/utils/build.py,sha256=4smLRrfSCmXmjEnVnMFh2tBEpNcSLRe6J0ejZJ-wWJE,1312 +pip/utils/deprecation.py,sha256=X_FMjtDbMJqfqEkdRrki-mYyIdPB6I6DHUTCA_ChY6M,2232 +pip/utils/encoding.py,sha256=NQxGiFS5GbeAveLZTnx92t5r0PYqvt0iRnP2u9SGG1w,971 +pip/utils/filesystem.py,sha256=ZEVBuYM3fqr2_lgOESh4Y7fPFszGD474zVm_M3Mb5Tk,899 +pip/utils/glibc.py,sha256=jcQYjt_oJLPKVZB28Kauy4Sw70zS-wawxoU1HHX36_0,2939 +pip/utils/hashes.py,sha256=oMk7cd3PbJgzpSQyXq1MytMud5f6H5Oa2YY5hYuCq6I,2866 +pip/utils/logging.py,sha256=7yWu4gZw-Qclj7X80QVdpGWkdTWGKT4LiUVKcE04pro,3327 +pip/utils/outdated.py,sha256=fNwOCL5r2EftPGhgCYGMKu032HC8cV-JAr9lp0HmToM,5455 +pip/utils/packaging.py,sha256=qhmli14odw6DIhWJgQYS2Q0RrSbr8nXNcG48f5yTRms,2080 +pip/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 +pip/utils/ui.py,sha256=pbDkSAeumZ6jdZcOJ2yAbx8iBgeP2zfpqNnLJK1gskQ,11597 +pip/vcs/__init__.py,sha256=WafFliUTHMmsSISV8PHp1M5EXDNSWyJr78zKaQmPLdY,12374 +pip/vcs/bazaar.py,sha256=tYTwc4b4off8mr0O2o8SiGejqBDJxcbDBMSMd9-ISYc,3803 +pip/vcs/git.py,sha256=5LfWryi78A-2ULjEZJvCTarJ_3l8venwXASlwm8hiug,11197 +pip/vcs/mercurial.py,sha256=xG6rDiwHCRytJEs23SIHBXl_SwQo2jkkdD_6rVVP5h4,3472 +pip/vcs/subversion.py,sha256=GAuX2Sk7IZvJyEzENKcVld_wGBrQ3fpXDlXjapZEYdI,9350 +pip-9.0.1.dist-info/DESCRIPTION.rst,sha256=Va8Wj1XBpTbVQ2Z41mZRJdALEeziiS_ZewWn1H2ecY4,1287 +pip-9.0.1.dist-info/METADATA,sha256=mvs_tLoKAbECXY_6QHiVWQsagSL-1UjolQTpScT8JSk,2529 +pip-9.0.1.dist-info/RECORD,, +pip-9.0.1.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +pip-9.0.1.dist-info/entry_points.txt,sha256=GWc-Wb9WUKZ1EuVWNz-G0l3BeIpbNJLx0OJbZ61AAV0,68 +pip-9.0.1.dist-info/metadata.json,sha256=aqvkETDy4mHUBob-2Fn5WWlXORi_M2OSfQ2HQCUU_Fk,1565 +pip-9.0.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +../../Scripts/pip.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 +../../Scripts/pip3.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 +../../Scripts/pip3.6.exe,sha256=nrS8R1QK761ecBuzEMxpQi3fxfBszhmuBNRuOUg-OhI,98144 +pip-9.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/commands/__pycache__/check.cpython-36.pyc,, +pip/commands/__pycache__/completion.cpython-36.pyc,, +pip/commands/__pycache__/download.cpython-36.pyc,, +pip/commands/__pycache__/freeze.cpython-36.pyc,, +pip/commands/__pycache__/hash.cpython-36.pyc,, +pip/commands/__pycache__/help.cpython-36.pyc,, +pip/commands/__pycache__/install.cpython-36.pyc,, +pip/commands/__pycache__/list.cpython-36.pyc,, +pip/commands/__pycache__/search.cpython-36.pyc,, +pip/commands/__pycache__/show.cpython-36.pyc,, +pip/commands/__pycache__/uninstall.cpython-36.pyc,, +pip/commands/__pycache__/wheel.cpython-36.pyc,, +pip/commands/__pycache__/__init__.cpython-36.pyc,, +pip/compat/__pycache__/dictconfig.cpython-36.pyc,, +pip/compat/__pycache__/__init__.cpython-36.pyc,, +pip/models/__pycache__/index.cpython-36.pyc,, +pip/models/__pycache__/__init__.cpython-36.pyc,, +pip/operations/__pycache__/check.cpython-36.pyc,, +pip/operations/__pycache__/freeze.cpython-36.pyc,, +pip/operations/__pycache__/__init__.cpython-36.pyc,, +pip/req/__pycache__/req_file.cpython-36.pyc,, +pip/req/__pycache__/req_install.cpython-36.pyc,, +pip/req/__pycache__/req_set.cpython-36.pyc,, +pip/req/__pycache__/req_uninstall.cpython-36.pyc,, +pip/req/__pycache__/__init__.cpython-36.pyc,, +pip/utils/__pycache__/appdirs.cpython-36.pyc,, +pip/utils/__pycache__/build.cpython-36.pyc,, +pip/utils/__pycache__/deprecation.cpython-36.pyc,, +pip/utils/__pycache__/encoding.cpython-36.pyc,, +pip/utils/__pycache__/filesystem.cpython-36.pyc,, +pip/utils/__pycache__/glibc.cpython-36.pyc,, +pip/utils/__pycache__/hashes.cpython-36.pyc,, +pip/utils/__pycache__/logging.cpython-36.pyc,, +pip/utils/__pycache__/outdated.cpython-36.pyc,, +pip/utils/__pycache__/packaging.cpython-36.pyc,, +pip/utils/__pycache__/setuptools_build.cpython-36.pyc,, +pip/utils/__pycache__/ui.cpython-36.pyc,, +pip/utils/__pycache__/__init__.cpython-36.pyc,, +pip/vcs/__pycache__/bazaar.cpython-36.pyc,, +pip/vcs/__pycache__/git.cpython-36.pyc,, +pip/vcs/__pycache__/mercurial.cpython-36.pyc,, +pip/vcs/__pycache__/subversion.cpython-36.pyc,, +pip/vcs/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-36.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-36.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/compat.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-36.pyc,, +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/ansi.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/ansitowin32.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/initialise.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/win32.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/winterm.cpython-36.pyc,, +pip/_vendor/colorama/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/distlib/_backport/__pycache__/misc.cpython-36.pyc,, +pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-36.pyc,, +pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-36.pyc,, +pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-36.pyc,, +pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-36.pyc,, +pip/_vendor/distlib/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/base.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/lint.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-36.pyc,, +pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-36.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-36.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-36.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-36.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-36.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-36.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-36.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-36.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/py.cpython-36.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-36.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/constants.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/html5parser.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/serializer.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/_inputstream.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/_utils.cpython-36.pyc,, +pip/_vendor/html5lib/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/linklockfile.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/pidlockfile.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/sqlitelockfile.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/symlinklockfile.cpython-36.pyc,, +pip/_vendor/lockfile/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/_compat.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/__about__.cpython-36.pyc,, +pip/_vendor/packaging/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/progress/__pycache__/bar.cpython-36.pyc,, +pip/_vendor/progress/__pycache__/counter.cpython-36.pyc,, +pip/_vendor/progress/__pycache__/helpers.cpython-36.pyc,, +pip/_vendor/progress/__pycache__/spinner.cpython-36.pyc,, +pip/_vendor/progress/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/big5freq.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/big5prober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/chardetect.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/chardistribution.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/charsetgroupprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/charsetprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/codingstatemachine.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/compat.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/constants.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/cp949prober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/escprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/escsm.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/eucjpprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/euckrfreq.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/euckrprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/euctwfreq.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/euctwprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/gb2312freq.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/gb2312prober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/hebrewprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/jisfreq.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/jpcntx.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langbulgarianmodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langcyrillicmodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langgreekmodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langhebrewmodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langhungarianmodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/langthaimodel.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/latin1prober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/mbcharsetprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/mbcsgroupprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/mbcssm.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/sbcharsetprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/sbcsgroupprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/sjisprober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/universaldetector.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/utf8prober.cpython-36.pyc,, +pip/_vendor/requests/packages/chardet/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/contrib/__pycache__/appengine.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/contrib/__pycache__/ntlmpool.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/contrib/__pycache__/pyopenssl.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/contrib/__pycache__/socks.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/contrib/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/packages/__pycache__/ordered_dict.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/packages/__pycache__/six.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/packages/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/connection.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/request.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/response.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/retry.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/ssl_.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/timeout.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/url.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/util/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/connection.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/connectionpool.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/exceptions.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/fields.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/filepost.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/poolmanager.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/request.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/response.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/_collections.cpython-36.pyc,, +pip/_vendor/requests/packages/urllib3/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/packages/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-36.pyc,, +pip/_vendor/requests/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/webencodings/__pycache__/labels.cpython-36.pyc,, +pip/_vendor/webencodings/__pycache__/mklabels.cpython-36.pyc,, +pip/_vendor/webencodings/__pycache__/tests.cpython-36.pyc,, +pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-36.pyc,, +pip/_vendor/webencodings/__pycache__/__init__.cpython-36.pyc,, +pip/_vendor/__pycache__/appdirs.cpython-36.pyc,, +pip/_vendor/__pycache__/distro.cpython-36.pyc,, +pip/_vendor/__pycache__/ipaddress.cpython-36.pyc,, +pip/_vendor/__pycache__/ordereddict.cpython-36.pyc,, +pip/_vendor/__pycache__/pyparsing.cpython-36.pyc,, +pip/_vendor/__pycache__/re-vendor.cpython-36.pyc,, +pip/_vendor/__pycache__/retrying.cpython-36.pyc,, +pip/_vendor/__pycache__/six.cpython-36.pyc,, +pip/_vendor/__pycache__/__init__.cpython-36.pyc,, +pip/__pycache__/basecommand.cpython-36.pyc,, +pip/__pycache__/baseparser.cpython-36.pyc,, +pip/__pycache__/cmdoptions.cpython-36.pyc,, +pip/__pycache__/download.cpython-36.pyc,, +pip/__pycache__/exceptions.cpython-36.pyc,, +pip/__pycache__/index.cpython-36.pyc,, +pip/__pycache__/locations.cpython-36.pyc,, +pip/__pycache__/pep425tags.cpython-36.pyc,, +pip/__pycache__/status_codes.cpython-36.pyc,, +pip/__pycache__/wheel.cpython-36.pyc,, +pip/__pycache__/__init__.cpython-36.pyc,, +pip/__pycache__/__main__.cpython-36.pyc,, diff --git a/website/web/Lib/site-packages/pkg_resources/_vendor/pyparsing.py b/website/web/Lib/site-packages/pkg_resources/_vendor/pyparsing.py index cb46d411a..a21224359 100644 --- a/website/web/Lib/site-packages/pkg_resources/_vendor/pyparsing.py +++ b/website/web/Lib/site-packages/pkg_resources/_vendor/pyparsing.py @@ -1,5696 +1,5696 @@ -# module pyparsing.py -# -# Copyright (c) 2003-2016 Paul T. McGuire -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__doc__ = \ -""" -pyparsing module - Classes and methods to define and execute parsing grammars - -The pyparsing module is an alternative approach to creating and executing simple grammars, -vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you -don't need to learn a new syntax for defining grammars or matching expressions - the parsing module -provides a library of classes that you use to construct the grammar directly in Python. - -Here is a program to parse "Hello, World!" (or any greeting of the form -C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements -(L{'+'} operator gives L{And} expressions, strings are auto-converted to -L{Literal} expressions):: - - from pyparsing import Word, alphas - - # define grammar of a greeting - greet = Word(alphas) + "," + Word(alphas) + "!" - - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - -The program outputs the following:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - -The Python representation of the grammar is quite readable, owing to the self-explanatory -class names, and the use of '+', '|' and '^' operators. - -The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an -object with named attributes. - -The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - - quoted strings - - embedded comments -""" - -__version__ = "2.1.10" -__versionTime__ = "07 Oct 2016 01:31 UTC" -__author__ = "Paul McGuire " - -import string -from weakref import ref as wkref -import copy -import sys -import warnings -import re -import sre_constants -import collections -import pprint -import traceback -import types -from datetime import datetime - -try: - from _thread import RLock -except ImportError: - from threading import RLock - -try: - from collections import OrderedDict as _OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict as _OrderedDict - except ImportError: - _OrderedDict = None - -#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) - -__all__ = [ -'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', -'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', -'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', -'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', -'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', -'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', -'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', -'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', -'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', -'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', -'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', -'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', -'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', -'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', -'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', -'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', -'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', -'CloseMatch', 'tokenMap', 'pyparsing_common', -] - -system_version = tuple(sys.version_info)[:3] -PY_3 = system_version[0] == 3 -if PY_3: - _MAX_INT = sys.maxsize - basestring = str - unichr = chr - _ustr = str - - # build list of single arg builtins, that can be used as parse actions - singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] - -else: - _MAX_INT = sys.maxint - range = xrange - - def _ustr(obj): - """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries - str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It - then < returns the unicode object | encodes it with the default encoding | ... >. - """ - if isinstance(obj,unicode): - return obj - - try: - # If this works, then _ustr(obj) has the same behaviour as str(obj), so - # it won't break any existing code. - return str(obj) - - except UnicodeEncodeError: - # Else encode it - ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') - xmlcharref = Regex('&#\d+;') - xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) - return xmlcharref.transformString(ret) - - # build list of single arg builtins, tolerant of Python version, that can be used as parse actions - singleArgBuiltins = [] - import __builtin__ - for fname in "sum len sorted reversed list tuple set any all min max".split(): - try: - singleArgBuiltins.append(getattr(__builtin__,fname)) - except AttributeError: - continue - -_generatorType = type((y for y in range(1))) - -def _xml_escape(data): - """Escape &, <, >, ", ', etc. in a string of data.""" - - # ampersand must be replaced first - from_symbols = '&><"\'' - to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) - for from_,to_ in zip(from_symbols, to_symbols): - data = data.replace(from_, to_) - return data - -class _Constants(object): - pass - -alphas = string.ascii_uppercase + string.ascii_lowercase -nums = "0123456789" -hexnums = nums + "ABCDEFabcdef" -alphanums = alphas + nums -_bslash = chr(92) -printables = "".join(c for c in string.printable if c not in string.whitespace) - -class ParseBaseException(Exception): - """base exception class for all parsing runtime exceptions""" - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, pstr, loc=0, msg=None, elem=None ): - self.loc = loc - if msg is None: - self.msg = pstr - self.pstr = "" - else: - self.msg = msg - self.pstr = pstr - self.parserElement = elem - self.args = (pstr, loc, msg) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) - - def __getattr__( self, aname ): - """supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - """ - if( aname == "lineno" ): - return lineno( self.loc, self.pstr ) - elif( aname in ("col", "column") ): - return col( self.loc, self.pstr ) - elif( aname == "line" ): - return line( self.loc, self.pstr ) - else: - raise AttributeError(aname) - - def __str__( self ): - return "%s (at char %d), (line:%d, col:%d)" % \ - ( self.msg, self.loc, self.lineno, self.column ) - def __repr__( self ): - return _ustr(self) - def markInputline( self, markerString = ">!<" ): - """Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join((line_str[:line_column], - markerString, line_str[line_column:])) - return line_str.strip() - def __dir__(self): - return "lineno col line".split() + dir(type(self)) - -class ParseException(ParseBaseException): - """ - Exception thrown when parse expressions don't match class; - supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - - Example:: - try: - Word(nums).setName("integer").parseString("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.col)) - - prints:: - Expected integer (at char 0), (line:1, col:1) - column: 1 - """ - pass - -class ParseFatalException(ParseBaseException): - """user-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately""" - pass - -class ParseSyntaxException(ParseFatalException): - """just like L{ParseFatalException}, but thrown internally when an - L{ErrorStop} ('-' operator) indicates that parsing is to stop - immediately because an unbacktrackable syntax error has been found""" - pass - -#~ class ReparseException(ParseBaseException): - #~ """Experimental class - parse actions can raise this exception to cause - #~ pyparsing to reparse the input string: - #~ - with a modified input string, and/or - #~ - with a modified start location - #~ Set the values of the ReparseException in the constructor, and raise the - #~ exception in a parse action to cause pyparsing to use the new string/location. - #~ Setting the values as None causes no change to be made. - #~ """ - #~ def __init_( self, newstring, restartLoc ): - #~ self.newParseText = newstring - #~ self.reparseLoc = restartLoc - -class RecursiveGrammarException(Exception): - """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" - def __init__( self, parseElementList ): - self.parseElementTrace = parseElementList - - def __str__( self ): - return "RecursiveGrammarException: %s" % self.parseElementTrace - -class _ParseResultsWithOffset(object): - def __init__(self,p1,p2): - self.tup = (p1,p2) - def __getitem__(self,i): - return self.tup[i] - def __repr__(self): - return repr(self.tup[0]) - def setOffset(self,i): - self.tup = (self.tup[0],i) - -class ParseResults(object): - """ - Structured parse results, to provide multiple means of access to the parsed data: - - as a list (C{len(results)}) - - by list index (C{results[0], results[1]}, etc.) - - by attribute (C{results.} - see L{ParserElement.setResultsName}) - - Example:: - integer = Word(nums) - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - # equivalent form: - # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - # parseString returns a ParseResults object - result = date_str.parseString("1999/12/31") - - def test(s, fn=repr): - print("%s -> %s" % (s, fn(eval(s)))) - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - prints:: - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: 31 - - month: 12 - - year: 1999 - """ - def __new__(cls, toklist=None, name=None, asList=True, modal=True ): - if isinstance(toklist, cls): - return toklist - retobj = object.__new__(cls) - retobj.__doinit = True - return retobj - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): - if self.__doinit: - self.__doinit = False - self.__name = None - self.__parent = None - self.__accumNames = {} - self.__asList = asList - self.__modal = modal - if toklist is None: - toklist = [] - if isinstance(toklist, list): - self.__toklist = toklist[:] - elif isinstance(toklist, _generatorType): - self.__toklist = list(toklist) - else: - self.__toklist = [toklist] - self.__tokdict = dict() - - if name is not None and name: - if not modal: - self.__accumNames[name] = 0 - if isinstance(name,int): - name = _ustr(name) # will always return a str, but use _ustr for consistency - self.__name = name - if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): - if isinstance(toklist,basestring): - toklist = [ toklist ] - if asList: - if isinstance(toklist,ParseResults): - self[name] = _ParseResultsWithOffset(toklist.copy(),0) - else: - self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) - self[name].__name = name - else: - try: - self[name] = toklist[0] - except (KeyError,TypeError,IndexError): - self[name] = toklist - - def __getitem__( self, i ): - if isinstance( i, (int,slice) ): - return self.__toklist[i] - else: - if i not in self.__accumNames: - return self.__tokdict[i][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[i] ]) - - def __setitem__( self, k, v, isinstance=isinstance ): - if isinstance(v,_ParseResultsWithOffset): - self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] - sub = v[0] - elif isinstance(k,(int,slice)): - self.__toklist[k] = v - sub = v - else: - self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] - sub = v - if isinstance(sub,ParseResults): - sub.__parent = wkref(self) - - def __delitem__( self, i ): - if isinstance(i,(int,slice)): - mylen = len( self.__toklist ) - del self.__toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i+1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) - else: - del self.__tokdict[i] - - def __contains__( self, k ): - return k in self.__tokdict - - def __len__( self ): return len( self.__toklist ) - def __bool__(self): return ( not not self.__toklist ) - __nonzero__ = __bool__ - def __iter__( self ): return iter( self.__toklist ) - def __reversed__( self ): return iter( self.__toklist[::-1] ) - def _iterkeys( self ): - if hasattr(self.__tokdict, "iterkeys"): - return self.__tokdict.iterkeys() - else: - return iter(self.__tokdict) - - def _itervalues( self ): - return (self[k] for k in self._iterkeys()) - - def _iteritems( self ): - return ((k, self[k]) for k in self._iterkeys()) - - if PY_3: - keys = _iterkeys - """Returns an iterator of all named result keys (Python 3.x only).""" - - values = _itervalues - """Returns an iterator of all named result values (Python 3.x only).""" - - items = _iteritems - """Returns an iterator of all named result key-value tuples (Python 3.x only).""" - - else: - iterkeys = _iterkeys - """Returns an iterator of all named result keys (Python 2.x only).""" - - itervalues = _itervalues - """Returns an iterator of all named result values (Python 2.x only).""" - - iteritems = _iteritems - """Returns an iterator of all named result key-value tuples (Python 2.x only).""" - - def keys( self ): - """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iterkeys()) - - def values( self ): - """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.itervalues()) - - def items( self ): - """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iteritems()) - - def haskeys( self ): - """Since keys() returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return bool(self.__tokdict) - - def pop( self, *args, **kwargs): - """ - Removes and returns item at specified index (default=C{last}). - Supports both C{list} and C{dict} semantics for C{pop()}. If passed no - argument or an integer argument, it will use C{list} semantics - and pop tokens from the list of parsed tokens. If passed a - non-integer argument (most likely a string), it will use C{dict} - semantics and pop the corresponding value from any defined - results names. A second default return value argument is - supported, just as in C{dict.pop()}. - - Example:: - def remove_first(tokens): - tokens.pop(0) - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + OneOrMore(Word(nums)) - print(patt.parseString("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.addParseAction(remove_LABEL) - print(patt.parseString("AAB 123 321").dump()) - prints:: - ['AAB', '123', '321'] - - LABEL: AAB - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k,v in kwargs.items(): - if k == 'default': - args = (args[0], v) - else: - raise TypeError("pop() got an unexpected keyword argument '%s'" % k) - if (isinstance(args[0], int) or - len(args) == 1 or - args[0] in self): - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, defaultValue=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given C{defaultValue} or C{None} if no - C{defaultValue} is specified. - - Similar to C{dict.get()}. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return defaultValue - - def insert( self, index, insStr ): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to C{list.insert()}. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] - """ - self.__toklist.insert(index, insStr) - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) - - def append( self, item ): - """ - Add single element to end of ParseResults list of elements. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] - """ - self.__toklist.append(item) - - def extend( self, itemseq ): - """ - Add sequence of elements to end of ParseResults list of elements. - - Example:: - patt = OneOrMore(Word(alphas)) - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self += itemseq - else: - self.__toklist.extend(itemseq) - - def clear( self ): - """ - Clear all elements and results names. - """ - del self.__toklist[:] - self.__tokdict.clear() - - def __getattr__( self, name ): - try: - return self[name] - except KeyError: - return "" - - if name in self.__tokdict: - if name not in self.__accumNames: - return self.__tokdict[name][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[name] ]) - else: - return "" - - def __add__( self, other ): - ret = self.copy() - ret += other - return ret - - def __iadd__( self, other ): - if other.__tokdict: - offset = len(self.__toklist) - addoffset = lambda a: offset if a<0 else a+offset - otheritems = other.__tokdict.items() - otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) - for (k,vlist) in otheritems for v in vlist] - for k,v in otherdictitems: - self[k] = v - if isinstance(v[0],ParseResults): - v[0].__parent = wkref(self) - - self.__toklist += other.__toklist - self.__accumNames.update( other.__accumNames ) - return self - - def __radd__(self, other): - if isinstance(other,int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__( self ): - return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) - - def __str__( self ): - return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' - - def _asStringList( self, sep='' ): - out = [] - for item in self.__toklist: - if out and sep: - out.append(sep) - if isinstance( item, ParseResults ): - out += item._asStringList() - else: - out.append( _ustr(item) ) - return out - - def asList( self ): - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - patt = OneOrMore(Word(alphas)) - result = patt.parseString("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] - - # Use asList() to create an actual list - result_list = result.asList() - print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] - - def asDict( self ): - """ - Returns the named parse results as a nested dictionary. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.asDict() - print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - if PY_3: - item_fn = self.items - else: - item_fn = self.iteritems - - def toItem(obj): - if isinstance(obj, ParseResults): - if obj.haskeys(): - return obj.asDict() - else: - return [toItem(v) for v in obj] - else: - return obj - - return dict((k,toItem(v)) for k,v in item_fn()) - - def copy( self ): - """ - Returns a new copy of a C{ParseResults} object. - """ - ret = ParseResults( self.__toklist ) - ret.__tokdict = self.__tokdict.copy() - ret.__parent = self.__parent - ret.__accumNames.update( self.__accumNames ) - ret.__name = self.__name - return ret - - def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): - """ - (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. - """ - nl = "\n" - out = [] - namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() - for v in vlist) - nextLevelIndent = indent + " " - - # collapse out indents if formatting is not desired - if not formatted: - indent = "" - nextLevelIndent = "" - nl = "" - - selfTag = None - if doctag is not None: - selfTag = doctag - else: - if self.__name: - selfTag = self.__name - - if not selfTag: - if namedItemsOnly: - return "" - else: - selfTag = "ITEM" - - out += [ nl, indent, "<", selfTag, ">" ] - - for i,res in enumerate(self.__toklist): - if isinstance(res,ParseResults): - if i in namedItems: - out += [ res.asXML(namedItems[i], - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - out += [ res.asXML(None, - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - # individual token, see if there is a name for it - resTag = None - if i in namedItems: - resTag = namedItems[i] - if not resTag: - if namedItemsOnly: - continue - else: - resTag = "ITEM" - xmlBodyText = _xml_escape(_ustr(res)) - out += [ nl, nextLevelIndent, "<", resTag, ">", - xmlBodyText, - "" ] - - out += [ nl, indent, "" ] - return "".join(out) - - def __lookup(self,sub): - for k,vlist in self.__tokdict.items(): - for v,loc in vlist: - if sub is v: - return k - return None - - def getName(self): - """ - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = OneOrMore(user_data) - - result = user_info.parseString("22 111-22-3333 #221B") - for item in result: - print(item.getName(), ':', item[0]) - prints:: - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self.__name: - return self.__name - elif self.__parent: - par = self.__parent() - if par: - return par.__lookup(self) - else: - return None - elif (len(self) == 1 and - len(self.__tokdict) == 1 and - next(iter(self.__tokdict.values()))[0][1] in (0,-1)): - return next(iter(self.__tokdict.keys())) - else: - return None - - def dump(self, indent='', depth=0, full=True): - """ - Diagnostic method for listing out the contents of a C{ParseResults}. - Accepts an optional C{indent} argument so that this string can be embedded - in a nested display of other data. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(result.dump()) - prints:: - ['12', '/', '31', '/', '1999'] - - day: 1999 - - month: 31 - - year: 12 - """ - out = [] - NL = '\n' - out.append( indent+_ustr(self.asList()) ) - if full: - if self.haskeys(): - items = sorted((str(k), v) for k,v in self.items()) - for k,v in items: - if out: - out.append(NL) - out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) - if isinstance(v,ParseResults): - if v: - out.append( v.dump(indent,depth+1) ) - else: - out.append(_ustr(v)) - else: - out.append(repr(v)) - elif any(isinstance(vv,ParseResults) for vv in self): - v = self - for i,vv in enumerate(v): - if isinstance(vv,ParseResults): - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) - else: - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the C{pprint} module. - Accepts additional positional or keyword args as defined for the - C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) - - Example:: - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(delimitedList(term))) - result = func.parseString("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - prints:: - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.asList(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( self.__toklist, - ( self.__tokdict.copy(), - self.__parent is not None and self.__parent() or None, - self.__accumNames, - self.__name ) ) - - def __setstate__(self,state): - self.__toklist = state[0] - (self.__tokdict, - par, - inAccumNames, - self.__name) = state[1] - self.__accumNames = {} - self.__accumNames.update(inAccumNames) - if par is not None: - self.__parent = wkref(par) - else: - self.__parent = None - - def __getnewargs__(self): - return self.__toklist, self.__name, self.__asList, self.__modal - - def __dir__(self): - return (dir(type(self)) + list(self.keys())) - -collections.MutableMapping.register(ParseResults) - -def col (loc,strg): - """Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{ParserElement.parseString}} for more information - on parsing strings containing C{}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - s = strg - return 1 if 0} for more information - on parsing strings containing C{}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - return strg.count("\n",0,loc) + 1 - -def line( loc, strg ): - """Returns the line of text containing loc within a string, counting newlines as line separators. - """ - lastCR = strg.rfind("\n", 0, loc) - nextCR = strg.find("\n", loc) - if nextCR >= 0: - return strg[lastCR+1:nextCR] - else: - return strg[lastCR+1:] - -def _defaultStartDebugAction( instring, loc, expr ): - print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) - -def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): - print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) - -def _defaultExceptionDebugAction( instring, loc, expr, exc ): - print ("Exception raised:" + _ustr(exc)) - -def nullDebugAction(*args): - """'Do-nothing' debug action, to suppress debugging output during parsing.""" - pass - -# Only works on Python 3.x - nonlocal is toxic to Python 2 installs -#~ 'decorator to trim function calls to match the arity of the target' -#~ def _trim_arity(func, maxargs=3): - #~ if func in singleArgBuiltins: - #~ return lambda s,l,t: func(t) - #~ limit = 0 - #~ foundArity = False - #~ def wrapper(*args): - #~ nonlocal limit,foundArity - #~ while 1: - #~ try: - #~ ret = func(*args[limit:]) - #~ foundArity = True - #~ return ret - #~ except TypeError: - #~ if limit == maxargs or foundArity: - #~ raise - #~ limit += 1 - #~ continue - #~ return wrapper - -# this version is Python 2.x-3.x cross-compatible -'decorator to trim function calls to match the arity of the target' -def _trim_arity(func, maxargs=2): - if func in singleArgBuiltins: - return lambda s,l,t: func(t) - limit = [0] - foundArity = [False] - - # traceback return data structure changed in Py3.5 - normalize back to plain tuples - if system_version[:2] >= (3,5): - def extract_stack(limit=0): - # special handling for Python 3.5.0 - extra deep call stack by 1 - offset = -3 if system_version == (3,5,0) else -2 - frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] - return [(frame_summary.filename, frame_summary.lineno)] - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [(frame_summary.filename, frame_summary.lineno)] - else: - extract_stack = traceback.extract_stack - extract_tb = traceback.extract_tb - - # synthesize what would be returned by traceback.extract_stack at the call to - # user's parse action 'func', so that we don't incur call penalty at parse time - - LINE_DIFF = 6 - # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND - # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! - this_line = extract_stack(limit=2)[-1] - pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) - - def wrapper(*args): - while 1: - try: - ret = func(*args[limit[0]:]) - foundArity[0] = True - return ret - except TypeError: - # re-raise TypeErrors if they did not come from our arity testing - if foundArity[0]: - raise - else: - try: - tb = sys.exc_info()[-1] - if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: - raise - finally: - del tb - - if limit[0] <= maxargs: - limit[0] += 1 - continue - raise - - # copy func name to wrapper for sensible debug output - func_name = "" - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - wrapper.__name__ = func_name - - return wrapper - -class ParserElement(object): - """Abstract base level parser element class.""" - DEFAULT_WHITE_CHARS = " \n\t\r" - verbose_stacktrace = False - - @staticmethod - def setDefaultWhitespaceChars( chars ): - r""" - Overrides the default whitespace chars - - Example:: - # default whitespace chars are space, and newline - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] - - # change to just treat newline as significant - ParserElement.setDefaultWhitespaceChars(" \t") - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] - """ - ParserElement.DEFAULT_WHITE_CHARS = chars - - @staticmethod - def inlineLiteralsUsing(cls): - """ - Set class to be used for inclusion of string literals into a parser. - - Example:: - # default literal class used is Literal - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - - # change to Suppress - ParserElement.inlineLiteralsUsing(Suppress) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] - """ - ParserElement._literalStringClass = cls - - def __init__( self, savelist=False ): - self.parseAction = list() - self.failAction = None - #~ self.name = "" # don't define self.name, let subclasses try/except upcall - self.strRepr = None - self.resultsName = None - self.saveAsList = savelist - self.skipWhitespace = True - self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - self.copyDefaultWhiteChars = True - self.mayReturnEmpty = False # used when checking for left-recursion - self.keepTabs = False - self.ignoreExprs = list() - self.debug = False - self.streamlined = False - self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index - self.errmsg = "" - self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) - self.debugActions = ( None, None, None ) #custom debug actions - self.re = None - self.callPreparse = True # used to avoid redundant calls to preParse - self.callDuringTry = False - - def copy( self ): - """ - Make a copy of this C{ParserElement}. Useful for defining different parse actions - for the same parsing pattern, using copies of the original parse element. - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") - integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - - print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) - prints:: - [5120, 100, 655360, 268435456] - Equivalent form of C{expr.copy()} is just C{expr()}:: - integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - """ - cpy = copy.copy( self ) - cpy.parseAction = self.parseAction[:] - cpy.ignoreExprs = self.ignoreExprs[:] - if self.copyDefaultWhiteChars: - cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - return cpy - - def setName( self, name ): - """ - Define name for this expression, makes debugging and exception messages clearer. - - Example:: - Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) - Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) - """ - self.name = name - self.errmsg = "Expected " + self.name - if hasattr(self,"exception"): - self.exception.msg = self.errmsg - return self - - def setResultsName( self, name, listAllMatches=False ): - """ - Define name for referencing matching tokens as a nested attribute - of the returned parse results. - NOTE: this returns a *copy* of the original C{ParserElement} object; - this is so that the client can define a basic element, such as an - integer, and reference it in multiple places with different names. - - You can also set results names using the abbreviated syntax, - C{expr("name")} in place of C{expr.setResultsName("name")} - - see L{I{__call__}<__call__>}. - - Example:: - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - - # equivalent form: - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - """ - newself = self.copy() - if name.endswith("*"): - name = name[:-1] - listAllMatches=True - newself.resultsName = name - newself.modalResults = not listAllMatches - return newself - - def setBreak(self,breakFlag = True): - """Method to invoke the Python pdb debugger when this element is - about to be parsed. Set C{breakFlag} to True to enable, False to - disable. - """ - if breakFlag: - _parseMethod = self._parse - def breaker(instring, loc, doActions=True, callPreParse=True): - import pdb - pdb.set_trace() - return _parseMethod( instring, loc, doActions, callPreParse ) - breaker._originalParseMethod = _parseMethod - self._parse = breaker - else: - if hasattr(self._parse,"_originalParseMethod"): - self._parse = self._parse._originalParseMethod - return self - - def setParseAction( self, *fns, **kwargs ): - """ - Define action to perform when successfully matching parse element definition. - Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, - C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object - If the functions in fns modify the tokens, they can return them as the return - value from fn, and the modified list of tokens will replace the original. - Otherwise, fn does not need to return any value. - - Optional keyword arguments: - - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{parseString}} for more information - on parsing strings containing C{}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - - Example:: - integer = Word(nums) - date_str = integer + '/' + integer + '/' + integer - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - # use parse action to convert to ints at parse time - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - date_str = integer + '/' + integer + '/' + integer - - # note that integer fields are now ints, not strings - date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] - """ - self.parseAction = list(map(_trim_arity, list(fns))) - self.callDuringTry = kwargs.get("callDuringTry", False) - return self - - def addParseAction( self, *fns, **kwargs ): - """ - Add parse action to expression's list of parse actions. See L{I{setParseAction}}. - - See examples in L{I{copy}}. - """ - self.parseAction += list(map(_trim_arity, list(fns))) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def addCondition(self, *fns, **kwargs): - """Add a boolean predicate function to expression's list of parse actions. See - L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, - functions passed to C{addCondition} need to return boolean success/fail of the condition. - - Optional keyword arguments: - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - year_int = integer.copy() - year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") - date_str = year_int + '/' + integer + '/' + integer - - result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) - """ - msg = kwargs.get("message", "failed user-defined condition") - exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException - for fn in fns: - def pa(s,l,t): - if not bool(_trim_arity(fn)(s,l,t)): - raise exc_type(s,l,msg) - self.parseAction.append(pa) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def setFailAction( self, fn ): - """Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - C{fn(s,loc,expr,err)} where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown - The function returns no value. It may throw C{L{ParseFatalException}} - if it is desired to stop parsing immediately.""" - self.failAction = fn - return self - - def _skipIgnorables( self, instring, loc ): - exprsFound = True - while exprsFound: - exprsFound = False - for e in self.ignoreExprs: - try: - while 1: - loc,dummy = e._parse( instring, loc ) - exprsFound = True - except ParseException: - pass - return loc - - def preParse( self, instring, loc ): - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - - if self.skipWhitespace: - wt = self.whiteChars - instrlen = len(instring) - while loc < instrlen and instring[loc] in wt: - loc += 1 - - return loc - - def parseImpl( self, instring, loc, doActions=True ): - return loc, [] - - def postParse( self, instring, loc, tokenlist ): - return tokenlist - - #~ @profile - def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): - debugging = ( self.debug ) #and doActions ) - - if debugging or self.failAction: - #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) - if (self.debugActions[0] ): - self.debugActions[0]( instring, loc, self ) - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - try: - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - except ParseBaseException as err: - #~ print ("Exception raised:", err) - if self.debugActions[2]: - self.debugActions[2]( instring, tokensStart, self, err ) - if self.failAction: - self.failAction( instring, tokensStart, self, err ) - raise - else: - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - if self.mayIndexError or loc >= len(instring): - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - else: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - - tokens = self.postParse( instring, loc, tokens ) - - retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) - if self.parseAction and (doActions or self.callDuringTry): - if debugging: - try: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - except ParseBaseException as err: - #~ print "Exception raised in user parse action:", err - if (self.debugActions[2] ): - self.debugActions[2]( instring, tokensStart, self, err ) - raise - else: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - - if debugging: - #~ print ("Matched",self,"->",retTokens.asList()) - if (self.debugActions[1] ): - self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) - - return loc, retTokens - - def tryParse( self, instring, loc ): - try: - return self._parse( instring, loc, doActions=False )[0] - except ParseFatalException: - raise ParseException( instring, loc, self.errmsg, self) - - def canParseNext(self, instring, loc): - try: - self.tryParse(instring, loc) - except (ParseException, IndexError): - return False - else: - return True - - class _UnboundedCache(object): - def __init__(self): - cache = {} - self.not_in_cache = not_in_cache = object() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - - def clear(self): - cache.clear() - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - - if _OrderedDict is not None: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = _OrderedDict() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - if len(cache) > size: - cache.popitem(False) - - def clear(self): - cache.clear() - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - - else: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = {} - key_fifo = collections.deque([], size) - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - if len(cache) > size: - cache.pop(key_fifo.popleft(), None) - key_fifo.append(key) - - def clear(self): - cache.clear() - key_fifo.clear() - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - - # argument cache for optimizing repeated calls when backtracking through recursive expressions - packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail - packrat_cache_lock = RLock() - packrat_cache_stats = [0, 0] - - # this method gets repeatedly called during backtracking with the same arguments - - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression - def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): - HIT, MISS = 0, 1 - lookup = (self, instring, loc, callPreParse, doActions) - with ParserElement.packrat_cache_lock: - cache = ParserElement.packrat_cache - value = cache.get(lookup) - if value is cache.not_in_cache: - ParserElement.packrat_cache_stats[MISS] += 1 - try: - value = self._parseNoCache(instring, loc, doActions, callPreParse) - except ParseBaseException as pe: - # cache a copy of the exception, without the traceback - cache.set(lookup, pe.__class__(*pe.args)) - raise - else: - cache.set(lookup, (value[0], value[1].copy())) - return value - else: - ParserElement.packrat_cache_stats[HIT] += 1 - if isinstance(value, Exception): - raise value - return (value[0], value[1].copy()) - - _parse = _parseNoCache - - @staticmethod - def resetCache(): - ParserElement.packrat_cache.clear() - ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) - - _packratEnabled = False - @staticmethod - def enablePackrat(cache_size_limit=128): - """Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - cache_size_limit - (default=C{128}) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method C{ParserElement.enablePackrat()}. If - your program uses C{psyco} to "compile as you go", you must call - C{enablePackrat} before calling C{psyco.full()}. If you do not do this, - Python will crash. For best results, call C{enablePackrat()} immediately - after importing pyparsing. - - Example:: - import pyparsing - pyparsing.ParserElement.enablePackrat() - """ - if not ParserElement._packratEnabled: - ParserElement._packratEnabled = True - if cache_size_limit is None: - ParserElement.packrat_cache = ParserElement._UnboundedCache() - else: - ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) - ParserElement._parse = ParserElement._parseCache - - def parseString( self, instring, parseAll=False ): - """ - Execute the parse expression with the given string. - This is the main interface to the client code, once the complete - expression has been built. - - If you want the grammar to require that the entire input string be - successfully parsed, then set C{parseAll} to True (equivalent to ending - the grammar with C{L{StringEnd()}}). - - Note: C{parseString} implicitly calls C{expandtabs()} on the input string, - in order to report proper column numbers in parse actions. - If the input string contains tabs and - the grammar uses parse actions that use the C{loc} argument to index into the - string being parsed, you can ensure you have a consistent view of the input - string by: - - calling C{parseWithTabs} on your grammar before calling C{parseString} - (see L{I{parseWithTabs}}) - - define your parse action using the full C{(s,loc,toks)} signature, and - reference the input string using the parse action's C{s} argument - - explictly expand the tabs in your input string before calling - C{parseString} - - Example:: - Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] - Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text - """ - ParserElement.resetCache() - if not self.streamlined: - self.streamline() - #~ self.saveAsList = True - for e in self.ignoreExprs: - e.streamline() - if not self.keepTabs: - instring = instring.expandtabs() - try: - loc, tokens = self._parse( instring, 0 ) - if parseAll: - loc = self.preParse( instring, loc ) - se = Empty() + StringEnd() - se._parse( instring, loc ) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - else: - return tokens - - def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): - """ - Scan the input string for expression matches. Each match will return the - matching tokens, start location, and end location. May be called with optional - C{maxMatches} argument, to clip scanning after 'n' matches are found. If - C{overlap} is specified, then overlapping matches will be reported. - - Note that the start and end locations are reported relative to the string - being parsed. See L{I{parseString}} for more information on parsing - strings with embedded tabs. - - Example:: - source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" - print(source) - for tokens,start,end in Word(alphas).scanString(source): - print(' '*start + '^'*(end-start)) - print(' '*start + tokens[0]) - - prints:: - - sldjf123lsdjjkf345sldkjf879lkjsfd987 - ^^^^^ - sldjf - ^^^^^^^ - lsdjjkf - ^^^^^^ - sldkjf - ^^^^^^ - lkjsfd - """ - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - - if not self.keepTabs: - instring = _ustr(instring).expandtabs() - instrlen = len(instring) - loc = 0 - preparseFn = self.preParse - parseFn = self._parse - ParserElement.resetCache() - matches = 0 - try: - while loc <= instrlen and matches < maxMatches: - try: - preloc = preparseFn( instring, loc ) - nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) - except ParseException: - loc = preloc+1 - else: - if nextLoc > loc: - matches += 1 - yield tokens, preloc, nextLoc - if overlap: - nextloc = preparseFn( instring, loc ) - if nextloc > loc: - loc = nextLoc - else: - loc += 1 - else: - loc = nextLoc - else: - loc = preloc+1 - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def transformString( self, instring ): - """ - Extension to C{L{scanString}}, to modify matching text with modified tokens that may - be returned from a parse action. To use C{transformString}, define a grammar and - attach a parse action to it that modifies the returned token list. - Invoking C{transformString()} on a target string will then scan for matches, - and replace the matched text patterns according to the logic in the parse - action. C{transformString()} returns the resulting transformed string. - - Example:: - wd = Word(alphas) - wd.setParseAction(lambda toks: toks[0].title()) - - print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) - Prints:: - Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. - """ - out = [] - lastE = 0 - # force preservation of s, to minimize unwanted transformation of string, and to - # keep string locs straight between transformString and scanString - self.keepTabs = True - try: - for t,s,e in self.scanString( instring ): - out.append( instring[lastE:s] ) - if t: - if isinstance(t,ParseResults): - out += t.asList() - elif isinstance(t,list): - out += t - else: - out.append(t) - lastE = e - out.append(instring[lastE:]) - out = [o for o in out if o] - return "".join(map(_ustr,_flatten(out))) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def searchString( self, instring, maxMatches=_MAX_INT ): - """ - Another extension to C{L{scanString}}, simplifying the access to the tokens found - to match the given parse expression. May be called with optional - C{maxMatches} argument, to clip searching after 'n' matches are found. - - Example:: - # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters - cap_word = Word(alphas.upper(), alphas.lower()) - - print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) - prints:: - ['More', 'Iron', 'Lead', 'Gold', 'I'] - """ - try: - return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): - """ - Generator method to split a string using the given expression as a separator. - May be called with optional C{maxsplit} argument, to limit the number of splits; - and the optional C{includeSeparators} argument (default=C{False}), if the separating - matching text should be included in the split results. - - Example:: - punc = oneOf(list(".,;:/-!?")) - print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) - prints:: - ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] - """ - splits = 0 - last = 0 - for t,s,e in self.scanString(instring, maxMatches=maxsplit): - yield instring[last:s] - if includeSeparators: - yield t[0] - last = e - yield instring[last:] - - def __add__(self, other ): - """ - Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement - converts them to L{Literal}s by default. - - Example:: - greet = Word(alphas) + "," + Word(alphas) + "!" - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - Prints:: - Hello, World! -> ['Hello', ',', 'World', '!'] - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return And( [ self, other ] ) - - def __radd__(self, other ): - """ - Implementation of + operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other + self - - def __sub__(self, other): - """ - Implementation of - operator, returns C{L{And}} with error stop - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return And( [ self, And._ErrorStop(), other ] ) - - def __rsub__(self, other ): - """ - Implementation of - operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other - self - - def __mul__(self,other): - """ - Implementation of * operator, allows use of C{expr * 3} in place of - C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer - tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples - may also include C{None} as in: - - C{expr*(n,None)} or C{expr*(n,)} is equivalent - to C{expr*n + L{ZeroOrMore}(expr)} - (read as "at least n instances of C{expr}") - - C{expr*(None,n)} is equivalent to C{expr*(0,n)} - (read as "0 to n instances of C{expr}") - - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} - - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} - - Note that C{expr*(None,n)} does not raise an exception if - more than n exprs exist in the input stream; that is, - C{expr*(None,n)} does not enforce a maximum number of expr - occurrences. If this behavior is desired, then write - C{expr*(None,n) + ~expr} - """ - if isinstance(other,int): - minElements, optElements = other,0 - elif isinstance(other,tuple): - other = (other + (None, None))[:2] - if other[0] is None: - other = (0, other[1]) - if isinstance(other[0],int) and other[1] is None: - if other[0] == 0: - return ZeroOrMore(self) - if other[0] == 1: - return OneOrMore(self) - else: - return self*other[0] + ZeroOrMore(self) - elif isinstance(other[0],int) and isinstance(other[1],int): - minElements, optElements = other - optElements -= minElements - else: - raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) - else: - raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) - - if minElements < 0: - raise ValueError("cannot multiply ParserElement by negative value") - if optElements < 0: - raise ValueError("second tuple value must be greater or equal to first tuple value") - if minElements == optElements == 0: - raise ValueError("cannot multiply ParserElement by 0 or (0,0)") - - if (optElements): - def makeOptionalList(n): - if n>1: - return Optional(self + makeOptionalList(n-1)) - else: - return Optional(self) - if minElements: - if minElements == 1: - ret = self + makeOptionalList(optElements) - else: - ret = And([self]*minElements) + makeOptionalList(optElements) - else: - ret = makeOptionalList(optElements) - else: - if minElements == 1: - ret = self - else: - ret = And([self]*minElements) - return ret - - def __rmul__(self, other): - return self.__mul__(other) - - def __or__(self, other ): - """ - Implementation of | operator - returns C{L{MatchFirst}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return MatchFirst( [ self, other ] ) - - def __ror__(self, other ): - """ - Implementation of | operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other | self - - def __xor__(self, other ): - """ - Implementation of ^ operator - returns C{L{Or}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Or( [ self, other ] ) - - def __rxor__(self, other ): - """ - Implementation of ^ operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other ^ self - - def __and__(self, other ): - """ - Implementation of & operator - returns C{L{Each}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Each( [ self, other ] ) - - def __rand__(self, other ): - """ - Implementation of & operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other & self - - def __invert__( self ): - """ - Implementation of ~ operator - returns C{L{NotAny}} - """ - return NotAny( self ) - - def __call__(self, name=None): - """ - Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. - - If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be - passed as C{True}. - - If C{name} is omitted, same as calling C{L{copy}}. - - Example:: - # these are equivalent - userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") - userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") - """ - if name is not None: - return self.setResultsName(name) - else: - return self.copy() - - def suppress( self ): - """ - Suppresses the output of this C{ParserElement}; useful to keep punctuation from - cluttering up returned output. - """ - return Suppress( self ) - - def leaveWhitespace( self ): - """ - Disables the skipping of whitespace before matching the characters in the - C{ParserElement}'s defined pattern. This is normally only used internally by - the pyparsing module, but may be needed in some whitespace-sensitive grammars. - """ - self.skipWhitespace = False - return self - - def setWhitespaceChars( self, chars ): - """ - Overrides the default whitespace chars - """ - self.skipWhitespace = True - self.whiteChars = chars - self.copyDefaultWhiteChars = False - return self - - def parseWithTabs( self ): - """ - Overrides default behavior to expand C{}s to spaces before parsing the input string. - Must be called before C{parseString} when the input grammar contains elements that - match C{} characters. - """ - self.keepTabs = True - return self - - def ignore( self, other ): - """ - Define expression to be ignored (e.g., comments) while doing pattern - matching; may be called repeatedly, to define multiple comment or other - ignorable patterns. - - Example:: - patt = OneOrMore(Word(alphas)) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] - - patt.ignore(cStyleComment) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] - """ - if isinstance(other, basestring): - other = Suppress(other) - - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - self.ignoreExprs.append(other) - else: - self.ignoreExprs.append( Suppress( other.copy() ) ) - return self - - def setDebugActions( self, startAction, successAction, exceptionAction ): - """ - Enable display of debugging messages while doing pattern matching. - """ - self.debugActions = (startAction or _defaultStartDebugAction, - successAction or _defaultSuccessDebugAction, - exceptionAction or _defaultExceptionDebugAction) - self.debug = True - return self - - def setDebug( self, flag=True ): - """ - Enable display of debugging messages while doing pattern matching. - Set C{flag} to True to enable, False to disable. - - Example:: - wd = Word(alphas).setName("alphaword") - integer = Word(nums).setName("numword") - term = wd | integer - - # turn on debugging for wd - wd.setDebug() - - OneOrMore(term).parseString("abc 123 xyz 890") - - prints:: - Match alphaword at loc 0(1,1) - Matched alphaword -> ['abc'] - Match alphaword at loc 3(1,4) - Exception raised:Expected alphaword (at char 4), (line:1, col:5) - Match alphaword at loc 7(1,8) - Matched alphaword -> ['xyz'] - Match alphaword at loc 11(1,12) - Exception raised:Expected alphaword (at char 12), (line:1, col:13) - Match alphaword at loc 15(1,16) - Exception raised:Expected alphaword (at char 15), (line:1, col:16) - - The output shown is that produced by the default debug actions - custom debug actions can be - specified using L{setDebugActions}. Prior to attempting - to match the C{wd} expression, the debugging message C{"Match at loc (,)"} - is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} - message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, - which makes debugging and exception messages easier to understand - for instance, the default - name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. - """ - if flag: - self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) - else: - self.debug = False - return self - - def __str__( self ): - return self.name - - def __repr__( self ): - return _ustr(self) - - def streamline( self ): - self.streamlined = True - self.strRepr = None - return self - - def checkRecursion( self, parseElementList ): - pass - - def validate( self, validateTrace=[] ): - """ - Check defined expressions for valid structure, check for infinite recursive definitions. - """ - self.checkRecursion( [] ) - - def parseFile( self, file_or_filename, parseAll=False ): - """ - Execute the parse expression on the given file or filename. - If a filename is specified (instead of a file object), - the entire file is opened, read, and closed before parsing. - """ - try: - file_contents = file_or_filename.read() - except AttributeError: - with open(file_or_filename, "r") as f: - file_contents = f.read() - try: - return self.parseString(file_contents, parseAll) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def __eq__(self,other): - if isinstance(other, ParserElement): - return self is other or vars(self) == vars(other) - elif isinstance(other, basestring): - return self.matches(other) - else: - return super(ParserElement,self)==other - - def __ne__(self,other): - return not (self == other) - - def __hash__(self): - return hash(id(self)) - - def __req__(self,other): - return self == other - - def __rne__(self,other): - return not (self == other) - - def matches(self, testString, parseAll=True): - """ - Method for quick testing of a parser against a test string. Good for simple - inline microtests of sub expressions while building up larger parser. - - Parameters: - - testString - to test against this expression for a match - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - Example:: - expr = Word(nums) - assert expr.matches("100") - """ - try: - self.parseString(_ustr(testString), parseAll=parseAll) - return True - except ParseBaseException: - return False - - def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): - """ - Execute the parse expression on a series of test strings, showing each - test, the parsed results or where the parse failed. Quick and easy way to - run a parse expression against a list of sample strings. - - Parameters: - - tests - a list of separate test strings, or a multiline string of test strings - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - comment - (default=C{'#'}) - expression for indicating embedded comments in the test - string; pass None to disable comment filtering - - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; - if False, only dump nested list - - printResults - (default=C{True}) prints test output to stdout - - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing - - Returns: a (success, results) tuple, where success indicates that all tests succeeded - (or failed if C{failureTests} is True), and the results contain a list of lines of each - test's output - - Example:: - number_expr = pyparsing_common.number.copy() - - result = number_expr.runTests(''' - # unsigned integer - 100 - # negative integer - -100 - # float with scientific notation - 6.02e23 - # integer with scientific notation - 1e-12 - ''') - print("Success" if result[0] else "Failed!") - - result = number_expr.runTests(''' - # stray character - 100Z - # missing leading digit before '.' - -.100 - # too many '.' - 3.14.159 - ''', failureTests=True) - print("Success" if result[0] else "Failed!") - prints:: - # unsigned integer - 100 - [100] - - # negative integer - -100 - [-100] - - # float with scientific notation - 6.02e23 - [6.02e+23] - - # integer with scientific notation - 1e-12 - [1e-12] - - Success - - # stray character - 100Z - ^ - FAIL: Expected end of text (at char 3), (line:1, col:4) - - # missing leading digit before '.' - -.100 - ^ - FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) - - # too many '.' - 3.14.159 - ^ - FAIL: Expected end of text (at char 4), (line:1, col:5) - - Success - - Each test string must be on a single line. If you want to test a string that spans multiple - lines, create a test like this:: - - expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") - - (Note that this is a raw string literal, you must include the leading 'r'.) - """ - if isinstance(tests, basestring): - tests = list(map(str.strip, tests.rstrip().splitlines())) - if isinstance(comment, basestring): - comment = Literal(comment) - allResults = [] - comments = [] - success = True - for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: - comments.append(t) - continue - if not t: - continue - out = ['\n'.join(comments), t] - comments = [] - try: - t = t.replace(r'\n','\n') - result = self.parseString(t, parseAll=parseAll) - out.append(result.dump(full=fullDump)) - success = success and not failureTests - except ParseBaseException as pe: - fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" - if '\n' in t: - out.append(line(pe.loc, t)) - out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) - else: - out.append(' '*pe.loc + '^' + fatal) - out.append("FAIL: " + str(pe)) - success = success and failureTests - result = pe - except Exception as exc: - out.append("FAIL-EXCEPTION: " + str(exc)) - success = success and failureTests - result = exc - - if printResults: - if fullDump: - out.append('') - print('\n'.join(out)) - - allResults.append((t, result)) - - return success, allResults - - -class Token(ParserElement): - """ - Abstract C{ParserElement} subclass, for defining atomic matching patterns. - """ - def __init__( self ): - super(Token,self).__init__( savelist=False ) - - -class Empty(Token): - """ - An empty token, will always match. - """ - def __init__( self ): - super(Empty,self).__init__() - self.name = "Empty" - self.mayReturnEmpty = True - self.mayIndexError = False - - -class NoMatch(Token): - """ - A token that will never match. - """ - def __init__( self ): - super(NoMatch,self).__init__() - self.name = "NoMatch" - self.mayReturnEmpty = True - self.mayIndexError = False - self.errmsg = "Unmatchable token" - - def parseImpl( self, instring, loc, doActions=True ): - raise ParseException(instring, loc, self.errmsg, self) - - -class Literal(Token): - """ - Token to exactly match a specified string. - - Example:: - Literal('blah').parseString('blah') # -> ['blah'] - Literal('blah').parseString('blahfooblah') # -> ['blah'] - Literal('blah').parseString('bla') # -> Exception: Expected "blah" - - For case-insensitive matching, use L{CaselessLiteral}. - - For keyword matching (force word break before and after the matched string), - use L{Keyword} or L{CaselessKeyword}. - """ - def __init__( self, matchString ): - super(Literal,self).__init__() - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Literal; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.__class__ = Empty - self.name = '"%s"' % _ustr(self.match) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - - # Performance tuning: this routine gets called a *lot* - # if this is a single character match string and the first character matches, - # short-circuit as quickly as possible, and avoid calling startswith - #~ @profile - def parseImpl( self, instring, loc, doActions=True ): - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) -_L = Literal -ParserElement._literalStringClass = Literal - -class Keyword(Token): - """ - Token to exactly match a specified string as a keyword, that is, it must be - immediately followed by a non-keyword character. Compare with C{L{Literal}}: - - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. - - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} - Accepts two optional constructor arguments in addition to the keyword string: - - C{identChars} is a string of characters that would be valid identifier characters, - defaulting to all alphanumerics + "_" and "$" - - C{caseless} allows case-insensitive matching, default is C{False}. - - Example:: - Keyword("start").parseString("start") # -> ['start'] - Keyword("start").parseString("starting") # -> Exception - - For case-insensitive matching, use L{CaselessKeyword}. - """ - DEFAULT_KEYWORD_CHARS = alphanums+"_$" - - def __init__( self, matchString, identChars=None, caseless=False ): - super(Keyword,self).__init__() - if identChars is None: - identChars = Keyword.DEFAULT_KEYWORD_CHARS - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Keyword; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.name = '"%s"' % self.match - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - self.caseless = caseless - if caseless: - self.caselessmatch = matchString.upper() - identChars = identChars.upper() - self.identChars = set(identChars) - - def parseImpl( self, instring, loc, doActions=True ): - if self.caseless: - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and - (loc == 0 or instring[loc-1].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - else: - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and - (loc == 0 or instring[loc-1] not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - - def copy(self): - c = super(Keyword,self).copy() - c.identChars = Keyword.DEFAULT_KEYWORD_CHARS - return c - - @staticmethod - def setDefaultKeywordChars( chars ): - """Overrides the default Keyword chars - """ - Keyword.DEFAULT_KEYWORD_CHARS = chars - -class CaselessLiteral(Literal): - """ - Token to match a specified string, ignoring case of letters. - Note: the matched results will always be in the case of the given - match string, NOT the case of the input text. - - Example:: - OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] - - (Contrast with example for L{CaselessKeyword}.) - """ - def __init__( self, matchString ): - super(CaselessLiteral,self).__init__( matchString.upper() ) - # Preserve the defining literal. - self.returnString = matchString - self.name = "'%s'" % self.returnString - self.errmsg = "Expected " + self.name - - def parseImpl( self, instring, loc, doActions=True ): - if instring[ loc:loc+self.matchLen ].upper() == self.match: - return loc+self.matchLen, self.returnString - raise ParseException(instring, loc, self.errmsg, self) - -class CaselessKeyword(Keyword): - """ - Caseless version of L{Keyword}. - - Example:: - OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] - - (Contrast with example for L{CaselessLiteral}.) - """ - def __init__( self, matchString, identChars=None ): - super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) - - def parseImpl( self, instring, loc, doActions=True ): - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - -class CloseMatch(Token): - """ - A variation on L{Literal} which matches "close" matches, that is, - strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: - - C{match_string} - string to be matched - - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match - - The results from a successful parse will contain the matched text from the input string and the following named results: - - C{mismatches} - a list of the positions within the match_string where mismatches were found - - C{original} - the original match_string used to compare against the input string - - If C{mismatches} is an empty list, then the match was an exact match. - - Example:: - patt = CloseMatch("ATCATCGAATGGA") - patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) - patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) - - # exact match - patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) - - # close match allowing up to 2 mismatches - patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) - patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) - """ - def __init__(self, match_string, maxMismatches=1): - super(CloseMatch,self).__init__() - self.name = match_string - self.match_string = match_string - self.maxMismatches = maxMismatches - self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) - self.mayIndexError = False - self.mayReturnEmpty = False - - def parseImpl( self, instring, loc, doActions=True ): - start = loc - instrlen = len(instring) - maxloc = start + len(self.match_string) - - if maxloc <= instrlen: - match_string = self.match_string - match_stringloc = 0 - mismatches = [] - maxMismatches = self.maxMismatches - - for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): - src,mat = s_m - if src != mat: - mismatches.append(match_stringloc) - if len(mismatches) > maxMismatches: - break - else: - loc = match_stringloc + 1 - results = ParseResults([instring[start:loc]]) - results['original'] = self.match_string - results['mismatches'] = mismatches - return loc, results - - raise ParseException(instring, loc, self.errmsg, self) - - -class Word(Token): - """ - Token for matching words composed of allowed character sets. - Defined with string containing all allowed initial characters, - an optional string containing allowed body characters (if omitted, - defaults to the initial character set), and an optional minimum, - maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. An optional - C{excludeChars} parameter can list characters that might be found in - the input C{bodyChars} string; useful to define a word of all printables - except for one or two characters, for instance. - - L{srange} is useful for defining custom character set strings for defining - C{Word} expressions, using range notation from regular expression character sets. - - A common mistake is to use C{Word} to match a specific literal string, as in - C{Word("Address")}. Remember that C{Word} uses the string argument to define - I{sets} of matchable characters. This expression would match "Add", "AAA", - "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. - To match an exact literal string, use L{Literal} or L{Keyword}. - - pyparsing includes helper strings for building Words: - - L{alphas} - - L{nums} - - L{alphanums} - - L{hexnums} - - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) - - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) - - L{printables} (any non-whitespace character) - - Example:: - # a word composed of digits - integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) - - # a word with a leading capital, and zero or more lowercase - capital_word = Word(alphas.upper(), alphas.lower()) - - # hostnames are alphanumeric, with leading alpha, and '-' - hostname = Word(alphas, alphanums+'-') - - # roman numeral (not a strict parser, accepts invalid mix of characters) - roman = Word("IVXLCDM") - - # any string of non-whitespace characters, except for ',' - csv_value = Word(printables, excludeChars=",") - """ - def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): - super(Word,self).__init__() - if excludeChars: - initChars = ''.join(c for c in initChars if c not in excludeChars) - if bodyChars: - bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) - self.initCharsOrig = initChars - self.initChars = set(initChars) - if bodyChars : - self.bodyCharsOrig = bodyChars - self.bodyChars = set(bodyChars) - else: - self.bodyCharsOrig = initChars - self.bodyChars = set(initChars) - - self.maxSpecified = max > 0 - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asKeyword = asKeyword - - if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): - if self.bodyCharsOrig == self.initCharsOrig: - self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) - elif len(self.initCharsOrig) == 1: - self.reString = "%s[%s]*" % \ - (re.escape(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - else: - self.reString = "[%s][%s]*" % \ - (_escapeRegexRangeChars(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - if self.asKeyword: - self.reString = r"\b"+self.reString+r"\b" - try: - self.re = re.compile( self.reString ) - except Exception: - self.re = None - - def parseImpl( self, instring, loc, doActions=True ): - if self.re: - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - return loc, result.group() - - if not(instring[ loc ] in self.initChars): - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - instrlen = len(instring) - bodychars = self.bodyChars - maxloc = start + self.maxLen - maxloc = min( maxloc, instrlen ) - while loc < maxloc and instring[loc] in bodychars: - loc += 1 - - throwException = False - if loc - start < self.minLen: - throwException = True - if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: - throwException = True - if self.asKeyword: - if (start>0 and instring[start-1] in bodychars) or (loc4: - return s[:4]+"..." - else: - return s - - if ( self.initCharsOrig != self.bodyCharsOrig ): - self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) - else: - self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) - - return self.strRepr - - -class Regex(Token): - """ - Token for matching strings that match a given regular expression. - Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. - If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as - named parse results. - - Example:: - realnum = Regex(r"[+-]?\d+\.\d*") - date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') - # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression - roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") - """ - compiledREtype = type(re.compile("[A-Z]")) - def __init__( self, pattern, flags=0): - """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" - super(Regex,self).__init__() - - if isinstance(pattern, basestring): - if not pattern: - warnings.warn("null string passed to Regex; use Empty() instead", - SyntaxWarning, stacklevel=2) - - self.pattern = pattern - self.flags = flags - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % pattern, - SyntaxWarning, stacklevel=2) - raise - - elif isinstance(pattern, Regex.compiledREtype): - self.re = pattern - self.pattern = \ - self.reString = str(pattern) - self.flags = flags - - else: - raise ValueError("Regex may only be constructed with a string or a compiled RE object") - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - d = result.groupdict() - ret = ParseResults(result.group()) - if d: - for k in d: - ret[k] = d[k] - return loc,ret - - def __str__( self ): - try: - return super(Regex,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "Re:(%s)" % repr(self.pattern) - - return self.strRepr - - -class QuotedString(Token): - r""" - Token for matching strings that are delimited by quoting characters. - - Defined with the following parameters: - - quoteChar - string of one or more characters defining the quote delimiting string - - escChar - character to escape quotes, typically backslash (default=C{None}) - - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) - - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) - - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) - - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) - - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) - - Example:: - qs = QuotedString('"') - print(qs.searchString('lsjdf "This is the quote" sldjf')) - complex_qs = QuotedString('{{', endQuoteChar='}}') - print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) - sql_qs = QuotedString('"', escQuote='""') - print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) - prints:: - [['This is the quote']] - [['This is the "quote"']] - [['This is the quote with "embedded" quotes']] - """ - def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): - super(QuotedString,self).__init__() - - # remove white space from quote chars - wont work anyway - quoteChar = quoteChar.strip() - if not quoteChar: - warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - if endQuoteChar is None: - endQuoteChar = quoteChar - else: - endQuoteChar = endQuoteChar.strip() - if not endQuoteChar: - warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - self.quoteChar = quoteChar - self.quoteCharLen = len(quoteChar) - self.firstQuoteChar = quoteChar[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes - - if multiline: - self.flags = re.MULTILINE | re.DOTALL - self.pattern = r'%s(?:[^%s%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - else: - self.flags = 0 - self.pattern = r'%s(?:[^%s\n\r%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - if len(self.endQuoteChar) > 1: - self.pattern += ( - '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), - _escapeRegexRangeChars(self.endQuoteChar[i])) - for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' - ) - if escQuote: - self.pattern += (r'|(?:%s)' % re.escape(escQuote)) - if escChar: - self.pattern += (r'|(?:%s.)' % re.escape(escChar)) - self.escCharReplacePattern = re.escape(self.escChar)+"(.)" - self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, - SyntaxWarning, stacklevel=2) - raise - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.group() - - if self.unquoteResults: - - # strip off quotes - ret = ret[self.quoteCharLen:-self.endQuoteCharLen] - - if isinstance(ret,basestring): - # replace escaped whitespace - if '\\' in ret and self.convertWhitespaceEscapes: - ws_map = { - r'\t' : '\t', - r'\n' : '\n', - r'\f' : '\f', - r'\r' : '\r', - } - for wslit,wschar in ws_map.items(): - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern,"\g<1>",ret) - - # replace escaped quotes - if self.escQuote: - ret = ret.replace(self.escQuote, self.endQuoteChar) - - return loc, ret - - def __str__( self ): - try: - return super(QuotedString,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) - - return self.strRepr - - -class CharsNotIn(Token): - """ - Token for matching words composed of characters I{not} in a given set (will - include whitespace in matched characters if not listed in the provided exclusion set - see example). - Defined with string containing all disallowed characters, and an optional - minimum, maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. - - Example:: - # define a comma-separated-value as anything that is not a ',' - csv_value = CharsNotIn(',') - print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) - prints:: - ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] - """ - def __init__( self, notChars, min=1, max=0, exact=0 ): - super(CharsNotIn,self).__init__() - self.skipWhitespace = False - self.notChars = notChars - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = ( self.minLen == 0 ) - self.mayIndexError = False - - def parseImpl( self, instring, loc, doActions=True ): - if instring[loc] in self.notChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - notchars = self.notChars - maxlen = min( start+self.maxLen, len(instring) ) - while loc < maxlen and \ - (instring[loc] not in notchars): - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(CharsNotIn, self).__str__() - except Exception: - pass - - if self.strRepr is None: - if len(self.notChars) > 4: - self.strRepr = "!W:(%s...)" % self.notChars[:4] - else: - self.strRepr = "!W:(%s)" % self.notChars - - return self.strRepr - -class White(Token): - """ - Special matching class for matching whitespace. Normally, whitespace is ignored - by pyparsing grammars. This class is included when some whitespace structures - are significant. Define with a string containing the whitespace characters to be - matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, - as defined for the C{L{Word}} class. - """ - whiteStrs = { - " " : "", - "\t": "", - "\n": "", - "\r": "", - "\f": "", - } - def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): - super(White,self).__init__() - self.matchWhite = ws - self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) - #~ self.leaveWhitespace() - self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) - self.mayReturnEmpty = True - self.errmsg = "Expected " + self.name - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - def parseImpl( self, instring, loc, doActions=True ): - if not(instring[ loc ] in self.matchWhite): - raise ParseException(instring, loc, self.errmsg, self) - start = loc - loc += 1 - maxloc = start + self.maxLen - maxloc = min( maxloc, len(instring) ) - while loc < maxloc and instring[loc] in self.matchWhite: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class _PositionToken(Token): - def __init__( self ): - super(_PositionToken,self).__init__() - self.name=self.__class__.__name__ - self.mayReturnEmpty = True - self.mayIndexError = False - -class GoToColumn(_PositionToken): - """ - Token to advance to a specific column of input text; useful for tabular report scraping. - """ - def __init__( self, colno ): - super(GoToColumn,self).__init__() - self.col = colno - - def preParse( self, instring, loc ): - if col(loc,instring) != self.col: - instrlen = len(instring) - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : - loc += 1 - return loc - - def parseImpl( self, instring, loc, doActions=True ): - thiscol = col( loc, instring ) - if thiscol > self.col: - raise ParseException( instring, loc, "Text not in expected column", self ) - newloc = loc + self.col - thiscol - ret = instring[ loc: newloc ] - return newloc, ret - - -class LineStart(_PositionToken): - """ - Matches if current position is at the beginning of a line within the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (LineStart() + 'AAA' + restOfLine).searchString(test): - print(t) - - Prints:: - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - def __init__( self ): - super(LineStart,self).__init__() - self.errmsg = "Expected start of line" - - def parseImpl( self, instring, loc, doActions=True ): - if col(loc, instring) == 1: - return loc, [] - raise ParseException(instring, loc, self.errmsg, self) - -class LineEnd(_PositionToken): - """ - Matches if current position is at the end of a line within the parse string - """ - def __init__( self ): - super(LineEnd,self).__init__() - self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) - self.errmsg = "Expected end of line" - - def parseImpl( self, instring, loc, doActions=True ): - if loc len(instring): - return loc, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class WordStart(_PositionToken): - """ - Matches if the current position is at the beginning of a Word, and - is not preceded by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of - the string being parsed, or at the beginning of a line. - """ - def __init__(self, wordChars = printables): - super(WordStart,self).__init__() - self.wordChars = set(wordChars) - self.errmsg = "Not at the start of a word" - - def parseImpl(self, instring, loc, doActions=True ): - if loc != 0: - if (instring[loc-1] in self.wordChars or - instring[loc] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class WordEnd(_PositionToken): - """ - Matches if the current position is at the end of a Word, and - is not followed by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of - the string being parsed, or at the end of a line. - """ - def __init__(self, wordChars = printables): - super(WordEnd,self).__init__() - self.wordChars = set(wordChars) - self.skipWhitespace = False - self.errmsg = "Not at the end of a word" - - def parseImpl(self, instring, loc, doActions=True ): - instrlen = len(instring) - if instrlen>0 and loc maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - else: - # save match among all matches, to retry longest to shortest - matches.append((loc2, e)) - - if matches: - matches.sort(key=lambda x: -x[0]) - for _,e in matches: - try: - return e._parse( instring, loc, doActions ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - - def __ixor__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #Or( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class MatchFirst(ParseExpression): - """ - Requires that at least one C{ParseExpression} is found. - If two expressions match, the first one listed is the one that will match. - May be constructed using the C{'|'} operator. - - Example:: - # construct MatchFirst using '|' operator - - # watch the order of expressions to match - number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] - - # put more selective expression first - number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) - print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(MatchFirst,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - for e in self.exprs: - try: - ret = e._parse( instring, loc, doActions ) - return ret - except ParseException as err: - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - - # only got here if no expression matched, raise exception for match that made it the furthest - else: - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - def __ior__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #MatchFirst( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class Each(ParseExpression): - """ - Requires all given C{ParseExpression}s to be found, but in any order. - Expressions may be separated by whitespace. - May be constructed using the C{'&'} operator. - - Example:: - color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") - shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") - integer = Word(nums) - shape_attr = "shape:" + shape_type("shape") - posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") - color_attr = "color:" + color("color") - size_attr = "size:" + integer("size") - - # use Each (using operator '&') to accept attributes in any order - # (shape and posn are required, color and size are optional) - shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) - - shape_spec.runTests(''' - shape: SQUARE color: BLACK posn: 100, 120 - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - color:GREEN size:20 shape:TRIANGLE posn:20,40 - ''' - ) - prints:: - shape: SQUARE color: BLACK posn: 100, 120 - ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - - color: BLACK - - posn: ['100', ',', '120'] - - x: 100 - - y: 120 - - shape: SQUARE - - - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - - color: BLUE - - posn: ['50', ',', '80'] - - x: 50 - - y: 80 - - shape: CIRCLE - - size: 50 - - - color: GREEN size: 20 shape: TRIANGLE posn: 20,40 - ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - - color: GREEN - - posn: ['20', ',', '40'] - - x: 20 - - y: 40 - - shape: TRIANGLE - - size: 20 - """ - def __init__( self, exprs, savelist = True ): - super(Each,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = True - self.initExprGroups = True - - def parseImpl( self, instring, loc, doActions=True ): - if self.initExprGroups: - self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) - opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] - opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] - self.optionals = opt1 + opt2 - self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] - self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] - self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] - self.required += self.multirequired - self.initExprGroups = False - tmpLoc = loc - tmpReqd = self.required[:] - tmpOpt = self.optionals[:] - matchOrder = [] - - keepMatching = True - while keepMatching: - tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired - failed = [] - for e in tmpExprs: - try: - tmpLoc = e.tryParse( instring, tmpLoc ) - except ParseException: - failed.append(e) - else: - matchOrder.append(self.opt1map.get(id(e),e)) - if e in tmpReqd: - tmpReqd.remove(e) - elif e in tmpOpt: - tmpOpt.remove(e) - if len(failed) == len(tmpExprs): - keepMatching = False - - if tmpReqd: - missing = ", ".join(_ustr(e) for e in tmpReqd) - raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) - - # add any unmatched Optionals, in case they have default values defined - matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] - - resultlist = [] - for e in matchOrder: - loc,results = e._parse(instring,loc,doActions) - resultlist.append(results) - - finalResults = sum(resultlist, ParseResults([])) - return loc, finalResults - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class ParseElementEnhance(ParserElement): - """ - Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. - """ - def __init__( self, expr, savelist=False ): - super(ParseElementEnhance,self).__init__(savelist) - if isinstance( expr, basestring ): - if issubclass(ParserElement._literalStringClass, Token): - expr = ParserElement._literalStringClass(expr) - else: - expr = ParserElement._literalStringClass(Literal(expr)) - self.expr = expr - self.strRepr = None - if expr is not None: - self.mayIndexError = expr.mayIndexError - self.mayReturnEmpty = expr.mayReturnEmpty - self.setWhitespaceChars( expr.whiteChars ) - self.skipWhitespace = expr.skipWhitespace - self.saveAsList = expr.saveAsList - self.callPreparse = expr.callPreparse - self.ignoreExprs.extend(expr.ignoreExprs) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr is not None: - return self.expr._parse( instring, loc, doActions, callPreParse=False ) - else: - raise ParseException("",loc,self.errmsg,self) - - def leaveWhitespace( self ): - self.skipWhitespace = False - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - else: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - return self - - def streamline( self ): - super(ParseElementEnhance,self).streamline() - if self.expr is not None: - self.expr.streamline() - return self - - def checkRecursion( self, parseElementList ): - if self in parseElementList: - raise RecursiveGrammarException( parseElementList+[self] ) - subRecCheckList = parseElementList[:] + [ self ] - if self.expr is not None: - self.expr.checkRecursion( subRecCheckList ) - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion( [] ) - - def __str__( self ): - try: - return super(ParseElementEnhance,self).__str__() - except Exception: - pass - - if self.strRepr is None and self.expr is not None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) - return self.strRepr - - -class FollowedBy(ParseElementEnhance): - """ - Lookahead matching of the given parse expression. C{FollowedBy} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression matches at the current - position. C{FollowedBy} always returns a null token list. - - Example:: - # use FollowedBy to match a label only if it is followed by a ':' - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() - prints:: - [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] - """ - def __init__( self, expr ): - super(FollowedBy,self).__init__(expr) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - self.expr.tryParse( instring, loc ) - return loc, [] - - -class NotAny(ParseElementEnhance): - """ - Lookahead to disallow matching with the given parse expression. C{NotAny} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression does I{not} match at the current - position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} - always returns a null token list. May be constructed using the '~' operator. - - Example:: - - """ - def __init__( self, expr ): - super(NotAny,self).__init__(expr) - #~ self.leaveWhitespace() - self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs - self.mayReturnEmpty = True - self.errmsg = "Found unwanted token, "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr.canParseNext(instring, loc): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "~{" + _ustr(self.expr) + "}" - - return self.strRepr - -class _MultipleMatch(ParseElementEnhance): - def __init__( self, expr, stopOn=None): - super(_MultipleMatch, self).__init__(expr) - self.saveAsList = True - ender = stopOn - if isinstance(ender, basestring): - ender = ParserElement._literalStringClass(ender) - self.not_ender = ~ender if ender is not None else None - - def parseImpl( self, instring, loc, doActions=True ): - self_expr_parse = self.expr._parse - self_skip_ignorables = self._skipIgnorables - check_ender = self.not_ender is not None - if check_ender: - try_not_ender = self.not_ender.tryParse - - # must be at least one (but first see if we are the stopOn sentinel; - # if so, fail) - if check_ender: - try_not_ender(instring, loc) - loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) - try: - hasIgnoreExprs = (not not self.ignoreExprs) - while 1: - if check_ender: - try_not_ender(instring, loc) - if hasIgnoreExprs: - preloc = self_skip_ignorables( instring, loc ) - else: - preloc = loc - loc, tmptokens = self_expr_parse( instring, preloc, doActions ) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens - except (ParseException,IndexError): - pass - - return loc, tokens - -class OneOrMore(_MultipleMatch): - """ - Repetition of one or more of the given expression. - - Parameters: - - expr - expression that must match one or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: BLACK" - OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] - - # use stopOn attribute for OneOrMore to avoid reading label string as part of the data - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] - - # could also be written as - (attr_expr * (1,)).parseString(text).pprint() - """ - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + _ustr(self.expr) + "}..." - - return self.strRepr - -class ZeroOrMore(_MultipleMatch): - """ - Optional repetition of zero or more of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example: similar to L{OneOrMore} - """ - def __init__( self, expr, stopOn=None): - super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) - except (ParseException,IndexError): - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]..." - - return self.strRepr - -class _NullToken(object): - def __bool__(self): - return False - __nonzero__ = __bool__ - def __str__(self): - return "" - -_optionalNotMatched = _NullToken() -class Optional(ParseElementEnhance): - """ - Optional matching of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - default (optional) - value to be returned if the optional expression is not found. - - Example:: - # US postal code can be a 5-digit zip, plus optional 4-digit qualifier - zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) - zip.runTests(''' - # traditional ZIP code - 12345 - - # ZIP+4 form - 12101-0001 - - # invalid ZIP - 98765- - ''') - prints:: - # traditional ZIP code - 12345 - ['12345'] - - # ZIP+4 form - 12101-0001 - ['12101-0001'] - - # invalid ZIP - 98765- - ^ - FAIL: Expected end of text (at char 5), (line:1, col:6) - """ - def __init__( self, expr, default=_optionalNotMatched ): - super(Optional,self).__init__( expr, savelist=False ) - self.saveAsList = self.expr.saveAsList - self.defaultValue = default - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) - except (ParseException,IndexError): - if self.defaultValue is not _optionalNotMatched: - if self.expr.resultsName: - tokens = ParseResults([ self.defaultValue ]) - tokens[self.expr.resultsName] = self.defaultValue - else: - tokens = [ self.defaultValue ] - else: - tokens = [] - return loc, tokens - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]" - - return self.strRepr - -class SkipTo(ParseElementEnhance): - """ - Token for skipping over all undefined text until the matched expression is found. - - Parameters: - - expr - target expression marking the end of the data to be skipped - - include - (default=C{False}) if True, the target expression is also parsed - (the skipped text and target expression are returned as a 2-element list). - - ignore - (default=C{None}) used to define grammars (typically quoted strings and - comments) that might contain false matches to the target expression - - failOn - (default=C{None}) define expressions that are not allowed to be - included in the skipped test; if found before the target expression is found, - the SkipTo is not a match - - Example:: - report = ''' - Outstanding Issues Report - 1 Jan 2000 - - # | Severity | Description | Days Open - -----+----------+-------------------------------------------+----------- - 101 | Critical | Intermittent system crash | 6 - 94 | Cosmetic | Spelling error on Login ('log|n') | 14 - 79 | Minor | System slow when running too many reports | 47 - ''' - integer = Word(nums) - SEP = Suppress('|') - # use SkipTo to simply match everything up until the next SEP - # - ignore quoted strings, so that a '|' character inside a quoted string does not match - # - parse action will call token.strip() for each matched token, i.e., the description body - string_data = SkipTo(SEP, ignore=quotedString) - string_data.setParseAction(tokenMap(str.strip)) - ticket_expr = (integer("issue_num") + SEP - + string_data("sev") + SEP - + string_data("desc") + SEP - + integer("days_open")) - - for tkt in ticket_expr.searchString(report): - print tkt.dump() - prints:: - ['101', 'Critical', 'Intermittent system crash', '6'] - - days_open: 6 - - desc: Intermittent system crash - - issue_num: 101 - - sev: Critical - ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - - days_open: 14 - - desc: Spelling error on Login ('log|n') - - issue_num: 94 - - sev: Cosmetic - ['79', 'Minor', 'System slow when running too many reports', '47'] - - days_open: 47 - - desc: System slow when running too many reports - - issue_num: 79 - - sev: Minor - """ - def __init__( self, other, include=False, ignore=None, failOn=None ): - super( SkipTo, self ).__init__( other ) - self.ignoreExpr = ignore - self.mayReturnEmpty = True - self.mayIndexError = False - self.includeMatch = include - self.asList = False - if isinstance(failOn, basestring): - self.failOn = ParserElement._literalStringClass(failOn) - else: - self.failOn = failOn - self.errmsg = "No match found for "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - startloc = loc - instrlen = len(instring) - expr = self.expr - expr_parse = self.expr._parse - self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None - self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - - tmploc = loc - while tmploc <= instrlen: - if self_failOn_canParseNext is not None: - # break if failOn expression matches - if self_failOn_canParseNext(instring, tmploc): - break - - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break - - try: - expr_parse(instring, tmploc, doActions=False, callPreParse=False) - except (ParseException, IndexError): - # no match, advance loc in string - tmploc += 1 - else: - # matched skipto expr, done - break - - else: - # ran off the end of the input string without matching skipto expr, fail - raise ParseException(instring, loc, self.errmsg, self) - - # build up return values - loc = tmploc - skiptext = instring[startloc:loc] - skipresult = ParseResults(skiptext) - - if self.includeMatch: - loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) - skipresult += mat - - return loc, skipresult - -class Forward(ParseElementEnhance): - """ - Forward declaration of an expression to be defined later - - used for recursive grammars, such as algebraic infix notation. - When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. - - Note: take care when assigning to C{Forward} not to overlook precedence of operators. - Specifically, '|' has a lower precedence than '<<', so that:: - fwdExpr << a | b | c - will actually be evaluated as:: - (fwdExpr << a) | b | c - thereby leaving b and c out as parseable alternatives. It is recommended that you - explicitly group the values inserted into the C{Forward}:: - fwdExpr << (a | b | c) - Converting to use the '<<=' operator instead will avoid this problem. - - See L{ParseResults.pprint} for an example of a recursive parser created using - C{Forward}. - """ - def __init__( self, other=None ): - super(Forward,self).__init__( other, savelist=False ) - - def __lshift__( self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass(other) - self.expr = other - self.strRepr = None - self.mayIndexError = self.expr.mayIndexError - self.mayReturnEmpty = self.expr.mayReturnEmpty - self.setWhitespaceChars( self.expr.whiteChars ) - self.skipWhitespace = self.expr.skipWhitespace - self.saveAsList = self.expr.saveAsList - self.ignoreExprs.extend(self.expr.ignoreExprs) - return self - - def __ilshift__(self, other): - return self << other - - def leaveWhitespace( self ): - self.skipWhitespace = False - return self - - def streamline( self ): - if not self.streamlined: - self.streamlined = True - if self.expr is not None: - self.expr.streamline() - return self - - def validate( self, validateTrace=[] ): - if self not in validateTrace: - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion([]) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - return self.__class__.__name__ + ": ..." - - # stubbed out for now - creates awful memory and perf issues - self._revertClass = self.__class__ - self.__class__ = _ForwardNoRecurse - try: - if self.expr is not None: - retString = _ustr(self.expr) - else: - retString = "None" - finally: - self.__class__ = self._revertClass - return self.__class__.__name__ + ": " + retString - - def copy(self): - if self.expr is not None: - return super(Forward,self).copy() - else: - ret = Forward() - ret <<= self - return ret - -class _ForwardNoRecurse(Forward): - def __str__( self ): - return "..." - -class TokenConverter(ParseElementEnhance): - """ - Abstract subclass of C{ParseExpression}, for converting parsed results. - """ - def __init__( self, expr, savelist=False ): - super(TokenConverter,self).__init__( expr )#, savelist ) - self.saveAsList = False - -class Combine(TokenConverter): - """ - Converter to concatenate all matching tokens to a single string. - By default, the matching patterns must also be contiguous in the input string; - this can be disabled by specifying C{'adjacent=False'} in the constructor. - - Example:: - real = Word(nums) + '.' + Word(nums) - print(real.parseString('3.1416')) # -> ['3', '.', '1416'] - # will also erroneously match the following - print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] - - real = Combine(Word(nums) + '.' + Word(nums)) - print(real.parseString('3.1416')) # -> ['3.1416'] - # no match when there are internal spaces - print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) - """ - def __init__( self, expr, joinString="", adjacent=True ): - super(Combine,self).__init__( expr ) - # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself - if adjacent: - self.leaveWhitespace() - self.adjacent = adjacent - self.skipWhitespace = True - self.joinString = joinString - self.callPreparse = True - - def ignore( self, other ): - if self.adjacent: - ParserElement.ignore(self, other) - else: - super( Combine, self).ignore( other ) - return self - - def postParse( self, instring, loc, tokenlist ): - retToks = tokenlist.copy() - del retToks[:] - retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) - - if self.resultsName and retToks.haskeys(): - return [ retToks ] - else: - return retToks - -class Group(TokenConverter): - """ - Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. - - Example:: - ident = Word(alphas) - num = Word(nums) - term = ident | num - func = ident + Optional(delimitedList(term)) - print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] - - func = ident + Group(Optional(delimitedList(term))) - print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] - """ - def __init__( self, expr ): - super(Group,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - return [ tokenlist ] - -class Dict(TokenConverter): - """ - Converter to return a repetitive expression as a list, but also as a dictionary. - Each element can also be referenced using the first token in the expression as its key. - Useful for tabular report scraping when the first column can be used as a item key. - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - # print attributes as plain groups - print(OneOrMore(attr_expr).parseString(text).dump()) - - # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names - result = Dict(OneOrMore(Group(attr_expr))).parseString(text) - print(result.dump()) - - # access named fields as dict entries, or output as dict - print(result['shape']) - print(result.asDict()) - prints:: - ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} - See more examples at L{ParseResults} of accessing fields by results name. - """ - def __init__( self, expr ): - super(Dict,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - for i,tok in enumerate(tokenlist): - if len(tok) == 0: - continue - ikey = tok[0] - if isinstance(ikey,int): - ikey = _ustr(tok[0]).strip() - if len(tok)==1: - tokenlist[ikey] = _ParseResultsWithOffset("",i) - elif len(tok)==2 and not isinstance(tok[1],ParseResults): - tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) - else: - dictvalue = tok.copy() #ParseResults(i) - del dictvalue[0] - if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) - else: - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) - - if self.resultsName: - return [ tokenlist ] - else: - return tokenlist - - -class Suppress(TokenConverter): - """ - Converter for ignoring the results of a parsed expression. - - Example:: - source = "a, b, c,d" - wd = Word(alphas) - wd_list1 = wd + ZeroOrMore(',' + wd) - print(wd_list1.parseString(source)) - - # often, delimiters that are useful during parsing are just in the - # way afterward - use Suppress to keep them out of the parsed output - wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) - print(wd_list2.parseString(source)) - prints:: - ['a', ',', 'b', ',', 'c', ',', 'd'] - ['a', 'b', 'c', 'd'] - (See also L{delimitedList}.) - """ - def postParse( self, instring, loc, tokenlist ): - return [] - - def suppress( self ): - return self - - -class OnlyOnce(object): - """ - Wrapper for parse actions, to ensure they are only called once. - """ - def __init__(self, methodCall): - self.callable = _trim_arity(methodCall) - self.called = False - def __call__(self,s,l,t): - if not self.called: - results = self.callable(s,l,t) - self.called = True - return results - raise ParseException(s,l,"") - def reset(self): - self.called = False - -def traceParseAction(f): - """ - Decorator for debugging parse actions. - - When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} - When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. - - Example:: - wd = Word(alphas) - - @traceParseAction - def remove_duplicate_chars(tokens): - return ''.join(sorted(set(''.join(tokens))) - - wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) - print(wds.parseString("slkdjs sld sldd sdlf sdljf")) - prints:: - >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) - <3: - thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc - sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) - try: - ret = f(*paArgs) - except Exception as exc: - sys.stderr.write( "< ['aa', 'bb', 'cc'] - delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] - """ - dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." - if combine: - return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) - else: - return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) - -def countedArray( expr, intExpr=None ): - """ - Helper to define a counted list of expressions. - This helper defines a pattern of the form:: - integer expr expr expr... - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. - - If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. - - Example:: - countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) - countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] - """ - arrayExpr = Forward() - def countFieldParseAction(s,l,t): - n = t[0] - arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) - return [] - if intExpr is None: - intExpr = Word(nums).setParseAction(lambda t:int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.setName("arrayLen") - intExpr.addParseAction(countFieldParseAction, callDuringTry=True) - return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') - -def _flatten(L): - ret = [] - for i in L: - if isinstance(i,list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret - -def matchPreviousLiteral(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousLiteral(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches a - previous literal, will also match the leading C{"1:1"} in C{"1:10"}. - If this is not desired, use C{matchPreviousExpr}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - def copyTokenToRepeater(s,l,t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.asList()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def matchPreviousExpr(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousExpr(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches by - expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; - the expressions are evaluated first, and then compared, so - C{"1"} is compared with C{"10"}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - def copyTokenToRepeater(s,l,t): - matchTokens = _flatten(t.asList()) - def mustMatchTheseTokens(s,l,t): - theseTokens = _flatten(t.asList()) - if theseTokens != matchTokens: - raise ParseException("",0,"") - rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def _escapeRegexRangeChars(s): - #~ escape these chars: ^-] - for c in r"\^-]": - s = s.replace(c,_bslash+c) - s = s.replace("\n",r"\n") - s = s.replace("\t",r"\t") - return _ustr(s) - -def oneOf( strs, caseless=False, useRegex=True ): - """ - Helper to quickly define a set of alternative Literals, and makes sure to do - longest-first testing when there is a conflict, regardless of the input order, - but returns a C{L{MatchFirst}} for best performance. - - Parameters: - - strs - a string of space-delimited literals, or a collection of string literals - - caseless - (default=C{False}) - treat all literals as caseless - - useRegex - (default=C{True}) - as an optimization, will generate a Regex - object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or - if creating a C{Regex} raises an exception) - - Example:: - comp_oper = oneOf("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) - prints:: - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - if caseless: - isequal = ( lambda a,b: a.upper() == b.upper() ) - masks = ( lambda a,b: b.upper().startswith(a.upper()) ) - parseElementClass = CaselessLiteral - else: - isequal = ( lambda a,b: a == b ) - masks = ( lambda a,b: b.startswith(a) ) - parseElementClass = Literal - - symbols = [] - if isinstance(strs,basestring): - symbols = strs.split() - elif isinstance(strs, collections.Iterable): - symbols = list(strs) - else: - warnings.warn("Invalid argument to oneOf, expected string or iterable", - SyntaxWarning, stacklevel=2) - if not symbols: - return NoMatch() - - i = 0 - while i < len(symbols)-1: - cur = symbols[i] - for j,other in enumerate(symbols[i+1:]): - if ( isequal(other, cur) ): - del symbols[i+j+1] - break - elif ( masks(cur, other) ): - del symbols[i+j+1] - symbols.insert(i,other) - cur = other - break - else: - i += 1 - - if not caseless and useRegex: - #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) - try: - if len(symbols)==len("".join(symbols)): - return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) - else: - return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) - except Exception: - warnings.warn("Exception creating Regex for oneOf, building MatchFirst", - SyntaxWarning, stacklevel=2) - - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) - -def dictOf( key, value ): - """ - Helper to easily and clearly define a dictionary by specifying the respective patterns - for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens - in the proper order. The key pattern can include delimiting markers or punctuation, - as long as they are suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the C{Dict} results can include named token - fields. - - Example:: - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - print(OneOrMore(attr_expr).parseString(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) - - # similar to Dict, but simpler call format - result = dictOf(attr_label, attr_value).parseString(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.asDict()) - prints:: - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict( ZeroOrMore( Group ( key + value ) ) ) - -def originalTextFor(expr, asString=True): - """ - Helper to return the original, untokenized text for a given expression. Useful to - restore the parsed fields of an HTML start tag into the raw tag text itself, or to - revert separate tokens with intervening whitespace back to the original matching - input text. By default, returns astring containing the original parsed text. - - If the optional C{asString} argument is passed as C{False}, then the return value is a - C{L{ParseResults}} containing any results names that were originally matched, and a - single token containing the original matched text from the input string. So if - the expression passed to C{L{originalTextFor}} contains expressions with defined - results names, you must set C{asString} to C{False} if you want to preserve those - results name values. - - Example:: - src = "this is test bold text normal text " - for tag in ("b","i"): - opener,closer = makeHTMLTags(tag) - patt = originalTextFor(opener + SkipTo(closer) + closer) - print(patt.searchString(src)[0]) - prints:: - [' bold text '] - ['text'] - """ - locMarker = Empty().setParseAction(lambda s,loc,t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s,l,t: s[t._original_start:t._original_end] - else: - def extractText(s,l,t): - t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] - matchExpr.setParseAction(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - return matchExpr - -def ungroup(expr): - """ - Helper to undo pyparsing's default grouping of And expressions, even - if all but one are non-empty. - """ - return TokenConverter(expr).setParseAction(lambda t:t[0]) - -def locatedExpr(expr): - """ - Helper to decorate a returned token with its starting and ending locations in the input string. - This helper adds the following results names: - - locn_start = location where matched expression begins - - locn_end = location where matched expression ends - - value = the actual parsed results - - Be careful if the input text contains C{} characters, you may want to call - C{L{ParserElement.parseWithTabs}} - - Example:: - wd = Word(alphas) - for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): - print(match) - prints:: - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().setParseAction(lambda s,l,t: l) - return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) - - -# convenience constants for positional expressions -empty = Empty().setName("empty") -lineStart = LineStart().setName("lineStart") -lineEnd = LineEnd().setName("lineEnd") -stringStart = StringStart().setName("stringStart") -stringEnd = StringEnd().setName("stringEnd") - -_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) -_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) -_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) -_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(printables, excludeChars=r'\]', exact=1) | Regex(r"\w", re.UNICODE) -_charRange = Group(_singleChar + Suppress("-") + _singleChar) -_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" - -def srange(s): - r""" - Helper to easily define string ranges for use in Word construction. Borrows - syntax from regexp '[]' string range definitions:: - srange("[0-9]") -> "0123456789" - srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" - srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" - The input string must be enclosed in []'s, and the returned string is the expanded - character set joined into a single string. - The values enclosed in the []'s may be: - - a single character - - an escaped character with a leading backslash (such as C{\-} or C{\]}) - - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) - (C{\0x##} is also supported for backwards compatibility) - - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) - - a range of any of the above, separated by a dash (C{'a-z'}, etc.) - - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) - """ - _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) - try: - return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) - except Exception: - return "" - -def matchOnlyAtCol(n): - """ - Helper method for defining parse actions that require matching at a specific - column in the input text. - """ - def verifyCol(strg,locn,toks): - if col(locn,strg) != n: - raise ParseException(strg,locn,"matched token not at column %d" % n) - return verifyCol - -def replaceWith(replStr): - """ - Helper method for common parse actions that simply return a literal value. Especially - useful when used with C{L{transformString}()}. - - Example:: - num = Word(nums).setParseAction(lambda toks: int(toks[0])) - na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) - term = na | num - - OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] - """ - return lambda s,l,t: [replStr] - -def removeQuotes(s,l,t): - """ - Helper parse action for removing quotation marks from parsed quoted strings. - - Example:: - # by default, quotation marks are included in parsed results - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] - - # use removeQuotes to strip quotation marks from parsed results - quotedString.setParseAction(removeQuotes) - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] - """ - return t[0][1:-1] - -def tokenMap(func, *args): - """ - Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional - args are passed, they are forwarded to the given function as additional arguments after - the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the - parsed data to an integer using base 16. - - Example (compare the last to example in L{ParserElement.transformString}:: - hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) - hex_ints.runTests(''' - 00 11 22 aa FF 0a 0d 1a - ''') - - upperword = Word(alphas).setParseAction(tokenMap(str.upper)) - OneOrMore(upperword).runTests(''' - my kingdom for a horse - ''') - - wd = Word(alphas).setParseAction(tokenMap(str.title)) - OneOrMore(wd).setParseAction(' '.join).runTests(''' - now is the winter of our discontent made glorious summer by this sun of york - ''') - prints:: - 00 11 22 aa FF 0a 0d 1a - [0, 17, 34, 170, 255, 10, 13, 26] - - my kingdom for a horse - ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] - - now is the winter of our discontent made glorious summer by this sun of york - ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] - """ - def pa(s,l,t): - return [func(tokn, *args) for tokn in t] - - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - pa.__name__ = func_name - - return pa - -upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) -"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" - -downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) -"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" - -def _makeTags(tagStr, xml): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr,basestring): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas,alphanums+"_-:") - if (xml): - tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - else: - printablesLessRAbrack = "".join(c for c in printables if c not in ">") - tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ - Optional( Suppress("=") + tagAttrValue ) ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - closeTag = Combine(_L("") - - openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) - closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname) - openTag.tag = resname - closeTag.tag = resname - return openTag, closeTag - -def makeHTMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches - tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. - - Example:: - text = 'More info at the pyparsing wiki page' - # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple - a,a_end = makeHTMLTags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.searchString(text): - # attributes in the tag (like "href" shown here) are also accessible as named results - print(link.link_text, '->', link.href) - prints:: - pyparsing -> http://pyparsing.wikispaces.com - """ - return _makeTags( tagStr, False ) - -def makeXMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for XML, given a tag name. Matches - tags only in the given upper/lower case. - - Example: similar to L{makeHTMLTags} - """ - return _makeTags( tagStr, True ) - -def withAttribute(*args,**attrDict): - """ - Helper to create a validating parse action to be used with start tags created - with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag - with a required attribute value, to avoid false matches on common tags such as - C{} or C{

}. - - Call C{withAttribute} with a series of attribute names and values. Specify the list - of filter attributes names and values as: - - keyword arguments, as in C{(align="right")}, or - - as an explicit dict with C{**} operator, when an attribute name is also a Python - reserved word, as in C{**{"class":"Customer", "align":"right"}} - - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) - For attribute names with a namespace prefix, you must use the second form. Attribute - names are matched insensitive to upper/lower case. - - If just testing for C{class} (with or without a namespace), use C{L{withClass}}. - - To verify that the attribute exists, but without specifying a value, pass - C{withAttribute.ANY_VALUE} as the value. - - Example:: - html = ''' -
- Some text -
1 4 0 1 0
-
1,3 2,3 1,1
-
this has no type
-
- - ''' - div,div_end = makeHTMLTags("div") - - # only match div tag having a type attribute with value "grid" - div_grid = div().setParseAction(withAttribute(type="grid")) - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - # construct a match with any div tag having a type attribute, regardless of the value - div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - if args: - attrs = args[:] - else: - attrs = attrDict.items() - attrs = [(k,v) for k,v in attrs] - def pa(s,l,tokens): - for attrName,attrValue in attrs: - if attrName not in tokens: - raise ParseException(s,l,"no matching attribute " + attrName) - if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: - raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % - (attrName, tokens[attrName], attrValue)) - return pa -withAttribute.ANY_VALUE = object() - -def withClass(classname, namespace=''): - """ - Simplified version of C{L{withAttribute}} when matching on a div class - made - difficult because C{class} is a reserved word in Python. - - Example:: - html = ''' -
- Some text -
1 4 0 1 0
-
1,3 2,3 1,1
-
this <div> has no class
-
- - ''' - div,div_end = makeHTMLTags("div") - div_grid = div().setParseAction(withClass("grid")) - - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - classattr = "%s:class" % namespace if namespace else "class" - return withAttribute(**{classattr : classname}) - -opAssoc = _Constants() -opAssoc.LEFT = object() -opAssoc.RIGHT = object() - -def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): - """ - Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary or - binary, left- or right-associative. Parse actions can also be attached - to operator expressions. The generated parser will also recognize the use - of parentheses to override operator precedences (see example below). - - Note: if you define a deep operator list, you may see performance issues - when using infixNotation. See L{ParserElement.enablePackrat} for a - mechanism to potentially improve your parser performance. - - Parameters: - - baseExpr - expression representing the most basic element for the nested - - opList - list of tuples, one for each operator precedence level in the - expression grammar; each tuple is of the form - (opExpr, numTerms, rightLeftAssoc, parseAction), where: - - opExpr is the pyparsing expression for the operator; - may also be a string, which will be converted to a Literal; - if numTerms is 3, opExpr is a tuple of two expressions, for the - two operators separating the 3 terms - - numTerms is the number of terms for this operator (must - be 1, 2, or 3) - - rightLeftAssoc is the indicator whether the operator is - right or left associative, using the pyparsing-defined - constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - - parseAction is the parse action to be associated with - expressions matching this operator expression (the - parse action tuple member may be omitted) - - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) - - Example:: - # simple example of four-function arithmetic with ints and variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infixNotation(integer | varname, - [ - ('-', 1, opAssoc.RIGHT), - (oneOf('* /'), 2, opAssoc.LEFT), - (oneOf('+ -'), 2, opAssoc.LEFT), - ]) - - arith_expr.runTests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', fullDump=False) - prints:: - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - ret = Forward() - lastExpr = baseExpr | ( lpar + ret + rpar ) - for i,operDef in enumerate(opList): - opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] - termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr - if arity == 3: - if opExpr is None or len(opExpr) != 2: - raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") - opExpr1, opExpr2 = opExpr - thisExpr = Forward().setName(termName) - if rightLeftAssoc == opAssoc.LEFT: - if arity == 1: - matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) - else: - matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ - Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - elif rightLeftAssoc == opAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Optional): - opExpr = Optional(opExpr) - matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) - else: - matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ - Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - else: - raise ValueError("operator must indicate right or left associativity") - if pa: - matchExpr.setParseAction( pa ) - thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) - lastExpr = thisExpr - ret <<= lastExpr - return ret - -operatorPrecedence = infixNotation -"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" - -dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") -sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") -quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| - Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") -unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") - -def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): - """ - Helper method for defining nested lists enclosed in opening and closing - delimiters ("(" and ")" are the default). - - Parameters: - - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - - content - expression for items within the nested lists (default=C{None}) - - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) - - If an expression is not provided for the content argument, the nested - expression will capture all whitespace-delimited content between delimiters - as a list of separate values. - - Use the C{ignoreExpr} argument to define expressions that may contain - opening or closing characters that should not be treated as opening - or closing characters for nesting, such as quotedString or a comment - expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. - The default is L{quotedString}, but if no expressions are to be ignored, - then pass C{None} for this argument. - - Example:: - data_type = oneOf("void int short long char float double") - decl_data_type = Combine(data_type + Optional(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR,RPAR = map(Suppress, "()") - - code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Optional(delimitedList(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(cStyleComment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.searchString(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - prints:: - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener,basestring) and isinstance(closer,basestring): - if len(opener) == 1 and len(closer)==1: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS - ).setParseAction(lambda t:t[0].strip())) - else: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - ~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - raise ValueError("opening and closing arguments must be strings if no content expression is given") - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) - else: - ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) - ret.setName('nested %s%s expression' % (opener,closer)) - return ret - -def indentedBlock(blockStatementExpr, indentStack, indent=True): - """ - Helper method for defining space-delimited indentation blocks, such as - those used to define block statements in Python source code. - - Parameters: - - blockStatementExpr - expression defining syntax of statement that - is repeated within the indented block - - indentStack - list created by caller to manage indentation stack - (multiple statementWithIndentedBlock expressions within a single grammar - should share a common indentStack) - - indent - boolean indicating whether block must be indented beyond the - the current level; set to False for block of left-most statements - (default=C{True}) - - A valid block must contain at least one C{blockStatement}. - - Example:: - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group( funcDecl + func_body ) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << ( funcDef | assignment | identifier ) - - module_body = OneOrMore(stmt) - - parseTree = module_body.parseString(data) - parseTree.pprint() - prints:: - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - def checkPeerIndent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseFatalException(s,l,"illegal nesting") - raise ParseException(s,l,"not a peer entry") - - def checkSubIndent(s,l,t): - curCol = col(l,s) - if curCol > indentStack[-1]: - indentStack.append( curCol ) - else: - raise ParseException(s,l,"not a subentry") - - def checkUnindent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): - raise ParseException(s,l,"not an unindent") - indentStack.pop() - - NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) - INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') - PEER = Empty().setParseAction(checkPeerIndent).setName('') - UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') - if indent: - smExpr = Group( Optional(NL) + - #~ FollowedBy(blockStatementExpr) + - INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) - else: - smExpr = Group( Optional(NL) + - (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.setName('indented block') - -alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") -punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") - -anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) -_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) -commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") -def replaceHTMLEntity(t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") -"Comment of the form C{/* ... */}" - -htmlComment = Regex(r"").setName("HTML comment") -"Comment of the form C{}" - -restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") -dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") -"Comment of the form C{// ... (to end of line)}" - -cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") -"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" - -javaStyleComment = cppStyleComment -"Same as C{L{cppStyleComment}}" - -pythonStyleComment = Regex(r"#.*").setName("Python style comment") -"Comment of the form C{# ... (to end of line)}" - -_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + - Optional( Word(" \t") + - ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") -commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") -"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. - This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" - -# some other useful expressions - using lower-case class name since we are really using this as a namespace -class pyparsing_common: - """ - Here are some common low-level expressions that may be useful in jump-starting parser development: - - numeric forms (L{integers}, L{reals}, L{scientific notation}) - - common L{programming identifiers} - - network addresses (L{MAC}, L{IPv4}, L{IPv6}) - - ISO8601 L{dates} and L{datetime} - - L{UUID} - - L{comma-separated list} - Parse actions: - - C{L{convertToInteger}} - - C{L{convertToFloat}} - - C{L{convertToDate}} - - C{L{convertToDatetime}} - - C{L{stripHTMLTags}} - - C{L{upcaseTokens}} - - C{L{downcaseTokens}} - - Example:: - pyparsing_common.number.runTests(''' - # any int or real number, returned as the appropriate type - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.fnumber.runTests(''' - # any int or real number, returned as float - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.hex_integer.runTests(''' - # hex numbers - 100 - FF - ''') - - pyparsing_common.fraction.runTests(''' - # fractions - 1/2 - -3/4 - ''') - - pyparsing_common.mixed_integer.runTests(''' - # mixed fractions - 1 - 1/2 - -3/4 - 1-3/4 - ''') - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' - # uuid - 12345678-1234-5678-1234-567812345678 - ''') - prints:: - # any int or real number, returned as the appropriate type - 100 - [100] - - -100 - [-100] - - +100 - [100] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # any int or real number, returned as float - 100 - [100.0] - - -100 - [-100.0] - - +100 - [100.0] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # hex numbers - 100 - [256] - - FF - [255] - - # fractions - 1/2 - [0.5] - - -3/4 - [-0.75] - - # mixed fractions - 1 - [1] - - 1/2 - [0.5] - - -3/4 - [-0.75] - - 1-3/4 - [1.75] - - # uuid - 12345678-1234-5678-1234-567812345678 - [UUID('12345678-1234-5678-1234-567812345678')] - """ - - convertToInteger = tokenMap(int) - """ - Parse action for converting parsed integers to Python int - """ - - convertToFloat = tokenMap(float) - """ - Parse action for converting parsed numbers to Python float - """ - - integer = Word(nums).setName("integer").setParseAction(convertToInteger) - """expression that parses an unsigned integer, returns an int""" - - hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) - """expression that parses a hexadecimal integer, returns an int""" - - signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) - """expression that parses an integer with optional leading sign, returns an int""" - - fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") - """fractional expression of an integer divided by an integer, returns a float""" - fraction.addParseAction(lambda t: t[0]/t[-1]) - - mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") - """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" - mixed_integer.addParseAction(sum) - - real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) - """expression that parses a floating point number and returns a float""" - - sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) - """expression that parses a floating point number with optional scientific notation and returns a float""" - - # streamlining this expression makes the docs nicer-looking - number = (sci_real | real | signed_integer).streamline() - """any numeric expression, returns the corresponding Python type""" - - fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) - """any int or real number, returned as float""" - - identifier = Word(alphas+'_', alphanums+'_').setName("identifier") - """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" - - ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") - "IPv4 address (C{0.0.0.0 - 255.255.255.255})" - - _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") - _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") - _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") - _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) - _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") - ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") - "IPv6 address (long, short, or mixed form)" - - mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") - "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" - - @staticmethod - def convertToDate(fmt="%Y-%m-%d"): - """ - Helper to create a parse action for converting parsed date string to Python datetime.date - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) - - Example:: - date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) - prints:: - [datetime.date(1999, 12, 31)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt).date() - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - @staticmethod - def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): - """ - Helper to create a parse action for converting parsed datetime string to Python datetime.datetime - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) - - Example:: - dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) - prints:: - [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt) - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") - "ISO8601 date (C{yyyy-mm-dd})" - - iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") - "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" - - uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") - "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" - - _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() - @staticmethod - def stripHTMLTags(s, l, tokens): - """ - Parse action to remove HTML tags from web page HTML source - - Example:: - # strip HTML links from normal text - text = 'More info at the
pyparsing wiki page' - td,td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - - print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' - """ - return pyparsing_common._html_stripper.transformString(tokens[0]) - - _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') - + Optional( White(" \t") ) ) ).streamline().setName("commaItem") - comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") - """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" - - upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) - """Parse action to convert tokens to upper case.""" - - downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) - """Parse action to convert tokens to lower case.""" - - -if __name__ == "__main__": - - selectToken = CaselessLiteral("select") - fromToken = CaselessLiteral("from") - - ident = Word(alphas, alphanums + "_$") - - columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - columnNameList = Group(delimitedList(columnName)).setName("columns") - columnSpec = ('*' | columnNameList) - - tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - tableNameList = Group(delimitedList(tableName)).setName("tables") - - simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") - - # demo runTests method, including embedded comments in test string - simpleSQL.runTests(""" - # '*' as column list and dotted table name - select * from SYS.XYZZY - - # caseless match on "SELECT", and casts back to "select" - SELECT * from XYZZY, ABC - - # list of column names, and mixed case SELECT keyword - Select AA,BB,CC from Sys.dual - - # multiple tables - Select A, B, C from Sys.dual, Table2 - - # invalid SELECT keyword - should fail - Xelect A, B, C from Sys.dual - - # incomplete command - should fail - Select - - # invalid column name - should fail - Select ^^^ frox Sys.dual - - """) - - pyparsing_common.number.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - # any int or real number, returned as float - pyparsing_common.fnumber.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - pyparsing_common.hex_integer.runTests(""" - 100 - FF - """) - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(""" - 12345678-1234-5678-1234-567812345678 - """) +# module pyparsing.py +# +# Copyright (c) 2003-2016 Paul T. McGuire +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments +""" + +__version__ = "2.1.10" +__versionTime__ = "07 Oct 2016 01:31 UTC" +__author__ = "Paul McGuire " + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex('&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "" ] + + out += [ nl, indent, "" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + """ + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +collections.MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [(frame_summary.filename, frame_summary.lineno)] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [(frame_summary.filename, frame_summary.lineno)] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define action to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add parse action to expression's list of parse actions. See L{I{setParseAction}}. + + See examples in L{I{copy}}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or loc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + if len(cache) > size: + cache.popitem(False) + + def clear(self): + cache.clear() + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + if len(cache) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + prints:: + ['More', 'Iron', 'Lead', 'Gold', 'I'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, And._ErrorStop(), other ] ) + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match at loc (,)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + """ + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern,"\g<1>",ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "", + "\t": "", + "\n": "", + "\r": "", + "\f": "", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "< ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, collections.Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test bold text normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + [' bold text '] + ['text'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(printables, excludeChars=r'\]', exact=1) | Regex(r"\w", re.UNICODE) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = 'More info at the pyparsing wiki page' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{} or C{
}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this has no type
+
+ + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this <div> has no class
+
+ + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + matchExpr.setParseAction( pa ) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"").setName("HTML comment") +"Comment of the form C{}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers}, L{reals}, L{scientific notation}) + - common L{programming identifiers} + - network addresses (L{MAC}, L{IPv4}, L{IPv6}) + - ISO8601 L{dates} and L{datetime} + - L{UUID} + - L{comma-separated list} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = 'More info at the
pyparsing wiki page' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/PKG-INFO b/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/PKG-INFO index fc5146800..340460dc9 100644 --- a/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/PKG-INFO +++ b/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/PKG-INFO @@ -1,17 +1,17 @@ -Metadata-Version: 1.1 -Name: pycparser -Version: 2.18 -Summary: C parser in Python -Home-page: https://github.com/eliben/pycparser -Author: Eli Bendersky -Author-email: eliben@gmail.com -License: BSD -Description: - pycparser is a complete parser of the C language, written in - pure Python using the PLY parsing library. - It parses C code into an AST and can serve as a front-end for - C compilers or analysis tools. - -Platform: Cross Platform -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 3 +Metadata-Version: 1.1 +Name: pycparser +Version: 2.18 +Summary: C parser in Python +Home-page: https://github.com/eliben/pycparser +Author: Eli Bendersky +Author-email: eliben@gmail.com +License: BSD +Description: + pycparser is a complete parser of the C language, written in + pure Python using the PLY parsing library. + It parses C code into an AST and can serve as a front-end for + C compilers or analysis tools. + +Platform: Cross Platform +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 diff --git a/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/installed-files.txt b/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/installed-files.txt index 2f1fb6db8..67bfc55fa 100644 --- a/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/installed-files.txt +++ b/website/web/Lib/site-packages/pycparser-2.18-py3.6.egg-info/installed-files.txt @@ -1,39 +1,39 @@ -..\pycparser\ast_transforms.py -..\pycparser\c_ast.py -..\pycparser\c_generator.py -..\pycparser\c_lexer.py -..\pycparser\c_parser.py -..\pycparser\lextab.py -..\pycparser\plyparser.py -..\pycparser\yacctab.py -..\pycparser\_ast_gen.py -..\pycparser\_build_tables.py -..\pycparser\__init__.py -..\pycparser\ply\cpp.py -..\pycparser\ply\ctokens.py -..\pycparser\ply\lex.py -..\pycparser\ply\yacc.py -..\pycparser\ply\ygen.py -..\pycparser\ply\__init__.py -..\pycparser\_c_ast.cfg -..\pycparser\__pycache__\ast_transforms.cpython-36.pyc -..\pycparser\__pycache__\c_ast.cpython-36.pyc -..\pycparser\__pycache__\c_generator.cpython-36.pyc -..\pycparser\__pycache__\c_lexer.cpython-36.pyc -..\pycparser\__pycache__\c_parser.cpython-36.pyc -..\pycparser\__pycache__\lextab.cpython-36.pyc -..\pycparser\__pycache__\plyparser.cpython-36.pyc -..\pycparser\__pycache__\yacctab.cpython-36.pyc -..\pycparser\__pycache__\_ast_gen.cpython-36.pyc -..\pycparser\__pycache__\_build_tables.cpython-36.pyc -..\pycparser\__pycache__\__init__.cpython-36.pyc -..\pycparser\ply\__pycache__\cpp.cpython-36.pyc -..\pycparser\ply\__pycache__\ctokens.cpython-36.pyc -..\pycparser\ply\__pycache__\lex.cpython-36.pyc -..\pycparser\ply\__pycache__\yacc.cpython-36.pyc -..\pycparser\ply\__pycache__\ygen.cpython-36.pyc -..\pycparser\ply\__pycache__\__init__.cpython-36.pyc -dependency_links.txt -PKG-INFO -SOURCES.txt -top_level.txt +..\pycparser\ast_transforms.py +..\pycparser\c_ast.py +..\pycparser\c_generator.py +..\pycparser\c_lexer.py +..\pycparser\c_parser.py +..\pycparser\lextab.py +..\pycparser\plyparser.py +..\pycparser\yacctab.py +..\pycparser\_ast_gen.py +..\pycparser\_build_tables.py +..\pycparser\__init__.py +..\pycparser\ply\cpp.py +..\pycparser\ply\ctokens.py +..\pycparser\ply\lex.py +..\pycparser\ply\yacc.py +..\pycparser\ply\ygen.py +..\pycparser\ply\__init__.py +..\pycparser\_c_ast.cfg +..\pycparser\__pycache__\ast_transforms.cpython-36.pyc +..\pycparser\__pycache__\c_ast.cpython-36.pyc +..\pycparser\__pycache__\c_generator.cpython-36.pyc +..\pycparser\__pycache__\c_lexer.cpython-36.pyc +..\pycparser\__pycache__\c_parser.cpython-36.pyc +..\pycparser\__pycache__\lextab.cpython-36.pyc +..\pycparser\__pycache__\plyparser.cpython-36.pyc +..\pycparser\__pycache__\yacctab.cpython-36.pyc +..\pycparser\__pycache__\_ast_gen.cpython-36.pyc +..\pycparser\__pycache__\_build_tables.cpython-36.pyc +..\pycparser\__pycache__\__init__.cpython-36.pyc +..\pycparser\ply\__pycache__\cpp.cpython-36.pyc +..\pycparser\ply\__pycache__\ctokens.cpython-36.pyc +..\pycparser\ply\__pycache__\lex.cpython-36.pyc +..\pycparser\ply\__pycache__\yacc.cpython-36.pyc +..\pycparser\ply\__pycache__\ygen.cpython-36.pyc +..\pycparser\ply\__pycache__\__init__.cpython-36.pyc +dependency_links.txt +PKG-INFO +SOURCES.txt +top_level.txt diff --git a/website/web/Lib/site-packages/pycparser/c_ast.py b/website/web/Lib/site-packages/pycparser/c_ast.py index 5e81648d6..09c894186 100644 --- a/website/web/Lib/site-packages/pycparser/c_ast.py +++ b/website/web/Lib/site-packages/pycparser/c_ast.py @@ -1,809 +1,809 @@ -#----------------------------------------------------------------- -# ** ATTENTION ** -# This code was automatically generated from the file: -# _c_ast.cfg -# -# Do not modify it directly. Modify the configuration file and -# run the generator again. -# ** ** *** ** ** -# -# pycparser: c_ast.py -# -# AST Node classes. -# -# Eli Bendersky [http://eli.thegreenplace.net] -# License: BSD -#----------------------------------------------------------------- - - -import sys - - -class Node(object): - __slots__ = () - """ Abstract base class for AST nodes. - """ - def children(self): - """ A sequence of all children that are Nodes - """ - pass - - def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): - """ Pretty print the Node and all its attributes and - children (recursively) to a buffer. - - buf: - Open IO buffer into which the Node is printed. - - offset: - Initial offset (amount of leading spaces) - - attrnames: - True if you want to see the attribute names in - name=value pairs. False to only see the values. - - nodenames: - True if you want to see the actual node names - within their parents. - - showcoord: - Do you want the coordinates of each Node to be - displayed. - """ - lead = ' ' * offset - if nodenames and _my_node_name is not None: - buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ') - else: - buf.write(lead + self.__class__.__name__+ ': ') - - if self.attr_names: - if attrnames: - nvlist = [(n, getattr(self,n)) for n in self.attr_names] - attrstr = ', '.join('%s=%s' % nv for nv in nvlist) - else: - vlist = [getattr(self, n) for n in self.attr_names] - attrstr = ', '.join('%s' % v for v in vlist) - buf.write(attrstr) - - if showcoord: - buf.write(' (at %s)' % self.coord) - buf.write('\n') - - for (child_name, child) in self.children(): - child.show( - buf, - offset=offset + 2, - attrnames=attrnames, - nodenames=nodenames, - showcoord=showcoord, - _my_node_name=child_name) - - -class NodeVisitor(object): - """ A base NodeVisitor class for visiting c_ast nodes. - Subclass it and define your own visit_XXX methods, where - XXX is the class name you want to visit with these - methods. - - For example: - - class ConstantVisitor(NodeVisitor): - def __init__(self): - self.values = [] - - def visit_Constant(self, node): - self.values.append(node.value) - - Creates a list of values of all the constant nodes - encountered below the given node. To use it: - - cv = ConstantVisitor() - cv.visit(node) - - Notes: - - * generic_visit() will be called for AST nodes for which - no visit_XXX method was defined. - * The children of nodes for which a visit_XXX was - defined will not be visited - if you need this, call - generic_visit() on the node. - You can use: - NodeVisitor.generic_visit(self, node) - * Modeled after Python's own AST visiting facilities - (the ast module of Python 3.0) - """ - def visit(self, node): - """ Visit a node. - """ - method = 'visit_' + node.__class__.__name__ - visitor = getattr(self, method, self.generic_visit) - return visitor(node) - - def generic_visit(self, node): - """ Called if no explicit visitor function exists for a - node. Implements preorder visiting of the node. - """ - for c_name, c in node.children(): - self.visit(c) - - -class ArrayDecl(Node): - __slots__ = ('type', 'dim', 'dim_quals', 'coord', '__weakref__') - def __init__(self, type, dim, dim_quals, coord=None): - self.type = type - self.dim = dim - self.dim_quals = dim_quals - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - if self.dim is not None: nodelist.append(("dim", self.dim)) - return tuple(nodelist) - - attr_names = ('dim_quals', ) - -class ArrayRef(Node): - __slots__ = ('name', 'subscript', 'coord', '__weakref__') - def __init__(self, name, subscript, coord=None): - self.name = name - self.subscript = subscript - self.coord = coord - - def children(self): - nodelist = [] - if self.name is not None: nodelist.append(("name", self.name)) - if self.subscript is not None: nodelist.append(("subscript", self.subscript)) - return tuple(nodelist) - - attr_names = () - -class Assignment(Node): - __slots__ = ('op', 'lvalue', 'rvalue', 'coord', '__weakref__') - def __init__(self, op, lvalue, rvalue, coord=None): - self.op = op - self.lvalue = lvalue - self.rvalue = rvalue - self.coord = coord - - def children(self): - nodelist = [] - if self.lvalue is not None: nodelist.append(("lvalue", self.lvalue)) - if self.rvalue is not None: nodelist.append(("rvalue", self.rvalue)) - return tuple(nodelist) - - attr_names = ('op', ) - -class BinaryOp(Node): - __slots__ = ('op', 'left', 'right', 'coord', '__weakref__') - def __init__(self, op, left, right, coord=None): - self.op = op - self.left = left - self.right = right - self.coord = coord - - def children(self): - nodelist = [] - if self.left is not None: nodelist.append(("left", self.left)) - if self.right is not None: nodelist.append(("right", self.right)) - return tuple(nodelist) - - attr_names = ('op', ) - -class Break(Node): - __slots__ = ('coord', '__weakref__') - def __init__(self, coord=None): - self.coord = coord - - def children(self): - return () - - attr_names = () - -class Case(Node): - __slots__ = ('expr', 'stmts', 'coord', '__weakref__') - def __init__(self, expr, stmts, coord=None): - self.expr = expr - self.stmts = stmts - self.coord = coord - - def children(self): - nodelist = [] - if self.expr is not None: nodelist.append(("expr", self.expr)) - for i, child in enumerate(self.stmts or []): - nodelist.append(("stmts[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class Cast(Node): - __slots__ = ('to_type', 'expr', 'coord', '__weakref__') - def __init__(self, to_type, expr, coord=None): - self.to_type = to_type - self.expr = expr - self.coord = coord - - def children(self): - nodelist = [] - if self.to_type is not None: nodelist.append(("to_type", self.to_type)) - if self.expr is not None: nodelist.append(("expr", self.expr)) - return tuple(nodelist) - - attr_names = () - -class Compound(Node): - __slots__ = ('block_items', 'coord', '__weakref__') - def __init__(self, block_items, coord=None): - self.block_items = block_items - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.block_items or []): - nodelist.append(("block_items[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class CompoundLiteral(Node): - __slots__ = ('type', 'init', 'coord', '__weakref__') - def __init__(self, type, init, coord=None): - self.type = type - self.init = init - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - if self.init is not None: nodelist.append(("init", self.init)) - return tuple(nodelist) - - attr_names = () - -class Constant(Node): - __slots__ = ('type', 'value', 'coord', '__weakref__') - def __init__(self, type, value, coord=None): - self.type = type - self.value = value - self.coord = coord - - def children(self): - nodelist = [] - return tuple(nodelist) - - attr_names = ('type', 'value', ) - -class Continue(Node): - __slots__ = ('coord', '__weakref__') - def __init__(self, coord=None): - self.coord = coord - - def children(self): - return () - - attr_names = () - -class Decl(Node): - __slots__ = ('name', 'quals', 'storage', 'funcspec', 'type', 'init', 'bitsize', 'coord', '__weakref__') - def __init__(self, name, quals, storage, funcspec, type, init, bitsize, coord=None): - self.name = name - self.quals = quals - self.storage = storage - self.funcspec = funcspec - self.type = type - self.init = init - self.bitsize = bitsize - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - if self.init is not None: nodelist.append(("init", self.init)) - if self.bitsize is not None: nodelist.append(("bitsize", self.bitsize)) - return tuple(nodelist) - - attr_names = ('name', 'quals', 'storage', 'funcspec', ) - -class DeclList(Node): - __slots__ = ('decls', 'coord', '__weakref__') - def __init__(self, decls, coord=None): - self.decls = decls - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.decls or []): - nodelist.append(("decls[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class Default(Node): - __slots__ = ('stmts', 'coord', '__weakref__') - def __init__(self, stmts, coord=None): - self.stmts = stmts - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.stmts or []): - nodelist.append(("stmts[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class DoWhile(Node): - __slots__ = ('cond', 'stmt', 'coord', '__weakref__') - def __init__(self, cond, stmt, coord=None): - self.cond = cond - self.stmt = stmt - self.coord = coord - - def children(self): - nodelist = [] - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.stmt is not None: nodelist.append(("stmt", self.stmt)) - return tuple(nodelist) - - attr_names = () - -class EllipsisParam(Node): - __slots__ = ('coord', '__weakref__') - def __init__(self, coord=None): - self.coord = coord - - def children(self): - return () - - attr_names = () - -class EmptyStatement(Node): - __slots__ = ('coord', '__weakref__') - def __init__(self, coord=None): - self.coord = coord - - def children(self): - return () - - attr_names = () - -class Enum(Node): - __slots__ = ('name', 'values', 'coord', '__weakref__') - def __init__(self, name, values, coord=None): - self.name = name - self.values = values - self.coord = coord - - def children(self): - nodelist = [] - if self.values is not None: nodelist.append(("values", self.values)) - return tuple(nodelist) - - attr_names = ('name', ) - -class Enumerator(Node): - __slots__ = ('name', 'value', 'coord', '__weakref__') - def __init__(self, name, value, coord=None): - self.name = name - self.value = value - self.coord = coord - - def children(self): - nodelist = [] - if self.value is not None: nodelist.append(("value", self.value)) - return tuple(nodelist) - - attr_names = ('name', ) - -class EnumeratorList(Node): - __slots__ = ('enumerators', 'coord', '__weakref__') - def __init__(self, enumerators, coord=None): - self.enumerators = enumerators - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.enumerators or []): - nodelist.append(("enumerators[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class ExprList(Node): - __slots__ = ('exprs', 'coord', '__weakref__') - def __init__(self, exprs, coord=None): - self.exprs = exprs - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.exprs or []): - nodelist.append(("exprs[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class FileAST(Node): - __slots__ = ('ext', 'coord', '__weakref__') - def __init__(self, ext, coord=None): - self.ext = ext - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.ext or []): - nodelist.append(("ext[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class For(Node): - __slots__ = ('init', 'cond', 'next', 'stmt', 'coord', '__weakref__') - def __init__(self, init, cond, next, stmt, coord=None): - self.init = init - self.cond = cond - self.next = next - self.stmt = stmt - self.coord = coord - - def children(self): - nodelist = [] - if self.init is not None: nodelist.append(("init", self.init)) - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.next is not None: nodelist.append(("next", self.next)) - if self.stmt is not None: nodelist.append(("stmt", self.stmt)) - return tuple(nodelist) - - attr_names = () - -class FuncCall(Node): - __slots__ = ('name', 'args', 'coord', '__weakref__') - def __init__(self, name, args, coord=None): - self.name = name - self.args = args - self.coord = coord - - def children(self): - nodelist = [] - if self.name is not None: nodelist.append(("name", self.name)) - if self.args is not None: nodelist.append(("args", self.args)) - return tuple(nodelist) - - attr_names = () - -class FuncDecl(Node): - __slots__ = ('args', 'type', 'coord', '__weakref__') - def __init__(self, args, type, coord=None): - self.args = args - self.type = type - self.coord = coord - - def children(self): - nodelist = [] - if self.args is not None: nodelist.append(("args", self.args)) - if self.type is not None: nodelist.append(("type", self.type)) - return tuple(nodelist) - - attr_names = () - -class FuncDef(Node): - __slots__ = ('decl', 'param_decls', 'body', 'coord', '__weakref__') - def __init__(self, decl, param_decls, body, coord=None): - self.decl = decl - self.param_decls = param_decls - self.body = body - self.coord = coord - - def children(self): - nodelist = [] - if self.decl is not None: nodelist.append(("decl", self.decl)) - if self.body is not None: nodelist.append(("body", self.body)) - for i, child in enumerate(self.param_decls or []): - nodelist.append(("param_decls[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class Goto(Node): - __slots__ = ('name', 'coord', '__weakref__') - def __init__(self, name, coord=None): - self.name = name - self.coord = coord - - def children(self): - nodelist = [] - return tuple(nodelist) - - attr_names = ('name', ) - -class ID(Node): - __slots__ = ('name', 'coord', '__weakref__') - def __init__(self, name, coord=None): - self.name = name - self.coord = coord - - def children(self): - nodelist = [] - return tuple(nodelist) - - attr_names = ('name', ) - -class IdentifierType(Node): - __slots__ = ('names', 'coord', '__weakref__') - def __init__(self, names, coord=None): - self.names = names - self.coord = coord - - def children(self): - nodelist = [] - return tuple(nodelist) - - attr_names = ('names', ) - -class If(Node): - __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') - def __init__(self, cond, iftrue, iffalse, coord=None): - self.cond = cond - self.iftrue = iftrue - self.iffalse = iffalse - self.coord = coord - - def children(self): - nodelist = [] - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) - if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) - return tuple(nodelist) - - attr_names = () - -class InitList(Node): - __slots__ = ('exprs', 'coord', '__weakref__') - def __init__(self, exprs, coord=None): - self.exprs = exprs - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.exprs or []): - nodelist.append(("exprs[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class Label(Node): - __slots__ = ('name', 'stmt', 'coord', '__weakref__') - def __init__(self, name, stmt, coord=None): - self.name = name - self.stmt = stmt - self.coord = coord - - def children(self): - nodelist = [] - if self.stmt is not None: nodelist.append(("stmt", self.stmt)) - return tuple(nodelist) - - attr_names = ('name', ) - -class NamedInitializer(Node): - __slots__ = ('name', 'expr', 'coord', '__weakref__') - def __init__(self, name, expr, coord=None): - self.name = name - self.expr = expr - self.coord = coord - - def children(self): - nodelist = [] - if self.expr is not None: nodelist.append(("expr", self.expr)) - for i, child in enumerate(self.name or []): - nodelist.append(("name[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class ParamList(Node): - __slots__ = ('params', 'coord', '__weakref__') - def __init__(self, params, coord=None): - self.params = params - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.params or []): - nodelist.append(("params[%d]" % i, child)) - return tuple(nodelist) - - attr_names = () - -class PtrDecl(Node): - __slots__ = ('quals', 'type', 'coord', '__weakref__') - def __init__(self, quals, type, coord=None): - self.quals = quals - self.type = type - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - return tuple(nodelist) - - attr_names = ('quals', ) - -class Return(Node): - __slots__ = ('expr', 'coord', '__weakref__') - def __init__(self, expr, coord=None): - self.expr = expr - self.coord = coord - - def children(self): - nodelist = [] - if self.expr is not None: nodelist.append(("expr", self.expr)) - return tuple(nodelist) - - attr_names = () - -class Struct(Node): - __slots__ = ('name', 'decls', 'coord', '__weakref__') - def __init__(self, name, decls, coord=None): - self.name = name - self.decls = decls - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.decls or []): - nodelist.append(("decls[%d]" % i, child)) - return tuple(nodelist) - - attr_names = ('name', ) - -class StructRef(Node): - __slots__ = ('name', 'type', 'field', 'coord', '__weakref__') - def __init__(self, name, type, field, coord=None): - self.name = name - self.type = type - self.field = field - self.coord = coord - - def children(self): - nodelist = [] - if self.name is not None: nodelist.append(("name", self.name)) - if self.field is not None: nodelist.append(("field", self.field)) - return tuple(nodelist) - - attr_names = ('type', ) - -class Switch(Node): - __slots__ = ('cond', 'stmt', 'coord', '__weakref__') - def __init__(self, cond, stmt, coord=None): - self.cond = cond - self.stmt = stmt - self.coord = coord - - def children(self): - nodelist = [] - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.stmt is not None: nodelist.append(("stmt", self.stmt)) - return tuple(nodelist) - - attr_names = () - -class TernaryOp(Node): - __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') - def __init__(self, cond, iftrue, iffalse, coord=None): - self.cond = cond - self.iftrue = iftrue - self.iffalse = iffalse - self.coord = coord - - def children(self): - nodelist = [] - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) - if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) - return tuple(nodelist) - - attr_names = () - -class TypeDecl(Node): - __slots__ = ('declname', 'quals', 'type', 'coord', '__weakref__') - def __init__(self, declname, quals, type, coord=None): - self.declname = declname - self.quals = quals - self.type = type - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - return tuple(nodelist) - - attr_names = ('declname', 'quals', ) - -class Typedef(Node): - __slots__ = ('name', 'quals', 'storage', 'type', 'coord', '__weakref__') - def __init__(self, name, quals, storage, type, coord=None): - self.name = name - self.quals = quals - self.storage = storage - self.type = type - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - return tuple(nodelist) - - attr_names = ('name', 'quals', 'storage', ) - -class Typename(Node): - __slots__ = ('name', 'quals', 'type', 'coord', '__weakref__') - def __init__(self, name, quals, type, coord=None): - self.name = name - self.quals = quals - self.type = type - self.coord = coord - - def children(self): - nodelist = [] - if self.type is not None: nodelist.append(("type", self.type)) - return tuple(nodelist) - - attr_names = ('name', 'quals', ) - -class UnaryOp(Node): - __slots__ = ('op', 'expr', 'coord', '__weakref__') - def __init__(self, op, expr, coord=None): - self.op = op - self.expr = expr - self.coord = coord - - def children(self): - nodelist = [] - if self.expr is not None: nodelist.append(("expr", self.expr)) - return tuple(nodelist) - - attr_names = ('op', ) - -class Union(Node): - __slots__ = ('name', 'decls', 'coord', '__weakref__') - def __init__(self, name, decls, coord=None): - self.name = name - self.decls = decls - self.coord = coord - - def children(self): - nodelist = [] - for i, child in enumerate(self.decls or []): - nodelist.append(("decls[%d]" % i, child)) - return tuple(nodelist) - - attr_names = ('name', ) - -class While(Node): - __slots__ = ('cond', 'stmt', 'coord', '__weakref__') - def __init__(self, cond, stmt, coord=None): - self.cond = cond - self.stmt = stmt - self.coord = coord - - def children(self): - nodelist = [] - if self.cond is not None: nodelist.append(("cond", self.cond)) - if self.stmt is not None: nodelist.append(("stmt", self.stmt)) - return tuple(nodelist) - - attr_names = () - -class Pragma(Node): - __slots__ = ('string', 'coord', '__weakref__') - def __init__(self, string, coord=None): - self.string = string - self.coord = coord - - def children(self): - nodelist = [] - return tuple(nodelist) - - attr_names = ('string', ) - +#----------------------------------------------------------------- +# ** ATTENTION ** +# This code was automatically generated from the file: +# _c_ast.cfg +# +# Do not modify it directly. Modify the configuration file and +# run the generator again. +# ** ** *** ** ** +# +# pycparser: c_ast.py +# +# AST Node classes. +# +# Eli Bendersky [http://eli.thegreenplace.net] +# License: BSD +#----------------------------------------------------------------- + + +import sys + + +class Node(object): + __slots__ = () + """ Abstract base class for AST nodes. + """ + def children(self): + """ A sequence of all children that are Nodes + """ + pass + + def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): + """ Pretty print the Node and all its attributes and + children (recursively) to a buffer. + + buf: + Open IO buffer into which the Node is printed. + + offset: + Initial offset (amount of leading spaces) + + attrnames: + True if you want to see the attribute names in + name=value pairs. False to only see the values. + + nodenames: + True if you want to see the actual node names + within their parents. + + showcoord: + Do you want the coordinates of each Node to be + displayed. + """ + lead = ' ' * offset + if nodenames and _my_node_name is not None: + buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ') + else: + buf.write(lead + self.__class__.__name__+ ': ') + + if self.attr_names: + if attrnames: + nvlist = [(n, getattr(self,n)) for n in self.attr_names] + attrstr = ', '.join('%s=%s' % nv for nv in nvlist) + else: + vlist = [getattr(self, n) for n in self.attr_names] + attrstr = ', '.join('%s' % v for v in vlist) + buf.write(attrstr) + + if showcoord: + buf.write(' (at %s)' % self.coord) + buf.write('\n') + + for (child_name, child) in self.children(): + child.show( + buf, + offset=offset + 2, + attrnames=attrnames, + nodenames=nodenames, + showcoord=showcoord, + _my_node_name=child_name) + + +class NodeVisitor(object): + """ A base NodeVisitor class for visiting c_ast nodes. + Subclass it and define your own visit_XXX methods, where + XXX is the class name you want to visit with these + methods. + + For example: + + class ConstantVisitor(NodeVisitor): + def __init__(self): + self.values = [] + + def visit_Constant(self, node): + self.values.append(node.value) + + Creates a list of values of all the constant nodes + encountered below the given node. To use it: + + cv = ConstantVisitor() + cv.visit(node) + + Notes: + + * generic_visit() will be called for AST nodes for which + no visit_XXX method was defined. + * The children of nodes for which a visit_XXX was + defined will not be visited - if you need this, call + generic_visit() on the node. + You can use: + NodeVisitor.generic_visit(self, node) + * Modeled after Python's own AST visiting facilities + (the ast module of Python 3.0) + """ + def visit(self, node): + """ Visit a node. + """ + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + return visitor(node) + + def generic_visit(self, node): + """ Called if no explicit visitor function exists for a + node. Implements preorder visiting of the node. + """ + for c_name, c in node.children(): + self.visit(c) + + +class ArrayDecl(Node): + __slots__ = ('type', 'dim', 'dim_quals', 'coord', '__weakref__') + def __init__(self, type, dim, dim_quals, coord=None): + self.type = type + self.dim = dim + self.dim_quals = dim_quals + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.dim is not None: nodelist.append(("dim", self.dim)) + return tuple(nodelist) + + attr_names = ('dim_quals', ) + +class ArrayRef(Node): + __slots__ = ('name', 'subscript', 'coord', '__weakref__') + def __init__(self, name, subscript, coord=None): + self.name = name + self.subscript = subscript + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.subscript is not None: nodelist.append(("subscript", self.subscript)) + return tuple(nodelist) + + attr_names = () + +class Assignment(Node): + __slots__ = ('op', 'lvalue', 'rvalue', 'coord', '__weakref__') + def __init__(self, op, lvalue, rvalue, coord=None): + self.op = op + self.lvalue = lvalue + self.rvalue = rvalue + self.coord = coord + + def children(self): + nodelist = [] + if self.lvalue is not None: nodelist.append(("lvalue", self.lvalue)) + if self.rvalue is not None: nodelist.append(("rvalue", self.rvalue)) + return tuple(nodelist) + + attr_names = ('op', ) + +class BinaryOp(Node): + __slots__ = ('op', 'left', 'right', 'coord', '__weakref__') + def __init__(self, op, left, right, coord=None): + self.op = op + self.left = left + self.right = right + self.coord = coord + + def children(self): + nodelist = [] + if self.left is not None: nodelist.append(("left", self.left)) + if self.right is not None: nodelist.append(("right", self.right)) + return tuple(nodelist) + + attr_names = ('op', ) + +class Break(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Case(Node): + __slots__ = ('expr', 'stmts', 'coord', '__weakref__') + def __init__(self, expr, stmts, coord=None): + self.expr = expr + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Cast(Node): + __slots__ = ('to_type', 'expr', 'coord', '__weakref__') + def __init__(self, to_type, expr, coord=None): + self.to_type = to_type + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.to_type is not None: nodelist.append(("to_type", self.to_type)) + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = () + +class Compound(Node): + __slots__ = ('block_items', 'coord', '__weakref__') + def __init__(self, block_items, coord=None): + self.block_items = block_items + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.block_items or []): + nodelist.append(("block_items[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class CompoundLiteral(Node): + __slots__ = ('type', 'init', 'coord', '__weakref__') + def __init__(self, type, init, coord=None): + self.type = type + self.init = init + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + return tuple(nodelist) + + attr_names = () + +class Constant(Node): + __slots__ = ('type', 'value', 'coord', '__weakref__') + def __init__(self, type, value, coord=None): + self.type = type + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('type', 'value', ) + +class Continue(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Decl(Node): + __slots__ = ('name', 'quals', 'storage', 'funcspec', 'type', 'init', 'bitsize', 'coord', '__weakref__') + def __init__(self, name, quals, storage, funcspec, type, init, bitsize, coord=None): + self.name = name + self.quals = quals + self.storage = storage + self.funcspec = funcspec + self.type = type + self.init = init + self.bitsize = bitsize + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + if self.bitsize is not None: nodelist.append(("bitsize", self.bitsize)) + return tuple(nodelist) + + attr_names = ('name', 'quals', 'storage', 'funcspec', ) + +class DeclList(Node): + __slots__ = ('decls', 'coord', '__weakref__') + def __init__(self, decls, coord=None): + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Default(Node): + __slots__ = ('stmts', 'coord', '__weakref__') + def __init__(self, stmts, coord=None): + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class DoWhile(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class EllipsisParam(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class EmptyStatement(Node): + __slots__ = ('coord', '__weakref__') + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Enum(Node): + __slots__ = ('name', 'values', 'coord', '__weakref__') + def __init__(self, name, values, coord=None): + self.name = name + self.values = values + self.coord = coord + + def children(self): + nodelist = [] + if self.values is not None: nodelist.append(("values", self.values)) + return tuple(nodelist) + + attr_names = ('name', ) + +class Enumerator(Node): + __slots__ = ('name', 'value', 'coord', '__weakref__') + def __init__(self, name, value, coord=None): + self.name = name + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + if self.value is not None: nodelist.append(("value", self.value)) + return tuple(nodelist) + + attr_names = ('name', ) + +class EnumeratorList(Node): + __slots__ = ('enumerators', 'coord', '__weakref__') + def __init__(self, enumerators, coord=None): + self.enumerators = enumerators + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.enumerators or []): + nodelist.append(("enumerators[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class ExprList(Node): + __slots__ = ('exprs', 'coord', '__weakref__') + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class FileAST(Node): + __slots__ = ('ext', 'coord', '__weakref__') + def __init__(self, ext, coord=None): + self.ext = ext + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.ext or []): + nodelist.append(("ext[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class For(Node): + __slots__ = ('init', 'cond', 'next', 'stmt', 'coord', '__weakref__') + def __init__(self, init, cond, next, stmt, coord=None): + self.init = init + self.cond = cond + self.next = next + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.init is not None: nodelist.append(("init", self.init)) + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.next is not None: nodelist.append(("next", self.next)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class FuncCall(Node): + __slots__ = ('name', 'args', 'coord', '__weakref__') + def __init__(self, name, args, coord=None): + self.name = name + self.args = args + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.args is not None: nodelist.append(("args", self.args)) + return tuple(nodelist) + + attr_names = () + +class FuncDecl(Node): + __slots__ = ('args', 'type', 'coord', '__weakref__') + def __init__(self, args, type, coord=None): + self.args = args + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.args is not None: nodelist.append(("args", self.args)) + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = () + +class FuncDef(Node): + __slots__ = ('decl', 'param_decls', 'body', 'coord', '__weakref__') + def __init__(self, decl, param_decls, body, coord=None): + self.decl = decl + self.param_decls = param_decls + self.body = body + self.coord = coord + + def children(self): + nodelist = [] + if self.decl is not None: nodelist.append(("decl", self.decl)) + if self.body is not None: nodelist.append(("body", self.body)) + for i, child in enumerate(self.param_decls or []): + nodelist.append(("param_decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Goto(Node): + __slots__ = ('name', 'coord', '__weakref__') + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('name', ) + +class ID(Node): + __slots__ = ('name', 'coord', '__weakref__') + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('name', ) + +class IdentifierType(Node): + __slots__ = ('names', 'coord', '__weakref__') + def __init__(self, names, coord=None): + self.names = names + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('names', ) + +class If(Node): + __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + attr_names = () + +class InitList(Node): + __slots__ = ('exprs', 'coord', '__weakref__') + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Label(Node): + __slots__ = ('name', 'stmt', 'coord', '__weakref__') + def __init__(self, name, stmt, coord=None): + self.name = name + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = ('name', ) + +class NamedInitializer(Node): + __slots__ = ('name', 'expr', 'coord', '__weakref__') + def __init__(self, name, expr, coord=None): + self.name = name + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.name or []): + nodelist.append(("name[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class ParamList(Node): + __slots__ = ('params', 'coord', '__weakref__') + def __init__(self, params, coord=None): + self.params = params + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.params or []): + nodelist.append(("params[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class PtrDecl(Node): + __slots__ = ('quals', 'type', 'coord', '__weakref__') + def __init__(self, quals, type, coord=None): + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('quals', ) + +class Return(Node): + __slots__ = ('expr', 'coord', '__weakref__') + def __init__(self, expr, coord=None): + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = () + +class Struct(Node): + __slots__ = ('name', 'decls', 'coord', '__weakref__') + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = ('name', ) + +class StructRef(Node): + __slots__ = ('name', 'type', 'field', 'coord', '__weakref__') + def __init__(self, name, type, field, coord=None): + self.name = name + self.type = type + self.field = field + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.field is not None: nodelist.append(("field", self.field)) + return tuple(nodelist) + + attr_names = ('type', ) + +class Switch(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class TernaryOp(Node): + __slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__') + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + attr_names = () + +class TypeDecl(Node): + __slots__ = ('declname', 'quals', 'type', 'coord', '__weakref__') + def __init__(self, declname, quals, type, coord=None): + self.declname = declname + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('declname', 'quals', ) + +class Typedef(Node): + __slots__ = ('name', 'quals', 'storage', 'type', 'coord', '__weakref__') + def __init__(self, name, quals, storage, type, coord=None): + self.name = name + self.quals = quals + self.storage = storage + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('name', 'quals', 'storage', ) + +class Typename(Node): + __slots__ = ('name', 'quals', 'type', 'coord', '__weakref__') + def __init__(self, name, quals, type, coord=None): + self.name = name + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('name', 'quals', ) + +class UnaryOp(Node): + __slots__ = ('op', 'expr', 'coord', '__weakref__') + def __init__(self, op, expr, coord=None): + self.op = op + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = ('op', ) + +class Union(Node): + __slots__ = ('name', 'decls', 'coord', '__weakref__') + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = ('name', ) + +class While(Node): + __slots__ = ('cond', 'stmt', 'coord', '__weakref__') + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class Pragma(Node): + __slots__ = ('string', 'coord', '__weakref__') + def __init__(self, string, coord=None): + self.string = string + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('string', ) + diff --git a/website/web/Lib/site-packages/setuptools-28.8.0.dist-info/RECORD b/website/web/Lib/site-packages/setuptools-28.8.0.dist-info/RECORD index bc4ed9e7e..eec09f9a3 100644 --- a/website/web/Lib/site-packages/setuptools-28.8.0.dist-info/RECORD +++ b/website/web/Lib/site-packages/setuptools-28.8.0.dist-info/RECORD @@ -1,143 +1,143 @@ -easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 -pkg_resources/__init__.py,sha256=Z_i79ylo01fXF7p2lnMG7Ov4fLu0O-HLX-3JHMk0FCI,103301 -pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pkg_resources/_vendor/appdirs.py,sha256=tgGaL0m4Jo2VeuGfoOOifLv7a7oUEJu2n1vRkqoPw-0,22374 -pkg_resources/_vendor/pyparsing.py,sha256=PifeLY3-WhIcBVzLtv0U4T_pwDtPruBhBCkg5vLqa28,229867 -pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -pkg_resources/_vendor/packaging/__about__.py,sha256=E9KR5UJ_8U9K-R1mScu6FmkXtbnlFEEFjEXJp-7LxNU,720 -pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 -pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 -pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 -pkg_resources/_vendor/packaging/markers.py,sha256=ndShKOQb_OgpQkFju6LR-2msB1La5u5iAfD5MIqXE4c,7939 -pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 -pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 -pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 -pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 -pkg_resources/extern/__init__.py,sha256=JUtlHHvlxHSNuB4pWqNjcx7n6kG-fwXg7qmJ2zNJlIY,2487 -setuptools/__init__.py,sha256=hW5vya8Yp46AiWmYcALuQbGI7148nQSYVLsEIJLet54,5050 -setuptools/archive_util.py,sha256=Z58-gbZQ0j92UJy7X7uZevwI28JTVEXd__AjKy4aw78,6613 -setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 -setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/depends.py,sha256=h5tbRzianODRkECVsK4sLBbsOfpY1TGEnp9Zm0wg2To,6473 -setuptools/dist.py,sha256=5WUqgcvehkRw97T8NpV66vwneVp77LI9zOmWkPvgHoE,37129 -setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 -setuptools/glob.py,sha256=Y-fpv8wdHZzv9DPCaGACpMSBWJ6amq_1e0R_i8_el4w,5207 -setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 -setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 -setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 -setuptools/monkey.py,sha256=qHoZT9IgmFM-_yF7BjCoPtXg4DYF1H49t_1nLq7dPRo,5337 -setuptools/msvc.py,sha256=6cKqwOxTH8pJNMrNyRLBGB6Efz2rxTTdQQJABUW-6WU,37091 -setuptools/namespaces.py,sha256=I2YrskOZU2ctBS8jdFwAc9q4M8SxbOr0DsFLxxO7gfA,2648 -setuptools/package_index.py,sha256=eYtVpQiaP_4RRFp8zsNbsvNGPAzyOUDM2Lf_q4hePcs,39947 -setuptools/py26compat.py,sha256=VRGHC7z2gliR4_uICJsQNodUcNUzybpus3BrJkWbnK4,679 -setuptools/py27compat.py,sha256=Yu8hW3y8Djps_IenCuz5xZ9OD9qQ-kmBIoVGVpWeQ5Y,330 -setuptools/py31compat.py,sha256=qGRk3tefux8HbhNzhM0laR3mD8vhAZtffZgzLkBMXJs,1645 -setuptools/sandbox.py,sha256=0aNeoJ2tCLhHmQZlx8DQPhuuhGt2690Q7PoGLz6KJ30,14324 -setuptools/script (dev).tmpl,sha256=f7MR17dTkzaqkCMSVseyOCMVrPVSMdmTQsaB8cZzfuI,201 -setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 -setuptools/site-patch.py,sha256=BVt6yIrDMXJoflA5J6DJIcsJUfW_XEeVhOzelTTFDP4,2307 -setuptools/ssl_support.py,sha256=qUzJ_2WeFWBVkGoN638qC42Uzs-Wvmb8cZub9gT1xuI,8131 -setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 -setuptools/version.py,sha256=fvr31nm9BOi4wvMhGVoU0VwmyGeeEAeF3fh33z84wx4,138 -setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 -setuptools/command/__init__.py,sha256=FCLDWoQEGsNexQviqbeJ4MEYGYpYVbbwc7i-9gjzBkM,563 -setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 -setuptools/command/bdist_egg.py,sha256=XDamu6-cfyYrqd67YGQ5gWo-0c8kuWqkPy1vYpfsAxw,17178 -setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 -setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 -setuptools/command/build_ext.py,sha256=dO89j-IC0dAjSty1sSZxvi0LSdkPGR_ZPXFuAAFDZj4,13049 -setuptools/command/build_py.py,sha256=FwU7GNUnd2dT3yEtsTPsJBcl9a7loOcN6GB4uQ0W_IM,9596 -setuptools/command/develop.py,sha256=cHScw5hhILsZM3pk-ddORnd51aLFIbi-4gRm3yTnS_k,7384 -setuptools/command/easy_install.py,sha256=AlmasFuULxUXXgTcUhARle87a74rwStU5nSQn9Oakjw,85720 -setuptools/command/egg_info.py,sha256=f89c5gu9hWS89XheFLD0h0yONVmB4Z3FJR5hkAjn0SY,25110 -setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 -setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 -setuptools/command/install_lib.py,sha256=11mxf0Ch12NsuYwS8PHwXBRvyh671QAM4cTRh7epzG0,3840 -setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 -setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 -setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 -setuptools/command/register.py,sha256=bHlMm1qmBbSdahTOT8w6UhA-EgeQIz7p6cD-qOauaiI,270 -setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 -setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 -setuptools/command/sdist.py,sha256=cu745bayFZMEEGqzMg6kUbIYY9ZKXAbJjPBDXznNUyc,6650 -setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 -setuptools/command/test.py,sha256=IqkQ6rKdQsPh2BiLEXIx5FpzfGMpZttGl8dMa9utxVY,8535 -setuptools/command/upload.py,sha256=6LbdC9NWFe19tb8u-6L3Hriei-nVgtqfO7tn0Si7yLo,1077 -setuptools/command/upload_docs.py,sha256=0Ft5uo7Unnk4lJdZtIm6Nzq7hlyux-9zIYcXC8k_Czs,7275 -setuptools/extern/__init__.py,sha256=ZtCLYQ8JTtOtm7SYoxekZw-UzY3TR50SRIUaeqr2ROk,131 -setuptools-28.8.0.dist-info/DESCRIPTION.rst,sha256=UnjDOK_xBlHg-QN2JbfTbA55nmD_kStv89yxF9aOkqU,10257 -setuptools-28.8.0.dist-info/METADATA,sha256=Xf6UtJ6jxpg-nF5OHBErvUwMGLz-4nizC7iwdYmOcGc,11486 -setuptools-28.8.0.dist-info/RECORD,, -setuptools-28.8.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 -setuptools-28.8.0.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 -setuptools-28.8.0.dist-info/entry_points.txt,sha256=zPeIHv66mpCraHdiLlHQjxKDe-6gFIepEbEIjCvu8x4,2885 -setuptools-28.8.0.dist-info/metadata.json,sha256=EIv4nnlOffwLVnetEwhIkFs74vm5jfPJHsxZrjQyXFE,4614 -setuptools-28.8.0.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 -setuptools-28.8.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 -../../Scripts/easy_install.exe,sha256=w-ypzMIDXqnbbltKexCwN6Rv6_2qvmD1Ng6gGJ1dLmQ,98172 -../../Scripts/easy_install-3.6.exe,sha256=w-ypzMIDXqnbbltKexCwN6Rv6_2qvmD1Ng6gGJ1dLmQ,98172 -setuptools-28.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pkg_resources/extern/__pycache__/__init__.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/markers.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/utils.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/version.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-36.pyc,, -pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-36.pyc,, -pkg_resources/_vendor/__pycache__/appdirs.cpython-36.pyc,, -pkg_resources/_vendor/__pycache__/pyparsing.cpython-36.pyc,, -pkg_resources/_vendor/__pycache__/six.cpython-36.pyc,, -pkg_resources/_vendor/__pycache__/__init__.cpython-36.pyc,, -pkg_resources/__pycache__/__init__.cpython-36.pyc,, -setuptools/command/__pycache__/alias.cpython-36.pyc,, -setuptools/command/__pycache__/bdist_egg.cpython-36.pyc,, -setuptools/command/__pycache__/bdist_rpm.cpython-36.pyc,, -setuptools/command/__pycache__/bdist_wininst.cpython-36.pyc,, -setuptools/command/__pycache__/build_ext.cpython-36.pyc,, -setuptools/command/__pycache__/build_py.cpython-36.pyc,, -setuptools/command/__pycache__/develop.cpython-36.pyc,, -setuptools/command/__pycache__/easy_install.cpython-36.pyc,, -setuptools/command/__pycache__/egg_info.cpython-36.pyc,, -setuptools/command/__pycache__/install.cpython-36.pyc,, -setuptools/command/__pycache__/install_egg_info.cpython-36.pyc,, -setuptools/command/__pycache__/install_lib.cpython-36.pyc,, -setuptools/command/__pycache__/install_scripts.cpython-36.pyc,, -setuptools/command/__pycache__/py36compat.cpython-36.pyc,, -setuptools/command/__pycache__/register.cpython-36.pyc,, -setuptools/command/__pycache__/rotate.cpython-36.pyc,, -setuptools/command/__pycache__/saveopts.cpython-36.pyc,, -setuptools/command/__pycache__/sdist.cpython-36.pyc,, -setuptools/command/__pycache__/setopt.cpython-36.pyc,, -setuptools/command/__pycache__/test.cpython-36.pyc,, -setuptools/command/__pycache__/upload.cpython-36.pyc,, -setuptools/command/__pycache__/upload_docs.cpython-36.pyc,, -setuptools/command/__pycache__/__init__.cpython-36.pyc,, -setuptools/extern/__pycache__/__init__.cpython-36.pyc,, -setuptools/__pycache__/archive_util.cpython-36.pyc,, -setuptools/__pycache__/depends.cpython-36.pyc,, -setuptools/__pycache__/dist.cpython-36.pyc,, -setuptools/__pycache__/extension.cpython-36.pyc,, -setuptools/__pycache__/glob.cpython-36.pyc,, -setuptools/__pycache__/launch.cpython-36.pyc,, -setuptools/__pycache__/lib2to3_ex.cpython-36.pyc,, -setuptools/__pycache__/monkey.cpython-36.pyc,, -setuptools/__pycache__/msvc.cpython-36.pyc,, -setuptools/__pycache__/namespaces.cpython-36.pyc,, -setuptools/__pycache__/package_index.cpython-36.pyc,, -setuptools/__pycache__/py26compat.cpython-36.pyc,, -setuptools/__pycache__/py27compat.cpython-36.pyc,, -setuptools/__pycache__/py31compat.cpython-36.pyc,, -setuptools/__pycache__/sandbox.cpython-36.pyc,, -setuptools/__pycache__/site-patch.cpython-36.pyc,, -setuptools/__pycache__/ssl_support.cpython-36.pyc,, -setuptools/__pycache__/unicode_utils.cpython-36.pyc,, -setuptools/__pycache__/version.cpython-36.pyc,, -setuptools/__pycache__/windows_support.cpython-36.pyc,, -setuptools/__pycache__/__init__.cpython-36.pyc,, -__pycache__/easy_install.cpython-36.pyc,, +easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 +pkg_resources/__init__.py,sha256=Z_i79ylo01fXF7p2lnMG7Ov4fLu0O-HLX-3JHMk0FCI,103301 +pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/appdirs.py,sha256=tgGaL0m4Jo2VeuGfoOOifLv7a7oUEJu2n1vRkqoPw-0,22374 +pkg_resources/_vendor/pyparsing.py,sha256=PifeLY3-WhIcBVzLtv0U4T_pwDtPruBhBCkg5vLqa28,229867 +pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pkg_resources/_vendor/packaging/__about__.py,sha256=E9KR5UJ_8U9K-R1mScu6FmkXtbnlFEEFjEXJp-7LxNU,720 +pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +pkg_resources/_vendor/packaging/markers.py,sha256=ndShKOQb_OgpQkFju6LR-2msB1La5u5iAfD5MIqXE4c,7939 +pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 +pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +pkg_resources/extern/__init__.py,sha256=JUtlHHvlxHSNuB4pWqNjcx7n6kG-fwXg7qmJ2zNJlIY,2487 +setuptools/__init__.py,sha256=hW5vya8Yp46AiWmYcALuQbGI7148nQSYVLsEIJLet54,5050 +setuptools/archive_util.py,sha256=Z58-gbZQ0j92UJy7X7uZevwI28JTVEXd__AjKy4aw78,6613 +setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 +setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/depends.py,sha256=h5tbRzianODRkECVsK4sLBbsOfpY1TGEnp9Zm0wg2To,6473 +setuptools/dist.py,sha256=5WUqgcvehkRw97T8NpV66vwneVp77LI9zOmWkPvgHoE,37129 +setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 +setuptools/glob.py,sha256=Y-fpv8wdHZzv9DPCaGACpMSBWJ6amq_1e0R_i8_el4w,5207 +setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 +setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 +setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 +setuptools/monkey.py,sha256=qHoZT9IgmFM-_yF7BjCoPtXg4DYF1H49t_1nLq7dPRo,5337 +setuptools/msvc.py,sha256=6cKqwOxTH8pJNMrNyRLBGB6Efz2rxTTdQQJABUW-6WU,37091 +setuptools/namespaces.py,sha256=I2YrskOZU2ctBS8jdFwAc9q4M8SxbOr0DsFLxxO7gfA,2648 +setuptools/package_index.py,sha256=eYtVpQiaP_4RRFp8zsNbsvNGPAzyOUDM2Lf_q4hePcs,39947 +setuptools/py26compat.py,sha256=VRGHC7z2gliR4_uICJsQNodUcNUzybpus3BrJkWbnK4,679 +setuptools/py27compat.py,sha256=Yu8hW3y8Djps_IenCuz5xZ9OD9qQ-kmBIoVGVpWeQ5Y,330 +setuptools/py31compat.py,sha256=qGRk3tefux8HbhNzhM0laR3mD8vhAZtffZgzLkBMXJs,1645 +setuptools/sandbox.py,sha256=0aNeoJ2tCLhHmQZlx8DQPhuuhGt2690Q7PoGLz6KJ30,14324 +setuptools/script (dev).tmpl,sha256=f7MR17dTkzaqkCMSVseyOCMVrPVSMdmTQsaB8cZzfuI,201 +setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 +setuptools/site-patch.py,sha256=BVt6yIrDMXJoflA5J6DJIcsJUfW_XEeVhOzelTTFDP4,2307 +setuptools/ssl_support.py,sha256=qUzJ_2WeFWBVkGoN638qC42Uzs-Wvmb8cZub9gT1xuI,8131 +setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 +setuptools/version.py,sha256=fvr31nm9BOi4wvMhGVoU0VwmyGeeEAeF3fh33z84wx4,138 +setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 +setuptools/command/__init__.py,sha256=FCLDWoQEGsNexQviqbeJ4MEYGYpYVbbwc7i-9gjzBkM,563 +setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 +setuptools/command/bdist_egg.py,sha256=XDamu6-cfyYrqd67YGQ5gWo-0c8kuWqkPy1vYpfsAxw,17178 +setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 +setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 +setuptools/command/build_ext.py,sha256=dO89j-IC0dAjSty1sSZxvi0LSdkPGR_ZPXFuAAFDZj4,13049 +setuptools/command/build_py.py,sha256=FwU7GNUnd2dT3yEtsTPsJBcl9a7loOcN6GB4uQ0W_IM,9596 +setuptools/command/develop.py,sha256=cHScw5hhILsZM3pk-ddORnd51aLFIbi-4gRm3yTnS_k,7384 +setuptools/command/easy_install.py,sha256=AlmasFuULxUXXgTcUhARle87a74rwStU5nSQn9Oakjw,85720 +setuptools/command/egg_info.py,sha256=f89c5gu9hWS89XheFLD0h0yONVmB4Z3FJR5hkAjn0SY,25110 +setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 +setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 +setuptools/command/install_lib.py,sha256=11mxf0Ch12NsuYwS8PHwXBRvyh671QAM4cTRh7epzG0,3840 +setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 +setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 +setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 +setuptools/command/register.py,sha256=bHlMm1qmBbSdahTOT8w6UhA-EgeQIz7p6cD-qOauaiI,270 +setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 +setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 +setuptools/command/sdist.py,sha256=cu745bayFZMEEGqzMg6kUbIYY9ZKXAbJjPBDXznNUyc,6650 +setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 +setuptools/command/test.py,sha256=IqkQ6rKdQsPh2BiLEXIx5FpzfGMpZttGl8dMa9utxVY,8535 +setuptools/command/upload.py,sha256=6LbdC9NWFe19tb8u-6L3Hriei-nVgtqfO7tn0Si7yLo,1077 +setuptools/command/upload_docs.py,sha256=0Ft5uo7Unnk4lJdZtIm6Nzq7hlyux-9zIYcXC8k_Czs,7275 +setuptools/extern/__init__.py,sha256=ZtCLYQ8JTtOtm7SYoxekZw-UzY3TR50SRIUaeqr2ROk,131 +setuptools-28.8.0.dist-info/DESCRIPTION.rst,sha256=UnjDOK_xBlHg-QN2JbfTbA55nmD_kStv89yxF9aOkqU,10257 +setuptools-28.8.0.dist-info/METADATA,sha256=Xf6UtJ6jxpg-nF5OHBErvUwMGLz-4nizC7iwdYmOcGc,11486 +setuptools-28.8.0.dist-info/RECORD,, +setuptools-28.8.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +setuptools-28.8.0.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 +setuptools-28.8.0.dist-info/entry_points.txt,sha256=zPeIHv66mpCraHdiLlHQjxKDe-6gFIepEbEIjCvu8x4,2885 +setuptools-28.8.0.dist-info/metadata.json,sha256=EIv4nnlOffwLVnetEwhIkFs74vm5jfPJHsxZrjQyXFE,4614 +setuptools-28.8.0.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 +setuptools-28.8.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +../../Scripts/easy_install.exe,sha256=w-ypzMIDXqnbbltKexCwN6Rv6_2qvmD1Ng6gGJ1dLmQ,98172 +../../Scripts/easy_install-3.6.exe,sha256=w-ypzMIDXqnbbltKexCwN6Rv6_2qvmD1Ng6gGJ1dLmQ,98172 +setuptools-28.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pkg_resources/extern/__pycache__/__init__.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/markers.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/utils.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/version.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-36.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-36.pyc,, +pkg_resources/_vendor/__pycache__/appdirs.cpython-36.pyc,, +pkg_resources/_vendor/__pycache__/pyparsing.cpython-36.pyc,, +pkg_resources/_vendor/__pycache__/six.cpython-36.pyc,, +pkg_resources/_vendor/__pycache__/__init__.cpython-36.pyc,, +pkg_resources/__pycache__/__init__.cpython-36.pyc,, +setuptools/command/__pycache__/alias.cpython-36.pyc,, +setuptools/command/__pycache__/bdist_egg.cpython-36.pyc,, +setuptools/command/__pycache__/bdist_rpm.cpython-36.pyc,, +setuptools/command/__pycache__/bdist_wininst.cpython-36.pyc,, +setuptools/command/__pycache__/build_ext.cpython-36.pyc,, +setuptools/command/__pycache__/build_py.cpython-36.pyc,, +setuptools/command/__pycache__/develop.cpython-36.pyc,, +setuptools/command/__pycache__/easy_install.cpython-36.pyc,, +setuptools/command/__pycache__/egg_info.cpython-36.pyc,, +setuptools/command/__pycache__/install.cpython-36.pyc,, +setuptools/command/__pycache__/install_egg_info.cpython-36.pyc,, +setuptools/command/__pycache__/install_lib.cpython-36.pyc,, +setuptools/command/__pycache__/install_scripts.cpython-36.pyc,, +setuptools/command/__pycache__/py36compat.cpython-36.pyc,, +setuptools/command/__pycache__/register.cpython-36.pyc,, +setuptools/command/__pycache__/rotate.cpython-36.pyc,, +setuptools/command/__pycache__/saveopts.cpython-36.pyc,, +setuptools/command/__pycache__/sdist.cpython-36.pyc,, +setuptools/command/__pycache__/setopt.cpython-36.pyc,, +setuptools/command/__pycache__/test.cpython-36.pyc,, +setuptools/command/__pycache__/upload.cpython-36.pyc,, +setuptools/command/__pycache__/upload_docs.cpython-36.pyc,, +setuptools/command/__pycache__/__init__.cpython-36.pyc,, +setuptools/extern/__pycache__/__init__.cpython-36.pyc,, +setuptools/__pycache__/archive_util.cpython-36.pyc,, +setuptools/__pycache__/depends.cpython-36.pyc,, +setuptools/__pycache__/dist.cpython-36.pyc,, +setuptools/__pycache__/extension.cpython-36.pyc,, +setuptools/__pycache__/glob.cpython-36.pyc,, +setuptools/__pycache__/launch.cpython-36.pyc,, +setuptools/__pycache__/lib2to3_ex.cpython-36.pyc,, +setuptools/__pycache__/monkey.cpython-36.pyc,, +setuptools/__pycache__/msvc.cpython-36.pyc,, +setuptools/__pycache__/namespaces.cpython-36.pyc,, +setuptools/__pycache__/package_index.cpython-36.pyc,, +setuptools/__pycache__/py26compat.cpython-36.pyc,, +setuptools/__pycache__/py27compat.cpython-36.pyc,, +setuptools/__pycache__/py31compat.cpython-36.pyc,, +setuptools/__pycache__/sandbox.cpython-36.pyc,, +setuptools/__pycache__/site-patch.cpython-36.pyc,, +setuptools/__pycache__/ssl_support.cpython-36.pyc,, +setuptools/__pycache__/unicode_utils.cpython-36.pyc,, +setuptools/__pycache__/version.cpython-36.pyc,, +setuptools/__pycache__/windows_support.cpython-36.pyc,, +setuptools/__pycache__/__init__.cpython-36.pyc,, +__pycache__/easy_install.cpython-36.pyc,, diff --git a/website/web/Scripts/Activate.ps1 b/website/web/Scripts/Activate.ps1 index 59d90700e..c77f59cc4 100644 --- a/website/web/Scripts/Activate.ps1 +++ b/website/web/Scripts/Activate.ps1 @@ -1,51 +1,51 @@ -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - if (Test-Path function:_OLD_VIRTUAL_PROMPT) { - copy-item function:_OLD_VIRTUAL_PROMPT function:prompt - remove-item function:_OLD_VIRTUAL_PROMPT - } - - if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { - copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME - remove-item env:_OLD_VIRTUAL_PYTHONHOME - } - - if (Test-Path env:_OLD_VIRTUAL_PATH) { - copy-item env:_OLD_VIRTUAL_PATH env:PATH - remove-item env:_OLD_VIRTUAL_PATH - } - - if (Test-Path env:VIRTUAL_ENV) { - remove-item env:VIRTUAL_ENV - } - - if (!$NonDestructive) { - # Self destruct! - remove-item function:deactivate - } -} - -deactivate -nondestructive - -$env:VIRTUAL_ENV="R:\github\website\web" - -if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT {""} - copy-item function:prompt function:_OLD_VIRTUAL_PROMPT - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green '(web) ' - _OLD_VIRTUAL_PROMPT - } -} - -# Clear PYTHONHOME -if (Test-Path env:PYTHONHOME) { - copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME - remove-item env:PYTHONHOME -} - -# Add the venv to the PATH -copy-item env:PATH env:_OLD_VIRTUAL_PATH -$env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH" +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + if (Test-Path function:_OLD_VIRTUAL_PROMPT) { + copy-item function:_OLD_VIRTUAL_PROMPT function:prompt + remove-item function:_OLD_VIRTUAL_PROMPT + } + + if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { + copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME + remove-item env:_OLD_VIRTUAL_PYTHONHOME + } + + if (Test-Path env:_OLD_VIRTUAL_PATH) { + copy-item env:_OLD_VIRTUAL_PATH env:PATH + remove-item env:_OLD_VIRTUAL_PATH + } + + if (Test-Path env:VIRTUAL_ENV) { + remove-item env:VIRTUAL_ENV + } + + if (!$NonDestructive) { + # Self destruct! + remove-item function:deactivate + } +} + +deactivate -nondestructive + +$env:VIRTUAL_ENV="R:\github\website\web" + +if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT {""} + copy-item function:prompt function:_OLD_VIRTUAL_PROMPT + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green '(web) ' + _OLD_VIRTUAL_PROMPT + } +} + +# Clear PYTHONHOME +if (Test-Path env:PYTHONHOME) { + copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME + remove-item env:PYTHONHOME +} + +# Add the venv to the PATH +copy-item env:PATH env:_OLD_VIRTUAL_PATH +$env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH" diff --git a/website/web/Scripts/activate b/website/web/Scripts/activate index 0401b599a..568ccee2d 100644 --- a/website/web/Scripts/activate +++ b/website/web/Scripts/activate @@ -1,76 +1,76 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "$_OLD_VIRTUAL_PATH" ] ; then - PATH="$_OLD_VIRTUAL_PATH" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then - PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then - hash -r - fi - - if [ -n "$_OLD_VIRTUAL_PS1" ] ; then - PS1="$_OLD_VIRTUAL_PS1" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "$1" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="R:\github\website\web" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/Scripts:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "$PYTHONHOME" ] ; then - _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" - unset PYTHONHOME -fi - -if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then - _OLD_VIRTUAL_PS1="$PS1" - if [ "x(web) " != x ] ; then - PS1="(web) $PS1" - else - if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" - else - PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" - fi - fi - export PS1 -fi - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then - hash -r -fi +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "$_OLD_VIRTUAL_PATH" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then + hash -r + fi + + if [ -n "$_OLD_VIRTUAL_PS1" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "$1" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="R:\github\website\web" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "$PYTHONHOME" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then + _OLD_VIRTUAL_PS1="$PS1" + if [ "x(web) " != x ] ; then + PS1="(web) $PS1" + else + if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then + # special case for Aspen magic directories + # see http://www.zetadev.com/software/aspen/ + PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" + fi + fi + export PS1 +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then + hash -r +fi diff --git a/website/web/Scripts/activate.bat b/website/web/Scripts/activate.bat index 8b3113632..61d6ccf6d 100644 --- a/website/web/Scripts/activate.bat +++ b/website/web/Scripts/activate.bat @@ -1,32 +1,32 @@ -@echo off -set "VIRTUAL_ENV=R:\github\website\web" - -if not defined PROMPT ( - set "PROMPT=$P$G" -) - -if defined _OLD_VIRTUAL_PROMPT ( - set "PROMPT=%_OLD_VIRTUAL_PROMPT%" -) - -if defined _OLD_VIRTUAL_PYTHONHOME ( - set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" -) - -set "_OLD_VIRTUAL_PROMPT=%PROMPT%" -set "PROMPT=(web) %PROMPT%" - -if defined PYTHONHOME ( - set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" - set PYTHONHOME= -) - -if defined _OLD_VIRTUAL_PATH ( - set "PATH=%_OLD_VIRTUAL_PATH%" -) else ( - set "_OLD_VIRTUAL_PATH=%PATH%" -) - -set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" - -:END +@echo off +set "VIRTUAL_ENV=R:\github\website\web" + +if not defined PROMPT ( + set "PROMPT=$P$G" +) + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" +) + +set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +set "PROMPT=(web) %PROMPT%" + +if defined PYTHONHOME ( + set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" + set PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) else ( + set "_OLD_VIRTUAL_PATH=%PATH%" +) + +set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" + +:END diff --git a/website/web/Scripts/deactivate.bat b/website/web/Scripts/deactivate.bat index 1205c6186..313c07911 100644 --- a/website/web/Scripts/deactivate.bat +++ b/website/web/Scripts/deactivate.bat @@ -1,21 +1,21 @@ -@echo off - -if defined _OLD_VIRTUAL_PROMPT ( - set "PROMPT=%_OLD_VIRTUAL_PROMPT%" -) -set _OLD_VIRTUAL_PROMPT= - -if defined _OLD_VIRTUAL_PYTHONHOME ( - set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" - set _OLD_VIRTUAL_PYTHONHOME= -) - -if defined _OLD_VIRTUAL_PATH ( - set "PATH=%_OLD_VIRTUAL_PATH%" -) - -set _OLD_VIRTUAL_PATH= - -set VIRTUAL_ENV= - -:END +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= + +:END diff --git a/website/web/pyvenv.cfg b/website/web/pyvenv.cfg index 6d0f4a7ab..7f72ee522 100644 --- a/website/web/pyvenv.cfg +++ b/website/web/pyvenv.cfg @@ -1,3 +1,3 @@ -home = C:\Program Files\Python36 -include-system-site-packages = false -version = 3.6.2 +home = C:\Program Files\Python36 +include-system-site-packages = false +version = 3.6.2