[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [koxudaxi]\ncustom: ['https://stakes.social/0x87E30B7640ac3949e1594C8231304435Edb9B560']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\nAlso, gif movies are recommended.\n\n**Environments (please complete the following information):**\n - IDE: [e.g. PyCharm Community 2020.1 ]\n - OS: [e.g. macOS  10.15.5 ]\n - Poetry Version [e.g. 1.0.8 ]\n - Plugin version [e.g. 0.0.10 ]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: gradle\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"10:00\"\n    timezone: Asia/Tokyo\n  open-pull-requests-limit: 10\n  ignore:\n  - dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin\n    versions:\n    - 1.4.30\n    - 1.4.31\n    - 1.4.32\n    - 1.5.0\n  - dependency-name: org.jetbrains.intellij\n    versions:\n    - 0.7.0\n    - 0.7.1\n    - 0.7.2\n- package-ecosystem: pip\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"10:00\"\n    timezone: Asia/Tokyo\n  open-pull-requests-limit: 10\n  ignore:\n  - dependency-name: mkdocs-material\n    versions:\n    - 6.2.6\n    - 7.0.2\n    - 7.0.3\n    - 7.0.7\n    - 7.1.2\n"
  },
  {
    "path": ".github/workflows/CI.yml",
    "content": "name: CI\n\non:\n  pull_request: {}\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v2\n    - name: Cache\n      uses: actions/cache@v1.1.2\n      with:\n        path: ~/.cache/pip\n        key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.cfg') }}\n        restore-keys: |\n          ${{ runner.os }}-pip-\n    - name: Cache\n      uses: actions/cache@v1.1.2\n      with:\n        path: ~/.gradle\n        key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle') }}\n        restore-keys: |\n          ${{ runner.os }}-gradle-\n    - name: Set up JDK 11\n      uses: actions/setup-java@v1\n      with:\n        java-version: 11\n    - name: test \n      run: ./gradlew buildPlugin test jacocoTestReport\n    - name: IntelliJ Platform Plugin Verifier\n      uses: ChrisCarini/intellij-platform-plugin-verifier-action@v0.0.2\n      with: \n        ide-versions: |\n            pycharmPC:2020.1\n            pycharmPC:LATEST-EAP-SNAPSHOT\n    - name: setup python\n      uses: actions/setup-python@v1\n      with:\n        python-version: 3.8\n    - name: Install dependencies\n      run: |\n        pip install -r requirements.txt\n    - name: build document\n      run: |\n        python scripts/build_changelog.py\n        mkdocs build --verbose --clean --strict\n\n#    - name: Upload coverage to Codecov\n#      uses: codecov/codecov-action@v1\n#      with:\n#        token: ${{ secrets.CODECOV_TOKEN }}\n#        file: ./build/reports/jacoco/test/jacocoTestReport.xml \n#        flags: unittests\n#        fail_ci_if_error: true\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    branches:\n    - master\n\njobs:\n  build-deploy:\n    runs-on: ubuntu-18.04\n    steps:\n    - uses: actions/checkout@v1\n\n    - name: Setup Python\n      uses: actions/setup-python@v1\n      with:\n        python-version: '3.8'\n        architecture: 'x64'\n\n    - uses: actions/cache@v1\n      with:\n        path: ~/.cache/pip\n        key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n    - name: Install dependencies\n      run: |\n         pip install -r requirements.txt\n    - run: | \n         python scripts/build_changelog.py\n         mkdocs build --verbose --clean --strict\n\n    - name: Deploy\n      uses: peaceiris/actions-gh-pages@v2\n      env:\n        PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}\n        PUBLISH_BRANCH: gh-pages\n        PUBLISH_DIR: ./site\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\n\non:\n  push:\n    tags:\n      - '**'\n\njobs:\n  build-n-publish:\n    name: Build and publish plugin 📦 to JetBrains merket\n    if: \"success() && startsWith(github.ref, 'refs/tags/')\"\n    runs-on: ubuntu-latest\n    steps:\n\n     - uses: actions/checkout@v2\n     - name: Setup Python\n       uses: actions/setup-python@v1\n       with:\n         python-version: '3.8'\n         architecture: 'x64'\n\n     - uses: actions/cache@v1\n       with:\n         path: ~/.cache/pip\n         key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n     - name: Install dependencies\n       run: |\n         pip install -r requirements.txt\n     - name: build changelog \n       env: \n         ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'\n       run: |\n         python scripts/build_changelog.py\n         CHANGELOG_LATEST=$(cat docs/changelog_latest.md)\n         CHANGELOG_LATEST=\"${CHANGELOG_LATEST//'%'/'%25'}\"\n         CHANGELOG_LATEST=\"${CHANGELOG_LATEST//$'\\n'/'%0A'}\"\n         CHANGELOG_LATEST=\"${CHANGELOG_LATEST//$'\\r'/'%0D'}\"\n         echo ::set-env name=CHANGELOG_LATEST::$CHANGELOG_LATEST\n     - name: Cache\n       uses: actions/cache@v1.1.2\n       with:\n        path: ~/.gradle\n        key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle') }}\n        restore-keys: |\n          ${{ runner.os }}-gradle-\n     - name: Set up JDK 11\n       uses: actions/setup-java@v1\n       with:\n        java-version: 11\n     - name: test \n       run: ./gradlew buildPlugin test jacocoTestReport\n     - name: Create Release\n       id: create_release\n       uses: actions/create-release@v1\n       env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n       with:\n         tag_name: ${{ github.ref }}\n         release_name: Release ${{ github.ref }}\n         body: |\n            ${{ env.CHANGELOG_LATEST }}\n         draft: false\n         prerelease: false\n     - name: Upload Release Asset\n       id: upload-release-asset \n       uses: actions/upload-release-asset@v1\n       env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n       with:\n          upload_url: ${{ steps.create_release.outputs.upload_url }}\n          asset_path: ./build/distributions/poetry-pycharm-plugin.zip\n          asset_name: poetry-pycharm-plugin.zip\n          asset_content_type: application/zip\n     - name: Publish a plugin\n       run: |\n         curl --fail --header \"Authorization: Bearer ${{secrets.JETBRAINS_TOKEN}}\" \\\n               -F pluginId=14307 -F file=@build/distributions/poetry-pycharm-plugin.zip \\\n                https://plugins.jetbrains.com/plugin/uploadPlugin\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.nar\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n.idea/workspace.xml\n.idea/modules.xml\n.idea/compiler.xml\n.idea/misc.xml\n.idea/gradle.xml\n.idea/shelf/\n.idea/libraries/\n.idea/dictionaries\n.idea/.name\n*.iml\n\n/build/\n/jps-plugin/build/\n.gradle\n/out/\n/poetry-pycahrm-plugin/out/\n/venv/\n/site\n/docs/changelog.md\n/docs/changelog_latest.md"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NOTICE.txt",
    "content": "This software includes code from IntelliJ IDEA Community Edition\nCopyright (C) JetBrains s.r.o.\nhttps://www.jetbrains.com/idea/\n"
  },
  {
    "path": "README.md",
    "content": "# Poetry PyCharm Plugin\n![CI](https://github.com/koxudaxi/poetry-pycharm-plugin/workflows/CI/badge.svg)\n[![](https://img.shields.io/jetbrains/plugin/v/14307)](https://plugins.jetbrains.com/plugin/14307-poetry)\n![JetBrains IntelliJ plugins](https://img.shields.io/jetbrains/plugin/d/14307-poetry)\n![JetBrains IntelliJ Plugins](https://img.shields.io/jetbrains/plugin/r/rating/14307-poetry)\n![license](https://img.shields.io/github/license/koxudaxi/poetry-pycharm-plugin.svg)\n\n[A JetBrains PyCharm plugin](https://plugins.jetbrains.com/plugin/14307-poetry) for [`poetry`](https://python-poetry.org/).\n\n# [This plugin has been merged into PyCharm source code🎉](https://www.jetbrains.com/pycharm/whatsnew/)\nPyCharm 2021.3 or later provide poetry integration as a built-in feature😎\n\n👉[What’s New in PyCharm 2021.3](https://www.jetbrains.com/pycharm/whatsnew/)\n\nIf you have any questions then please crate an issue on [JetBrains youtrack](https://youtrack.jetbrains.com/issues)\n\nJetBrains maintains the poetry feature in PyCharm.\n\n## Sponsors\n[![JetBrains](https://avatars.githubusercontent.com/u/60931315?s=200&v=4)](https://github.com/JetBrainsOfficial)\n\n## Help\nSee [documentation](https://koxudaxi.github.io/poetry-pycharm-plugin/) for more details.\n\n## Demo\n![poetry_demo1](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/poetry_demo1.gif)\n\n\n## Quick Installation\n\nThe plugin is in JetBrains repository ([Poetry Plugin Page](https://plugins.jetbrains.com/plugin/14307-poetry))\n\nYou can install the stable version on PyCharm's `Marketplace` (Preference -> Plugins -> Marketplace) [Official Document](https://www.jetbrains.com/help/idea/managing-plugins.html)\n\n**I recommend PyCharm 2020.3 and the plugin version 1.0 or later to get all features and performance.**\n\n\n\n![search plugin](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/search_plugin.png)\n\n##  Features\n### Implemented\n- add a new/existing poetry environment as a interpreter \n- install packages with pyproject.toml when add a interpreter\n- add a new pyproject.toml when it does not exists\n- [install and import a package with poetry (QuickFix)](#screen-shots)\n- install packages from poetry.lock\n- update and lock with a popup\n- show a message and a link to fix settings (QuickFix)\n- install extras and run scripts by clicking a line marker ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required)\n- show a message for outdated version packages ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required)\n- install/uninstall packages from GUI\n- detect poetry project when open new project\n\n## Motivation\nPoetry is a popular package manager of python.\n\nHowever, PyCharm doesn't support poetry.\n\nThis plugin support poetry. This source code was forked from the Pipenv integration code in IntelliJ-community.\n\nIn this issue [PY-30702](https://youtrack.jetbrains.com/issue/PY-30702), the feature is discussing. But, We need time to get the proper functionality in PyCharm.\n\nThe plugin has useful features like installing from poetry.lock.(you can watch demo video)\n\nHowever, The feature is limited. PyCharm has to provided extension points for perfect features.\n\nI guess if the plugin be used a lot of people, then JetBrains developers will implement extension points or poetry integration in PyCharm. \n\n\n## This project is currently in an experimental phase\n~~This plugin supports minimum [features](#features) to use poetry in PyCharm.~~\n\n~~There is [feature restrictions](#feature-restrictions).~~\n\n~~But, PyCharm team will add a few api to resolve the problem. The detail is in [this issue](https://github.com/koxudaxi/poetry-pycharm-plugin/issues/58).~~\n\nPyCharm provides APIs that are for third-party package manager plugins.  \n\nThe project needs any feedback and PRs. We're waiting for your feedback and PRs.\n\n\n## Feature Restrictions  \n\nThe plugin can't provide some features for technical reasons.\n\nBecause PyCharm has not provided APIs to support third-party python package managers yet. (a.k.a [extension points](https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_extensions.html)) \n\nWe will be able to implement the following features when JetBrains add extension points to PyCharms.\n\n- ~~Create a new environment when creating a new project.~~  \n- Use the Custom Icon for poetry. (Coming Soon)\n- ~~Install/uninstall a package from GUI(settings)~~ \n- And more.\n\n## Screen Shots\n![add_package](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/add_package.gif)\n![new_sdk](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/new_sdk.png)\n![installed_package](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/installed_package.png)\n![run_config](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/run_config.png)\n![update_lock](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/update_lock.png)\n![quick_fix](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/quick_fix.png)\n![install_from_lock_file](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/install_from_lock_file.png)\n![install_extras](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/extras.png)\n\n\n## Contribute\nWe are waiting for your contributions to `poetry-pycharm-plugin`.\n\n\n## Links\n- [A JetBrains PyCharm plugin](https://plugins.jetbrains.com/plugin/12861-pydantic) for [`pydantic`](https://github.com/samuelcolvin/pydantic).\n- I got interviewed about creating a plugin for [JetBrains' PyCharm Blog](https://blog.jetbrains.com/pycharm/2020/04/interview-koudai-aono-author-of-pydantic-plugin-for-pycharm/).\n\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    ext.kotlin_version = \"1.5.30\"\n    ext.toml_version = \"0.2.154.4085-212\"\n    ext.tuweni_toml_version = \"2.0.0\"\n    ext.jvm_version = \"11\"\n    ext.language_version = \"1.3\"\n    repositories {\n        mavenCentral()\n    }\n    dependencies {\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\", \"org.apache.tuweni:tuweni-toml:$tuweni_toml_version\"\n    }\n}\n\nplugins {\n    id \"org.jetbrains.intellij\" version \"1.1.6\"\n}\n\nintellij {\n    pluginName = project.name\n    version = \"2021.2.1\"\n    type = \"PC\"\n    updateSinceUntilBuild = false\n    downloadSources = true\n    plugins = [\"python-ce\", \"org.toml.lang:$toml_version\"]\n}\n\npatchPluginXml {\n    sinceBuild = \"212.4746.13\"\n    untilBuild = \"212.*\"\n}\n\nallprojects {\n    apply plugin: \"org.jetbrains.intellij\"\n    apply plugin: \"kotlin\"\n    apply plugin: \"jacoco\"\n    repositories {\n        mavenCentral()\n    }\n\n    compileKotlin {\n        kotlinOptions {\n            jvmTarget = jvm_version\n            languageVersion = language_version\n            apiVersion = language_version\n        }\n    }\n\n    compileTestKotlin {\n        kotlinOptions {\n            jvmTarget = jvm_version\n            languageVersion = language_version\n            apiVersion = language_version\n        }\n    }\n\n    dependencies {\n        testImplementation 'junit:junit:4.13.2'\n        implementation \"org.apache.tuweni:tuweni-toml:$tuweni_toml_version\"\n        compile \"org.jetbrains:annotations:23.0.0\"\n    }\n\n    jacocoTestReport {\n        reports {\n            xml.enabled true\n            html.enabled true\n        }\n    }\n\n    sourceCompatibility = jvm_version\n    targetCompatibility = jvm_version\n\n}\n\nsourceSets {\n    main {\n        java.srcDir 'src'\n        resources.srcDir 'resources'\n    }\n    test {\n        java.srcDir 'testSrc'\n        resources.srcDir 'testData'\n    }\n}\n"
  },
  {
    "path": "docs/development.md",
    "content": "# Development\n## Building the plugin\nYou can build and run the plugin either via the command line or through IntelliJ IDEA:\n\n### Shell on Linux or MacOS \n```bash\n$ ./gradlew buildPlugin\n```\n\n### Command Prompt on Windows\n```\n$ gradlew.bat buildPlugin\n```\n\n### JetBrains IDE on any platform\n\n[Official documentation](https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/using_dev_kit.html])\n\n## Running the IDE with the built plugin\n```bash\n$ ./gradlew runIde\n```\n\n## Unittest\nYou should add a unittest for the new code. But, This plugin do complex behavior to modules.\n\nYou may feel writing unittest difficult.\n\nWe should write a unittest as much as possible.\n\nUnittest is not blocker for PRs.\n\n## License For JetBrains' Code\nThese files are forked from [IntelliJ IDEA Community Edition](https://github.com/JetBrains/intellij-community)\n\nThe files are licensed under the Apache License, Version 2.0.\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n"
  },
  {
    "path": "docs/index.md",
    "content": "# Poetry PyCharm Plugin\n![CI](https://github.com/koxudaxi/poetry-pycharm-plugin/workflows/CI/badge.svg)\n[![](https://img.shields.io/jetbrains/plugin/v/14307)](https://plugins.jetbrains.com/plugin/14307-poetry)\n![JetBrains IntelliJ Plugins](https://img.shields.io/jetbrains/plugin/r/rating/14307-poetry)\n![license](https://img.shields.io/github/license/koxudaxi/poetry-pycharm-plugin.svg)\n\n[A JetBrains PyCharm plugin](https://plugins.jetbrains.com/plugin/14307-poetry) for [`poetry`](https://python-poetry.org/).\n\n# [This plugin has been merged into PyCharm source code🎉](https://www.jetbrains.com/pycharm/whatsnew/)\nPyCharm 2021.3 or later provide poetry integration as a built-in feature😎\n\n👉[What’s New in PyCharm 2021.3](https://www.jetbrains.com/pycharm/whatsnew/)\n\nIf you have any questions then please crate an issue on [JetBrains youtrack](https://youtrack.jetbrains.com/issues)\n\nJetBrains maintains the poetry feature in PyCharm.\n\n## Sponsors\n[![JetBrains](https://avatars.githubusercontent.com/u/60931315?s=200&v=4)](https://github.com/JetBrainsOfficial)\n\n\n## Demo\n![poetry_demo1](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/poetry_demo1.gif)\n\n\n## Quick Installation\n\nThe plugin is in JetBrains repository ([Poetry Plugin Page](https://plugins.jetbrains.com/plugin/14307-poetry))\n\nYou can install the stable version on PyCharm's `Marketplace` (Preference -> Plugins -> Marketplace) [Official Document](https://www.jetbrains.com/help/idea/managing-plugins.html)\n\n**I recommend PyCharm 2020.3 and the plugin version 1.0 or later to get all features and performance.**\n\n\n\n![search plugin](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/search_plugin.png)\n\n##  Features\n### Implemented\n- add a new/existing poetry environment as a interpreter \n- install packages with pyproject.toml when add a interpreter\n- add a new pyproject.toml when it does not exists\n- [install and import a package with poetry (QuickFix)](#screen-shots)\n- install packages from poetry.lock\n- update and lock with a popup\n- show a message and a link to fix settings (QuickFix)\n- install extras and run scripts by clicking a line marker ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required)\n- show a message for outdated version packages ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required)\n- install/uninstall packages from GUI\n- detect poetry project when open new project\n\n## Motivation\nPoetry is a popular package manager of python.\n\nHowever, PyCharm doesn't support poetry.\n\nThis plugin support poetry. This source code was forked from the Pipenv integration code in IntelliJ-community.\n\nIn this issue [PY-30702](https://youtrack.jetbrains.com/issue/PY-30702), the feature is discussing. But, We need time to get the proper functionality in PyCharm.\n\nThe plugin has useful features like installing from poetry.lock.(you can watch demo video)\n\nHowever, The feature is limited. PyCharm has to provided extension points for perfect features.\n\nI guess if the plugin be used a lot of people, then JetBrains developers will implement extension points or poetry integration in PyCharm. \n\n\n## This project is currently in an experimental phase\n~~This plugin supports minimum [features](#features) to use poetry in PyCharm.~~\n\n~~There is [feature restrictions](#feature-restrictions).~~\n\n~~But, PyCharm team will add a few api to resolve the problem. The detail is in [this issue](https://github.com/koxudaxi/poetry-pycharm-plugin/issues/58).~~\n\nPyCharm provides APIs that are for third-party package manager plugins.  \n\nThe project needs any feedback and PRs. We're waiting for your feedback and PRs.\n\n\n## Feature Restrictions  \n\nThe plugin can't provide some features for technical reasons.\n\nBecause PyCharm has not provided APIs to support third-party python package managers yet. (a.k.a [extension points](https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_extensions.html)) \n\nWe will be able to implement the following features when JetBrains add extension points to PyCharms.\n\n- ~~Create a new environment when creating a new project.~~  \n- Use the Custom Icon for poetry. (Coming Soon)\n- ~~Install/uninstall a package from GUI(settings)~~ \n- And more.\n\n## Screen Shots\n![add_package](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/add_package.gif)\n![new_sdk](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/new_sdk.png)\n![installed_package](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/installed_package.png)\n![run_config](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/run_config.png)\n![update_lock](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/update_lock.png)\n![quick_fix](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/quick_fix.png)\n![install_from_lock_file](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/install_from_lock_file.png)\n![install_extras](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/extras.png)\n\n\n## Contribute\nWe are waiting for your contributions to `poetry-pycharm-plugin`.\n\n\n## Links\n- [A JetBrains PyCharm plugin](https://plugins.jetbrains.com/plugin/12861-pydantic) for [`pydantic`](https://github.com/samuelcolvin/pydantic).\n- I got interviewed about creating a plugin for [JetBrains' PyCharm Blog](https://blog.jetbrains.com/pycharm/2020/04/interview-koudai-aono-author-of-pydantic-plugin-for-pycharm/).\n\n"
  },
  {
    "path": "docs/install.md",
    "content": "# Installation\n\n**The plugin requires PyCharm 2020.3 or later (include other JetBrains IDEs)**\n\n## MarketPlace \nThe plugin is in JetBrains repository ([Poetry Plugin Page](https://plugins.jetbrains.com/plugin/14307-poetry))\n\nYou can install the stable version on PyCharm's `Marketplace` (Preference -> Plugins -> Marketplace) [Official Document](https://www.jetbrains.com/help/idea/managing-plugins.html)\n\n![search plugin](https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/search_plugin.png)\n\n## Complied binary\nThe releases section of this repository contains a compiled version of the plugin: [poetry-pycharm-plugin.zip(latest)](https://github.com/koxudaxi/poetry-pycharm-plugin/releases/latest/download/poetry-pycharm-plugin.zip)\n\nAfter downloading this file, you can install the plugin from disk by following [the JetBrains instructions here](https://www.jetbrains.com/help/pycharm/plugins-settings.html).\n\n## Source\nAlternatively, you can clone this repository and follow the instructions under the \"Building the plugin\" heading below to build from source.\nThe build process will create the file `build/distributions/poetry-pycharm-plugin.zip`.\nThis file can be installed as a PyCharm plugin from disk following the same instructions.\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Sat May 16 18:47:10 JST 2020\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.8-all.zip\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStorePath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\n"
  },
  {
    "path": "gradle.properties",
    "content": "#org.gradle.jvmargs= -XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m -Dfile.encoding=utf-8"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    \n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: Poetry PyCharm Plugin\nsite_description: A JetBrains PyCharm plugin for poetry.\n\ntheme:\n    name: 'material'\n    palette:\n      primary: 'light blue'\n      accent: 'light blue'\n    analytics:\n      gtag: 275257853\nmarkdown_extensions:\n  - codehilite\n  - admonition\n  - toc:\n      permalink: 🔗\n\nrepo_name: koxudaxi/poetry-pycharm-plugin\nrepo_url: https://github.com/koxudaxi/poetry-pycharm-plugin\nsite_url: https://koxudaxi.github.io/poetry-pycharm-plugin\n\nnav:\n    - Overview: index.md\n    - Install: install.md\n    - Development: development.md\n    - Changelog: changelog.md\n\nplugins:\n  - search"
  },
  {
    "path": "requirements.txt",
    "content": "mkdocs==1.2.3\nmkdocs-material==8.0.5\n"
  },
  {
    "path": "resources/META-INF/only-toml.xml",
    "content": "<idea-plugin>\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <runLineMarkerContributor language=\"TOML\"\n                                  implementationClass=\"com.koxudaxi.poetry.PoetryExtrasLineMarkerContributor\"/>\n        <runLineMarkerContributor language=\"TOML\"\n                                  implementationClass=\"com.koxudaxi.poetry.PoetryScriptsLineMarkerContributor\"/>\n        <localInspection language=\"TOML\" enabledByDefault=\"true\" implementationClass=\"com.koxudaxi.poetry.PoetryVersionInspection\" displayName=\"Poetry Package versions\"  bundle=\"messages.PyPsiBundle\"  groupKey=\"INSP.GROUP.python\" suppressId=\"PoetryPackageVersion\" shortName=\"PoetryPackageVersion\"/>\n    </extensions>\n</idea-plugin>"
  },
  {
    "path": "resources/META-INF/plugin.xml",
    "content": "<idea-plugin url=\"https://github.com/koxudaxi/poetry-pycharm-plugin\" require-restart=\"true\">\n    <id>com.koxudaxi.poetry</id>\n    <name>Poetry</name>\n    <version>1.1.5-212</version>\n    <vendor email=\"koaxudai@gmail.com\">Koudai Aono @koxudaxi</vendor>\n    <change-notes><![CDATA[\n    <h2>version 1.1.5-212</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix toml header problem [#271]</li>\n    </ul>\n    <p>Features</p>\n    <ul>\n        <li>Update versions [#270]</li>\n    </ul>\n    <h2>version 1.1.4-212</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support PyCharm EAP 212.* [#240]</li>\n    </ul>\n    <h2>version 1.1.4</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Update an error dialog to the same as the dialog of pipenv [#224]</li>\n    </ul>\n    <h2>version 1.1.3</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>[#215] Suggest existing poetry venvs that are in existing modules [#217] by @roxchkplusony </li>\n    </ul>\n    <h2>version 1.1.2</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Improve responsiveness of the Poetry add new venv panel [#214] by @roxchkplusony </li>\n    </ul>\n    <h2>version 1.1.1</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Remove checking poetry executable [#203]</li>\n    </ul>\n    <h2>version 1.1.0</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support PyCharm EAP 211.* [#181]</li>\n    </ul>\n    <h2>version 1.0.7</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix replaced Python restricted dependencies [#184]</li>\n    </ul>\n    <h2>version 1.0.6</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Change command timeout to 30 sec [#177]</li>\n        <li>Fix broken dependency on Toml plugin [#176]</li>\n    </ul>\n    <h2>version 1.0.5</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Support Toml plugin version 0.2.139.3615-203 or earlier version [#174]</li>\n    </ul>\n    <h2>version 1.0.4</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Support Toml plugin version 0.2.140.3644-202 [#169]</li>\n    </ul>\n    <h2>version 1.0.3</h2>\n    <p>Features</p>\n    <ul>\n        <li>Add validation for poetry executable [#165]</li>\n    </ul>\n    <h2>version 1.0.2</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support poetry lock with \"--no-update\" [#161]</li>\n    </ul>\n    <h2>version 1.0.1</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Remove configuration collector [#150] by @sproshev </li>\n        <li>Apply changes in python bundles in 2020.3 [#149] by @sproshev </li>\n    </ul>\n    <h2>version 1.0.0</h2>\n    <p>Features</p>\n    <ul>\n        <li>Remove deprecated APIs [#148]</li>\n        <li>Support PyCharm 2020.3 [#147]</li>\n    </ul>\n    <h2>version 0.5.5</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix compatibility problems for IntelliJ IDEA Ultimate IU-203.4818.26 [#130]</li>\n    </ul>\n    <h2>version 0.5.4</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix wrong warning for installed packages [#128]</li>\n        <li>Fix wrong icon for system interpreter [#127]</li>\n    </ul>\n    <h2>version 0.5.3</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix invalid build target version for IntelliJ [#119]</li>\n    </ul>\n    <h2>version 0.5.2</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix broken inspection config [#116]</li>\n    </ul>\n    <h2>version 0.5.1</h2>\n    <p>Features</p>\n    <ul>\n        <li>Change max target version to 2020.3 [#112]</li>\n    </ul>\n    <h2>version 0.5.0</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support 2020.2.2 [#104]</li>\n    </ul>\n    <h2>version 0.1.3</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support running scripts with RunConfiguration [#100]</li>\n        <li>Improve build config [#96]</li>\n    </ul>\n    <h2>version 0.1.2</h2>\n    <p>Features</p>\n    <ul>\n        <li>Add a version inspection [#85]</li>\n    </ul>\n    <h2>version 0.1.1</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support script [#81]</li>\n    </ul>\n    <h2>version 0.1.0</h2>\n    <p>Features</p>\n    <ul>\n        <li>Add python version for environment name [#77]</li>\n    </ul>\n    <h2>version 0.0.13</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix invalid notification to install packages [#62] </li>\n    </ul>\n    <h2>version 0.0.12</h2>\n    <p>Bug fixes</p>\n    <ul>\n    <li>Create new windows interpreter [#53] by @akinnear</li>\n    Thanks to @akinnear\n    </ul>\n    <h2>version 0.0.11</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support adding existing env [#48] </li>\n    </ul>\n    <p>Improvements</p>\n    <ul>\n        <li>Improve supporting windows [#51]</li>\n    </ul>\n    <p>Bug fixes</p>\n    <ul>\n        <li>fix detecting poetry envs [#50] </li>\n    </ul>\n    <h2>version 0.0.10</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support adding packages with a quick fix [#44] </li>\n    </ul>\n    <h2>version 0.0.9</h2>\n    <p>Features</p>\n    <ul>\n        <li>Add unittest [#41] </li>\n    </ul>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Fix an error not found toml plugin [#42] </li>\n    </ul>\n    <h2>version 0.0.8</h2>\n    <p>Features</p>\n    <ul>\n        <li>improve detecting extras [#39] </li>\n        <li>improve showing popup [#38] </li>\n        <li>improve handling invalid interpreter [#37] </li>\n    </ul>\n    <p>Bug fixes</p>\n    <ul>\n        <li>Remove a invalid content in Open Project menu [#35] </li>\n    </ul>\n    <h2>version 0.0.7</h2>\n    <p>Features</p>\n    <ul>\n        <li>Improve handling sdk [#32] </li>\n        <li>Support installing extras [#31] </li>\n        <li>Update jvm version [#26] </li>\n    </ul>\n    <h2>version 0.0.6</h2>\n    <p>Bug fixes</p>\n    <ul>\n        <li>fix project already disposed error [#21] </li>\n    </ul>\n    <h2>version 0.0.5</h2>\n    <p>Features</p>\n    </ul>\n        <li>update documents [#20] </li>\n    </ul>\n    <h2>version 0.0.4</h2>\n    <p>Features</p>\n    </ul>\n        <li>support creating new pyproject.toml [#17] </li>\n        <li>check pyproject.toml [#16] </li>\n    </ul>\n    <h2>version 0.0.3</h2>\n    <p>Features</p>\n    <ul>\n        <li>add installing from poetry.lock [#10] </li>\n    </ul>\n    <p>Bug fixes</p>\n    <ul>\n        <li>disable custom icon [#11] </li>\n    </ul>\n    <h2>version 0.0.2</h2>\n    <p>Features</p>\n    <ul>\n        <li>add quick fix [#9] </li>\n    </ul>\n    <h2>version 0.0.1</h2>\n    <p>Features</p>\n    <ul>\n        <li>Support update and lock [#3] </li>\n        <li>Support poetry [#2] </li>\n    </ul>\n    ]]></change-notes>\n    <description><![CDATA[\n    <p>This plugin supports <a href=\"https://python-poetry.org\">poetry</a> which is a package manager for Python</p>\n    <h2>Help</h2>\n    <p>See <a href=\"https://koxudaxi.github.io/poetry-pycharm-plugin/\">documentation</a> for more details.</p>\n    <h3>This project is currently in an experimental phase</h3>\n    <img width=\"700\"  src=\"https://raw.githubusercontent.com/koxudaxi/poetry-pycharm-plugin/master/docs/poetry_demo1.gif\"/>\n\n    <h2>Features</h2>\n    <h3>Implemented</h3>\n    <li>add a new/existing poetry environment as a interpreter </li>\n    <li>install packages with pyproject.toml when add a interpreter</li>\n    <li>add a new pyproject.toml when it does not exists</li>\n    <li>install and import a package with poetry (QuickFix)</li>\n    <li>install packages from poetry.lock</li>\n    <li>update and lock with a popup</li>\n    <li>show a message and a link to fix settings (QuickFix)</li>\n    <li>install extras and run scripts by clicking a line marker (<a href=\"https://plugins.jetbrains.com/plugin/8195-toml\">Toml plugin</a> is required)</li>\n    <li>show a message for outdated version packages (<a href=\"https://plugins.jetbrains.com/plugin/8195-toml\">Toml plugin</a> is required)</li>\n    <li>install/uninstall packages from GUI</li>\n    <li>- detect poetry project when open new project</li>\n\n    ]]></description>\n\n    <depends>com.intellij.modules.lang</depends>\n    <depends>com.intellij.modules.python</depends>\n    <depends>com.intellij.modules.platform</depends>\n    <depends optional=\"true\" config-file=\"only-toml.xml\">org.toml.lang</depends>\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <editorFactoryListener implementation=\"com.koxudaxi.poetry.PyProjectTomlWatcher\"/>\n        <projectService serviceImplementation=\"com.koxudaxi.poetry.PoetryConfigService\"/>\n        <postStartupActivity implementation=\"com.koxudaxi.poetry.PoetryConfigLoader\" order=\"last\"/>\n    </extensions>\n    <extensions defaultExtensionNs=\"Pythonid\">\n        <pyAddSdkProvider implementation=\"com.koxudaxi.poetry.PyAddPoetrySdkProvider\"/>\n        <pythonFlavorProvider implementation=\"com.koxudaxi.poetry.PyPoetrySdkFlavorProvider\"/>\n        <pySdkProvider implementation=\"com.koxudaxi.poetry.PoetrySdkProvider\"/>\n        <packageManagerProvider implementation=\"com.koxudaxi.poetry.PyPoetryPackageManagerProvider\"/>\n        <projectSdkConfigurationExtension implementation=\"com.koxudaxi.poetry.PyPoetrySdkConfiguration\"/>\n    </extensions>\n    <actions>\n        <action id=\"poetryInstallExtras\" class=\"com.koxudaxi.poetry.PoetryInstallExtras\" text=\"Install Packages\"\n                description=\"Poetry install extras packages\">\n        </action>\n        <action id=\"poetryRunScript\" class=\"com.koxudaxi.poetry.PoetryRunScript\" text=\"Run Scripts\"\n                description=\"Poetry run scripts\">\n        </action>\n    </actions>\n</idea-plugin>\n\n"
  },
  {
    "path": "resources/inspectionDescriptions/PoetryPackageVersion.html",
    "content": "<html>\n<body>\nThis inspection checks versions of installed packages and pyproject.toml.\n</body>\n</html>"
  },
  {
    "path": "scripts/build_changelog.py",
    "content": "import re\nimport xml.etree.ElementTree\nfrom enum import Enum\nfrom html.parser import HTMLParser\nfrom pathlib import Path\nfrom typing import List, Optional\n\nPROJECT_ROOT = Path(__file__).parent.parent\n\nGITHUB_PR_URL: str = 'https://github.com/koxudaxi/poetry-pycharm-plugin/pull/'\n\n\nclass Tag(Enum):\n    Version = 'h2'\n    ChangeType = 'p'\n    ChangeBody = 'ul'\n    ChangeContent = 'li'\n\n\ndef get_markdown_hyperlinks(text: str) -> List[str]:\n    return [\n        f'[#{pr_number}]({GITHUB_PR_URL}/{pr_number})'\n        for pr_number in re.findall(r'#(\\d+)', text)\n    ]\n\n\nclass HistoryHTMLParser(HTMLParser):\n    def error(self, message):\n        pass\n\n    def __init__(self):\n        super().__init__()\n        self.current_tag: Tag = Tag.Version\n        self.markdown: str = ''\n        self.markdown_latest_log: str = ''\n        self.latest: Optional[bool] = None\n\n    def handle_starttag(self, tag: str, attrs):\n        self.current_tag = Tag(tag)\n\n    def handle_endtag(self, tag):\n        pass\n\n    def handle_data(self, data: str):\n        if not data.strip():\n            return\n        if self.current_tag == Tag.Version:\n            if self.latest is None:\n                self.latest = True\n            elif self.latest is True:\n                self.latest = False\n                self.markdown_latest_log = '\\n'.join(self.markdown.splitlines()[1:])\n            self.markdown += f'## {data.replace(\"version \", \"\")}\\n'\n        elif self.current_tag == Tag.ChangeType:\n            self.markdown += f'### {data}\\n'\n        elif self.current_tag == Tag.ChangeContent:\n            links = get_markdown_hyperlinks(data)\n            converted_data = re.sub(r'\\[[^]].+\\]', f'[{\", \".join(links)}]', data)\n            self.markdown += f'- {converted_data}\\n'\n\n\ndef main():\n    plugin_xml = PROJECT_ROOT / 'resources/META-INF/plugin.xml'\n    tree = xml.etree.ElementTree.parse(str(plugin_xml))\n    root = tree.getroot()\n    history: str = root.find('change-notes').text\n\n    html_parser = HistoryHTMLParser()\n    html_parser.feed(history)\n    with open(PROJECT_ROOT / 'docs/changelog.md', 'w') as f:\n        f.write(html_parser.markdown)\n    with open(PROJECT_ROOT / 'docs/changelog_latest.md', 'w') as f:\n        f.write(html_parser.markdown_latest_log)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'poetry-pycharm-plugin'"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryConfigLoader.kt",
    "content": "package com.koxudaxi.poetry\n\n\nimport com.intellij.openapi.application.ApplicationManager\nimport com.intellij.openapi.project.DumbService\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.startup.StartupActivity\nimport com.intellij.serviceContainer.AlreadyDisposedException\nimport com.jetbrains.python.statistics.sdks\n\n\n/**\n *  This source code is created by @koxudaxi  (Koudai Aono)\n */\n\n\nclass PoetryConfigLoader : StartupActivity {\n    override fun runActivity(project: Project) {\n        if (ApplicationManager.getApplication().isUnitTestMode) return\n        if (project.isDisposed) return\n        DumbService.getInstance(project).smartInvokeLater {\n            try {\n                project.sdks\n                        .filterNot { it.isPoetry }\n                        .filter { isPoetryFromConfig(project, it) }\n                        .forEach { it.isPoetry = true }\n            } catch (e: AlreadyDisposedException) {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryConfigService.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.openapi.components.PersistentStateComponent\nimport com.intellij.openapi.components.ServiceManager\nimport com.intellij.openapi.components.State\nimport com.intellij.openapi.components.Storage\nimport com.intellij.openapi.project.Project\nimport com.intellij.util.xmlb.XmlSerializerUtil\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\n@State(name = \"PoetryConfigService\", storages = [Storage(\"poetry.xml\")])\nclass PoetryConfigService : PersistentStateComponent<PoetryConfigService> {\n    var poetryVirtualenvPaths = mutableSetOf<String>()\n\n    override fun getState(): PoetryConfigService {\n        return this\n    }\n\n    override fun loadState(config: PoetryConfigService) {\n        XmlSerializerUtil.copyBean(config, this)\n    }\n\n    companion object {\n        fun getInstance(project: Project): PoetryConfigService {\n            return ServiceManager.getService(project, PoetryConfigService::class.java)\n        }\n    }\n\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryExtrasLineMarkerContributor.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.execution.lineMarker.RunLineMarkerContributor\nimport com.intellij.icons.AllIcons.Actions.Install\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.psi.PsiElement\nimport com.jetbrains.python.sdk.pythonSdk\nimport org.toml.lang.psi.*\n\nobject PoetryExtrasLineMarkerContributor : RunLineMarkerContributor() {\n    override fun getInfo(element: PsiElement): Info? {\n        val sdk = element.project.pythonSdk ?: return null\n        if (!sdk.isPoetry) return null\n        try {\n            if (element !is TomlKey) return null\n        } catch (e: NoClassDefFoundError) {\n            return null //Toml plugin is installed. But, PyCharm has not restarted yet.\n        }\n        val keyValue = element.parent as? TomlKeyValue ?: return null\n        val header = (keyValue.parent as? TomlTable)?.header ?: return null\n        if (header.key?.text != \"tool.poetry.extras\") return null\n        if (keyValue.key.text == null) return null\n        val value = keyValue.value as? TomlArray ?: return null\n        if (value.elements.isEmpty() || value.elements.any { it !is TomlLiteral || it.textLength < 3}) return null\n        val action =ActionManager.getInstance().getAction(PoetryInstallExtras.actionID)\n        return Info(Install, { parameter ->  \"Install \" + ((parameter as? TomlKey)?.text ?: \"extra\")}, arrayOf(action))\n    }\n}\n\n\n\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryInstallExtras.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.execution.Location\nimport com.intellij.openapi.actionSystem.AnAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.jetbrains.python.sdk.isAssociatedWithModule\nimport com.jetbrains.python.sdk.pythonSdk\nimport com.jetbrains.python.statistics.modules\nimport org.toml.lang.psi.TomlKey\n\nclass PoetryInstallExtras : AnAction() {\n    override fun actionPerformed(e: AnActionEvent) {\n        val tomlKey = e.dataContext.getData(Location.DATA_KEY)?.psiElement  as? TomlKey ?: return\n        val project = e.project ?: return\n        val pythonSdk = project.pythonSdk ?: return\n        project.modules.firstOrNull { pythonSdk.isAssociatedWithModule(it) }?.let { runPoetryInBackground(it, listOf(\"install\", \"--extras\", tomlKey.text), \"installing ${tomlKey.text}\") }\n    }\n    companion object {\n        const val actionID = \"poetryInstallExtras\"\n    }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryRunScript.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.execution.ExecutionManager\nimport com.intellij.execution.Location\nimport com.intellij.execution.RunManager\nimport com.intellij.execution.actions.ConfigurationContext\nimport com.intellij.execution.actions.RunConfigurationProducer\nimport com.intellij.execution.executors.DefaultRunExecutor\nimport com.intellij.execution.runners.ExecutionEnvironmentBuilder\nimport com.intellij.execution.util.ExecutionErrorDialog\nimport com.intellij.icons.AllIcons\nimport com.intellij.openapi.actionSystem.AnAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.project.Project\nimport com.intellij.psi.PsiFile\nimport com.jetbrains.extensions.python.toPsi\nimport com.jetbrains.python.packaging.PyExecutionException\nimport com.jetbrains.python.run.PythonRunConfigurationProducer\nimport com.jetbrains.python.sdk.pythonSdk\nimport org.toml.lang.psi.*\n\n\nclass PoetryRunScript : AnAction() {\n    private fun runScriptFromRunConfiguration(project: Project, file: PsiFile) {\n        val configurationFromContext = RunConfigurationProducer\n                .getInstance(PythonRunConfigurationProducer::class.java)\n                .createConfigurationFromContext(ConfigurationContext(file)) ?: return\n        val settings = configurationFromContext.configurationSettings\n        val runManager = RunManager.getInstance(project)\n        runManager.addConfiguration(settings)\n        runManager.selectedConfiguration = settings\n        val builder = ExecutionEnvironmentBuilder.createOrNull(DefaultRunExecutor.getRunExecutorInstance(), settings)\n                ?: return\n        ExecutionManager.getInstance(project).restartRunProfile(builder.build())\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val tomlKey = e.dataContext.getData(Location.DATA_KEY)?.psiElement as? TomlKey ?: return\n        val project = e.project ?: return\n        val scriptPath = project.pythonSdk?.homeDirectory?.parent?.findChild(tomlKey.text) ?: return\n        val scriptFile = scriptPath.toPsi(project) ?: return ExecutionErrorDialog.show(PyExecutionException(\"Cannot find a script file\\nPlease run 'poetry install' before executing scripts\", \"poetry\", emptyList()), \"Poetry Plugin\", project)\n        runScriptFromRunConfiguration(project, scriptFile.containingFile)\n\n    }\n\n    init {\n        templatePresentation.icon = AllIcons.Actions.Execute\n    }\n\n    companion object {\n        const val actionID = \"poetryRunScript\"\n    }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryScriptsLineMarkerContributor.kt",
    "content": "package com.koxudaxi.poetry\n\n\nimport com.intellij.execution.lineMarker.RunLineMarkerContributor\nimport com.intellij.icons.AllIcons.Actions.Execute\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.psi.PsiElement\nimport com.jetbrains.python.sdk.pythonSdk\nimport org.toml.lang.psi.TomlKey\nimport org.toml.lang.psi.TomlKeyValue\nimport org.toml.lang.psi.TomlLiteral\nimport org.toml.lang.psi.TomlTable\n\nobject PoetryScriptsLineMarkerContributor : RunLineMarkerContributor() {\n    override fun getInfo(element: PsiElement): Info? {\n        val sdk = element.project.pythonSdk ?: return null\n        if (!sdk.isPoetry) return null\n        try {\n            if (element !is TomlKey) return null\n        } catch (e: NoClassDefFoundError) {\n            return null //Toml plugin is installed. But, PyCharm has not restarted yet.\n        }\n        val keyValue = element.parent as? TomlKeyValue ?: return null\n        val header = (keyValue.parent as? TomlTable)?.header ?: return null\n        if (header.key?.text != \"tool.poetry.scripts\") return null\n        if (keyValue.key.text == null) return null\n        val value = keyValue.value as? TomlLiteral ?: return null\n        if (value.textLength < 3) return null\n        val action = ActionManager.getInstance().getAction(PoetryRunScript.actionID)\n        action.templatePresentation.text = \"Run '${keyValue.key.text}'\"\n        return Info(Execute, { parameter -> \"Run '${((parameter as? TomlKey)?.text ?: \"script\")}'\" }, arrayOf(action))\n    }\n}\n\n\n\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetrySdkProvider.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.codeInspection.LocalQuickFix\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.projectRoots.SdkAdditionalData\nimport com.intellij.openapi.util.UserDataHolder\nimport com.jetbrains.python.packaging.ui.PyPackageManagementService\nimport com.jetbrains.python.sdk.PyInterpreterInspectionQuickFixData\nimport com.jetbrains.python.sdk.PySdkProvider\nimport com.jetbrains.python.sdk.PythonSdkUtil\nimport com.jetbrains.python.sdk.add.PyAddNewEnvPanel\nimport org.jdom.Element\nimport javax.swing.Icon\n\nclass PoetrySdkProvider : PySdkProvider {\n    override fun createEnvironmentAssociationFix(module: Module, sdk: Sdk, isPyCharm: Boolean, associatedModulePath: String?): PyInterpreterInspectionQuickFixData? {\n        if (sdk.isPoetry) {\n            val message = when {\n                associatedModulePath != null -> when {\n                    isPyCharm -> \"Poetry interpreter is associated with another project: $associatedModulePath\"\n                    else -> \"Poetry interpreter is associated with another module: $associatedModulePath\"\n                }\n                else -> when {\n                    isPyCharm -> \"Poetry interpreter is not associated with any project\"\n                    else -> \"Poetry interpreter is not associated with any module\"\n                }\n            }\n            return PyInterpreterInspectionQuickFixData(UsePoetryQuickFix(sdk, module), message)\n        }\n        return null\n    }\n\n    override fun createInstallPackagesQuickFix(module: Module): LocalQuickFix? {\n        val sdk = PythonSdkUtil.findPythonSdk(module) ?: return null\n        return if (sdk.isPoetry) PoetryInstallQuickFix() else null\n    }\n\n    override fun createNewEnvironmentPanel(project: Project?, module: Module?, existingSdks: List<Sdk>, newProjectPath: String?, context: UserDataHolder): PyAddNewEnvPanel {\n        return PyAddNewPoetryPanel(null, null, existingSdks, newProjectPath, context)\n    }\n\n    override fun getSdkAdditionalText(sdk: Sdk): String? = if (sdk.isPoetry) sdk.versionString else null\n\n    override fun getSdkIcon(sdk: Sdk): Icon? {\n        return if (sdk.isPoetry) POETRY_ICON else null\n    }\n\n    override fun loadAdditionalDataForSdk(element: Element): SdkAdditionalData? {\n        return PyPoetrySdkAdditionalData.load(element)\n    }\n\n    override fun tryCreatePackageManagementServiceForSdk(project: Project, sdk: Sdk): PyPackageManagementService? {\n        return if (sdk.isPoetry) PyPoetryPackageManagementService(project, sdk) else null\n    }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PoetryVersionInspection.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.codeInspection.*\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.module.ModuleManager\nimport com.intellij.openapi.module.ModuleUtilCore\nimport com.intellij.psi.PsiElement\nimport com.intellij.psi.PsiElementVisitor\nimport com.intellij.psi.PsiFile\nimport com.jetbrains.python.packaging.PyPackageManager\nimport com.jetbrains.python.sdk.*\nimport org.toml.lang.psi.*\n\nclass PoetryVersionInspection : LocalInspectionTool() {\n    override fun buildVisitor(holder: ProblemsHolder,\n                              isOnTheFly: Boolean,\n                              session: LocalInspectionToolSession): PsiElementVisitor {\n        return PoetryFileVisitor(holder, session)\n    }\n\n    class PoetryFileVisitor(val holder: ProblemsHolder,\n                            session: LocalInspectionToolSession) : PsiElementVisitor() {\n        private fun guessModule(element: PsiElement): Module? {\n            return ModuleUtilCore.findModuleForPsiElement(element)\n                    ?: ModuleManager.getInstance(element.project).modules.let { if (it.size != 1) null else it[0] }\n        }\n\n        override fun visitFile(file: PsiFile) {\n            val module = guessModule(file) ?: return\n            val sdk = PythonSdkUtil.findPythonSdk(module) ?: return\n            if (!sdk.isPoetry) return\n            if (file.virtualFile != module.pyProjectToml) return\n            file.children\n                    .filter { element ->\n                        (element as? TomlTable)?.header?.key?.text in listOf(\"tool.poetry.dependencies\", \"tool.poetry.dev-dependencies\")\n                    }.flatMap {\n                        it.children.mapNotNull { line -> line as? TomlKeyValue }\n                    }.forEach { keyValue ->\n                        val packageName = keyValue.key.text\n                        val outdatedVersion = (PyPackageManager.getInstance(sdk) as? PyPoetryPackageManager)?.let { it.getOutdatedPackages()[packageName] }\n                        if (outdatedVersion is PoetryOutdatedVersion) {\n                            val message = \"'${packageName}' version ${outdatedVersion.currentVersion} is outdated (latest: ${outdatedVersion.latestVersion})\"\n                            holder.registerProblem(keyValue, message, ProblemHighlightType.WARNING)\n                        }\n                    }\n        }\n    }\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyAddExistingPoetryEnvPanel.kt",
    "content": "/*\n * Copyright 2000-2017 JetBrains s.r.o.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.koxudaxi.poetry\n\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.ui.ValidationInfo\nimport com.intellij.openapi.util.UserDataHolder\nimport com.intellij.util.ui.FormBuilder\nimport com.jetbrains.python.PyBundle\nimport com.jetbrains.python.PySdkBundle\nimport com.jetbrains.python.sdk.*\nimport com.jetbrains.python.sdk.add.PyAddSdkPanel\nimport com.jetbrains.python.sdk.add.PyAddSdkView\nimport com.jetbrains.python.sdk.add.PySdkPathChoosingComboBox\nimport com.jetbrains.python.sdk.add.addInterpretersAsync\nimport java.awt.BorderLayout\nimport java.util.concurrent.ConcurrentHashMap\nimport javax.swing.Icon\nimport kotlin.streams.toList\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nclass PyAddExistingPoetryEnvPanel(private val project: Project?,\n                                  private val module: Module?,\n                                  private val existingSdks: List<Sdk>,\n                                  override var newProjectPath: String?,\n                                  context: UserDataHolder) : PyAddSdkPanel() {\n    private var sdkToModule = ConcurrentHashMap<String, Module>()\n    override val panelName: String get() = PyBundle.message(\"python.add.sdk.panel.name.existing.environment\")\n    override val icon: Icon = POETRY_ICON\n    private val sdkComboBox = PySdkPathChoosingComboBox()\n\n    init {\n        layout = BorderLayout()\n        val formPanel = FormBuilder.createFormBuilder()\n                .addLabeledComponent(PySdkBundle.message(\"python.interpreter.label\"), sdkComboBox)\n                .panel\n        add(formPanel, BorderLayout.NORTH)\n        addInterpretersAsync(sdkComboBox) {\n            val existingSdkPaths = sdkHomes(existingSdks)\n            val moduleSdks = allModules(project).parallelStream().flatMap { module ->\n                val sdks = detectPoetryEnvs(module, existingSdkPaths, module.basePath)\n                        .filterNot { it.isAssociatedWithAnotherModule(module) }\n                sdks.forEach { sdkToModule.putIfAbsent(it.name, module) }\n                sdks.stream()\n            }.toList()\n            val rootSdks = detectPoetryEnvs(module, existingSdkPaths, project?.basePath ?: newProjectPath)\n                    .filterNot { it.isAssociatedWithAnotherModule(module) }\n            val moduleSdkPaths = moduleSdks.map { it.name }.toSet()\n            val sdks = rootSdks.filterNot { moduleSdkPaths.contains(it.name) } + moduleSdks\n            sdks.sortedBy { it.name }\n        }\n    }\n\n    override fun validateAll(): List<ValidationInfo> = listOfNotNull(validateSdkComboBox(sdkComboBox, this))\n\n    override fun getOrCreateSdk(): Sdk? {\n        return when (val sdk = sdkComboBox.selectedSdk) {\n            is PyDetectedSdk -> {\n                val mappedModule = sdkToModule[sdk.name] ?: module\n                setupPoetrySdkUnderProgress(project, mappedModule, existingSdks, newProjectPath,\n                        getPythonExecutable(sdk.name), false, sdk.name)?.apply {\n                    PySdkSettings.instance.preferredVirtualEnvBaseSdk = getPythonExecutable(sdk.name)\n                }\n            }\n            else -> sdk\n        }\n    }\n\n    companion object {\n        fun validateSdkComboBox(field: PySdkPathChoosingComboBox, view: PyAddSdkView): ValidationInfo? {\n            return when (val sdk = field.selectedSdk) {\n                null -> ValidationInfo(PySdkBundle.message(\"python.sdk.field.is.empty\"), field)\n                // This plugin does not support installing python sdk.\n//                is PySdkToInstall -> {\n//                    val message = sdk.getInstallationWarning(getDefaultButtonName(view))\n//                    ValidationInfo(message).asWarning().withOKEnabled()\n//                }\n                else -> null\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyAddNewPoetryFromFilePanel.kt",
    "content": "package com.koxudaxi.poetry\n\n\nimport com.intellij.openapi.fileChooser.FileChooserDescriptorFactory\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.ui.TextFieldWithBrowseButton\nimport com.intellij.openapi.ui.ValidationInfo\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.util.ui.FormBuilder\nimport org.jetbrains.annotations.SystemDependent\nimport java.awt.BorderLayout\nimport javax.swing.JPanel\n\nclass PyAddNewPoetryFromFilePanel(private val module: Module) : JPanel() {\n\n    val envData: Data\n        get() = Data(poetryPathField.text)\n\n    private val poetryPathField = TextFieldWithBrowseButton()\n\n    init {\n        poetryPathField.apply {\n            getPoetryExecutable()?.absolutePath?.also { text = it }\n\n            addBrowseFolderListener(\n                    \"Select Path to Poetry Executable\",\n                    null,\n                    module.project,\n                    FileChooserDescriptorFactory.createSingleFileOrExecutableAppDescriptor()\n            )\n        }\n\n        layout = BorderLayout()\n        val formPanel = FormBuilder.createFormBuilder()\n                .addLabeledComponent(\"Poetry executable:\", poetryPathField)\n                .panel\n        add(formPanel, BorderLayout.NORTH)\n    }\n\n    fun validateAll(): List<ValidationInfo> = listOfNotNull( validatePoetryExecutable(poetryPathField.text))\n\n    data class Data(val poetryPath: @NlsSafe @SystemDependent String)\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyAddNewPoetryPanel.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.intellij.application.options.ModuleListCellRenderer\nimport com.intellij.ide.util.PropertiesComponent\nimport com.intellij.openapi.fileChooser.FileChooserDescriptorFactory\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.module.ModuleUtil\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.ui.TextFieldWithBrowseButton\nimport com.intellij.openapi.ui.ValidationInfo\nimport com.intellij.openapi.util.UserDataHolder\nimport com.intellij.openapi.vfs.StandardFileSystems\nimport com.intellij.ui.DocumentAdapter\nimport com.intellij.ui.components.JBCheckBox\nimport com.intellij.ui.components.JBTextField\nimport com.intellij.util.PlatformUtils\nimport com.intellij.util.text.nullize\nimport com.intellij.util.ui.FormBuilder\nimport com.jetbrains.python.PyBundle\nimport com.jetbrains.python.PySdkBundle\nimport com.jetbrains.python.PythonModuleTypeBase\nimport com.jetbrains.python.sdk.*\nimport com.jetbrains.python.sdk.add.PyAddNewEnvPanel\nimport com.jetbrains.python.sdk.add.PySdkPathChoosingComboBox\nimport com.jetbrains.python.sdk.add.addInterpretersAsync\nimport java.awt.BorderLayout\nimport java.awt.Dimension\nimport java.awt.event.ItemEvent\nimport java.io.File\nimport java.nio.file.Files\nimport java.util.concurrent.ConcurrentHashMap\nimport javax.swing.Icon\nimport javax.swing.JComboBox\nimport javax.swing.event.DocumentEvent\n\n/**\n * The UI panel for adding the poetry interpreter for the project.\n *\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nclass PyAddNewPoetryPanel(private val project: Project?,\n                          private val module: Module?,\n                          private val existingSdks: List<Sdk>,\n                          override var newProjectPath: String?,\n                          context: UserDataHolder) : PyAddNewEnvPanel() {\n    override val envName = \"Poetry\"\n    override val panelName: String get() = \"Poetry Environment\"\n\n    // TODO: Need a extension point\n    override val icon: Icon = POETRY_ICON\n\n    private val moduleField: JComboBox<Module>\n\n    private val baseSdkField = PySdkPathChoosingComboBox()\n\n    init {\n        addInterpretersAsync(baseSdkField) {\n            val sdks = findBaseSdks(existingSdks, module, context).takeIf { it.isNotEmpty() }\n                    ?: detectSystemWideSdks(module, existingSdks, context)\n            sdks.filterNot { PythonSdkUtil.isInvalid(it) || it.isPoetry }\n        }\n    }\n\n\n    private val installPackagesCheckBox = JBCheckBox(\"Install packages from pyproject.toml\").apply {\n        isVisible = projectPath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PY_PROJECT_TOML)?.let { file -> getPyProjectTomlForPoetry(file) } } != null\n        isSelected = isVisible\n    }\n\n    private val poetryPathField = TextFieldWithBrowseButton().apply {\n        addBrowseFolderListener(null, null, null, FileChooserDescriptorFactory.createSingleFileDescriptor())\n        val field = textField as? JBTextField ?: return@apply\n        detectPoetryExecutable()?.let {\n            field.emptyText.text = \"Auto-detected: ${it.absolutePath}\"\n        }\n        PropertiesComponent.getInstance().poetryPath?.let {\n            field.text = it\n        }\n    }\n\n    init {\n        layout = BorderLayout()\n\n        val modules = allModules(project)\n\n        moduleField = JComboBox(modules.toTypedArray()).apply {\n            renderer = ModuleListCellRenderer()\n            preferredSize = Dimension(Int.MAX_VALUE, preferredSize.height)\n            addItemListener {\n                if (it.stateChange == ItemEvent.SELECTED) {\n                    update()\n                }\n            }\n        }\n\n        poetryPathField.textField.document.addDocumentListener(object : DocumentAdapter() {\n            override fun textChanged(e: DocumentEvent) {\n                update()\n            }\n        })\n\n        val builder = FormBuilder.createFormBuilder().apply {\n            if (module == null && modules.size > 1) {\n                val associatedObject = if (PlatformUtils.isPyCharm()) \"project\" else \"module\"\n                addLabeledComponent(\"Associated $associatedObject\", moduleField)\n            }\n            addLabeledComponent(PySdkBundle.message(\"python.venv.base.label\"), baseSdkField)\n            addComponent(installPackagesCheckBox)\n            addLabeledComponent(\"Poetry executable:\", poetryPathField)\n        }\n        add(builder.panel, BorderLayout.NORTH)\n        update()\n    }\n\n    override fun getOrCreateSdk(): Sdk? {\n        PropertiesComponent.getInstance().poetryPath = poetryPathField.text.nullize()\n        return setupPoetrySdkUnderProgress(project, selectedModule, existingSdks, newProjectPath,\n                baseSdkField.selectedSdk?.homePath, installPackagesCheckBox.isSelected)?.apply {\n            PySdkSettings.instance.preferredVirtualEnvBaseSdk = baseSdkField.selectedSdk?.homePath\n        }\n    }\n\n    override fun validateAll(): List<ValidationInfo> =\n            listOfNotNull(validatePoetryExecutable(), validatePoetryIsNotAdded())\n\n    override fun addChangeListener(listener: Runnable) {\n        poetryPathField.textField.document.addDocumentListener(object : DocumentAdapter() {\n            override fun textChanged(e: DocumentEvent) {\n                listener.run()\n            }\n        })\n        super.addChangeListener(listener)\n    }\n\n    /**\n     * Updates the view according to the current state of UI controls.\n     */\n    private fun update() {\n        selectedModule?.let {\n            installPackagesCheckBox.isEnabled = it.pyProjectToml != null\n        }\n    }\n\n    /**\n     * The effective module for which we add a new environment.\n     */\n    private val selectedModule: Module?\n        get() = module ?: try {\n            moduleField.selectedItem\n        } catch (e: NullPointerException) {\n            null\n        } as? Module\n\n    /**\n     * Checks if `poetry` is available on `$PATH`.\n     */\n    private fun validatePoetryExecutable(): ValidationInfo? {\n        val executable = poetryPathField.text.nullize()?.let { File(it) }\n                ?: detectPoetryExecutable()\n                ?: return ValidationInfo(\"Poetry executable is not found\")\n        return when {\n            !executable.exists() -> ValidationInfo(PyBundle.message(\"python.sdk.file.not.found\", executable.absolutePath))\n            !Files.isExecutable(executable.toPath()) || !executable.isFile -> ValidationInfo(PyBundle.message(\"python.sdk.cannot.execute\", executable.absolutePath))\n            else -> null\n        }\n    }\n\n    private val isPoetry by lazy { existingSdks.filter { it.isPoetry }.associateBy { it.associatedModulePath } }\n    private val homePath by lazy { existingSdks.associateBy { it.homePath } }\n    private val pythonExecutable = ConcurrentHashMap<String, String>()\n    private val venvInProject = ConcurrentHashMap<String, Boolean?>()\n\n    private fun computePythonExecutable(homePath: String): String? {\n        return pythonExecutable.getOrPut(homePath) { getPythonExecutable(homePath) }\n    }\n\n    private fun isVenvInProject(path: String): Boolean? {\n        return venvInProject.getOrPut(path) { isVirtualEnvsInProject(path) }\n    }\n\n    /**\n     * Checks if the poetry for the project hasn't been already added.\n     */\n    private fun validatePoetryIsNotAdded(): ValidationInfo? {\n        val path = projectPath ?: return null\n        val project = project ?: return null\n        val addedPoetry = isPoetry[path] ?: return null\n        if (addedPoetry.homeDirectory == null) return null\n        // TODO: check existing envs\n        if (isVenvInProject(path) == false) return null\n        val inProjectEnvExecutable = inProjectEnvPath?.let {computePythonExecutable(it)} ?: return null\n        val inProjectEnv = homePath[inProjectEnvExecutable] ?: return null\n        return ValidationInfo(\"Poetry interpreter has been already added, select '${inProjectEnv.name}'\")\n    }\n\n\n    /**\n     * The effective project path for the new project or for the existing project.\n     */\n    private val projectPath: String?\n        get() = newProjectPath ?: selectedModule?.basePath ?: project?.basePath\n\n    private val inProjectEnvDir = \".venv\"\n    private val inProjectEnvPath: String?\n        get() = projectPath?.let { it + File.separator + inProjectEnvDir }\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyAddPoetrySdkProvider.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.util.UserDataHolder\nimport com.jetbrains.python.sdk.add.PyAddSdkProvider\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nclass PyAddPoetrySdkProvider : PyAddSdkProvider {\n    override fun createView(project: Project?,\n                            module: Module?,\n                            newProjectPath: String?,\n                            existingSdks: List<Sdk>,\n                            context: UserDataHolder) =\n            createPoetryPanel(project, module, existingSdks, newProjectPath, context)\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetryPackageManagementService.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.intellij.execution.ExecutionException\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.webcore.packaging.RepoPackage\nimport com.jetbrains.python.packaging.PyPIPackageUtil\nimport com.jetbrains.python.packaging.PyPackageManagerUI\nimport com.jetbrains.python.packaging.PyRequirementParser\nimport com.jetbrains.python.packaging.ui.PyPackageManagementService\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nclass PyPoetryPackageManagementService(project: Project, sdk: Sdk) : PyPackageManagementService(project, sdk) {\n    override fun getAllRepositories(): List<String>? = null\n\n    override fun canInstallToUser() = false\n\n    override fun getAllPackages(): List<RepoPackage> {\n        PyPIPackageUtil.INSTANCE.loadAdditionalPackages(sdk.poetrySources, false)\n        return allPackagesCached\n    }\n\n    override fun reloadAllPackages(): List<RepoPackage> {\n        PyPIPackageUtil.INSTANCE.loadAdditionalPackages(sdk.poetrySources, true)\n        return allPackagesCached\n    }\n\n    override fun getAllPackagesCached(): List<RepoPackage> =\n            PyPIPackageUtil.INSTANCE.getAdditionalPackages(sdk.poetrySources)\n\n    override fun installPackage(repoPackage: RepoPackage,\n                                version: String?,\n                                forceUpgrade: Boolean,\n                                extraOptions: String?,\n                                listener: Listener,\n                                installToUser: Boolean) {\n        val ui = PyPackageManagerUI(project, sdk, object : PyPackageManagerUI.Listener {\n          override fun started() {\n            listener.operationStarted(repoPackage.name)\n          }\n\n          override fun finished(exceptions: List<ExecutionException?>?) {\n            listener.operationFinished(repoPackage.name, toErrorDescription(exceptions, sdk))\n          }\n        })\n        val requirement = when {\n            version != null -> PyRequirementParser.fromLine(\"${repoPackage.name}==$version\")\n            else -> PyRequirementParser.fromLine(repoPackage.name)\n        } ?: return\n        val extraArgs = extraOptions?.split(\" +\".toRegex()) ?: emptyList()\n        ui.install(listOf(requirement), extraArgs)\n    }\n\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetryPackageManager.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.intellij.execution.ExecutionException\nimport com.intellij.openapi.application.ApplicationManager\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.roots.OrderRootType\nimport com.intellij.openapi.vfs.VfsUtil\nimport com.intellij.openapi.vfs.VirtualFile\nimport com.jetbrains.python.packaging.*\nimport com.jetbrains.python.sdk.PythonSdkType\nimport com.jetbrains.python.sdk.associatedModuleDir\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nclass PyPoetryPackageManager(val sdk: Sdk) : PyPackageManager() {\n    private val installedLines = listOf(\"Already installed\", \"Skipping\", \"Updating\")\n\n    @Volatile\n    private var packages: List<PyPackage>? = null\n\n    private var requirements: List<PyRequirement>? = null\n\n    private var outdatedPackages: Map<String, PoetryOutdatedVersion> = emptyMap()\n\n    init {\n        PyPackageUtil.runOnChangeUnderInterpreterPaths(sdk, this, Runnable{\n            PythonSdkType.getInstance().setupSdkPaths(sdk)\n        })\n    }\n\n    override fun installManagement() {}\n\n    override fun hasManagement() = true\n\n    override fun install(requirementString: String) {\n        install(parseRequirements(requirementString), emptyList())\n    }\n\n    override fun install(requirements: List<PyRequirement>?, extraArgs: List<String>) {\n        val args = if (requirements == null || requirements.isEmpty()) {\n            listOfNotNull(listOf(\"install\"),\n                    extraArgs)\n                    .flatten()\n        } else {\n            listOfNotNull(listOf(\"add\"),\n                    requirements.map { it.name },\n                    extraArgs)\n                    .flatten()\n        }\n\n        try {\n            runPoetry(sdk, *args.toTypedArray())\n        } finally {\n            sdk.associatedModuleDir?.refresh(true, false)\n            refreshAndGetPackages(true)\n        }\n    }\n\n    override fun uninstall(packages: List<PyPackage>) {\n        val args = listOf(\"remove\") +\n                packages.map { it.name }\n        try {\n            runPoetry(sdk, *args.toTypedArray())\n        } finally {\n            sdk.associatedModuleDir?.refresh(true, false)\n            refreshAndGetPackages(true)\n        }\n    }\n\n    override fun refresh() {\n        with(ApplicationManager.getApplication()) {\n            invokeLater {\n                runWriteAction {\n                    val files = sdk.rootProvider.getFiles(OrderRootType.CLASSES)\n                    VfsUtil.markDirtyAndRefresh(true, true, true, *files)\n                }\n                PythonSdkType.getInstance().setupSdkPaths(sdk)\n            }\n        }\n    }\n\n    override fun createVirtualEnv(destinationDir: String, useGlobalSite: Boolean): String {\n        throw ExecutionException(\"Creating virtual environments based on Poetry environments is not supported\")\n    }\n\n    override fun getPackages() = packages\n\n    fun getOutdatedPackages() = outdatedPackages\n\n    override fun refreshAndGetPackages(alwaysRefresh: Boolean): List<PyPackage> {\n        if (alwaysRefresh || packages == null) {\n            packages = null\n            val outputInstallDryRun = try {\n                runPoetry(sdk, \"install\", \"--dry-run\", \"--no-root\")\n            } catch (e: ExecutionException) {\n                packages = emptyList()\n                return packages ?: emptyList()\n            }\n            val allPackage = parsePoetryInstallDryRun(outputInstallDryRun)\n            packages = allPackage.first\n            requirements = allPackage.second\n\n            val outputOutdatedPackages = try {\n                runPoetry(sdk, \"show\", \"--outdated\")\n            } catch (e: ExecutionException) {\n                outdatedPackages = emptyMap()\n            }\n            if (outputOutdatedPackages is String) {\n                outdatedPackages = parsePoetryShowOutdated(outputOutdatedPackages)\n            }\n            ApplicationManager.getApplication().messageBus.syncPublisher(PACKAGE_MANAGER_TOPIC).packagesRefreshed(sdk)\n        }\n        return packages ?: emptyList()\n    }\n\n    override fun getRequirements(module: Module): List<PyRequirement>? {\n        return requirements\n    }\n\n    override fun parseRequirements(text: String): List<PyRequirement> =\n            PyRequirementParser.fromText(text)\n\n    override fun parseRequirement(line: String): PyRequirement? =\n            PyRequirementParser.fromLine(line)\n\n    override fun parseRequirements(file: VirtualFile): List<PyRequirement> =\n            PyRequirementParser.fromFile(file)\n\n    override fun getDependents(pkg: PyPackage): Set<PyPackage> {\n        // TODO: Parse the dependency information from `pipenv graph`\n        return emptySet()\n    }\n\n    private fun getVersion(version: String): String {\n        return if (Regex(\"^[0-9]\").containsMatchIn(version)) \"==$version\" else version\n    }\n\n    private fun toRequirements(packages: List<PyPackage>): List<PyRequirement> =\n            packages\n                    .asSequence()\n//                    .filterNot { (_, pkg) -> pkg.editable ?: false }\n                    // TODO: Support requirements markers (PEP 496), currently any packages with markers are ignored due to PY-30803\n//                    .filter { (_, pkg) -> pkg.markers == null }\n                    .flatMap { it -> this.parseRequirements(\"${it.name}${it.version?.let { getVersion(it) } ?: \"\"}\").asSequence() }\n                    .toList()\n\n    /**\n     * Parses the output of `poetry install --dry-run ` into a list of packages.\n     */\n    fun parsePoetryInstallDryRun(input: String): Pair<List<PyPackage>, List<PyRequirement>> {\n        fun getNameAndVersion(line: String): Triple<String, String, String> {\n            return line.split(\" \").let {\n                val installedVersion = it[5].replace(Regex(\"[():]\"), \"\")\n                val requiredVersion = when {\n                    it.size > 7 && it[6] == \"->\" -> it[7].replace(Regex(\"[():]\"), \"\")\n                    else -> installedVersion\n                }\n                Triple(it[4], installedVersion, requiredVersion)\n            }\n        }\n\n        val pyPackages = mutableListOf<PyPackage>()\n        val pyRequirements = mutableListOf<PyRequirement>()\n        input\n                .lineSequence()\n                .filter { listOf(\")\", \"Already installed\").any{ lastWords -> it.endsWith(lastWords) } }\n                .forEach { line ->\n                    getNameAndVersion(line).also {\n                        if (installedLines.any { installedLine -> line.contains(installedLine) } ) {\n                            pyPackages.add(PyPackage(it.first, it.second, null, emptyList()))\n                            this.parseRequirement(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }\n                        } else if ( line.contains(\"Installing\")) {\n                            this.parseRequirement(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }\n                        }\n                    }\n                }\n        return Pair(pyPackages.distinct().toList(), pyRequirements.distinct().toList())\n    }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetryPackageManagerProvider.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.jetbrains.python.packaging.PyPackageManager\nimport com.jetbrains.python.packaging.PyPackageManagerProvider\n\nclass PyPoetryPackageManagerProvider : PyPackageManagerProvider {\n    override fun tryCreateForSdk(sdk: Sdk): PyPackageManager? = if (sdk.isPoetry)  PyPoetryPackageManager(sdk) else null\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetrySdkAdditionalData.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.jetbrains.python.sdk.PythonSdkAdditionalData\nimport org.jdom.Element\n\n/**\n * Additional Poetry data associated with an SDK.\n *\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n// TODO: Need a extension point\nclass PyPoetrySdkAdditionalData : PythonSdkAdditionalData {\n  constructor() : super(PyPoetrySdkFlavor)\n  constructor(data: PythonSdkAdditionalData) : super(data)\n\n  override fun save(element: Element) {\n    super.save(element)\n    // We use this flag to create an instance of the correct additional data class. The flag itself is not used after that\n    element.setAttribute(IS_POETRY, \"true\")\n  }\n\n  companion object {\n    private const val IS_POETRY = \"IS_POETRY\"\n\n    /**\n     * Loads serialized data from an XML element.\n     */\n    @JvmStatic\n    fun load(element: Element): PyPoetrySdkAdditionalData? =\n      when {\n        element.getAttributeValue(IS_POETRY) == \"true\" -> {\n          PyPoetrySdkAdditionalData().apply {\n            load(element)\n          }\n        }\n        else -> null\n      }\n\n    /**\n     * Creates a new instance of data with copied fields.\n     */\n    @JvmStatic\n    fun copy(data: PythonSdkAdditionalData): PyPoetrySdkAdditionalData =\n      PyPoetrySdkAdditionalData(data)\n  }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetrySdkConfiguration.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.codeInspection.util.IntentionName\nimport com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension\nimport com.intellij.execution.ExecutionException\nimport com.intellij.ide.util.PropertiesComponent\nimport com.intellij.openapi.application.ApplicationManager\nimport com.intellij.openapi.diagnostic.Logger\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.progress.ProgressManager\nimport com.intellij.openapi.projectRoots.ProjectJdkTable\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil\nimport com.intellij.openapi.ui.DialogWrapper\nimport com.intellij.openapi.ui.ValidationInfo\nimport com.intellij.openapi.util.io.FileUtil\nimport com.intellij.openapi.vfs.LocalFileSystem\nimport com.intellij.openapi.vfs.StandardFileSystems\nimport com.intellij.ui.IdeBorderFactory\nimport com.intellij.ui.components.JBLabel\nimport com.intellij.util.ui.JBUI\nimport com.jetbrains.python.sdk.*\nimport java.awt.BorderLayout\nimport java.awt.Insets\nimport javax.swing.JComponent\nimport javax.swing.JPanel\n\nclass PyPoetrySdkConfiguration : PyProjectSdkConfigurationExtension {\n\n    private val LOGGER = Logger.getInstance(PyPoetrySdkConfiguration::class.java)\n\n    override fun createAndAddSdkForConfigurator(module: Module): Sdk? = createAndAddSDk(module, false)\n\n    override fun getIntention(module: Module): @IntentionName String? =\n        module.pyProjectToml?.let { \"Create a poetry environment using ${it.name}\" }\n\n    override fun createAndAddSdkForInspection(module: Module): Sdk? = createAndAddSDk(module, true)\n\n    private fun createAndAddSDk(module: Module, inspection: Boolean): Sdk? {\n        val poetryEnvExecutable = askForEnvData(module, inspection) ?: return null\n        PropertiesComponent.getInstance().poetryPath = poetryEnvExecutable.poetryPath\n        return createPoetry(module)\n    }\n\n    private fun askForEnvData(module: Module, inspection: Boolean): PyAddNewPoetryFromFilePanel.Data? {\n        val poetryExecutable = getPoetryExecutable()?.absolutePath\n\n        if (inspection && validatePoetryExecutable(poetryExecutable) == null) {\n            return PyAddNewPoetryFromFilePanel.Data(poetryExecutable!!)\n        }\n\n        var permitted = false\n        var envData: PyAddNewPoetryFromFilePanel.Data? = null\n\n        ApplicationManager.getApplication().invokeAndWait {\n            val dialog = Dialog(module)\n\n            permitted = dialog.showAndGet()\n            envData = dialog.envData\n\n            LOGGER.debug(\"Dialog exit code: ${dialog.exitCode}, $permitted\")\n        }\n\n        return if (permitted) envData else null\n    }\n\n    private fun createPoetry(module: Module): Sdk? {\n        ProgressManager.progress(\"Setting up poetry environment\")\n        LOGGER.debug(\"Creating poetry environment\")\n\n        val basePath = module.basePath ?: return null\n        val poetry = try {\n            val init = StandardFileSystems.local().findFileByPath(basePath)?.findChild(PY_PROJECT_TOML)?.let { getPyProjectTomlForPoetry(it) } == null\n            setupPoetry(FileUtil.toSystemDependentName(basePath), null, true, init)\n        }\n        catch (e: ExecutionException) {\n            LOGGER.warn(\"Exception during creating poetry environment\", e)\n            showSdkExecutionException(null, e, \"Failed To Create Poetry Environment\")\n            return null\n        }\n\n        val path = PythonSdkUtil.getPythonExecutable(poetry).also {\n            if (it == null) {\n                LOGGER.warn(\"Python executable is not found: $poetry\")\n            }\n        } ?: return null\n\n        val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path).also {\n            if (it == null) {\n                LOGGER.warn(\"Python executable file is not found: $path\")\n            }\n        } ?: return null\n\n        LOGGER.debug(\"Setting up associated poetry environment: $path, $basePath\")\n        val sdk = SdkConfigurationUtil.setupSdk(\n                ProjectJdkTable.getInstance().allJdks,\n                file,\n                PythonSdkType.getInstance(),\n                false,\n                null,\n                suggestedSdkName(basePath)\n        ) ?: return null\n\n        ApplicationManager.getApplication().invokeAndWait {\n            LOGGER.debug(\"Adding associated poetry environment: $path, $basePath\")\n            SdkConfigurationUtil.addSdk(sdk)\n            sdk.isPoetry = true\n            sdk.associateWithModule(module, null)\n        }\n\n        return sdk\n    }\n\n    private class Dialog(module: Module) : DialogWrapper(module.project, false, IdeModalityType.PROJECT) {\n\n        private val panel = PyAddNewPoetryFromFilePanel(module)\n\n        val envData\n            get() = panel.envData\n\n        init {\n            title = \"Setting Up Poetry Environment\"\n            init()\n        }\n\n        override fun createCenterPanel(): JComponent {\n            return JPanel(BorderLayout()).apply {\n                val border = IdeBorderFactory.createEmptyBorder(Insets(4, 0, 6, 0))\n                val message = \"File pyproject.toml contains project dependencies. Would you like to create a poetry environment using it?\"\n\n                add(\n                        JBUI.Panels.simplePanel(JBLabel(message)).withBorder(border),\n                        BorderLayout.NORTH\n                )\n\n                add(panel, BorderLayout.CENTER)\n            }\n        }\n\n        override fun postponeValidation(): Boolean = false\n\n        override fun doValidateAll(): List<ValidationInfo> = panel.validateAll()\n    }\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetrySdkFlavor.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.jetbrains.python.sdk.flavors.CPythonSdkFlavor\nimport java.io.File\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nobject PyPoetrySdkFlavor : CPythonSdkFlavor() {\n  // TODO: Need a extension point\n   override fun getIcon() = POETRY_ICON\n\n  override fun isValidSdkPath(file: File) = false\n}"
  },
  {
    "path": "src/com/koxudaxi/poetry/PyPoetrySdkFlavorProvider.kt",
    "content": "// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.jetbrains.python.sdk.flavors.PythonFlavorProvider\n\n/**\n * @author vlan\n */\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\nclass PyPoetrySdkFlavorProvider : PythonFlavorProvider {\n  override fun getFlavor(platformIndependent: Boolean) = PyPoetrySdkFlavor\n}\n"
  },
  {
    "path": "src/com/koxudaxi/poetry/poetry.kt",
    "content": "// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.koxudaxi.poetry\n\nimport com.google.gson.annotations.SerializedName\nimport com.intellij.CommonBundle\nimport com.intellij.codeInspection.LocalQuickFix\nimport com.intellij.codeInspection.ProblemDescriptor\nimport com.intellij.execution.ExecutionException\nimport com.intellij.execution.RunCanceledByUserException\nimport com.intellij.execution.configurations.GeneralCommandLine\nimport com.intellij.execution.configurations.PathEnvironmentVariableUtil\nimport com.intellij.execution.process.CapturingProcessHandler\nimport com.intellij.execution.process.ProcessNotCreatedException\nimport com.intellij.execution.process.ProcessOutput\nimport com.intellij.ide.util.PropertiesComponent\nimport com.intellij.notification.NotificationGroup\nimport com.intellij.notification.NotificationDisplayType\nimport com.intellij.notification.NotificationListener\nimport com.intellij.openapi.application.ApplicationManager\nimport com.intellij.openapi.application.ReadAction\nimport com.intellij.openapi.application.runInEdt\nimport com.intellij.openapi.editor.Document\nimport com.intellij.openapi.editor.Editor\nimport com.intellij.openapi.editor.event.DocumentEvent\nimport com.intellij.openapi.editor.event.DocumentListener\nimport com.intellij.openapi.editor.event.EditorFactoryEvent\nimport com.intellij.openapi.editor.event.EditorFactoryListener\nimport com.intellij.openapi.fileEditor.FileDocumentManager\nimport com.intellij.openapi.module.Module\nimport com.intellij.openapi.module.ModuleUtil\nimport com.intellij.openapi.module.ModuleUtilCore\nimport com.intellij.openapi.progress.ProgressIndicator\nimport com.intellij.openapi.progress.ProgressManager\nimport com.intellij.openapi.progress.Task\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.projectRoots.Sdk\nimport com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil\nimport com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel\nimport com.intellij.openapi.ui.Messages\nimport com.intellij.openapi.ui.ValidationInfo\nimport com.intellij.openapi.util.Key\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.openapi.util.SystemInfo\nimport com.intellij.openapi.util.UserDataHolder\nimport com.intellij.openapi.util.io.FileUtil\nimport com.intellij.openapi.util.text.StringUtil\nimport com.intellij.openapi.vfs.StandardFileSystems\nimport com.intellij.openapi.vfs.VirtualFile\nimport com.intellij.serviceContainer.AlreadyDisposedException\nimport com.intellij.util.PathUtil\nimport com.intellij.util.PlatformUtils\nimport com.jetbrains.python.PythonModuleTypeBase\nimport com.jetbrains.python.inspections.PyPackageRequirementsInspection\nimport com.jetbrains.python.packaging.*\nimport com.jetbrains.python.sdk.*\nimport com.jetbrains.python.sdk.add.*\nimport com.jetbrains.python.sdk.flavors.PythonSdkFlavor\nimport com.jetbrains.python.statistics.modules\nimport icons.PythonIcons\nimport org.apache.tuweni.toml.Toml\nimport org.apache.tuweni.toml.TomlInvalidTypeException\nimport org.apache.tuweni.toml.TomlParseResult\nimport org.apache.tuweni.toml.TomlTable\nimport org.jetbrains.annotations.NonNls\nimport org.jetbrains.annotations.Nullable\nimport org.jetbrains.annotations.SystemDependent\nimport org.jetbrains.annotations.TestOnly\nimport org.toml.lang.psi.TomlKey\nimport org.toml.lang.psi.TomlTableHeader\nimport java.io.File\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.TimeoutException\nimport java.util.function.Supplier\nimport java.util.regex.Pattern\nimport kotlin.reflect.full.memberProperties\n\nconst val PY_PROJECT_TOML: String = \"pyproject.toml\"\nconst val POETRY_LOCK: String = \"poetry.lock\"\nconst val POETRY_DEFAULT_SOURCE_URL: String = \"https://pypi.org/simple\"\nconst val POETRY_PATH_SETTING: String = \"PyCharm.Poetry.Path\"\nconst val REPLACE_PYTHON_VERSION = \"\"\"import re,sys;f=open(\"pyproject.toml\", \"r+\");orig=f.read();f.seek(0);f.write(re.sub(r\"(python = \\\"\\^)[^\\\"]+(\\\")\", \"\\g<1>\"+'.'.join(str(v) for v in sys.version_info[:2])+\"\\g<2>\", orig))\"\"\"\n\n// TODO: Provide a special icon for poetry\n// TODO: Need a extension point\nval POETRY_ICON = PythonIcons.Python.Virtualenv\n\n/**\n *  This source code is edited by @koxudaxi  (Koudai Aono)\n */\n\nfun getPyProjectTomlForPoetry(virtualFile: VirtualFile): Pair<Long, VirtualFile?> {\n    return Pair(virtualFile.modificationStamp, try {\n        ReadAction.compute<VirtualFile, Throwable> {\n            Toml.parse(virtualFile.inputStream).getTable(\"tool.poetry\")?.let { virtualFile }\n        }\n    } catch (e: Throwable) {\n        null\n    })\n}\n\n/**\n * The PyProject.toml found in the main content root of the module.\n */\nval pyProjectTomlCache = mutableMapOf<String, Pair<Long, VirtualFile?>>()\nval Module.pyProjectToml: VirtualFile?\n    get() =\n        baseDir?.findChild(PY_PROJECT_TOML)?.let { virtualFile ->\n            (this.name + virtualFile.path).let { key ->\n                pyProjectTomlCache.getOrPut(key, { getPyProjectTomlForPoetry(virtualFile) }).let { pair ->\n                    when (virtualFile.modificationStamp) {\n                        pair.first -> pair.second\n                        else -> pyProjectTomlCache.put(key, getPyProjectTomlForPoetry(virtualFile))?.second\n                    }\n                }\n            }\n        }\n\n/**\n * Tells if the SDK was added as a poetry.\n */\n\n/**\n * The user-set persisted path to the poetry executable.\n */\nvar PropertiesComponent.poetryPath: @SystemDependent String?\n    get() = getValue(POETRY_PATH_SETTING)\n    set(value) {\n        setValue(POETRY_PATH_SETTING, value)\n    }\n\n/**\n * Detects the poetry executable in `$PATH`.\n */\nfun detectPoetryExecutable(): File? {\n    val name = when {\n        SystemInfo.isWindows -> \"poetry.bat\"\n        else -> \"poetry\"\n    }\n    return PathEnvironmentVariableUtil.findInPath(name) ?: System.getProperty(\"user.home\")?.let { homePath ->\n        File(homePath + File.separator + \".poetry\" + File.separator + \"bin\" + File.separator + name).takeIf { it.exists() }\n    }\n}\n\n/**\n * Returns the configured poetry executable or detects it automatically.\n */\nfun getPoetryExecutable(): File? =\n        PropertiesComponent.getInstance().poetryPath?.let { File(it) }?.takeIf { it.exists() } ?: detectPoetryExecutable()\n\nfun validatePoetryExecutable(poetryExecutable: @SystemDependent String?): ValidationInfo? {\n    val message = if (poetryExecutable.isNullOrBlank()) {\n        \"Poetry executable is not found\"\n    }\n    else {\n        val file = File(poetryExecutable)\n        when {\n            !file.exists() -> \"File ${file.absolutePath} is not found\"\n            !file.canExecute() || !file.isFile -> \"Cannot execute ${file.absolutePath}\"\n            else -> null\n        }\n    }\n\n    return message?.let { ValidationInfo(it) }\n}\n\nfun suggestedSdkName(basePath: @NlsSafe String): @NlsSafe String = \"Poetry (${PathUtil.getFileName(basePath)})\"\n\n\n/**\n * Sets up the poetry environment under the modal progress window.\n *\n * The poetry is associated with the first valid object from this list:\n *\n * 1. New project specified by [newProjectPath]\n * 2. Existing module specified by [module]\n * 3. Existing project specified by [project]\n *\n * @return the SDK for poetry, not stored in the SDK table yet.\n */\nfun setupPoetrySdkUnderProgress(project: Project?,\n                                module: Module?,\n                                existingSdks: List<Sdk>,\n                                newProjectPath: String?,\n                                python: String?,\n                                installPackages: Boolean,\n                                poetryPath: String? = null): Sdk? {\n    val projectPath = newProjectPath ?: module?.basePath ?: project?.basePath ?: return null\n    val task = object : Task.WithResult<String, ExecutionException>(project, \"Setting Up Poetry Environment\", true) {\n        override fun compute(indicator: ProgressIndicator): String {\n            indicator.isIndeterminate = true\n            val poetry = when (poetryPath) {\n                is String -> poetryPath\n                else -> {\n                    val init = StandardFileSystems.local().findFileByPath(projectPath)?.findChild(PY_PROJECT_TOML)?.let { getPyProjectTomlForPoetry(it) } == null\n                    setupPoetry(FileUtil.toSystemDependentName(projectPath), python, installPackages, init)\n                }\n            }\n            return getPythonExecutable(poetry)\n        }\n    }\n\n    return createSdkByGenerateTask(task, existingSdks, null, projectPath, suggestedSdkName(projectPath))?.apply {\n        isPoetry = true\n        associateWithModule(module ?: project?.modules?.firstOrNull(), newProjectPath)\n//        project?.let { project ->\n//            existingSdks.find {\n//                it.associatedModulePath == projectPath && isPoetry(project, it) && it.homePath == homePath\n//            }?.run {\n//                 re-use existing invalid sdk\n//                return null\n//            }\n//            PoetryConfigService.getInstance(project).poetryVirtualenvPaths.add(homePath!!)\n//        }\n    }\n}\n\n/**\n * Sets up the poetry environment for the specified project path.\n *\n * @return the path to the poetry environment.\n */\nfun setupPoetry(projectPath: @SystemDependent String, python: String?, installPackages: Boolean, init: Boolean): @SystemDependent String {\n    if (init) {\n        runPoetry(projectPath, *listOf(\"init\", \"-n\").toTypedArray())\n        if (python != null) {\n            // Replace python version in toml\n            runCommand(projectPath, python, \"-c\", REPLACE_PYTHON_VERSION)\n        }\n    }\n    when {\n        installPackages -> {\n            python?.let { runPoetry(projectPath, \"env\", \"use\", it) }\n            runPoetry(projectPath, \"install\")\n        }\n        python != null -> runPoetry(projectPath, \"env\", \"use\", python)\n        else -> runPoetry(projectPath, \"run\", \"python\", \"-V\")\n    }\n    return runPoetry(projectPath, \"env\", \"info\", \"-p\")\n}\n\n\n@Deprecated(\"This function is for backward compatibility\")\nfun isPoetryFromConfig(project: Project, sdk: Sdk): Boolean {\n    return PoetryConfigService.getInstance(project).poetryVirtualenvPaths.contains(sdk.homePath)\n}\n\n\nvar Sdk.isPoetry: Boolean\n    get() = sdkAdditionalData is PyPoetrySdkAdditionalData\n    set(value) {\n        val oldData = sdkAdditionalData\n        val newData = if (value) {\n            when (oldData) {\n                is PythonSdkAdditionalData -> PyPoetrySdkAdditionalData(oldData)\n                else -> PyPoetrySdkAdditionalData()\n            }\n        } else {\n            when (oldData) {\n                is PyPoetrySdkAdditionalData -> PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(this))\n                else -> oldData\n            }\n        }\n        val modificator = sdkModificator\n        modificator.sdkAdditionalData = newData\n        ApplicationManager.getApplication().runWriteAction { modificator.commitChanges() }\n    }\n\n/**\n * Runs the configured poetry for the specified Poetry SDK with the associated project path.\n */\nfun runPoetry(sdk: Sdk, vararg args: String): String {\n    val projectPath = sdk.associatedModulePath\n            ?: throw PyExecutionException(\"Cannot find the project associated with this Poetry environment\",\n                    \"Poetry\", emptyList(), ProcessOutput())\n    runPoetry(projectPath, \"env\", \"use\", sdk.homePath!!)\n    return runPoetry(projectPath, *args)\n}\n\n/**\n * Runs the configured poetry for the specified project path.\n */\nfun runPoetry(projectPath: @SystemDependent String?, vararg args: String): String {\n    val executable = getPoetryExecutable()?.path\n            ?: throw PyExecutionException(\"Cannot find Poetry\", \"poetry\", emptyList(), ProcessOutput())\n\n    val command = listOf(executable) + args\n    val commandLine = GeneralCommandLine(command).withWorkDirectory(projectPath)\n    val handler = CapturingProcessHandler(commandLine)\n    val indicator = ProgressManager.getInstance().progressIndicator\n    val result = with(handler) {\n        when {\n            indicator != null -> {\n                addProcessListener(IndicatedProcessOutputListener(indicator))\n                runProcessWithProgressIndicator(indicator)\n            }\n            else ->\n                runProcess()\n        }\n    }\n    return with(result) {\n        when {\n            isCancelled ->\n                throw RunCanceledByUserException()\n            exitCode != 0 ->\n                throw PyExecutionException(\"Error Running Poetry\", executable, args.asList(),\n                        stdout, stderr, exitCode, emptyList())\n            else -> stdout.trim()\n        }\n    }\n}\n\nfun runCommand(projectPath: @SystemDependent String, command: String, vararg args: String): String {\n    val commandLine = GeneralCommandLine(listOf(command) + args).withWorkDirectory(projectPath)\n    val handler = CapturingProcessHandler(commandLine)\n\n    val result = with(handler) {\n        runProcess()\n    }\n    return with(result) {\n        when {\n            isCancelled ->\n                throw RunCanceledByUserException()\n            exitCode != 0 ->\n                throw PyExecutionException(\"Error Running\", command, args.asList(),\n                        stdout, stderr, exitCode, emptyList())\n            else -> stdout\n        }\n    }\n}\n\n/**\n * Detects and sets up poetry SDK for a module with Pipfile.\n */\nfun detectAndSetupPoetry(project: Project?, module: Module?, existingSdks: List<Sdk>): Sdk? {\n    if (module?.pyProjectToml == null || getPoetryExecutable() == null) {\n        return null\n    }\n    return setupPoetrySdkUnderProgress(project, module, existingSdks, null, null, false)\n}\n\n/**\n * The URLs of package sources configured in the Pipfile.lock of the module associated with this SDK.\n */\nval Sdk.poetrySources: List<String>\n    // TODO parse pyproject.toml for tool.poetry.source.url\n    get() = listOf(POETRY_DEFAULT_SOURCE_URL)\n\n/**\n * The list of requirements defined in the poetry.lock of the module associated with this SDK.\n */\n//val Sdk.poetryLockRequirements: List<PyRequirement>?\n//    get() {\n//        return poetryLock?.let { PyPoetryPackageManager.getInstance(this).getRequirements() }\n//    }\n\n/**\n * A quick-fix for setting up the poetry for the module of the current PSI element.\n */\nclass UsePoetryQuickFix(sdk: Sdk?, module: Module) : LocalQuickFix {\n    private val quickFixName = when {\n        sdk != null && sdk.isAssociatedWithAnotherModule(module) -> \"Fix Poetry interpreter\"\n        else -> \"Use Poetry interpreter\"\n    }\n\n    companion object {\n        fun isApplicable(module: Module): Boolean = module.pyProjectToml != null\n\n        fun setUpPoetry(project: Project, module: Module) {\n            val sdksModel = ProjectSdksModel().apply {\n                reset(project)\n            }\n            val existingSdks = sdksModel.sdks.filter { it.sdkType is PythonSdkType }\n            // XXX: Should we show an error message on exceptions and on null?\n            val newSdk = setupPoetrySdkUnderProgress(project, module, existingSdks, null, null, false)\n                    ?: return\n            val existingSdk = existingSdks.find { it.isPoetry && it.homePath == newSdk.homePath }\n            val sdk = existingSdk ?: newSdk\n            if (sdk == newSdk) {\n                SdkConfigurationUtil.addSdk(newSdk)\n            } else {\n                sdk.associateWithModule(module, null)\n            }\n            project.pythonSdk = sdk\n            module.pythonSdk = sdk\n            PoetryConfigService.getInstance(project).poetryVirtualenvPaths.add(sdk.homePath!!)\n\n        }\n    }\n\n    override fun getFamilyName() = quickFixName\n\n    override fun applyFix(project: Project, descriptor: ProblemDescriptor) {\n        val element = descriptor.psiElement ?: return\n        val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return\n        // Invoke the setup later to escape the write action of the quick fix in order to show the modal progress dialog\n        ApplicationManager.getApplication().invokeLater {\n            if (project.isDisposed || module.isDisposed) return@invokeLater\n            setUpPoetry(project, module)\n        }\n    }\n}\n\n/**\n * A quick-fix for installing packages specified in Pipfile.lock.\n */\nclass PoetryInstallQuickFix : LocalQuickFix {\n    companion object {\n        fun poetryInstall(project: Project, module: Module) {\n            val sdk = module.pythonSdk ?: return\n            if (!sdk.isPoetry) return\n            // TODO: create UI\n            val listener = PyPackageRequirementsInspection.RunningPackagingTasksListener(module)\n            val ui = PyPackageManagerUI(project, sdk, listener)\n            ui.install(null, listOf())\n        }\n    }\n\n    override fun getFamilyName() = \"Install requirements from poetry.lock\"\n\n    override fun applyFix(project: Project, descriptor: ProblemDescriptor) {\n        val element = descriptor.psiElement ?: return\n        val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return\n        poetryInstall(project, module)\n    }\n}\n\n/**\n * Watches for edits in PyProjectToml inside modules with a poetry SDK set.\n */\nclass PyProjectTomlWatcher : EditorFactoryListener {\n    private val changeListenerKey = Key.create<DocumentListener>(\"PyProjectToml.change.listener\")\n    private val notificationActive = Key.create<Boolean>(\"PyProjectToml.notification.active\")\n    private val content: String = if (poetryVersion?.let { it < \"1.1.1\" } == true) {\n        \"Run <a href='#lock'>poetry lock</a> or <a href='#update'>poetry update</a>\"\n    } else {\n        \"Run <a href='#lock'>poetry lock</a>, <a href='#noupdate'>poetry lock --no-update</a> or <a href='#update'>poetry update</a>\"\n    }\n\n    override fun editorCreated(event: EditorFactoryEvent) {\n        val project = event.editor.project\n        if (project == null || !isPyProjectTomlEditor(event.editor)) return\n        val listener = object : DocumentListener {\n            override fun documentChanged(event: DocumentEvent) {\n                try {\n                    val document = event.document\n                    val module = document.virtualFile?.getModule(project) ?: return\n                    // TODO: Should we remove listener when a sdk is changed to non-poetry sdk?\n//                    if (!isPoetry(module.project)) {\n//                        with(document) {\n//                            putUserData(notificationActive, null)\n//                            val listener = getUserData(changeListenerKey) ?: return\n//                            removeDocumentListener(listener)\n//                            putUserData(changeListenerKey, null)\n//                            return\n//                        }\n//                    }\n                    if (FileDocumentManager.getInstance().isDocumentUnsaved(document)) {\n                        notifyPyProjectTomlChanged(module)\n                    }\n                } catch (e: AlreadyDisposedException) {\n                }\n            }\n        }\n        with(event.editor.document) {\n            addDocumentListener(listener)\n            putUserData(changeListenerKey, listener)\n        }\n    }\n\n    override fun editorReleased(event: EditorFactoryEvent) {\n        val listener = event.editor.getUserData(changeListenerKey) ?: return\n        event.editor.document.removeDocumentListener(listener)\n    }\n\n    private fun notifyPyProjectTomlChanged(module: Module) {\n        if (module.getUserData(notificationActive) == true) return\n        val what = when {\n            module.poetryLock == null -> \"not found\"\n            else -> \"out of date\"\n        }\n        val title = \"$POETRY_LOCK is $what\"\n        val notification = LOCK_NOTIFICATION_GROUP.createNotification(title = title, content = content, listener = NotificationListener { notification, event ->\n            FileDocumentManager.getInstance().saveAllDocuments()\n            when (event.description) {\n                \"#lock\" ->\n                    runPoetryInBackground(module, listOf(\"lock\"), \"Locking $POETRY_LOCK\")\n                \"#noupdate\" ->\n                    runPoetryInBackground(module, listOf(\"lock\", \"--no-update\"), \"Locking $POETRY_LOCK without updating\")\n                \"#update\" ->\n                    runPoetryInBackground(module, listOf(\"update\"), \"Updating Poetry environment\")\n            }\n            notification.expire()\n            module.putUserData(notificationActive, null)\n        })\n        module.putUserData(notificationActive, true)\n        notification.whenExpired {\n            module.putUserData(notificationActive, null)\n        }\n        notification.notify(module.project)\n    }\n\n    private fun isPyProjectTomlEditor(editor: Editor): Boolean {\n        val file = editor.document.virtualFile ?: return false\n        if (file.name != PY_PROJECT_TOML) return false\n        val project = editor.project ?: return false\n        val module = file.getModule(project) ?: return false\n        val sdk = module.pythonSdk ?: return false\n        if (!sdk.isPoetry) return false\n        return module.pyProjectToml == file\n    }\n}\n\nprivate val Document.virtualFile: VirtualFile?\n    get() = FileDocumentManager.getInstance().getFile(this)\n\nprivate fun VirtualFile.getModule(project: Project): Module? =\n        ModuleUtil.findModuleForFile(this, project)\n\nprivate val LOCK_NOTIFICATION_GROUP = NotificationGroup(\"$PY_PROJECT_TOML Watcher\", NotificationDisplayType.STICKY_BALLOON, false)\n\n//private val Sdk.packageManager: PyPoetryPackageManager\n//    get() = PyPoetryPackageManager.getInstance(this)\n//\n\n@TestOnly\nfun getPoetryLockRequirements(virtualFile: VirtualFile, packageManager: PyPackageManager): List<PyRequirement>? {\n    fun getVersion(version: String): String {\n        return if (Regex(\"^[0-9]\").containsMatchIn(version)) \"==$version\" else version\n    }\n\n    fun toRequirements(packages: Map<String, PoetryLockPackage>): List<PyRequirement> =\n            packages\n                    .asSequence()\n//                    .filterNot { (_, pkg) -> pkg.editable ?: false }\n                    // TODO: Support requirements markers (PEP 496), currently any packages with markers are ignored due to PY-30803\n//                    .filter { (_, pkg) -> pkg.markers == null }\n                    .flatMap { (name, pkg) -> packageManager.parseRequirements(\"$name${pkg.version?.let { getVersion(it) } ?: \"\"}\").asSequence() }\n                    .toList()\n\n    //TODO: Support extras\n    val poetryLock = parsePoetryLock(virtualFile) ?: return null\n    return poetryLock.packages?.let { toRequirements(it) } ?: emptyList()\n}\n\nprivate fun Sdk.parsePoetryLock(): PoetryLock? {\n    // TODO: Log errors if poetry.lock is not found\n    val file = poetryLock ?: return null\n    return parsePoetryLock(file)\n}\n\nval Sdk.poetryLock: VirtualFile?\n    get() =\n        associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(POETRY_LOCK) }\n\nprivate val Module.poetryLock: VirtualFile?\n    get() = baseDir?.findChild(POETRY_LOCK)\n\nprivate fun parsePoetryLock(pyProjectToml: VirtualFile): PoetryLock? {\n    val text = ReadAction.compute<String, Throwable> { FileDocumentManager.getInstance().getDocument(pyProjectToml)?.text }\n    return try {\n        val result: TomlParseResult = Toml.parse(text)\n        val packages = result.getArrayOrEmpty(\"package\")\n        if (packages.isEmpty) return null\n        PoetryLock(packages = packages.toList().filterIsInstance(TomlTable::class.java).map {\n            Pair(it[\"name\"] as String,\n                    PoetryLockPackage(\n                            version = it[\"version\"] as? String\n                    )\n            )\n        }.toMap())\n\n//        return try {\n//            Gson().fromJson(Toml.parse(text).toJson(), PoetryLock::class.java)\n    } catch (e: Throwable) {\n        if (e is IllegalArgumentException || e is TomlInvalidTypeException || e is ClassCastException) return null\n        throw e\n    }\n}\n\n\nprivate data class PoetryLock(\n        @SerializedName(\"package\") var packages: Map<String, PoetryLockPackage>?)\n\n//private data class PoetryLockMeta(@SerializedName(\"sources\") var sources: List<PoetryLockSource>?)\n\nprivate data class PoetryLockSource(@SerializedName(\"url\") var url: String?)\n\nprivate data class PoetryLockPackage(@SerializedName(\"version\") var version: String?,\n//                                     @SerializedName(\"category\") var category: String?,\n//                                            @SerializedName(\"editable\") var editable: Boolean?,\n                                     @SerializedName(\"hashes\") var hashes: List<String>? = null,\n                                     @SerializedName(\"markers\") var markers: MutableList<Any> = mutableListOf(),\n                                     @SerializedName(\"extras\") var extras: List<MutableMap<String, List<String>>>? = null)\n\nfun runPoetryInBackground(module: Module, args: List<String>, description: String) {\n    val task = object : Task.Backgroundable(module.project, StringUtil.toTitleCase(description), true) {\n        override fun run(indicator: ProgressIndicator) {\n            val sdk = module.pythonSdk ?: return\n            indicator.text = \"$description...\"\n            try {\n                runPoetry(sdk, *args.toTypedArray())\n            } catch (e: RunCanceledByUserException) {\n            } catch (e: ExecutionException) {\n                showSdkExecutionException(sdk, e, \"Error Running Poetry\")\n            } finally {\n                PythonSdkUtil.getSitePackagesDirectory(sdk)?.refresh(true, true)\n                sdk.associatedModuleDir?.refresh(true, false)\n                PyPackageManager.getInstance(sdk).refreshAndGetPackages(true)\n            }\n        }\n    }\n    ProgressManager.getInstance().run(task)\n}\n\nprivate fun allowCreatingNewEnvironments(project: Project?) =\n        project != null || !PlatformUtils.isPyCharm() || PlatformUtils.isPyCharmEducational()\n\nfun createPoetryPanel(project: Project?,\n                      module: Module?,\n                      existingSdks: List<Sdk>,\n                      newProjectPath: String?,\n                      context: UserDataHolder\n): PyAddSdkPanel {\n    val newPoetryPanel = when {\n        allowCreatingNewEnvironments(project) -> PyAddNewPoetryPanel(project, module, existingSdks, null, context)\n        else -> null\n    }\n    val existingPoetryPanel = PyAddExistingPoetryEnvPanel(project, module, existingSdks, null, context)\n    val panels = listOfNotNull(newPoetryPanel, existingPoetryPanel)\n    val existingSdkPaths = sdkHomes(existingSdks)\n    val defaultPanel = when {\n     detectPoetryEnvs(module, existingSdkPaths, project?.basePath\n             ?: newProjectPath).any { it.isAssociatedWithModule(module) } -> existingPoetryPanel\n        newPoetryPanel != null -> newPoetryPanel\n        else -> existingPoetryPanel\n    }\n    return PyAddSdkGroupPanel(Supplier { \"Poetry environment\" },\n            POETRY_ICON, panels, defaultPanel)\n}\n\n\nfun allModules(project: Project?): List<Module> {\n    return project?.let {\n        ModuleUtil.getModulesOfType(it, PythonModuleTypeBase.getInstance())\n    }?.sortedBy { it.name } ?: emptyList()\n}\n\nfun sdkHomes(sdks: List<Sdk>): Set<String> = sdks.mapNotNull { it.homePath }.toSet()\n\nfun detectPoetryEnvs(module: Module?, existingSdkPaths: Set<String>, projectPath: String?): List<PyDetectedSdk> {\n    val path = module?.basePath ?: projectPath ?: return emptyList()\n    return try {\n        getPoetryEnvs(path).filterNot { existingSdkPaths.contains(getPythonExecutable(it)) }.map { PyDetectedSdk(it) }\n    } catch (e: Throwable) {\n        emptyList()\n    }\n}\n\nfun getPoetryEnvs(projectPath: String): List<String> =\n        syncRunPoetry(projectPath, \"env\", \"list\", \"--full-path\", defaultResult = emptyList()) { result ->\n            result.lineSequence().mapNotNull { it.split(\" \")[0] }.filterNot { it.isEmpty() }.toList()\n        }\n\n\nfun isVirtualEnvsInProject(projectPath: String): Boolean? =\n        syncRunPoetry(projectPath, \"config\", \"virtualenvs.in-project\", defaultResult = null) {\n            it.trim() == \"true\"\n        }\n\nval poetryVersion: String?\n    get() = syncRunPoetry(null, \"--version\", defaultResult = \"\") {\n        it.split(' ').lastOrNull()\n    }\n\ninline fun <reified T> syncRunCommand(projectPath: @SystemDependent String, command: String, vararg args: String, defaultResult: T, crossinline callback: (String) -> T): T {\n    return try {\n        ApplicationManager.getApplication().executeOnPooledThread<T> {\n            try {\n                val result = runCommand(projectPath, command, *args)\n                callback(result)\n            } catch (e: PyExecutionException) {\n                defaultResult\n            } catch (e: ProcessNotCreatedException) {\n                defaultResult\n            }\n        }.get(30, TimeUnit.SECONDS)\n    } catch (e: TimeoutException) {\n        defaultResult\n    }\n}\n\ninline fun <reified T> syncRunPoetry(projectPath: @SystemDependent String?, vararg args: String, defaultResult: T, crossinline callback: (String) -> T): T {\n    return try {\n        ApplicationManager.getApplication().executeOnPooledThread<T> {\n            try {\n                val result = runPoetry(projectPath, *args)\n                callback(result)\n            } catch (e: PyExecutionException) {\n                defaultResult\n            } catch (e: ProcessNotCreatedException) {\n                defaultResult\n            }\n        }.get(30, TimeUnit.SECONDS)\n    } catch (e: TimeoutException) {\n        defaultResult\n    }\n}\n\nfun getPythonExecutable(homePath: String): String =\n        PythonSdkUtil.getPythonExecutable(homePath) ?: FileUtil.join(homePath, \"bin\", \"python\")\n\n/**\n * Parses the output of `poetry show --outdated` into a list of packages.\n */\nfun parsePoetryShowOutdated(input: String): Map<String, PoetryOutdatedVersion> {\n    return input\n            .lines()\n            .mapNotNull { line ->\n                line.split(Pattern.compile(\" +\"))\n                        .takeIf { it.size > 3 }?.let { it[0] to PoetryOutdatedVersion(it[1], it[2]) }\n            }.toMap()\n}\n\n\ndata class PoetryOutdatedVersion(\n        @SerializedName(\"currentVersion\") var currentVersion: String,\n        @SerializedName(\"latestVersion\") var latestVersion: String)\n\n"
  },
  {
    "path": "testData/Poetry/getPyProjectTomlForPoetry/pyproject.toml",
    "content": "[tool.poetry]\nname = \"unittest\"\nversion = \"0.1.0\"\ndescription = \"\"\nauthors = [\"Koudai Aono <koxudaxi@gmail.com>\"]\n\n[tool.poetry.dependencies]\npython = \"^3.7\"\n\n[tool.poetry.extras]\n\n[build-system]\nrequires = [\"poetry>=0.12\"]\nbuild-backend = \"poetry.masonry.api\"\n"
  },
  {
    "path": "testData/Poetry/getPyProjectTomlForPoetryBroken/pyproject.toml",
    "content": "{\"name\": \"unittest\"}"
  },
  {
    "path": "testData/Poetry/getPyProjectTomlForPoetryInvalid/pyproject.toml",
    "content": "[tool.invalid]\nname = \"unittest\"\nversion = \"0.1.0\"\ndescription = \"\"\n"
  },
  {
    "path": "testData/Poetry/parsePoetryShoOutdated/show-outdated.txt",
    "content": "boto3    1.13.26 1.14.38 The AWS SDK for Python\nbotocore 1.16.26 1.17.38 Low-level, data-driven core of boto 3.\ndocutils 0.15.2  0.16    Docutils -- Python Documentation Utilities\npydantic 1.4     1.6.1   Data validation and settings management using python 3.6 type hinting\n\n"
  },
  {
    "path": "testData/PyPoetryPackageManager/parsePoetryInstallDryRun1_0/dry-run-result.txt",
    "content": "Installing dependencies from lock file\n\n\nPackage operations: 2 installs, 1 updates, 0 removals, 2 skipped\n\n  - Skipping six (1.15.0) Already installed\n  - Skipping attrs (20.2.0) Already installed\n  - Installing jmespath (0.10.0)\n  - Installing botocore (1.18.18)\n  - Updating colorama (0.4.3 -> 0.4.4)\n"
  },
  {
    "path": "testData/PyPoetryPackageManager/parsePoetryInstallDryRun1_1/dry-run-result.txt",
    "content": "Installing dependencies from lock file\n\nPackage operations: 2 installs, 1 updates, 0 removals, 2 skipped\n\n  • Installing six (1.15.0): Skipped for the following reason: Already installed\n  • Installing attrs (20.2.0): Skipped for the following reason: Already installed\n  • Installing jmespath (0.10.0)\n  • Installing jmespath (0.10.0)\n  • Installing botocore (1.18.18)\n  • Updating colorama (0.4.3 -> 0.4.4)"
  },
  {
    "path": "testSrc/com/jetbrains/python/fixtures/PythonMockSdk.java",
    "content": "// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.\npackage com.jetbrains.python.fixtures;\n\nimport com.intellij.openapi.projectRoots.Sdk;\nimport com.intellij.openapi.projectRoots.SdkAdditionalData;\nimport com.intellij.openapi.projectRoots.SdkTypeId;\nimport com.intellij.openapi.projectRoots.impl.MockSdk;\nimport com.intellij.openapi.roots.OrderRootType;\nimport com.intellij.openapi.vfs.LocalFileSystem;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport com.intellij.util.containers.ContainerUtil;\nimport com.intellij.util.containers.MultiMap;\nimport com.jetbrains.python.codeInsight.typing.PyTypeShed;\nimport com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil;\nimport com.jetbrains.python.psi.LanguageLevel;\nimport com.jetbrains.python.sdk.PythonSdkUtil;\nimport org.jdom.Element;\nimport org.jetbrains.annotations.NonNls;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n\npublic final class PythonMockSdk {\n    public static final String PYTHON_SDK_ID_NAME = \"Python SDK\";\n    private PythonMockSdk() {\n    }\n\n    public static @NotNull Sdk create(@NotNull String name) {\n        return create(name, LanguageLevel.getLatest());\n    }\n\n    public static @NotNull Sdk create(@NotNull LanguageLevel level, VirtualFile @NotNull ... additionalRoots) {\n        return create(\"MockSdk\", level, additionalRoots);\n    }\n\n    private static @NotNull Sdk create(@NotNull String name, @NotNull LanguageLevel level, VirtualFile @NotNull ... additionalRoots) {\n        return create(name, new PyMockSdkType(level), level, additionalRoots);\n    }\n\n    public static @NotNull Sdk create(@NotNull String pathSuffix, @NotNull SdkTypeId sdkType, @NotNull LanguageLevel level, VirtualFile @NotNull ... additionalRoots) {\n        String sdkName = \"Mock \" + PYTHON_SDK_ID_NAME + \" \" + level.toPythonVersion();\n        return create(sdkName, pathSuffix, sdkType, level, additionalRoots);\n    }\n\n    public static @NotNull Sdk create(@NotNull String name, @NotNull String pathSuffix, @NotNull SdkTypeId sdkType, @NotNull LanguageLevel level, VirtualFile @NotNull ... additionalRoots) {\n        final String mockSdkPath = PythonTestUtil.getTestDataPath() + \"/\" + pathSuffix;\n\n        MultiMap<OrderRootType, VirtualFile> roots = MultiMap.create();\n        roots.putValues(OrderRootType.CLASSES, createRoots(mockSdkPath, level));\n        roots.putValues(OrderRootType.CLASSES, Arrays.asList(additionalRoots));\n\n        MockSdk sdk = new MockSdk(\n                name,\n                mockSdkPath + \"/bin/python\",\n                toVersionString(level),\n                roots,\n                sdkType\n        );\n\n        // com.jetbrains.python.psi.resolve.PythonSdkPathCache.getInstance() corrupts SDK, so have to clone\n        return sdk.clone();\n    }\n\n    private static @NotNull List<VirtualFile> createRoots(@NotNull @NonNls String mockSdkPath, @NotNull LanguageLevel level) {\n        final var result = new ArrayList<VirtualFile>();\n\n        final var localFS = LocalFileSystem.getInstance();\n        ContainerUtil.addIfNotNull(result, localFS.refreshAndFindFileByIoFile(new File(mockSdkPath, \"Lib\")));\n        ContainerUtil.addIfNotNull(result, localFS.refreshAndFindFileByIoFile(new File(mockSdkPath, PythonSdkUtil.SKELETON_DIR_NAME)));\n\n        ContainerUtil.addIfNotNull(result, PyUserSkeletonsUtil.getUserSkeletonsDirectory());\n\n        result.addAll(PyTypeShed.INSTANCE.findRootsForLanguageLevel(level));\n\n        return result;\n    }\n\n    private static @NotNull String toVersionString(@NotNull LanguageLevel level) {\n        return \"Python \" + level.toPythonVersion();\n    }\n\n    private static final class PyMockSdkType implements SdkTypeId {\n\n        @NotNull\n        private final LanguageLevel myLevel;\n\n        private PyMockSdkType(@NotNull LanguageLevel level) {\n            myLevel = level;\n        }\n\n        @NotNull\n        @Override\n        public String getName() {\n            return PYTHON_SDK_ID_NAME;\n        }\n\n        @Nullable\n        @Override\n        public @NotNull String getVersionString(@NotNull Sdk sdk) {\n            return toVersionString(myLevel);\n        }\n\n        @Override\n        public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {\n        }\n\n        @Nullable\n        @Override\n        public SdkAdditionalData loadAdditionalData(@NotNull Sdk currentSdk, @NotNull Element additional) {\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "testSrc/com/jetbrains/python/fixtures/PythonTestUtil.java",
    "content": "/*\n * Copyright 2000-2013 JetBrains s.r.o.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jetbrains.python.fixtures;\n\n/**\n * @author yole\n */\npublic class PythonTestUtil {\n    private PythonTestUtil() {\n    }\n\n    public static String getTestDataPath() {\n        return System.getProperty(\"user.dir\") + \"/testData\";\n    }\n}\n"
  },
  {
    "path": "testSrc/com/koxudaxi/poetry/PoetryTest.kt",
    "content": "package com.koxudaxi.poetry\n\n\nimport com.intellij.openapi.vfs.VirtualFile\n\n\nclass PoetryTest : PoetryTestCase() {\n    private val testFile: VirtualFile\n        get() {\n            return getTestData(\"pyproject.toml\")\n        }\n\n    fun testGetPyProjectTomlForPoetry() {\n        val result = getPyProjectTomlForPoetry(testFile)\n        assertEquals(result.first, 0)\n        assertEquals(result.second, testFile)\n    }\n\n    fun testGetPyProjectTomlForPoetryInvalid() {\n        val result = getPyProjectTomlForPoetry(testFile)\n        assertEquals(result.first, 0)\n        assertEquals(result.second, null)\n    }\n\n    fun testGetPyProjectTomlForPoetryBroken() {\n        val result = getPyProjectTomlForPoetry(testFile)\n        assertEquals(result.first, 0)\n        assertEquals(result.second, null)\n    }\n\n    private val testShowOutdatedDataAsText: String\n        get() {\n            return getTestDataAsText(\"show-outdated.txt\")\n        }\n\n    fun testParsePoetryShoOutdated() {\n        val result = parsePoetryShowOutdated(testShowOutdatedDataAsText)\n        assertEquals(result.size, 4)\n        assertEquals(result,\n                mapOf(\n                        \"boto3\" to PoetryOutdatedVersion(currentVersion = \"1.13.26\", latestVersion = \"1.14.38\"),\n                        \"botocore\" to PoetryOutdatedVersion(currentVersion = \"1.16.26\", latestVersion = \"1.17.38\"),\n                        \"docutils\" to PoetryOutdatedVersion(currentVersion = \"0.15.2\", latestVersion = \"0.16\"),\n                        \"pydantic\" to PoetryOutdatedVersion(currentVersion = \"1.4\", latestVersion = \"1.6.1\")\n                )\n        )\n    }\n\n}"
  },
  {
    "path": "testSrc/com/koxudaxi/poetry/PoetryTestCase.kt",
    "content": "package com.koxudaxi.poetry\n\nimport com.intellij.openapi.vfs.VirtualFile\nimport com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl\nimport com.intellij.testFramework.fixtures.BasePlatformTestCase\nimport java.io.File\n\nabstract class PoetryTestCase : BasePlatformTestCase() {\n    protected open val testClassName: String = this.javaClass.simpleName.replace(\"Test\", \"\")\n    protected val dataDir: String\n        get() {\n            return \"testData\" + File.separator + testClassName + File.separator + getTestName(true)\n        }\n    fun getTestData(fileName: String): VirtualFile {\n        return LocalFileSystemImpl.getInstance().refreshAndFindFileByPath(dataDir + File.separator + fileName)!!\n    }\n    fun getTestDataAsText(fileName: String): String {\n        return getTestData(fileName).inputStream.bufferedReader().readText()\n    }\n}\n\n"
  },
  {
    "path": "testSrc/com/koxudaxi/poetry/PyPoetryPackageManagerTest.kt",
    "content": "package com.koxudaxi.poetry\n\n\nimport com.jetbrains.python.fixtures.PythonMockSdk\nimport com.jetbrains.python.packaging.PyPackage\nimport com.jetbrains.python.packaging.PyRequirement\nimport com.jetbrains.python.packaging.PyRequirementParser\n\n\nclass PyPoetryPackageManagerTest : PoetryTestCase() {\n    private val testDataAsText: String\n        get() {\n            return getTestDataAsText(\"dry-run-result.txt\")\n        }\n    private fun getPyPackage(name: String, version: String) :PyPackage {\n        return PyPackage(name, version, null, emptyList())\n    }\n    fun getPyRequirement(name: String, version: String): PyRequirement? {\n        return PyRequirementParser.fromLine(\"${name}==${version}\")\n    }\n    fun testParsePoetryInstallDryRun1_0() {\n        val sdk = PythonMockSdk.create(\"3.7\")\n        val pyPoetryPackageManager = PyPoetryPackageManager(sdk)\n        val result = pyPoetryPackageManager.parsePoetryInstallDryRun(testDataAsText)\n        assertEquals(result.first.size, 3)\n        assertEquals(result.first,\n                listOf(\n                        getPyPackage(\"six\", \"1.15.0\"),\n                        getPyPackage(\"attrs\", \"20.2.0\"),\n                        getPyPackage(\"colorama\", \"0.4.3\")\n                )\n        )\n        assertEquals(result.second.size, 5)\n        assertEquals(result.second,\n                listOf(\n                        getPyRequirement(\"six\",\"1.15.0\"),\n                        getPyRequirement(\"attrs\",\"20.2.0\"),\n                        getPyRequirement(\"jmespath\",\"0.10.0\"),\n                        getPyRequirement(\"botocore\",\"1.18.18\"),\n                        getPyRequirement(\"colorama\",\"0.4.4\")\n                )\n        )\n\n    }\n    fun testParsePoetryInstallDryRun1_1() {\n        val sdk = PythonMockSdk.create(\"3.7\")\n        val pyPoetryPackageManager = PyPoetryPackageManager(sdk)\n        val result = pyPoetryPackageManager.parsePoetryInstallDryRun(testDataAsText)\n        assertEquals(result.first.size, 3)\n        assertEquals(result.first,\n                listOf(\n                        getPyPackage(\"six\", \"1.15.0\"),\n                        getPyPackage(\"attrs\", \"20.2.0\"),\n                        getPyPackage(\"colorama\", \"0.4.3\")\n                )\n        )\n        assertEquals(result.second.size, 5)\n        assertEquals(result.second,\n                listOf(\n                        getPyRequirement(\"six\",\"1.15.0\"),\n                        getPyRequirement(\"attrs\",\"20.2.0\"),\n                        getPyRequirement(\"jmespath\",\"0.10.0\"),\n                        getPyRequirement(\"botocore\",\"1.18.18\"),\n                        getPyRequirement(\"colorama\",\"0.4.4\")\n                )\n        )\n\n    }\n}"
  }
]