Merge branch 'release/v5.2.3'

This commit is contained in:
Ivan Kravets
2021-11-05 17:31:40 +02:00
86 changed files with 560 additions and 430 deletions

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[report]
# Regexes for lines to exclude from consideration
exclude_lines =
pragma: no cover
def __repr__
raise AssertionError
raise NotImplementedError

View File

@ -103,7 +103,7 @@ jobs:
- name: Deploy to Github Pages
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.PERSONAL_TOKEN }}
personal_token: ${{ secrets.DEPLOY_GH_DOCS_TOKEN }}
external_repository: ${{ env.DOCS_REPO }}
publish_dir: ./${{ env.DOCS_DIR }}
commit_message: Sync Docs

View File

@ -1,12 +0,0 @@
# See https://docs.readthedocs.io/en/stable/config-file/index.html
version: 2
sphinx:
configuration: docs/conf.py
formats:
- pdf
submodules:
include: all

View File

@ -8,20 +8,35 @@ PlatformIO Core 5
**A professional collaborative platform for embedded development**
5.2.3 (2021-11-05)
~~~~~~~~~~~~~~~~~~
- Automatically synchronize active projects between IDE and `PlatformIO Home <https://docs.platformio.org/en/latest/home/index.html>`__
- Added support for custom `device monitor filters <https://docs.platformio.org/en/latest/core/userguide/device/cmd_monitor.html#filters>`__ (`issue #3924 <https://github.com/platformio/platformio-core/issues/3924>`_)
- Show human-readable message when infinite recursion is detected while processing `Interpolation of Values <https://docs.platformio.org/en/latest/projectconf/interpolation.html>`__ (`issue #3883 <https://github.com/platformio/platformio-core/issues/3883>`_)
- Improved directory interpolation (``${platformio.***_dir}``) in `"platformio.ini" <https://docs.platformio.org/en/latest/projectconf.html>`__ configuration file (`issue #3934 <https://github.com/platformio/platformio-core/issues/3934>`_)
- Ignore resolving of SCons variables (e.g., ``${(SOURCE.get_abspath())}``) when preprocessing interpolations (`issue #3933 <https://github.com/platformio/platformio-core/issues/3933>`_)
- Added "inc" as a sign that it's the root of the library (`issue #4093 <https://github.com/platformio/platformio-core/issues/4093>`_)
- Fixed an issue when the ``$PROJECT_DIR`` variable was not properly replaced in the `debug_server <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html#debug-server>`__ option (`issue #4086 <https://github.com/platformio/platformio-core/issues/4086>`_)
- Fixed an issue when `PIO Remote <https://docs.platformio.org/en/latest/plus/pio-remote.html>`__ device monitor crashes on the first keypress (`issue #3832 <https://github.com/platformio/platformio-core/issues/3832>`_)
- Fixed "Do not know how to make File target 'debug'" issue when debugging project using `CLion IDE <https://docs.platformio.org/en/latest/integration/ide/clion.html>`__ (`pull #4089 <https://github.com/platformio/platformio-core/issues/4089>`_)
- Fixed "UnicodeEncodeError" when a build output contains non-ASCII characters (`issue #3971 <https://github.com/platformio/platformio-core/issues/3971>`_)
- Fixed an issue when VSCode's debugger does not the honor default environment (`issue #4098 <https://github.com/platformio/platformio-core/issues/4098>`_)
5.2.2 (2021-10-20)
~~~~~~~~~~~~~~~~~~
- Override debugging firmware loading mode using ``--load-mode`` option for `pio debug <https://docs.platformio.org/en/latest/core/userguide/cmd_debug.html>`__ command
- Added support for CLion IDE 2021.3 (`pull #4085 <https://github.com/platformio/platformio-core/issues/4085>`_)
- Removed debugging "legacy Click" message from CLI (`issue #4083 <https://github.com/platformio/platformio-core/issues/4083>`_)
- Fixed a "TypeError: sequence item 1: expected str instance, list found" issue when extending configuration option in `"platformio.ini" <https://docs.platformio.org/page/projectconf.html>`__ with the multi-line default value (`issue #4082 <https://github.com/platformio/platformio-core/issues/4082>`_)
- Fixed a "TypeError: sequence item 1: expected str instance, list found" issue when extending configuration option in `"platformio.ini" <https://docs.platformio.org/en/latest/projectconf.html>`__ with the multi-line default value (`issue #4082 <https://github.com/platformio/platformio-core/issues/4082>`_)
5.2.1 (2021-10-11)
~~~~~~~~~~~~~~~~~~
- Clean a build environment and installed library dependencies using a new ``cleanall`` target (`issue #4062 <https://github.com/platformio/platformio-core/issues/4062>`_)
- Override a default library builder via a new ``builder`` field in a ``build`` group of `library.json <https://docs.platformio.org/page/librarymanager/config.html#build>`__ manifest (`issue #3957 <https://github.com/platformio/platformio-core/issues/3957>`_)
- Updated `Cppcheck <https://docs.platformio.org/page/plus/check-tools/cppcheck.html>`__ v2.6 with new checks, increased reliability of advanced addons (MISRA/CERT) and various improvements
- Override a default library builder via a new ``builder`` field in a ``build`` group of `library.json <https://docs.platformio.org/en/latest/librarymanager/config.html#build>`__ manifest (`issue #3957 <https://github.com/platformio/platformio-core/issues/3957>`_)
- Updated `Cppcheck <https://docs.platformio.org/en/latest/plus/check-tools/cppcheck.html>`__ v2.6 with new checks, increased reliability of advanced addons (MISRA/CERT) and various improvements
- Handle the "test" folder as a part of CLion project (`issue #4005 <https://github.com/platformio/platformio-core/issues/4005>`_)
- Improved handling of a library root based on "Conan" or "CMake" build systems (`issue #3887 <https://github.com/platformio/platformio-core/issues/3887>`_)
- Fixed a "KeyError: Invalid board option 'build.cpu'" when using a precompiled library with a board that does not have a CPU field in the manifest (`issue #4056 <https://github.com/platformio/platformio-core/issues/4056>`_)
@ -33,11 +48,11 @@ PlatformIO Core 5
* **PlatformIO Debugging**
- Boosted `PlatformIO Debugging <https://docs.platformio.org/page/plus/debugging.html>`__ performance thanks to migrating the codebase to the pure Python 3 Asynchronous I/O stack
- `Debug unit tests <https://docs.platformio.org/page/plus/debugging.html#debug-unit-tests>`__ created with `PlatformIO Unit Testing <https://docs.platformio.org/page/plus/unit-testing.html>`__ solution (`issue #948 <https://github.com/platformio/platformio-core/issues/948>`_)
- Boosted `PlatformIO Debugging <https://docs.platformio.org/en/latest/plus/debugging.html>`__ performance thanks to migrating the codebase to the pure Python 3 Asynchronous I/O stack
- `Debug unit tests <https://docs.platformio.org/en/latest/plus/debugging.html#debug-unit-tests>`__ created with `PlatformIO Unit Testing <https://docs.platformio.org/en/latest/plus/unit-testing.html>`__ solution (`issue #948 <https://github.com/platformio/platformio-core/issues/948>`_)
- Debug native (desktop) applications on a host machine (`issue #980 <https://github.com/platformio/platformio-core/issues/980>`_)
- Support debugging on Windows using Windows CMD/CLI (`pio debug <https://docs.platformio.org/page/core/userguide/cmd_debug.html>`__) (`issue #3793 <https://github.com/platformio/platformio-core/issues/3793>`_)
- Configure a custom pattern to determine when debugging server is started with a new `debug_server_ready_pattern <https://docs.platformio.org/page/projectconf/section_env_debug.html#debug-server-ready-pattern>`__ option
- Support debugging on Windows using Windows CMD/CLI (`pio debug <https://docs.platformio.org/en/latest/core/userguide/cmd_debug.html>`__) (`issue #3793 <https://github.com/platformio/platformio-core/issues/3793>`_)
- Configure a custom pattern to determine when debugging server is started with a new `debug_server_ready_pattern <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html#debug-server-ready-pattern>`__ option
- Fixed an issue with silent hanging when a custom debug server is not found (`issue #3756 <https://github.com/platformio/platformio-core/issues/3756>`_)
* **Package Management**
@ -49,7 +64,7 @@ PlatformIO Core 5
* Check for duplicates and used version
* Validate package manifest
- Added a new option ``--non-interactive`` to `pio package publish <https://docs.platformio.org/page/core/userguide/package/cmd_publish.html>`__ command
- Added a new option ``--non-interactive`` to `pio package publish <https://docs.platformio.org/en/latest/core/userguide/package/cmd_publish.html>`__ command
* **Build System**
@ -62,9 +77,9 @@ PlatformIO Core 5
- Updated analysis tools:
* `Clang-Tidy <https://docs.platformio.org/page/plus/check-tools/clang-tidy.html>`__ v12.0.1 with new modules and extended checks list
* `Cppcheck <https://docs.platformio.org/page/plus/check-tools/cppcheck.html>`__ v2.5.0 with improved code analysis and MISRA improvements
* `PVS-Studio <https://docs.platformio.org/page/plus/check-tools/pvs-studio.html>`__ v7.14 with support for intermodular analysis, improved MISRA support and new diagnostics
* `Clang-Tidy <https://docs.platformio.org/en/latest/plus/check-tools/clang-tidy.html>`__ v12.0.1 with new modules and extended checks list
* `Cppcheck <https://docs.platformio.org/en/latest/plus/check-tools/cppcheck.html>`__ v2.5.0 with improved code analysis and MISRA improvements
* `PVS-Studio <https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html>`__ v7.14 with support for intermodular analysis, improved MISRA support and new diagnostics
* **Miscellaneous**
@ -76,7 +91,7 @@ PlatformIO Core 5
~~~~~~~~~~~~~~~~~~
* Fixed a "The command line is too long" issue with a linking process on Windows (`issue #3827 <https://github.com/platformio/platformio-core/issues/3827>`_)
* Fixed an issue with `device monitor <https://docs.platformio.org/page/core/userguide/device/cmd_monitor.html>`__ when the "send_on_enter" filter didn't send EOL chars (`issue #3787 <https://github.com/platformio/platformio-core/issues/3787>`_)
* Fixed an issue with `device monitor <https://docs.platformio.org/en/latest/core/userguide/device/cmd_monitor.html>`__ when the "send_on_enter" filter didn't send EOL chars (`issue #3787 <https://github.com/platformio/platformio-core/issues/3787>`_)
* Fixed an issue with silent mode when unwanted data is printed to stdout (`issue #3837 <https://github.com/platformio/platformio-core/issues/3837>`_)
* Fixed an issue when code inspection fails with "Bad JSON" (`issue #3790 <https://github.com/platformio/platformio-core/issues/3790>`_)
* Fixed an issue with overriding user-specified debugging configuration information in VSCode (`issue #3824 <https://github.com/platformio/platformio-core/issues/3824>`_)
@ -86,8 +101,8 @@ PlatformIO Core 5
* **PlatformIO Home**
- Boosted `PlatformIO Home <https://docs.platformio.org/page/home/index.html>`__ performance thanks to migrating the codebase to the pure Python 3 Asynchronous I/O stack
- Added a new ``--session-id`` option to `pio home <https://docs.platformio.org/page/core/userguide/cmd_home.html>`__ command that helps to keep PlatformIO Home isolated from other instances and protect from 3rd party access (`issue #3397 <https://github.com/platformio/platformio-core/issues/3397>`_)
- Boosted `PlatformIO Home <https://docs.platformio.org/en/latest/home/index.html>`__ performance thanks to migrating the codebase to the pure Python 3 Asynchronous I/O stack
- Added a new ``--session-id`` option to `pio home <https://docs.platformio.org/en/latest/core/userguide/cmd_home.html>`__ command that helps to keep PlatformIO Home isolated from other instances and protect from 3rd party access (`issue #3397 <https://github.com/platformio/platformio-core/issues/3397>`_)
* **Build System**
@ -97,28 +112,28 @@ PlatformIO Core 5
* **Package Management**
- New options for `pio system prune <https://docs.platformio.org/page/core/userguide/system/cmd_prune.html>`__ command:
- New options for `pio system prune <https://docs.platformio.org/en/latest/core/userguide/system/cmd_prune.html>`__ command:
+ ``--dry-run`` option to show data that will be removed
+ ``--core-packages`` option to remove unnecessary core packages
+ ``--platform-packages`` option to remove unnecessary development platform packages (`issue #923 <https://github.com/platformio/platformio-core/issues/923>`_)
- Added new `check_prune_system_threshold <https://docs.platformio.org/page/core/userguide/cmd_settings.html#check-prune-system-threshold>`__ setting
- Added new `check_prune_system_threshold <https://docs.platformio.org/en/latest/core/userguide/cmd_settings.html#check-prune-system-threshold>`__ setting
- Disabled automatic removal of unnecessary development platform packages (`issue #3708 <https://github.com/platformio/platformio-core/issues/3708>`_, `issue #3770 <https://github.com/platformio/platformio-core/issues/3770>`_)
- Fixed an issue when unnecessary packages were removed in ``update --dry-run`` mode (`issue #3809 <https://github.com/platformio/platformio-core/issues/3809>`_)
- Fixed a "ValueError: Invalid simple block" when uninstalling a package with a custom name and external source (`issue #3816 <https://github.com/platformio/platformio-core/issues/3816>`_)
* **Debugging**
- Configure a custom debug adapter speed using a new `debug_speed <https://docs.platformio.org/page/projectconf/section_env_debug.html#debug-speed>`__ option (`issue #3799 <https://github.com/platformio/platformio-core/issues/3799>`_)
- Configure a custom debug adapter speed using a new `debug_speed <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html#debug-speed>`__ option (`issue #3799 <https://github.com/platformio/platformio-core/issues/3799>`_)
- Handle debugging server's "ready_pattern" in "stderr" output
* **Miscellaneous**
- Improved listing of `multicast DNS services <https://docs.platformio.org/page/core/userguide/device/cmd_list.html>`_
- Improved listing of `multicast DNS services <https://docs.platformio.org/en/latest/core/userguide/device/cmd_list.html>`_
- Fixed a "UnicodeDecodeError: 'utf-8' codec can't decode byte" when using J-Link for firmware uploading on Linux (`issue #3804 <https://github.com/platformio/platformio-core/issues/3804>`_)
- Fixed an issue with a compiler driver for ".ccls" language server (`issue #3808 <https://github.com/platformio/platformio-core/issues/3808>`_)
- Fixed an issue when `pio device monitor --eol <https://docs.platformio.org/page/core/userguide/device/cmd_monitor.html#cmdoption-pio-device-monitor-eol>`__ and "send_on_enter" filter do not work properly (`issue #3787 <https://github.com/platformio/platformio-core/issues/3787>`_)
- Fixed an issue when `pio device monitor --eol <https://docs.platformio.org/en/latest/core/userguide/device/cmd_monitor.html#cmdoption-pio-device-monitor-eol>`__ and "send_on_enter" filter do not work properly (`issue #3787 <https://github.com/platformio/platformio-core/issues/3787>`_)
5.0.4 (2020-12-30)
~~~~~~~~~~~~~~~~~~
@ -127,8 +142,8 @@ PlatformIO Core 5
- Improved ".ccls" configuration file for Emacs, Vim, and Sublime Text integrations
- Updated analysis tools:
* `Cppcheck <https://docs.platformio.org/page/plus/check-tools/cppcheck.html>`__ v2.3 with improved C++ parser and several new MISRA rules
* `PVS-Studio <https://docs.platformio.org/page/plus/check-tools/pvs-studio.html>`__ v7.11 with new diagnostics and updated mass suppression mechanism
* `Cppcheck <https://docs.platformio.org/en/latest/plus/check-tools/cppcheck.html>`__ v2.3 with improved C++ parser and several new MISRA rules
* `PVS-Studio <https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html>`__ v7.11 with new diagnostics and updated mass suppression mechanism
- Show a warning message about deprecated support for Python 2 and Python 3.5
- Do not provide "intelliSenseMode" option when generating configuration for VSCode C/C++ extension
@ -138,12 +153,12 @@ PlatformIO Core 5
5.0.3 (2020-11-12)
~~~~~~~~~~~~~~~~~~
- Added an error selector for `Sublime Text <https://docs.platformio.org/page/integration/ide/sublimetext.html>`__ build runner (`issue #3733 <https://github.com/platformio/platformio-core/issues/3733>`_)
- Added an error selector for `Sublime Text <https://docs.platformio.org/en/latest/integration/ide/sublimetext.html>`__ build runner (`issue #3733 <https://github.com/platformio/platformio-core/issues/3733>`_)
- Generate a working "projectEnvName" for PlatformIO IDE's debugger for VSCode
- Force VSCode's intelliSenseMode to "gcc-x64" when GCC toolchain is used
- Print ignored test suites and environments in the test summary report only in verbose mode (`issue #3726 <https://github.com/platformio/platformio-core/issues/3726>`_)
- Fixed an issue when the package manager tries to install a built-in library from the registry (`issue #3662 <https://github.com/platformio/platformio-core/issues/3662>`_)
- Fixed an issue when `pio package pack <https://docs.platformio.org/page/core/userguide/package/cmd_pack.html>`__ ignores some folders (`issue #3730 <https://github.com/platformio/platformio-core/issues/3730>`_)
- Fixed an issue when `pio package pack <https://docs.platformio.org/en/latest/core/userguide/package/cmd_pack.html>`__ ignores some folders (`issue #3730 <https://github.com/platformio/platformio-core/issues/3730>`_)
5.0.2 (2020-10-30)
~~~~~~~~~~~~~~~~~~
@ -151,21 +166,21 @@ PlatformIO Core 5
- Initialize a new project or update the existing passing working environment name and its options (`issue #3686 <https://github.com/platformio/platformio-core/issues/3686>`_)
- Automatically build PlatformIO Core extra Python dependencies on a host machine if they are missed in the registry (`issue #3700 <https://github.com/platformio/platformio-core/issues/3700>`_)
- Improved "core.call" RPC for PlatformIO Home (`issue #3671 <https://github.com/platformio/platformio-core/issues/3671>`_)
- Fixed a "PermissionError: [WinError 5]" on Windows when an external repository is used with `lib_deps <https://docs.platformio.org/page/projectconf/section_env_library.html#lib-deps>`__ option (`issue #3664 <https://github.com/platformio/platformio-core/issues/3664>`_)
- Fixed a "PermissionError: [WinError 5]" on Windows when an external repository is used with `lib_deps <https://docs.platformio.org/en/latest/projectconf/section_env_library.html#lib-deps>`__ option (`issue #3664 <https://github.com/platformio/platformio-core/issues/3664>`_)
- Fixed a "KeyError: 'versions'" when dependency does not exist in the registry (`issue #3666 <https://github.com/platformio/platformio-core/issues/3666>`_)
- Fixed an issue with GCC linker when "native" dev-platform is used in pair with library dependencies (`issue #3669 <https://github.com/platformio/platformio-core/issues/3669>`_)
- Fixed an "AssertionError: ensure_dir_exists" when checking library updates from simultaneous subprocesses (`issue #3677 <https://github.com/platformio/platformio-core/issues/3677>`_)
- Fixed an issue when `pio package publish <https://docs.platformio.org/page/core/userguide/package/cmd_publish.html>`__ command removes original archive after submitting to the registry (`issue #3716 <https://github.com/platformio/platformio-core/issues/3716>`_)
- Fixed an issue when multiple `pio lib install <https://docs.platformio.org/page/core/userguide/lib/cmd_install.html>`__ command with the same local library results in duplicates in ``lib_deps`` (`issue #3715 <https://github.com/platformio/platformio-core/issues/3715>`_)
- Fixed an issue with a "wrong" timestamp in device monitor output using `"time" filter <https://docs.platformio.org/page/core/userguide/device/cmd_monitor.html#filters>`__ (`issue #3712 <https://github.com/platformio/platformio-core/issues/3712>`_)
- Fixed an issue when `pio package publish <https://docs.platformio.org/en/latest/core/userguide/package/cmd_publish.html>`__ command removes original archive after submitting to the registry (`issue #3716 <https://github.com/platformio/platformio-core/issues/3716>`_)
- Fixed an issue when multiple `pio lib install <https://docs.platformio.org/en/latest/core/userguide/lib/cmd_install.html>`__ command with the same local library results in duplicates in ``lib_deps`` (`issue #3715 <https://github.com/platformio/platformio-core/issues/3715>`_)
- Fixed an issue with a "wrong" timestamp in device monitor output using `"time" filter <https://docs.platformio.org/en/latest/core/userguide/device/cmd_monitor.html#filters>`__ (`issue #3712 <https://github.com/platformio/platformio-core/issues/3712>`_)
5.0.1 (2020-09-10)
~~~~~~~~~~~~~~~~~~
- Added support for "owner" requirement when declaring ``dependencies`` using `library.json <https://docs.platformio.org/page/librarymanager/config.html#dependencies>`__
- Fixed an issue when using a custom git/ssh package with `platform_packages <https://docs.platformio.org/page/projectconf/section_env_platform.html#platform-packages>`__ option (`issue #3624 <https://github.com/platformio/platformio-core/issues/3624>`_)
- Fixed an issue with "ImportError: cannot import name '_get_backend' from 'cryptography.hazmat.backends'" when using `Remote Development <https://docs.platformio.org/page/plus/pio-remote.html>`__ on RaspberryPi device (`issue #3652 <https://github.com/platformio/platformio-core/issues/3652>`_)
- Fixed an issue when `pio package unpublish <https://docs.platformio.org/page/core/userguide/package/cmd_unpublish.html>`__ command crashes (`issue #3660 <https://github.com/platformio/platformio-core/issues/3660>`_)
- Added support for "owner" requirement when declaring ``dependencies`` using `library.json <https://docs.platformio.org/en/latest/librarymanager/config.html#dependencies>`__
- Fixed an issue when using a custom git/ssh package with `platform_packages <https://docs.platformio.org/en/latest/projectconf/section_env_platform.html#platform-packages>`__ option (`issue #3624 <https://github.com/platformio/platformio-core/issues/3624>`_)
- Fixed an issue with "ImportError: cannot import name '_get_backend' from 'cryptography.hazmat.backends'" when using `Remote Development <https://docs.platformio.org/en/latest/plus/pio-remote.html>`__ on RaspberryPi device (`issue #3652 <https://github.com/platformio/platformio-core/issues/3652>`_)
- Fixed an issue when `pio package unpublish <https://docs.platformio.org/en/latest/core/userguide/package/cmd_unpublish.html>`__ command crashes (`issue #3660 <https://github.com/platformio/platformio-core/issues/3660>`_)
- Fixed an issue when the package manager tries to install a built-in library from the registry (`issue #3662 <https://github.com/platformio/platformio-core/issues/3662>`_)
- Fixed an issue with incorrect value for C++ language standard in IDE projects when an in-progress language standard is used (`issue #3653 <https://github.com/platformio/platformio-core/issues/3653>`_)
- Fixed an issue with "Invalid simple block (semantic_version)" from library dependency that refs to an external source (repository, ZIP/Tar archives) (`issue #3658 <https://github.com/platformio/platformio-core/issues/3658>`_)
@ -174,7 +189,7 @@ PlatformIO Core 5
5.0.0 (2020-09-03)
~~~~~~~~~~~~~~~~~~
Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/core/migration.html>`__.
Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/en/latest/core/migration.html>`__.
* Integration with the new **PlatformIO Trusted Registry**
@ -189,19 +204,19 @@ Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/
- Built-in fine-grained access control (role-based, teams, organizations)
- New CLI commands:
* `pio package <https://docs.platformio.org/page/core/userguide/package/index.html>`__ manage packages in the registry
* `pio access <https://docs.platformio.org/page/core/userguide/access/index.html>`__ manage package access for users, teams, and maintainers
* `pio package <https://docs.platformio.org/en/latest/core/userguide/package/index.html>`__ manage packages in the registry
* `pio access <https://docs.platformio.org/en/latest/core/userguide/access/index.html>`__ manage package access for users, teams, and maintainers
* Integration with the new **Account Management System**
- `Manage organizations <https://docs.platformio.org/page/core/userguide/org/index.html>`__
- `Manage teams and team memberships <https://docs.platformio.org/page/core/userguide/team/index.html>`__
- `Manage organizations <https://docs.platformio.org/en/latest/core/userguide/org/index.html>`__
- `Manage teams and team memberships <https://docs.platformio.org/en/latest/core/userguide/team/index.html>`__
* New **Package Management System**
- Integrated PlatformIO Core with the new PlatformIO Registry
- Support for owner-based dependency declaration (resolves name conflicts) (`issue #1824 <https://github.com/platformio/platformio-core/issues/1824>`_)
- Automatically save dependencies to `"platformio.ini" <https://docs.platformio.org/page/projectconf.html>`__ when installing using PlatformIO CLI (`issue #2964 <https://github.com/platformio/platformio-core/issues/2964>`_)
- Automatically save dependencies to `"platformio.ini" <https://docs.platformio.org/en/latest/projectconf.html>`__ when installing using PlatformIO CLI (`issue #2964 <https://github.com/platformio/platformio-core/issues/2964>`_)
- Follow SemVer complaint version constraints when checking library updates `issue #1281 <https://github.com/platformio/platformio-core/issues/1281>`_)
- Dropped support for "packageRepositories" section in "platform.json" manifest (please publish packages directly to the registry)
@ -209,29 +224,29 @@ Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/
- Upgraded build engine to the `SCons 4.0 - a next-generation software construction tool <https://scons.org/>`__
* `Configuration files are Python scripts <https://docs.platformio.org/page/projectconf/advanced_scripting.html>`__ use the power of a real programming language to solve build problems
* `Configuration files are Python scripts <https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html>`__ use the power of a real programming language to solve build problems
* Built-in reliable and automatic dependency analysis
* Improved support for parallel builds
* Ability to `share built files in a cache <https://docs.platformio.org/page/projectconf/section_platformio.html#projectconf-pio-build-cache-dir>`__ to speed up multiple builds
* Ability to `share built files in a cache <https://docs.platformio.org/en/latest/projectconf/section_platformio.html#projectconf-pio-build-cache-dir>`__ to speed up multiple builds
- New `Custom Targets <https://docs.platformio.org/page/projectconf/advanced_scripting.html#custom-targets>`__
- New `Custom Targets <https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html#custom-targets>`__
* Pre/Post processing based on dependent sources (another target, source file, etc.)
* Command launcher with own arguments
* Launch command with custom options declared in `"platformio.ini" <https://docs.platformio.org/page/projectconf.html>`__
* Launch command with custom options declared in `"platformio.ini" <https://docs.platformio.org/en/latest/projectconf.html>`__
* Python callback as a target (use the power of Python interpreter and PlatformIO Build API)
* List available project targets (including dev-platform specific and custom targets) with a new `pio run --list-targets <https://docs.platformio.org/page/core/userguide/cmd_run.html#cmdoption-platformio-run-list-targets>`__ command (`issue #3544 <https://github.com/platformio/platformio-core/issues/3544>`_)
* List available project targets (including dev-platform specific and custom targets) with a new `pio run --list-targets <https://docs.platformio.org/en/latest/core/userguide/cmd_run.html#cmdoption-platformio-run-list-targets>`__ command (`issue #3544 <https://github.com/platformio/platformio-core/issues/3544>`_)
- Enable "cyclic reference" for GCC linker only for the embedded dev-platforms (`issue #3570 <https://github.com/platformio/platformio-core/issues/3570>`_)
- Automatically enable LDF dependency `chain+ mode (evaluates C/C++ Preprocessor conditional syntax) <https://docs.platformio.org/page/librarymanager/ldf.html#dependency-finder-mode>`__ for Arduino library when "library.property" has "depends" field (`issue #3607 <https://github.com/platformio/platformio-core/issues/3607>`_)
- Automatically enable LDF dependency `chain+ mode (evaluates C/C++ Preprocessor conditional syntax) <https://docs.platformio.org/en/latest/librarymanager/ldf.html#dependency-finder-mode>`__ for Arduino library when "library.property" has "depends" field (`issue #3607 <https://github.com/platformio/platformio-core/issues/3607>`_)
- Fixed an issue with improper processing of source files added via multiple Build Middlewares (`issue #3531 <https://github.com/platformio/platformio-core/issues/3531>`_)
- Fixed an issue with the ``clean`` target on Windows when project and build directories are located on different logical drives (`issue #3542 <https://github.com/platformio/platformio-core/issues/3542>`_)
* **Project Management**
- Added support for "globstar/`**`" (recursive) pattern for the different commands and configuration options (`pio ci <https://docs.platformio.org/page/core/userguide/cmd_ci.html>`__, `src_filter <https://docs.platformio.org/page/projectconf/section_env_build.html#src-filter>`__, `check_patterns <https://docs.platformio.org/page/projectconf/section_env_check.html#check-patterns>`__, `library.json > srcFilter <https://docs.platformio.org/page/librarymanager/config.html#srcfilter>`__). Python 3.5+ is required
- Added a new ``-e, --environment`` option to `pio project init <https://docs.platformio.org/page/core/userguide/project/cmd_init.html#cmdoption-platformio-project-init-e>`__ command that helps to update a PlatformIO project using the existing environment
- Dump build system data intended for IDE extensions/plugins using a new `pio project data <https://docs.platformio.org/page/core/userguide/project/cmd_data.html>`__ command
- Added support for "globstar/`**`" (recursive) pattern for the different commands and configuration options (`pio ci <https://docs.platformio.org/en/latest/core/userguide/cmd_ci.html>`__, `src_filter <https://docs.platformio.org/en/latest/projectconf/section_env_build.html#src-filter>`__, `check_patterns <https://docs.platformio.org/en/latest/projectconf/section_env_check.html#check-patterns>`__, `library.json > srcFilter <https://docs.platformio.org/en/latest/librarymanager/config.html#srcfilter>`__). Python 3.5+ is required
- Added a new ``-e, --environment`` option to `pio project init <https://docs.platformio.org/en/latest/core/userguide/project/cmd_init.html#cmdoption-platformio-project-init-e>`__ command that helps to update a PlatformIO project using the existing environment
- Dump build system data intended for IDE extensions/plugins using a new `pio project data <https://docs.platformio.org/en/latest/core/userguide/project/cmd_data.html>`__ command
- Do not generate ".travis.yml" for a new project, let the user have a choice
* **Unit Testing**
@ -244,16 +259,16 @@ Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/
- Updated analysis tools:
* `Cppcheck <https://docs.platformio.org/page/plus/check-tools/cppcheck.html>`__ v2.1 with a new "soundy" analysis option and improved code parser
* `PVS-Studio <https://docs.platformio.org/page/plus/check-tools/pvs-studio.html>`__ v7.09 with a new file list analysis mode and an extended list of analysis diagnostics
* `Cppcheck <https://docs.platformio.org/en/latest/plus/check-tools/cppcheck.html>`__ v2.1 with a new "soundy" analysis option and improved code parser
* `PVS-Studio <https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html>`__ v7.09 with a new file list analysis mode and an extended list of analysis diagnostics
- Added Cppcheck package for ARM-based single-board computers (`issue #3559 <https://github.com/platformio/platformio-core/issues/3559>`_)
- Fixed an issue with PIO Check when a defect with a multiline error message is not reported in verbose mode (`issue #3631 <https://github.com/platformio/platformio-core/issues/3631>`_)
* **Miscellaneous**
- Display system-wide information using a new `pio system info <https://docs.platformio.org/page/core/userguide/system/cmd_info.html>`__ command (`issue #3521 <https://github.com/platformio/platformio-core/issues/3521>`_)
- Remove unused data using a new `pio system prune <https://docs.platformio.org/page/core/userguide/system/cmd_prune.html>`__ command (`issue #3522 <https://github.com/platformio/platformio-core/issues/3522>`_)
- Display system-wide information using a new `pio system info <https://docs.platformio.org/en/latest/core/userguide/system/cmd_info.html>`__ command (`issue #3521 <https://github.com/platformio/platformio-core/issues/3521>`_)
- Remove unused data using a new `pio system prune <https://docs.platformio.org/en/latest/core/userguide/system/cmd_prune.html>`__ command (`issue #3522 <https://github.com/platformio/platformio-core/issues/3522>`_)
- Show ignored project environments only in the verbose mode (`issue #3641 <https://github.com/platformio/platformio-core/issues/3641>`_)
- Do not escape compiler arguments in VSCode template on Windows
- Drop support for Python 2 and 3.5.

2
docs

Submodule docs updated: 66f67cb335...fed771ae8d

View File

@ -14,7 +14,7 @@
import sys
VERSION = (5, 2, 2)
VERSION = (5, 2, 3)
__version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio"
@ -47,7 +47,7 @@ __pioremote_endpoint__ = "ssl:host=remote.platformio.org:port=4413"
__default_requests_timeout__ = (10, None) # (connect, read)
__core_packages__ = {
"contrib-piohome": "~3.3.4",
"contrib-piohome": "~3.4.0",
"contrib-pysite": "~2.%d%d.0" % (sys.version_info.major, sys.version_info.minor),
"tool-unity": "~1.20500.0",
"tool-scons": "~4.40200.0",

View File

@ -21,17 +21,17 @@ import os
import platform
import socket
import uuid
from os.path import dirname, isdir, isfile, join, realpath
from platformio import __version__, exception, fs, proc
from platformio.compat import IS_WINDOWS, hashlib_encode_data
from platformio.package.lockfile import LockFile
from platformio.project.helpers import get_default_projects_dir, get_project_core_dir
from platformio.project.config import ProjectConfig
from platformio.project.helpers import get_default_projects_dir
def projects_dir_validate(projects_dir):
assert isdir(projects_dir)
return realpath(projects_dir)
assert os.path.isdir(projects_dir)
return os.path.realpath(projects_dir)
DEFAULT_SETTINGS = {
@ -64,7 +64,7 @@ DEFAULT_SETTINGS = {
"value": True,
},
"enable_telemetry": {
"description": ("Telemetry service <http://bit.ly/pio-telemetry> (Yes/No)"),
"description": ("Telemetry service <https://bit.ly/pio-telemetry> (Yes/No)"),
"value": True,
},
"force_verbose": {
@ -91,7 +91,10 @@ class State(object):
self.path = path
self.lock = lock
if not self.path:
self.path = join(get_project_core_dir(), "appstate.json")
core_dir = ProjectConfig.get_instance().get("platformio", "core_dir")
if not os.path.isdir(core_dir):
os.makedirs(core_dir)
self.path = os.path.join(core_dir, "appstate.json")
self._storage = {}
self._lockfile = None
self.modified = False
@ -99,7 +102,7 @@ class State(object):
def __enter__(self):
try:
self._lock_state_file()
if isfile(self.path):
if os.path.isfile(self.path):
self._storage = fs.load_json(self.path)
assert isinstance(self._storage, dict)
except (
@ -117,7 +120,7 @@ class State(object):
with open(self.path, mode="w", encoding="utf8") as fp:
fp.write(json.dumps(self._storage))
except IOError:
raise exception.HomeDirPermissionsError(get_project_core_dir())
raise exception.HomeDirPermissionsError(os.path.dirname(self.path))
self._unlock_state_file()
def _lock_state_file(self):
@ -127,7 +130,7 @@ class State(object):
try:
self._lockfile.acquire()
except IOError:
raise exception.HomeDirPermissionsError(dirname(self.path))
raise exception.HomeDirPermissionsError(os.path.dirname(self.path))
def _unlock_state_file(self):
if hasattr(self, "_lockfile") and self._lockfile:

View File

@ -109,22 +109,22 @@ env.Replace(
config = env.GetProjectConfig()
env.Replace(
PROJECT_DIR=get_project_dir(),
PROJECT_CORE_DIR=config.get_optional_dir("core"),
PROJECT_PACKAGES_DIR=config.get_optional_dir("packages"),
PROJECT_WORKSPACE_DIR=config.get_optional_dir("workspace"),
PROJECT_LIBDEPS_DIR=config.get_optional_dir("libdeps"),
PROJECT_INCLUDE_DIR=config.get_optional_dir("include"),
PROJECT_SRC_DIR=config.get_optional_dir("src"),
PROJECTSRC_DIR=config.get_optional_dir("src"), # legacy for dev/platform
PROJECT_TEST_DIR=config.get_optional_dir("test"),
PROJECT_DATA_DIR=config.get_optional_dir("data"),
PROJECTDATA_DIR=config.get_optional_dir("data"), # legacy for dev/platform
PROJECT_BUILD_DIR=config.get_optional_dir("build"),
BUILD_CACHE_DIR=config.get_optional_dir("build_cache"),
PROJECT_CORE_DIR=config.get("platformio", "core_dir"),
PROJECT_PACKAGES_DIR=config.get("platformio", "packages_dir"),
PROJECT_WORKSPACE_DIR=config.get("platformio", "workspace_dir"),
PROJECT_LIBDEPS_DIR=config.get("platformio", "libdeps_dir"),
PROJECT_INCLUDE_DIR=config.get("platformio", "include_dir"),
PROJECT_SRC_DIR=config.get("platformio", "src_dir"),
PROJECTSRC_DIR=config.get("platformio", "src_dir"), # legacy for dev/platform
PROJECT_TEST_DIR=config.get("platformio", "test_dir"),
PROJECT_DATA_DIR=config.get("platformio", "data_dir"),
PROJECTDATA_DIR=config.get("platformio", "data_dir"), # legacy for dev/platform
PROJECT_BUILD_DIR=config.get("platformio", "build_dir"),
BUILD_CACHE_DIR=config.get("platformio", "build_cache_dir"),
LIBSOURCE_DIRS=[
config.get_optional_dir("lib"),
config.get("platformio", "lib_dir"),
os.path.join("$PROJECT_LIBDEPS_DIR", "$PIOENV"),
config.get_optional_dir("globallib"),
config.get("platformio", "globallib_dir"),
],
)

View File

@ -63,7 +63,7 @@ def _dump_includes(env):
# include Unity framework if there are tests in project
includes["unity"] = []
auto_install_unity = False
test_dir = env.GetProjectConfig().get_optional_dir("test")
test_dir = env.GetProjectConfig().get("platformio", "test_dir")
if os.path.isdir(test_dir) and os.listdir(test_dir) != ["README"]:
auto_install_unity = True
unity_dir = get_core_package_dir(

View File

@ -1095,7 +1095,7 @@ def ConfigureProjectLibBuilder(env):
project = ProjectAsLibBuilder(env, "$PROJECT_DIR")
ldf_mode = LibBuilderBase.lib_ldf_mode.fget(project) # pylint: disable=no-member
click.echo("LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf")
click.echo("LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf")
click.echo(
"LDF Modes: Finder ~ %s, Compatibility ~ %s"
% (ldf_mode, project.lib_compat_mode)

View File

@ -106,8 +106,8 @@ def cli(
)
default_patterns = [
config.get_optional_dir("src"),
config.get_optional_dir("include"),
config.get("platformio", "src_dir"),
config.get("platformio", "include_dir"),
]
tool_options = dict(
verbose=verbose,

View File

@ -77,7 +77,7 @@ class ClangtidyCheckTool(CheckToolBase):
includes = []
for inc in self.cpp_includes:
if self.options.get("skip_packages") and inc.lower().startswith(
self.config.get_optional_dir("packages").lower()
self.config.get("platformio", "packages_dir").lower()
):
continue
includes.append(inc)

View File

@ -84,7 +84,7 @@ class CppcheckCheckTool(CheckToolBase):
if (
args.get("file", "")
.lower()
.startswith(self.config.get_optional_dir("packages").lower())
.startswith(self.config.get("platformio", "packages_dir").lower())
):
if args["id"] in breaking_defect_ids:
if self.options.get("verbose"):
@ -201,7 +201,7 @@ class CppcheckCheckTool(CheckToolBase):
result = []
for inc in self.cpp_includes:
if self.options.get("skip_packages") and inc.lower().startswith(
self.config.get_optional_dir("packages").lower()
self.config.get("platformio", "packages_dir").lower()
):
continue
result.append(inc)

View File

@ -43,7 +43,7 @@ class PvsStudioCheckTool(CheckToolBase): # pylint: disable=too-many-instance-at
with open(self._tmp_cfg_file, mode="w", encoding="utf8") as fp:
fp.write(
"exclude-path = "
+ self.config.get_optional_dir("packages").replace("\\", "/")
+ self.config.get("platformio", "packages_dir").replace("\\", "/")
)
with open(self._tmp_cmd_file, mode="w", encoding="utf8") as fp:

View File

@ -172,28 +172,21 @@ def device_list( # pylint: disable=too-many-branches
help="Load configuration from `platformio.ini` and specified environment",
)
def device_monitor(**kwargs): # pylint: disable=too-many-branches
# load default monitor filters
filters_dir = os.path.join(fs.get_source_dir(), "commands", "device", "filters")
for name in os.listdir(filters_dir):
if not name.endswith(".py"):
continue
device_helpers.load_monitor_filter(
os.path.join(filters_dir, name), options=kwargs
)
project_options = {}
platform = None
try:
with fs.cd(kwargs["project_dir"]):
project_options = device_helpers.get_project_options(kwargs["environment"])
kwargs = device_helpers.apply_project_monitor_options(kwargs, project_options)
kwargs = device_helpers.apply_project_monitor_options(
kwargs, project_options
)
if "platform" in project_options:
platform = PlatformFactory.new(project_options["platform"])
except NotPlatformIOProjectError:
pass
platform = None
if "platform" in project_options:
with fs.cd(kwargs["project_dir"]):
platform = PlatformFactory.new(project_options["platform"])
device_helpers.register_platform_filters(platform, options=kwargs)
device_helpers.register_filters(platform=platform, options=kwargs)
if not kwargs["port"]:
ports = util.get_serial_ports(filter_hwid=True)
@ -231,7 +224,7 @@ def device_monitor(**kwargs): # pylint: disable=too-many-branches
"--- Available filters and text transformations: %s"
% ", ".join(sorted(miniterm.TRANSFORMATIONS.keys()))
)
click.echo("--- More details at http://bit.ly/pio-monitor-filters")
click.echo("--- More details at https://bit.ly/pio-monitor-filters")
try:
miniterm.main(
default_port=kwargs["port"],

View File

@ -20,6 +20,7 @@ from serial.tools import miniterm
from platformio import fs
from platformio.commands.device import DeviceMonitorFilter
from platformio.compat import get_object_members, load_python_module
from platformio.package.manager.tool import ToolPackageManager
from platformio.project.config import ProjectConfig
@ -92,15 +93,40 @@ def load_monitor_filter(path, options=None):
return True
def register_platform_filters(platform, options=None):
monitor_dir = os.path.join(platform.get_dir(), "monitor")
def load_monitor_filters(monitor_dir, prefix=None, options=None):
if not os.path.isdir(monitor_dir):
return
for name in os.listdir(monitor_dir):
if not name.startswith("filter_") or not name.endswith(".py"):
if (prefix and not name.startswith(prefix)) or not name.endswith(".py"):
continue
path = os.path.join(monitor_dir, name)
if not os.path.isfile(path):
continue
load_monitor_filter(path, options)
def register_filters(platform=None, options=None):
# project filters
load_monitor_filters(
ProjectConfig.get_instance().get("platformio", "monitor_dir"),
prefix="filter_",
options=options,
)
# platform filters
if platform:
load_monitor_filters(
os.path.join(platform.get_dir(), "monitor"),
prefix="filter_",
options=options,
)
# load package filters
pm = ToolPackageManager()
for pkg in pm.get_installed():
load_monitor_filters(
os.path.join(pkg.path, "monitor"), prefix="filter_", options=options
)
# default filters
load_monitor_filters(
os.path.join(fs.get_source_dir(), "commands", "device", "filters"),
options=options,
)

View File

@ -14,16 +14,16 @@
from __future__ import absolute_import
from os.path import join
import os
from pathlib import Path
from platformio import __version__, app, fs, util
from platformio.project.helpers import get_project_core_dir, is_platformio_project
from platformio.project.config import ProjectConfig
from platformio.project.helpers import is_platformio_project
class AppRPC:
APPSTATE_PATH = join(get_project_core_dir(), "homestate.json")
IGNORE_STORAGE_KEYS = [
"cid",
"coreVersion",
@ -34,9 +34,16 @@ class AppRPC:
"projectsDir",
]
@staticmethod
def get_state_path():
core_dir = ProjectConfig.get_instance().get("platformio", "core_dir")
if not os.path.isdir(core_dir):
os.makedirs(core_dir)
return os.path.join(core_dir, "homestate.json")
@staticmethod
def load_state():
with app.State(AppRPC.APPSTATE_PATH, lock=True) as state:
with app.State(AppRPC.get_state_path(), lock=True) as state:
storage = state.get("storage", {})
# base data
@ -58,9 +65,13 @@ class AppRPC:
storage["projectsDir"] = storage["coreSettings"]["projects_dir"]["value"]
# skip non-existing recent projects
storage["recentProjects"] = [
p for p in storage.get("recentProjects", []) if is_platformio_project(p)
]
storage["recentProjects"] = list(
set(
str(Path(p).resolve())
for p in storage.get("recentProjects", [])
if is_platformio_project(p)
)
)
state["storage"] = storage
state.modified = False # skip saving extra fields
@ -72,7 +83,7 @@ class AppRPC:
@staticmethod
def save_state(state):
with app.State(AppRPC.APPSTATE_PATH, lock=True) as s:
with app.State(AppRPC.get_state_path(), lock=True) as s:
s.clear()
s.update(state)
storage = s.get("storage", {})

View File

@ -13,6 +13,7 @@
# limitations under the License.
import time
from pathlib import Path
from ajsonrpc.core import JSONRPC20DispatchException
@ -20,29 +21,65 @@ from platformio.compat import aio_get_running_loop
class IDERPC:
def __init__(self):
self._queue = {}
def send_command(self, sid, command, params):
if not self._queue.get(sid):
raise JSONRPC20DispatchException(
COMMAND_TIMEOUT = 1.5 # in seconds
def __init__(self):
self._ide_queue = []
self._cmd_queue = {}
async def listen_commands(self):
f = aio_get_running_loop().create_future()
self._ide_queue.append(f)
self._process_commands()
return await f
async def send_command(self, command, params=None):
cmd_id = f"ide-{command}-{time.time()}"
self._cmd_queue[cmd_id] = {
"method": command,
"params": params,
"time": time.time(),
"future": aio_get_running_loop().create_future(),
}
self._process_commands()
# in case if IDE agent has not been started
aio_get_running_loop().call_later(
self.COMMAND_TIMEOUT + 0.1, self._process_commands
)
return await self._cmd_queue[cmd_id]["future"]
def on_command_result(self, cmd_id, value):
if cmd_id not in self._cmd_queue:
return
if self._cmd_queue[cmd_id]["method"] == "get_pio_project_dirs":
value = [str(Path(p).resolve()) for p in value]
self._cmd_queue[cmd_id]["future"].set_result(value)
del self._cmd_queue[cmd_id]
def _process_commands(self):
for cmd_id in list(self._cmd_queue):
cmd_data = self._cmd_queue[cmd_id]
if cmd_data["future"].done():
del self._cmd_queue[cmd_id]
continue
if (
not self._ide_queue
and (time.time() - cmd_data["time"]) > self.COMMAND_TIMEOUT
):
cmd_data["future"].set_exception(
JSONRPC20DispatchException(
code=4005, message="PIO Home IDE agent is not started"
)
while self._queue[sid]:
self._queue[sid].pop().set_result(
{"id": time.time(), "method": command, "params": params}
)
continue
async def listen_commands(self, sid=0):
if sid not in self._queue:
self._queue[sid] = []
self._queue[sid].append(aio_get_running_loop().create_future())
return await self._queue[sid][-1]
def open_project(self, sid, project_dir):
return self.send_command(sid, "open_project", project_dir)
def open_text_document(self, sid, path, line=None, column=None):
return self.send_command(
sid, "open_text_document", dict(path=path, line=line, column=column)
while self._ide_queue:
self._ide_queue.pop().set_result(
{
"id": cmd_id,
"method": cmd_data["method"],
"params": cmd_data["params"],
}
)

View File

@ -23,10 +23,10 @@ from ajsonrpc.core import JSONRPC20DispatchException
from platformio import exception, fs
from platformio.commands.home.rpc.handlers.app import AppRPC
from platformio.commands.home.rpc.handlers.piocore import PIOCoreRPC
from platformio.ide.projectgenerator import ProjectGenerator
from platformio.package.manager.platform import PlatformPackageManager
from platformio.project.config import ProjectConfig
from platformio.project.exception import ProjectError
from platformio.project.generator import ProjectGenerator
from platformio.project.helpers import get_project_dir, is_platformio_project
from platformio.project.options import get_config_options_schema
@ -81,7 +81,7 @@ class ProjectRPC:
data["description"] = config.get("platformio", "description")
data["libExtraDirs"].extend(config.get("platformio", "lib_extra_dirs", []))
libdeps_dir = config.get_optional_dir("libdeps")
libdeps_dir = config.get("platformio", "libdeps_dir")
for section in config.sections():
if not section.startswith("env:"):
continue
@ -253,7 +253,7 @@ class ProjectRPC:
with fs.cd(project_dir):
config = ProjectConfig()
src_dir = config.get_optional_dir("src")
src_dir = config.get("platformio", "src_dir")
main_path = os.path.join(
src_dir, "main.%s" % ("cpp" if is_cpp_project else "c")
)
@ -308,7 +308,7 @@ class ProjectRPC:
)
with fs.cd(project_dir):
config = ProjectConfig()
src_dir = config.get_optional_dir("src")
src_dir = config.get("platformio", "src_dir")
if os.path.isdir(src_dir):
fs.rmtree(src_dir)
shutil.copytree(arduino_project_dir, src_dir, symlinks=True)

View File

@ -35,7 +35,7 @@ class JSONRPCServerFactoryBase:
def __call__(self, *args, **kwargs):
raise NotImplementedError
def addObjectHandler(self, handler, namespace):
def add_object_handler(self, handler, namespace):
self.manager.dispatcher.add_object(handler, prefix="%s." % namespace)
def on_client_connect(self):

View File

@ -65,13 +65,13 @@ def run_server(host, port, no_open, shutdown_timeout, home_url):
raise PlatformioException("Invalid path to PIO Home Contrib")
ws_rpc_factory = WebSocketJSONRPCServerFactory(shutdown_timeout)
ws_rpc_factory.addObjectHandler(AccountRPC(), namespace="account")
ws_rpc_factory.addObjectHandler(AppRPC(), namespace="app")
ws_rpc_factory.addObjectHandler(IDERPC(), namespace="ide")
ws_rpc_factory.addObjectHandler(MiscRPC(), namespace="misc")
ws_rpc_factory.addObjectHandler(OSRPC(), namespace="os")
ws_rpc_factory.addObjectHandler(PIOCoreRPC(), namespace="core")
ws_rpc_factory.addObjectHandler(ProjectRPC(), namespace="project")
ws_rpc_factory.add_object_handler(AccountRPC(), namespace="account")
ws_rpc_factory.add_object_handler(AppRPC(), namespace="app")
ws_rpc_factory.add_object_handler(IDERPC(), namespace="ide")
ws_rpc_factory.add_object_handler(MiscRPC(), namespace="misc")
ws_rpc_factory.add_object_handler(OSRPC(), namespace="os")
ws_rpc_factory.add_object_handler(PIOCoreRPC(), namespace="core")
ws_rpc_factory.add_object_handler(ProjectRPC(), namespace="project")
path = urlparse(home_url).path
routes = [

View File

@ -43,7 +43,7 @@ CTX_META_STORAGE_LIBDEPS_KEY = __name__ + ".storage_lib_deps"
def get_project_global_lib_dir():
return ProjectConfig.get_instance().get_optional_dir("globallib")
return ProjectConfig.get_instance().get("platformio", "globallib_dir")
@click.group(short_help="Library manager")
@ -111,7 +111,7 @@ def cli(ctx, **options):
os.path.join(storage_dir, "platformio.ini")
)
config.validate(options["environment"], silent=in_silence)
libdeps_dir = config.get_optional_dir("libdeps")
libdeps_dir = config.get("platformio", "libdeps_dir")
for env in config.envs():
if options["environment"] and env not in options["environment"]:
continue

View File

@ -22,11 +22,11 @@ from tabulate import tabulate
from platformio import fs
from platformio.commands.platform import platform_install as cli_platform_install
from platformio.ide.projectgenerator import ProjectGenerator
from platformio.package.manager.platform import PlatformPackageManager
from platformio.platform.exception import UnknownBoard
from platformio.project.config import ProjectConfig
from platformio.project.exception import NotPlatformIOProjectError
from platformio.project.generator import ProjectGenerator
from platformio.project.helpers import is_platformio_project, load_project_ide_data
@ -191,10 +191,7 @@ def project_init(
os.path.join(project_dir, "platformio.ini")
)
config.validate()
pg = ProjectGenerator(
config, environment or get_best_envname(config, board), ide
)
pg.generate()
ProjectGenerator(config, environment, ide, board).generate()
if is_new_project:
init_cvs_ignore(project_dir)
@ -226,10 +223,10 @@ def init_base_project(project_dir):
config = ProjectConfig()
config.save()
dir_to_readme = [
(config.get_optional_dir("src"), None),
(config.get_optional_dir("include"), init_include_readme),
(config.get_optional_dir("lib"), init_lib_readme),
(config.get_optional_dir("test"), init_test_readme),
(config.get("platformio", "src_dir"), None),
(config.get("platformio", "include_dir"), init_include_readme),
(config.get("platformio", "lib_dir"), init_lib_readme),
(config.get("platformio", "test_dir"), init_test_readme),
]
for (path, cb) in dir_to_readme:
if os.path.isdir(path):
@ -441,23 +438,3 @@ def update_project_env(project_dir, environment, project_option):
config.set(section, _name.strip(), _value.strip())
config.save()
def get_best_envname(config, board_ids=None):
envname = None
default_envs = config.default_envs()
if default_envs:
envname = default_envs[0]
if not board_ids:
return envname
for env in config.envs():
if not board_ids:
return env
if not envname:
envname = env
items = config.items(env=env, as_dict=True)
if "board" in items and items.get("board") in board_ids:
return env
return envname

View File

@ -13,7 +13,6 @@
# limitations under the License.
import os
from os.path import getatime, getmtime, isdir, isfile, join
from twisted.logger import LogLevel # pylint: disable=import-error
from twisted.spread import pb # pylint: disable=import-error
@ -25,15 +24,16 @@ from platformio.commands.remote.ac.serial import SerialPortAsyncCmd
from platformio.commands.remote.client.base import RemoteClientBase
from platformio.project.config import ProjectConfig
from platformio.project.exception import NotPlatformIOProjectError
from platformio.project.helpers import get_project_core_dir
class RemoteAgentService(RemoteClientBase):
def __init__(self, name, share, working_dir=None):
RemoteClientBase.__init__(self)
self.log_level = LogLevel.info
self.working_dir = working_dir or join(get_project_core_dir(), "remote")
if not isdir(self.working_dir):
self.working_dir = working_dir or os.path.join(
ProjectConfig.get_instance().get("platformio", "core_dir"), "remote"
)
if not os.path.isdir(self.working_dir):
os.makedirs(self.working_dir)
if name:
self.name = str(name)[:50]
@ -138,14 +138,14 @@ class RemoteAgentService(RemoteClientBase):
self, command, options
):
assert options and "project_id" in options
project_dir = join(self.working_dir, "projects", options["project_id"])
origin_pio_ini = join(project_dir, "platformio.ini")
back_pio_ini = join(project_dir, "platformio.ini.bak")
project_dir = os.path.join(self.working_dir, "projects", options["project_id"])
origin_pio_ini = os.path.join(project_dir, "platformio.ini")
back_pio_ini = os.path.join(project_dir, "platformio.ini.bak")
# remove insecure project options
try:
conf = ProjectConfig(origin_pio_ini)
if isfile(back_pio_ini):
if os.path.isfile(back_pio_ini):
os.remove(back_pio_ini)
os.rename(origin_pio_ini, back_pio_ini)
# cleanup
@ -159,7 +159,10 @@ class RemoteAgentService(RemoteClientBase):
conf.save(origin_pio_ini)
# restore A/M times
os.utime(origin_pio_ini, (getatime(back_pio_ini), getmtime(back_pio_ini)))
os.utime(
origin_pio_ini,
(os.path.getatime(back_pio_ini), os.path.getmtime(back_pio_ini)),
)
except NotPlatformIOProjectError as e:
raise pb.Error(str(e))
@ -194,8 +197,8 @@ class RemoteAgentService(RemoteClientBase):
paused_acs.append(ac)
def _cb_on_end():
if isfile(back_pio_ini):
if isfile(origin_pio_ini):
if os.path.isfile(back_pio_ini):
if os.path.isfile(origin_pio_ini):
os.remove(origin_pio_ini)
os.rename(back_pio_ini, origin_pio_ini)
for ac in paused_acs:

View File

@ -84,7 +84,7 @@ class DeviceMonitorClient( # pylint: disable=too-many-instance-attributes
self._ac_id = None
self._d_acread = None
self._d_acwrite = None
self._acwrite_buffer = ""
self._acwrite_buffer = b""
def agent_pool_ready(self):
d = task.deferLater(
@ -226,7 +226,7 @@ class DeviceMonitorClient( # pylint: disable=too-many-instance-attributes
return
data = self._acwrite_buffer
self._acwrite_buffer = ""
self._acwrite_buffer = b""
try:
d = self.agentpool.callRemote("acwrite", self._agent_id, self._ac_id, data)
d.addCallback(self.cb_acwrite_result)
@ -237,4 +237,4 @@ class DeviceMonitorClient( # pylint: disable=too-many-instance-attributes
def cb_acwrite_result(self, result):
assert result > 0
if self._acwrite_buffer:
self.acwrite_data("")
self.acwrite_data(b"")

View File

@ -69,8 +69,8 @@ class RunOrTestClient(AsyncClientBase):
os.path.join(self.options["project_dir"], "platformio.ini")
)
psync.add_item(cfg.path, "platformio.ini")
psync.add_item(cfg.get_optional_dir("shared"), "shared")
psync.add_item(cfg.get_optional_dir("boards"), "boards")
psync.add_item(cfg.get("platformio", "shared_dir"), "shared")
psync.add_item(cfg.get("platformio", "boards_dir"), "boards")
if self.options["force_remote"]:
self._add_project_source_items(cfg, psync)
@ -78,26 +78,26 @@ class RunOrTestClient(AsyncClientBase):
self._add_project_binary_items(cfg, psync)
if self.command == "test":
psync.add_item(cfg.get_optional_dir("test"), "test")
psync.add_item(cfg.get("platformio", "test_dir"), "test")
def _add_project_source_items(self, cfg, psync):
psync.add_item(cfg.get_optional_dir("lib"), "lib")
psync.add_item(cfg.get("platformio", "lib_dir"), "lib")
psync.add_item(
cfg.get_optional_dir("include"),
cfg.get("platformio", "include_dir"),
"include",
cb_filter=self._cb_tarfile_filter,
)
psync.add_item(
cfg.get_optional_dir("src"), "src", cb_filter=self._cb_tarfile_filter
cfg.get("platformio", "src_dir"), "src", cb_filter=self._cb_tarfile_filter
)
if set(["buildfs", "uploadfs", "uploadfsota"]) & set(
self.options.get("target", [])
):
psync.add_item(cfg.get_optional_dir("data"), "data")
psync.add_item(cfg.get("platformio", "data_dir"), "data")
@staticmethod
def _add_project_binary_items(cfg, psync):
build_dir = cfg.get_optional_dir("build")
build_dir = cfg.get("platformio", "build_dir")
for env_name in os.listdir(build_dir):
env_dir = os.path.join(build_dir, env_name)
if not os.path.isdir(env_dir):

View File

@ -101,7 +101,7 @@ def cli(
# clean obsolete build dir
if not disable_auto_clean:
build_dir = config.get_optional_dir("build")
build_dir = config.get("platformio", "build_dir")
try:
clean_build_dir(build_dir, config)
except: # pylint: disable=bare-except

View File

@ -23,8 +23,8 @@ from platformio.project.helpers import compute_project_checksum, get_project_dir
def handle_legacy_libdeps(project_dir, config):
legacy_libdeps_dir = join(project_dir, ".piolibdeps")
if not isdir(legacy_libdeps_dir) or legacy_libdeps_dir == config.get_optional_dir(
"libdeps"
if not isdir(legacy_libdeps_dir) or legacy_libdeps_dir == config.get(
"platformio", "libdeps_dir"
):
return
if not config.has_section("env"):

View File

@ -64,7 +64,7 @@ def system_info(json_output):
}
data["core_dir"] = {
"title": "PlatformIO Core Directory",
"value": project_config.get_optional_dir("core"),
"value": project_config.get("platformio", "core_dir"),
}
data["platformio_exe"] = {
"title": "PlatformIO Core Executable",
@ -88,7 +88,7 @@ def system_info(json_output):
"title": "Tools & Toolchains",
"value": len(
ToolPackageManager(
project_config.get_optional_dir("packages")
project_config.get("platformio", "packages_dir")
).get_installed()
),
}

View File

@ -18,7 +18,7 @@ from platformio import exception
def get_test_names(config):
test_dir = config.get_optional_dir("test")
test_dir = config.get("platformio", "test_dir")
if not os.path.isdir(test_dir):
raise exception.TestDirNotExists(test_dir)
names = []

View File

@ -31,7 +31,7 @@ class NativeTestProcessor(TestProcessorBase):
return self.run()
def run(self):
build_dir = self.options["project_config"].get_optional_dir("build")
build_dir = self.options["project_config"].get("platformio", "build_dir")
result = proc.exec_command(
[join(build_dir, self.env_name, "program")],
stdout=LineBufferedAsyncPipe(self.on_run_out),

View File

@ -124,7 +124,7 @@ class TestProcessorBase(object):
def build_or_upload(self, target):
if not self._output_file_generated:
self.generate_output_file(
self.options["project_config"].get_optional_dir("test")
self.options["project_config"].get("platformio", "test_dir")
)
self._output_file_generated = True

View File

@ -20,7 +20,7 @@ from platformio.compat import string_types
from platformio.debug.exception import DebugInvalidOptionsError
from platformio.debug.helpers import reveal_debug_port
from platformio.project.config import ProjectConfig
from platformio.project.helpers import get_project_core_dir, load_project_ide_data
from platformio.project.helpers import load_project_ide_data
from platformio.project.options import ProjectOptions
@ -208,9 +208,9 @@ class DebugConfigBase: # pylint: disable=too-many-instance-attributes
def reveal_patterns(self, source, recursive=True):
program_path = self.program_path or ""
patterns = {
"PLATFORMIO_CORE_DIR": get_project_core_dir(),
"PLATFORMIO_CORE_DIR": self.project_config.get("platformio", "core_dir"),
"PYTHONEXE": proc.get_pythonexe_path(),
"PROJECT_DIR": self.project_config.path,
"PROJECT_DIR": os.getcwd(),
"PROG_PATH": program_path,
"PROG_DIR": os.path.dirname(program_path),
"PROG_NAME": os.path.basename(os.path.splitext(program_path)[0]),

View File

@ -98,7 +98,7 @@ class GDBClientProcess(DebugClientProcess):
]
banner = [
"echo PlatformIO Unified Debugger -> http://bit.ly/pio-debug\\n",
"echo PlatformIO Unified Debugger -> https://bit.ly/pio-debug\\n",
"echo PlatformIO: debug_tool = %s\\n" % self.debug_config.tool_name,
"echo PlatformIO: Initializing remote target...\\n",
]
@ -157,7 +157,7 @@ class GDBClientProcess(DebugClientProcess):
% self.debug_config.init_break
)
self.console_log(
"PlatformIO: More configuration options -> http://bit.ly/pio-debug\n"
"PlatformIO: More configuration options -> https://bit.ly/pio-debug\n"
)
if self.debug_config.platform.is_embedded():
self.transport.get_pipe_transport(0).write(

View File

@ -1,13 +0,0 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

View File

@ -76,7 +76,7 @@ class PackageManagerDownloadMixin(object):
raise_error = True
if raise_error:
self.print_message(
"Error: Please read http://bit.ly/package-manager-ioerror",
"Error: Please read https://bit.ly/package-manager-ioerror",
fg="red",
err=True,
)

View File

@ -180,7 +180,7 @@ class PackageManageRegistryMixin(object):
)
self.print_message(
"Please specify detailed REQUIREMENTS using package owner and version "
"(showed above) to avoid name conflicts",
"(shown above) to avoid name conflicts",
fg="yellow",
)

View File

@ -216,7 +216,13 @@ def get_contrib_pysite_deps():
# twisted[tls], see setup.py for %twisted_version%
result.extend(
["pyopenssl >= 16.0.0", "service_identity >= 18.1.0", "idna >= 0.6, != 2.3"]
[
# pyopenssl depends on it, use RUST-less version
"cryptography >= 3.3, < 35.0.0",
"pyopenssl >= 16.0.0",
"service_identity >= 18.1.0",
"idna >= 0.6, != 2.3",
]
)
if "windows" in sys_type:

View File

@ -21,13 +21,15 @@ from platformio.package.exception import (
)
from platformio.package.manager.base import BasePackageManager
from platformio.package.meta import PackageItem, PackageSpec, PackageType
from platformio.project.helpers import get_project_global_lib_dir
from platformio.project.config import ProjectConfig
class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-ancestors
def __init__(self, package_dir=None):
super(LibraryPackageManager, self).__init__(
PackageType.LIBRARY, package_dir or get_project_global_lib_dir()
PackageType.LIBRARY,
package_dir
or ProjectConfig.get_instance().get("platformio", "globallib_dir"),
)
@property
@ -60,7 +62,7 @@ class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-anc
@staticmethod
def find_library_root(path):
root_dir_signs = set(["include", "Include", "src", "Src"])
root_dir_signs = set(["include", "Include", "inc", "Inc", "src", "Src"])
root_file_signs = set(
[
"conanfile.py", # Conan-based library

View File

@ -31,7 +31,7 @@ class PlatformPackageManager(BasePackageManager): # pylint: disable=too-many-an
self.config = ProjectConfig.get_instance()
super(PlatformPackageManager, self).__init__(
PackageType.PLATFORM,
package_dir or self.config.get_optional_dir("platforms"),
package_dir or self.config.get("platformio", "platforms_dir"),
)
@property

View File

@ -20,7 +20,7 @@ from platformio.project.config import ProjectConfig
class ToolPackageManager(BasePackageManager): # pylint: disable=too-many-ancestors
def __init__(self, package_dir=None):
if not package_dir:
package_dir = ProjectConfig.get_instance().get_optional_dir("packages")
package_dir = ProjectConfig.get_instance().get("platformio", "packages_dir")
super(ToolPackageManager, self).__init__(PackageType.TOOL, package_dir)
@property

View File

@ -89,7 +89,7 @@ class StrictListField(fields.List):
class AuthorSchema(StrictSchema):
name = fields.Str(required=True, validate=validate.Length(min=1, max=100))
email = fields.Email(validate=validate.Length(min=1, max=50))
maintainer = fields.Bool(default=False)
maintainer = fields.Bool(dump_default=False)
url = fields.Url(validate=validate.Length(min=1, max=255))

View File

@ -27,7 +27,7 @@ class ExtractArchiveItemError(PackageException):
MESSAGE = (
"Could not extract `{0}` to `{1}`. Try to disable antivirus "
"tool or check this solution -> http://bit.ly/faq-package-manager"
"tool or check this solution -> https://bit.ly/faq-package-manager"
)

View File

@ -110,6 +110,8 @@ class PlatformRunMixin(object):
args.append("%s=%s" % (key.upper(), self.encode_scons_arg(value)))
proc.copy_pythonpath_to_osenv()
# force SCons output to Unicode
os.environ["PYTHONIOENCODING"] = "utf-8"
if targets and "menuconfig" in targets:
return proc.exec_command(

View File

@ -45,7 +45,7 @@ class PlatformBase( # pylint: disable=too-many-instance-attributes,too-many-pub
self._custom_packages = None
self.config = ProjectConfig.get_instance()
self.pm = ToolPackageManager(self.config.get_optional_dir("packages"))
self.pm = ToolPackageManager(self.config.get("platformio", "packages_dir"))
@property
def name(self):
@ -145,8 +145,8 @@ class PlatformBase( # pylint: disable=too-many-instance-attributes,too-many-pub
self._BOARDS_CACHE[board_id] = config
bdirs = [
self.config.get_optional_dir("boards"),
os.path.join(self.config.get_optional_dir("core"), "boards"),
self.config.get("platformio", "boards_dir"),
os.path.join(self.config.get("platformio", "core_dir"), "boards"),
os.path.join(self.get_dir(), "boards"),
]

View File

@ -30,7 +30,9 @@ from platformio.compat import (
class AsyncPipeBase(object):
def __init__(self):
self._fd_read, self._fd_write = os.pipe()
self._pipe_reader = os.fdopen(self._fd_read, errors="backslashreplace")
self._pipe_reader = os.fdopen(
self._fd_read, encoding="utf-8", errors="backslashreplace"
)
self._buffer = ""
self._thread = Thread(target=self.run)
self._thread.start()

View File

@ -13,7 +13,6 @@
# limitations under the License.
import glob
import hashlib
import json
import os
import re
@ -21,7 +20,7 @@ import re
import click
from platformio import fs
from platformio.compat import IS_WINDOWS, hashlib_encode_data, string_types
from platformio.compat import string_types
from platformio.project import exception
from platformio.project.options import ProjectOptions
@ -49,7 +48,7 @@ MISSING = object()
class ProjectConfigBase(object):
INLINE_COMMENT_RE = re.compile(r"\s+;.*$")
VARTPL_RE = re.compile(r"\$\{([^\.\}]+)\.([^\}]+)\}")
VARTPL_RE = re.compile(r"\$\{([^\.\}\()]+)\.([^\}]+)\}")
expand_interpolations = True
warnings = []
@ -280,6 +279,9 @@ class ProjectConfigBase(object):
if value == MISSING:
return None
if option_meta.validate:
value = option_meta.validate(value)
return self._expand_interpolations(value)
def _expand_interpolations(self, value):
@ -295,7 +297,12 @@ class ProjectConfigBase(object):
section, option = match.group(1), match.group(2)
if section == "sysenv":
return os.getenv(option)
try:
value = self.getraw(section, option)
except RecursionError:
raise exception.ProjectOptionValueError(
"Infinite recursion has been detected", option, section
)
if isinstance(value, list):
return "\n".join(value)
return value
@ -354,70 +361,12 @@ class ProjectConfigBase(object):
class ProjectConfigDirsMixin(object):
def _get_core_dir(self, exists=False):
default = ProjectOptions["platformio.core_dir"].default
core_dir = self.get("platformio", "core_dir")
win_core_dir = None
if IS_WINDOWS and core_dir == default:
win_core_dir = os.path.splitdrive(core_dir)[0] + "\\.platformio"
if os.path.isdir(win_core_dir):
core_dir = win_core_dir
if exists and not os.path.isdir(core_dir):
try:
os.makedirs(core_dir)
except OSError as e:
if win_core_dir:
os.makedirs(win_core_dir)
core_dir = win_core_dir
else:
raise e
return core_dir
def get_optional_dir(self, name, exists=False):
if not ProjectOptions.get("platformio.%s_dir" % name):
raise ValueError("Unknown optional directory -> " + name)
if name == "core":
result = self._get_core_dir(exists)
else:
result = self.get("platformio", name + "_dir")
if result is None:
return None
project_dir = os.getcwd()
# patterns
if "$PROJECT_HASH" in result:
result = result.replace(
"$PROJECT_HASH",
"%s-%s"
% (
os.path.basename(project_dir),
hashlib.sha1(hashlib_encode_data(project_dir)).hexdigest()[:10],
),
)
if "$PROJECT_DIR" in result:
result = result.replace("$PROJECT_DIR", project_dir)
if "$PROJECT_CORE_DIR" in result:
result = result.replace("$PROJECT_CORE_DIR", self.get_optional_dir("core"))
if "$PROJECT_WORKSPACE_DIR" in result:
result = result.replace(
"$PROJECT_WORKSPACE_DIR", self.get_optional_dir("workspace")
)
if result.startswith("~"):
result = fs.expanduser(result)
result = os.path.realpath(result)
if exists and not os.path.isdir(result):
os.makedirs(result)
return result
def get_optional_dir(self, name):
"""
Deprecated, used by platformio-node-helpers.project.observer.fetchLibDirs
PlatformIO IDE for Atom depends on platformio-node-helpers@~7.2.0
"""
return self.get("platformio", f"{name}_dir")
class ProjectConfig(ProjectConfigBase, ProjectConfigDirsMixin):

View File

@ -24,15 +24,34 @@ from platformio.project.helpers import load_project_ide_data
class ProjectGenerator(object):
def __init__(self, config, env_name, ide):
def __init__(self, config, env_name, ide, board_ids=None):
self.config = config
self.project_dir = os.path.dirname(config.path)
self.env_name = str(env_name)
self.original_env_name = env_name
self.env_name = str(env_name or self.get_best_envname(board_ids))
self.ide = str(ide)
def get_best_envname(self, board_ids=None):
envname = None
default_envs = self.config.default_envs()
if default_envs:
envname = default_envs[0]
if not board_ids:
return envname
for env in self.config.envs():
if not board_ids:
return env
if not envname:
envname = env
items = self.config.items(env=env, as_dict=True)
if "board" in items and items.get("board") in board_ids:
return env
return envname
@staticmethod
def get_supported_ides():
tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls")
tpls_dir = os.path.join(fs.get_source_dir(), "project", "tpls")
return sorted(
[
d
@ -61,6 +80,7 @@ class ProjectGenerator(object):
"systype": util.get_systype(),
"project_name": os.path.basename(self.project_dir),
"project_dir": self.project_dir,
"original_env_name": self.original_env_name,
"env_name": self.env_name,
"user_home_dir": os.path.realpath(fs.expanduser("~")),
"platformio_path": sys.argv[0]
@ -79,11 +99,11 @@ class ProjectGenerator(object):
tpl_vars.update(
{
"src_files": self.get_src_files(),
"project_src_dir": self.config.get_optional_dir("src"),
"project_lib_dir": self.config.get_optional_dir("lib"),
"project_test_dir": self.config.get_optional_dir("test"),
"project_src_dir": self.config.get("platformio", "src_dir"),
"project_lib_dir": self.config.get("platformio", "lib_dir"),
"project_test_dir": self.config.get("platformio", "test_dir"),
"project_libdeps_dir": os.path.join(
self.config.get_optional_dir("libdeps"), self.env_name
self.config.get("platformio", "libdeps_dir"), self.env_name
),
}
)
@ -103,14 +123,14 @@ class ProjectGenerator(object):
def get_src_files(self):
result = []
with fs.cd(self.project_dir):
for root, _, files in os.walk(self.config.get_optional_dir("src")):
for root, _, files in os.walk(self.config.get("platformio", "src_dir")):
for f in files:
result.append(os.path.relpath(os.path.join(root, f)))
return result
def get_tpls(self):
tpls = []
tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls", self.ide)
tpls_dir = os.path.join(fs.get_source_dir(), "project", "tpls", self.ide)
for root, _, files in os.walk(tpls_dir):
for f in files:
if not f.endswith(".tpl"):

View File

@ -15,8 +15,6 @@
import json
import os
from hashlib import sha1
from os import walk
from os.path import dirname, isdir, isfile, join
from click.testing import CliRunner
@ -32,65 +30,43 @@ def get_project_dir():
def is_platformio_project(project_dir=None):
if not project_dir:
project_dir = get_project_dir()
return isfile(join(project_dir, "platformio.ini"))
return os.path.isfile(os.path.join(project_dir, "platformio.ini"))
def find_project_dir_above(path):
if isfile(path):
path = dirname(path)
if os.path.isfile(path):
path = os.path.dirname(path)
if is_platformio_project(path):
return path
if isdir(dirname(path)):
return find_project_dir_above(dirname(path))
if os.path.isdir(os.path.dirname(path)):
return find_project_dir_above(os.path.dirname(path))
return None
def get_project_core_dir():
"""Deprecated, use ProjectConfig.get_optional_dir("core") instead"""
return ProjectConfig.get_instance(
join(get_project_dir(), "platformio.ini")
).get_optional_dir("core", exists=True)
def get_project_all_lib_dirs():
"""Used by platformio-node-helpers.project.observer.fetchLibDirs"""
config = ProjectConfig.get_instance()
libdeps_dir = config.get("platformio", "libdeps_dir")
result = [
config.get("platformio", "globallib_dir"),
config.get("platformio", "lib_dir"),
libdeps_dir,
]
if not os.path.isdir(libdeps_dir):
return result
for d in os.listdir(libdeps_dir):
if os.path.isdir(os.path.join(libdeps_dir, d)):
result.append(os.path.join(libdeps_dir, d))
return result
def get_project_cache_dir():
"""Deprecated, use ProjectConfig.get_optional_dir("cache") instead"""
return ProjectConfig.get_instance(
join(get_project_dir(), "platformio.ini")
).get_optional_dir("cache")
def get_project_global_lib_dir():
"""
Deprecated, use ProjectConfig.get_optional_dir("globallib") instead
"platformio-node-helpers" depends on it
"""
return ProjectConfig.get_instance(
join(get_project_dir(), "platformio.ini")
).get_optional_dir("globallib")
def get_project_lib_dir():
"""
Deprecated, use ProjectConfig.get_optional_dir("lib") instead
"platformio-node-helpers" depends on it
"""
return ProjectConfig.get_instance(
join(get_project_dir(), "platformio.ini")
).get_optional_dir("lib")
def get_project_libdeps_dir():
"""
Deprecated, use ProjectConfig.get_optional_dir("libdeps") instead
"platformio-node-helpers" depends on it
"""
return ProjectConfig.get_instance(
join(get_project_dir(), "platformio.ini")
).get_optional_dir("libdeps")
"""Deprecated, use ProjectConfig.get("platformio", "cache_dir") instead"""
return ProjectConfig.get_instance().get("platformio", "cache_dir")
def get_default_projects_dir():
docs_dir = join(fs.expanduser("~"), "Documents")
docs_dir = os.path.join(fs.expanduser("~"), "Documents")
try:
assert IS_WINDOWS
import ctypes.wintypes # pylint: disable=import-outside-toplevel
@ -100,7 +76,7 @@ def get_default_projects_dir():
docs_dir = buf.value
except: # pylint: disable=bare-except
pass
return join(docs_dir, "PlatformIO", "Projects")
return os.path.join(docs_dir, "PlatformIO", "Projects")
def compute_project_checksum(config):
@ -113,16 +89,16 @@ def compute_project_checksum(config):
# project file structure
check_suffixes = (".c", ".cc", ".cpp", ".h", ".hpp", ".s", ".S")
for d in (
config.get_optional_dir("include"),
config.get_optional_dir("src"),
config.get_optional_dir("lib"),
config.get("platformio", "include_dir"),
config.get("platformio", "src_dir"),
config.get("platformio", "lib_dir"),
):
if not isdir(d):
if not os.path.isdir(d):
continue
chunks = []
for root, _, files in walk(d):
for root, _, files in os.walk(d):
for f in files:
path = join(root, f)
path = os.path.join(root, f)
if path.endswith(check_suffixes):
chunks.append(path)
if not chunks:
@ -171,8 +147,8 @@ def _load_project_ide_data(project_dir, env_names):
def _load_cached_project_ide_data(project_dir, env_names):
build_dir = ProjectConfig.get_instance(
join(project_dir, "platformio.ini")
).get_optional_dir("build")
os.path.join(project_dir, "platformio.ini")
).get("platformio", "build_dir")
result = {}
for name in env_names:
if not os.path.isfile(os.path.join(build_dir, name, "idedata.json")):

View File

@ -14,12 +14,14 @@
# pylint: disable=redefined-builtin, too-many-arguments
import hashlib
import os
from collections import OrderedDict
import click
from platformio import fs
from platformio.compat import IS_WINDOWS, hashlib_encode_data
class ConfigOption(object): # pylint: disable=too-many-instance-attributes
@ -35,6 +37,7 @@ class ConfigOption(object): # pylint: disable=too-many-instance-attributes
buildenvvar=None,
oldnames=None,
default=None,
validate=None,
):
self.scope = scope
self.group = group
@ -46,6 +49,7 @@ class ConfigOption(object): # pylint: disable=too-many-instance-attributes
self.buildenvvar = buildenvvar
self.oldnames = oldnames
self.default = default
self.validate = validate
def as_dict(self):
result = dict(
@ -60,13 +64,11 @@ class ConfigOption(object): # pylint: disable=too-many-instance-attributes
)
if isinstance(self.type, click.ParamType):
result["type"] = self.type.name
if isinstance(self.type, (click.IntRange, click.FloatRange)):
result["min"] = self.type.min
result["max"] = self.type.max
if isinstance(self.type, click.Choice):
result["choices"] = self.type.choices
return result
@ -78,6 +80,53 @@ def ConfigEnvOption(*args, **kwargs):
return ConfigOption("env", *args, **kwargs)
def calculate_path_hash(path):
return "%s-%s" % (
os.path.basename(path),
hashlib.sha1(hashlib_encode_data(path)).hexdigest()[:10],
)
def expand_dir_templates(path):
project_dir = os.getcwd()
tpls = {
"$PROJECT_DIR": lambda: project_dir,
"$PROJECT_HASH": lambda: calculate_path_hash(project_dir),
}
done = False
while not done:
done = True
for tpl, cb in tpls.items():
if tpl not in path:
continue
path = path.replace(tpl, cb())
done = False
return path
def validate_dir(path):
if not path:
return path
# if not all values expanded, ignore validation
if "${" in path and "}" in path:
return path
if path.startswith("~"):
path = fs.expanduser(path)
if "$" in path:
path = expand_dir_templates(path)
return os.path.realpath(path)
def validate_core_dir(path):
default_dir = ProjectOptions["platformio.core_dir"].default
win_core_dir = None
if IS_WINDOWS and path == default_dir:
win_core_dir = os.path.splitdrive(path)[0] + "\\.platformio"
if os.path.isdir(win_core_dir):
path = win_core_dir
return validate_dir(path)
ProjectOptions = OrderedDict(
[
("%s.%s" % (option.scope, option.name), option)
@ -121,6 +170,7 @@ ProjectOptions = OrderedDict(
oldnames=["home_dir"],
sysenvvar="PLATFORMIO_CORE_DIR",
default=os.path.join(fs.expanduser("~"), ".platformio"),
validate=validate_core_dir,
),
ConfigPlatformioOption(
group="directory",
@ -130,7 +180,8 @@ ProjectOptions = OrderedDict(
"Finder (LDF) looks for global libraries"
),
sysenvvar="PLATFORMIO_GLOBALLIB_DIR",
default=os.path.join("$PROJECT_CORE_DIR", "lib"),
default=os.path.join("${platformio.core_dir}", "lib"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -140,7 +191,8 @@ ProjectOptions = OrderedDict(
"platforms"
),
sysenvvar="PLATFORMIO_PLATFORMS_DIR",
default=os.path.join("$PROJECT_CORE_DIR", "platforms"),
default=os.path.join("${platformio.core_dir}", "platforms"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -149,7 +201,8 @@ ProjectOptions = OrderedDict(
"A location where PlatformIO Core keeps installed packages"
),
sysenvvar="PLATFORMIO_PACKAGES_DIR",
default=os.path.join("$PROJECT_CORE_DIR", "packages"),
default=os.path.join("${platformio.core_dir}", "packages"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -160,7 +213,8 @@ ProjectOptions = OrderedDict(
"other service information)"
),
sysenvvar="PLATFORMIO_CACHE_DIR",
default=os.path.join("$PROJECT_CORE_DIR", ".cache"),
default=os.path.join("${platformio.core_dir}", ".cache"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -171,6 +225,7 @@ ProjectOptions = OrderedDict(
"build environments"
),
sysenvvar="PLATFORMIO_BUILD_CACHE_DIR",
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -182,6 +237,7 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_WORKSPACE_DIR",
default=os.path.join("$PROJECT_DIR", ".pio"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -192,7 +248,8 @@ ProjectOptions = OrderedDict(
"and other cached information"
),
sysenvvar="PLATFORMIO_BUILD_DIR",
default=os.path.join("$PROJECT_WORKSPACE_DIR", "build"),
default=os.path.join("${platformio.workspace_dir}", "build"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -202,7 +259,8 @@ ProjectOptions = OrderedDict(
"dependencies declared via `lib_deps` option"
),
sysenvvar="PLATFORMIO_LIBDEPS_DIR",
default=os.path.join("$PROJECT_WORKSPACE_DIR", "libdeps"),
default=os.path.join("${platformio.workspace_dir}", "libdeps"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -213,6 +271,7 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_INCLUDE_DIR",
default=os.path.join("$PROJECT_DIR", "include"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -223,6 +282,7 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_SRC_DIR",
default=os.path.join("$PROJECT_DIR", "src"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -230,6 +290,7 @@ ProjectOptions = OrderedDict(
description="A storage for the custom/private project libraries",
sysenvvar="PLATFORMIO_LIB_DIR",
default=os.path.join("$PROJECT_DIR", "lib"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -240,6 +301,7 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_DATA_DIR",
default=os.path.join("$PROJECT_DIR", "data"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -250,13 +312,23 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_TEST_DIR",
default=os.path.join("$PROJECT_DIR", "test"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
name="boards_dir",
description="A global storage for custom board manifests",
description="A storage for custom board manifests",
sysenvvar="PLATFORMIO_BOARDS_DIR",
default=os.path.join("$PROJECT_DIR", "boards"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
name="monitor_dir",
description="A storage for custom monitor filters",
sysenvvar="PLATFORMIO_MONITOR_DIR",
default=os.path.join("$PROJECT_DIR", "monitor"),
validate=validate_dir,
),
ConfigPlatformioOption(
group="directory",
@ -267,6 +339,7 @@ ProjectOptions = OrderedDict(
),
sysenvvar="PLATFORMIO_SHARED_DIR",
default=os.path.join("$PROJECT_DIR", "shared"),
validate=validate_dir,
),
#
# [env]

View File

@ -26,7 +26,7 @@ add_custom_target(
add_custom_target(
Debug ALL
COMMAND platformio -c clion run --target debug "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
COMMAND platformio -c clion debug "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -40,7 +40,7 @@
% end
%
% def _get_lib_dirs(envname):
% env_libdeps_dir = os.path.join(config.get_optional_dir("libdeps"), envname)
% env_libdeps_dir = os.path.join(config.get("platformio", "libdeps_dir"), envname)
% env_lib_extra_dirs = config.get("env:" + envname, "lib_extra_dirs", [])
% return _fix_lib_dirs([env_libdeps_dir] + env_lib_extra_dirs)
% end

View File

@ -28,7 +28,7 @@
% debug["name"] = "PIO Debug"
% debug["preLaunchTask"] = {
% "type": "PlatformIO",
% "task": ("Pre-Debug (%s)" % env_name) if len(config.envs()) > 1 else "Pre-Debug",
% "task": ("Pre-Debug (%s)" % env_name) if len(config.envs()) > 1 and original_env_name else "Pre-Debug",
% }
% noloading = predebug.copy()
% noloading["name"] = "PIO Debug (without uploading)"

5
pytest.ini Normal file
View File

@ -0,0 +1,5 @@
[pytest]
filterwarnings =
error
# Marshmallow
ignore:The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives:DeprecationWarning

View File

@ -44,7 +44,7 @@ if not PY2:
home_requirements = [
"aiofiles==0.7.*",
"ajsonrpc==1.*",
"starlette==0.16.*",
"starlette==0.17.*",
"uvicorn==0.15.*",
"wsproto==1.0.*",
]
@ -62,10 +62,10 @@ setup(
packages=find_packages(exclude=["tests.*", "tests"]) + ["scripts"],
package_data={
"platformio": [
"ide/tpls/*/.*.tpl",
"ide/tpls/*/*.tpl",
"ide/tpls/*/*/*.tpl",
"ide/tpls/*/.*/*.tpl",
"project/tpls/*/.*.tpl",
"project/tpls/*/*.tpl",
"project/tpls/*/*/*.tpl",
"project/tpls/*/.*/*.tpl",
],
"scripts": ["99-platformio-udev.rules"],
},

View File

@ -486,5 +486,5 @@ def test_update_without_metadata(isolated_pio_core, tmpdir_factory):
# update
lm = LibraryPackageManager(str(storage_dir))
new_pkg = lm.update(pkg, silent=True)
assert len(lm.get_installed()) == 3
assert len(lm.get_installed()) == 4
assert new_pkg.metadata.spec.owner == "ottowinter"

View File

@ -67,7 +67,7 @@ def pytest_generate_tests(metafunc):
def test_run(pioproject_dir):
with fs.cd(pioproject_dir):
config = ProjectConfig()
build_dir = config.get_optional_dir("build")
build_dir = config.get("platformio", "build_dir")
if os.path.isdir(build_dir):
fs.rmtree(build_dir)

View File

@ -15,15 +15,18 @@
# pylint: disable=redefined-outer-name
import os
import sys
import pytest
from platformio import fs
from platformio.project.config import ConfigParser, ProjectConfig
from platformio.project.exception import InvalidProjectConfError, UnknownEnvNamesError
BASE_CONFIG = """
[platformio]
env_default = base, extra_2
build_dir = ~/tmp/pio-$PROJECT_HASH
extra_configs =
extra_envs.ini
extra_debug.ini
@ -83,17 +86,23 @@ lib_install = 574
build_flags = ${custom.debug_flags} ${custom.extra_flags}
lib_ignore = ${env.lib_ignore}, Lib3
upload_port = /dev/extra_2/port
debug_server = ${custom.debug_server}
"""
EXTRA_DEBUG_CONFIG = """
# Override original "custom.debug_flags"
[custom]
debug_flags = -D DEBUG=1
debug_server =
${platformio.packages_dir}/tool-openocd/openocd
--help
[env:extra_2]
build_flags = -Og
"""
DEFAULT_CORE_DIR = os.path.join(fs.expanduser("~"), ".platformio")
@pytest.fixture(scope="module")
def config(tmpdir_factory):
@ -124,7 +133,7 @@ def test_warnings(config):
def test_defaults(config):
assert config.get_optional_dir("core") == os.path.join(
assert config.get("platformio", "core_dir") == os.path.join(
os.path.expanduser("~"), ".platformio"
)
assert config.get("strict_ldf", "lib_deps", ["Empty"]) == ["Empty"]
@ -236,8 +245,9 @@ def test_sysenv_options(config):
]
# sysenv
os.environ["PLATFORMIO_HOME_DIR"] = "/custom/core/dir"
assert config.get("platformio", "core_dir") == "/custom/core/dir"
custom_core_dir = os.path.join(os.getcwd(), "custom")
os.environ["PLATFORMIO_HOME_DIR"] = custom_core_dir
assert config.get("platformio", "core_dir") == os.path.realpath(custom_core_dir)
# cleanup system environment variables
del os.environ["PLATFORMIO_BUILD_FLAGS"]
@ -272,6 +282,14 @@ def test_getraw_value(config):
assert config.getraw("env", "monitor_speed") == "9600"
assert config.getraw("env:test_extends", "monitor_speed") == "115200"
# dir options
packages_dir = os.path.join(DEFAULT_CORE_DIR, "packages")
assert config.get("platformio", "packages_dir") == packages_dir
assert (
config.getraw("custom", "debug_server")
== f"\n{packages_dir}/tool-openocd/openocd\n--help"
)
def test_get_value(config):
assert config.get("custom", "debug_flags") == "-D DEBUG=1"
@ -293,6 +311,15 @@ def test_get_value(config):
"-D CUSTOM_DEBUG_FLAG",
]
# dir options
assert config.get("platformio", "packages_dir") == os.path.join(
DEFAULT_CORE_DIR, "packages"
)
assert config.get("env:extra_2", "debug_server") == [
os.path.join(DEFAULT_CORE_DIR, "packages/tool-openocd/openocd"),
"--help",
]
def test_items(config):
assert config.items("custom") == [
@ -300,6 +327,11 @@ def test_items(config):
("lib_flags", "-lc -lm"),
("extra_flags", ""),
("lib_ignore", "LibIgnoreCustom"),
(
"debug_server",
"\n%s/tool-openocd/openocd\n--help"
% os.path.join(DEFAULT_CORE_DIR, "packages"),
),
]
assert config.items(env="base") == [
("build_flags", ["-D DEBUG=1"]),
@ -326,6 +358,13 @@ def test_items(config):
("build_flags", ["-Og"]),
("lib_ignore", ["LibIgnoreCustom", "Lib3"]),
("upload_port", "/dev/extra_2/port"),
(
"debug_server",
[
"%s/tool-openocd/openocd" % os.path.join(DEFAULT_CORE_DIR, "packages"),
"--help",
],
),
("monitor_speed", 9600),
("custom_monitor_speed", "115200"),
("lib_deps", ["Lib1", "Lib2"]),
@ -426,6 +465,7 @@ def test_dump(tmpdir_factory):
(
"platformio",
[
("build_dir", "~/tmp/pio-$PROJECT_HASH"),
("extra_configs", ["extra_envs.ini", "extra_debug.ini"]),
("default_envs", ["base", "extra_2"]),
],
@ -474,3 +514,39 @@ def test_dump(tmpdir_factory):
],
),
]
@pytest.mark.skipif(sys.platform != "win32", reason="runs only on windows")
def test_win_core_root_dir(tmpdir_factory):
try:
win_core_root_dir = os.path.splitdrive(fs.expanduser("~"))[0] + "\\.platformio"
remove_dir_at_exit = False
if not os.path.isdir(win_core_root_dir):
remove_dir_at_exit = True
os.makedirs(win_core_root_dir)
# Default config
config = ProjectConfig()
assert config.get("platformio", "core_dir") == win_core_root_dir
assert config.get("platformio", "packages_dir") == os.path.join(
win_core_root_dir, "packages"
)
# Override in config
tmpdir = tmpdir_factory.mktemp("project")
tmpdir.join("platformio.ini").write(
"""
[platformio]
core_dir = ~/.pio
"""
)
config = ProjectConfig(tmpdir.join("platformio.ini").strpath)
assert config.get("platformio", "core_dir") != win_core_root_dir
assert config.get("platformio", "core_dir") == os.path.realpath(
fs.expanduser("~/.pio")
)
if remove_dir_at_exit:
fs.rmtree(win_core_root_dir)
except PermissionError:
pass

View File

@ -40,7 +40,7 @@ commands =
[testenv:testcore]
commands =
{envpython} --version
py.test -v --basetemp="{envtmpdir}" -k-skip_ci tests --ignore tests/test_examples.py
py.test -v --basetemp="{envtmpdir}" -k "not skip_ci" tests --ignore tests/test_examples.py
[testenv:testexamples]
commands =