Compare commits

..

1835 Commits

Author SHA1 Message Date
Ivan Kravets
8dc20f93d5 Merge branch 'release/v6.1.3' 2022-07-18 20:48:22 +03:00
Ivan Kravets
72ac6c86df Bump version to v6.1.3 2022-07-18 20:48:10 +03:00
Ivan Kravets
8c2a7df53e Fixed a regression bug when opening device monitor without any filters // Resolve #4363 2022-07-18 20:46:27 +03:00
Ivan Kravets
d92e36efa0 Minor fixes to email regexp 2022-07-18 18:06:37 +03:00
Ivan Kravets
741e9a40b3 Bump version to 6.1.3a1 2022-07-18 17:27:13 +03:00
Ivan Kravets
7527143fff Merge branch 'release/v6.1.2' 2022-07-18 17:26:24 +03:00
Ivan Kravets
a23fef010f Merge tag 'v6.1.2' into develop
Bump version to 6.1.2
2022-07-18 17:26:24 +03:00
Ivan Kravets
cd4f5541ac Bump version to 6.1.2 2022-07-18 17:26:10 +03:00
Ivan Kravets
73089b3cb0 Warn about unknown device monitor filters // Resolve #4362 2022-07-18 17:24:38 +03:00
Ivan Kravets
3a70c902a9 Docs: Improve docs for the test suite filter/ignore options 2022-07-18 14:57:22 +03:00
Ivan Kravets
bedbae6311 Bump version to 6.1.2a3 2022-07-14 14:45:55 +03:00
Ivan Kravets
842679c32b Export a "PIO_UNIT_TESTING" macro to the project source files and dependent libraries in the Unit Testing mode 2022-07-14 14:45:31 +03:00
Ivan Kravets
10ff4ae77a Docs: Improve docs for advanced scripting 2022-07-14 14:45:16 +03:00
Ivan Kravets
bc325ab2cc Increase number of http retries to 5 2022-07-13 18:32:04 +03:00
Ivan Kravets
a31a7f2b06 Improved detection of Windows architecture // Resolve #4353 2022-07-13 18:26:21 +03:00
Ivan Kravets
4278574450 Fixed an issue when the "pio pkg publish" command didn’t work with Python 3.6 // #4352 2022-07-13 14:46:40 +03:00
Ivan Kravets
6f8f2511c2 Look for another mirror on any requests.exceptions.RequestException 2022-07-13 14:31:28 +03:00
Ivan Kravets
5282124664 Bump version to 6.1.2a2 2022-07-12 22:21:42 +03:00
Ivan Kravets
83bb6611b9 Fixed a regression bug when libArchive option declared in the library.json manifest was ignored // Resolve # 2022-07-12 22:21:09 +03:00
Ivan Kravets
dcc02c3e14 Revert "Use generic MISSING helper"
This reverts commit 31a24e1652.
2022-07-12 22:06:29 +03:00
Ivan Kravets
f070399cad Bump version to 6.1.2a1 2022-07-11 13:39:17 +03:00
Ivan Kravets
b9920b286f CI: Run deployment on the master branch 2022-07-11 13:36:32 +03:00
Ivan Kravets
d278f8f215 CI: Run deployment on the master branch 2022-07-11 13:36:01 +03:00
Ivan Kravets
3c5c65769c Merge tag 'v6.1.1' into develop
Bump version to 6.1.1
2022-07-11 13:34:00 +03:00
Ivan Kravets
2f7362951c Merge branch 'release/v6.1.1' 2022-07-11 13:33:59 +03:00
Ivan Kravets
f4535190a3 Bump version to 6.1.1 2022-07-11 13:33:34 +03:00
Ivan Kravets
236c4570cf Added new `monitor_encoding` project configuration option // Resolve #4350 2022-07-11 13:26:43 +03:00
Ivan Kravets
5844c536a4 Typo fix 2022-07-10 11:50:13 +03:00
smarq8
6627fd5790 fix compat mode when no framework (#4346)
fix strict compat mode when no framework
2022-07-09 22:50:02 +03:00
Ivan Kravets
25074d80d3 Allowed specifying project environments for "pio ci" command // Resolve #4347 2022-07-09 21:58:34 +03:00
Ivan Kravets
f032663b33 Bump version to 6.1.1rc1 2022-07-09 21:43:14 +03:00
Ivan Kravets
d24702eb29 Fixed an issue with endless scanning of project dependencies // Resolve #4349 2022-07-09 21:42:47 +03:00
Ivan Kravets
9051677d74 Deploy package to PyPi on the master push 2022-07-09 21:41:52 +03:00
Ivan Kravets
7637286efa Improve detecting of common builder by paths 2022-07-09 21:36:37 +03:00
Ivan Kravets
31a24e1652 Use generic MISSING helper 2022-07-09 19:25:04 +03:00
Ivan Kravets
c8c4028a23 Bump version to 6.1.1a3 2022-07-09 17:23:57 +03:00
Ivan Kravets
0bd27a36e9 Fixed an issue when a serial port was not automatically detected if the board has predefined HWIDs 2022-07-09 17:23:38 +03:00
Ivan Kravets
ddfe5a6c03 Extend udev rules with QinHeng Electronics CH9102 USB-Serial adapter 2022-07-08 21:13:39 +03:00
Ivan Kravets
ee93ca1615 Bump version to 6.1.1a2 2022-07-08 15:19:25 +03:00
Ivan Kravets
4c2aca4956 Show "TimeoutError" only in the verbose mode when can not find a serial port 2022-07-08 15:18:52 +03:00
Ivan Kravets
dd14b5e2ed Docs: Make supported IDEs "plural" 2022-07-08 14:22:13 +03:00
Ivan Kravets
6464420c1c Bump version to 6.1.1a1 2022-07-06 20:06:16 +03:00
Ivan Kravets
79ec493c79 Deployment: Build Python source tarball 2022-07-06 19:51:38 +03:00
Ivan Kravets
abb464707d Merge branch 'release/v6.1.0' 2022-07-06 18:41:44 +03:00
Ivan Kravets
7c846b8968 Merge tag 'v6.1.0' into develop
Bump version to 6.1.0
2022-07-06 18:41:44 +03:00
Ivan Kravets
84c2e0a3d6 Tests: fest latest package version in runtime 2022-07-06 18:41:00 +03:00
Ivan Kravets
c2ddc89e46 Bump version to 6.1.0 2022-07-06 16:24:03 +03:00
Ivan Kravets
1495e24e1e Temporary disable ESPHome from CI 2022-07-06 16:22:13 +03:00
Ivan Kravets
6e16b43568 Automatically upgrade outdated Unity library 2022-07-05 18:57:06 +03:00
Ivan Kravets
6c18b37d54 Bump version to 6.1.0rc1 2022-07-04 18:50:23 +03:00
Ivan Kravets
6134db8e81 Fixed an issue when library dependencies were installed for the incompatible project environment // Resolve #4338 2022-07-04 18:50:06 +03:00
Ivan Kravets
3cf62f8fa6 Disable GoogleTest and Doctest frameworks on CI/Github Actions 2022-07-04 18:04:45 +03:00
Ivan Kravets
523b6dfa98 Do not immediately terminate a testing program when results are received 2022-07-04 17:32:11 +03:00
Ivan Kravets
3928cb522e Bump version to 6.1.0b2 2022-07-04 13:55:11 +03:00
Ivan Kravets
de856ee730 Export IDEs templates 2022-07-04 13:54:40 +03:00
Tim Gates
d3b7508bd5 docs: Fix a few typos (#4340)
There are small typos in:
- platformio/test/helpers.py
- platformio/util.py
- tests/project/test_savedeps.py

Fixes:
- Should read `specified` rather than `sepcified`.
- Should read `overridden` rather than `overriden`.
- Should read `compatibility` rather than `compatiblty`.
2022-07-03 13:16:33 +03:00
Ivan Kravets
6c71a3bea2 Disable core linting with Python 3.6 2022-07-02 20:18:26 +03:00
Ivan Kravets
d2e27f5385 Better wording with dependency resolving 2022-07-02 20:17:31 +03:00
Ivan Kravets
2a5de43964 Refactor project IDE integration 2022-07-02 20:16:56 +03:00
Ivan Kravets
029e66cd06 PyLint fixes 2022-07-02 19:19:48 +03:00
Ivan Kravets
96fb8c74f9 PyLint: fix "superfluous-parens" 2022-07-02 19:05:32 +03:00
Ivan Kravets
b006f53010 PyLint: Fix "useless-object-inheritance" 2022-07-02 19:03:25 +03:00
Ivan Kravets
19d518fc4c Fix PyLint: Consider explicitly re-raising 2022-07-02 18:37:57 +03:00
Ivan Kravets
f01cd7570c Fix handling of unknown targets when processing pre/post actions 2022-07-01 20:14:58 +03:00
Ivan Kravets
ffebfd4376 Drop deprecated "program" target 2022-07-01 19:44:14 +03:00
Ivan Kravets
e4264a6a51 Make $PROGPATH configurable 2022-07-01 19:38:51 +03:00
Ivan Kravets
d85bc0f7f8 Make $PROGPATH configurable 2022-07-01 19:29:07 +03:00
Ivan Kravets
1445a91fab Docs: Refactor "Custom firmware/program name" scripting example 2022-07-01 18:43:08 +03:00
Ivan Kravets
3b878747f2 Bump GoogleTest dependency to 1.12.1 2022-07-01 18:03:48 +03:00
Ivan Kravets
401f8a4891 Added new "pio run --monitor-port" option to specify custom device monitor port to the "monitor" target // Resolve #4337 2022-06-29 22:46:53 +03:00
Ivan Kravets
6bec593b93 Simplify output from the clean target 2022-06-29 22:17:30 +03:00
Ivan Kravets
aef49a8bff Docs: Improve advanced scripting docs 2022-06-29 14:34:49 +03:00
Ivan Kravets
772e25df49 Bump version to 6.1.0b1 2022-06-28 19:37:16 +03:00
Ivan Kravets
3363b3a516 Significantly improved support for Pre & Post Actions 2022-06-28 19:36:49 +03:00
Ivan Kravets
1f096fe03f Fixed "non-existent variable ''projenv''" when ESP-IDF is used // Resolve #4329 2022-06-28 14:28:52 +03:00
Ivan Kravets
32e440bec7 Fixed an issue when testing results were wrong in the verbose mode // Resolve #4336 2022-06-28 12:59:23 +03:00
Ivan Kravets
99b5204802 Fixed a "PermissionError" on Windows when running "clean" or "cleanall" targets // Resolve #4331 2022-06-27 20:12:04 +03:00
Ollie Tedder
3c17b31d5e Export twice to maintain backward compatability (#4333)
* Export twice to maintain backward compattability

* Removed double import and just use another variable (after running make before-commit)

* Improve comment
2022-06-27 13:24:42 +03:00
Ivan Kravets
89a80f158e Bump version to 6.0.3rc2 2022-06-26 17:33:22 +03:00
Ivan Kravets
c42db2ec22 Rename pio pkg publish --non-interactive option to the --no-interactive 2022-06-26 17:32:47 +03:00
Ivan Kravets
6a3b6f0d44 Bump GoogleTest to ^1.12.0 and Doctest to ^2.4.9 2022-06-26 17:21:09 +03:00
Ivan Kravets
ca2622b7a6 Skip GoogleTest for CI on Windows 2022-06-26 16:06:25 +03:00
Ivan Kravets
b9a9fd4f43 Updated "Getting Started" documentation for GoogleTest 2022-06-26 14:47:25 +03:00
Ivan Kravets
1ea6d47110 Initialize unit testing target once per project builder 2022-06-25 22:44:35 +03:00
Ivan Kravets
256acf7e23 Merge branch 'feature/c-scanner' into develop 2022-06-25 20:53:18 +03:00
Ivan Kravets
284ccc9e8a Remove ProjectAsLibBuilder's singleton 2022-06-25 20:53:08 +03:00
Ivan Kravets
655eedd7b0 Export Unit Testing flags only to the project build environment 2022-06-25 20:20:13 +03:00
Ivan Kravets
bb6490d6f2 Do not automatically configure any flags for the testing frameworks 2022-06-25 20:11:17 +03:00
Ivan Kravets
300b7b2138 Minor improvements to the ProjectAsLibBuilder 2022-06-25 20:10:18 +03:00
Ivan Kravets
86c4bd69d2 Fixed an issue with the LDF when recursively scanning dependencies in the "chain" mode 2022-06-24 21:17:26 +03:00
Ivan Kravets
dd63c8002a Make "MatchSourceFiles' configurable for source extensions 2022-06-24 21:09:44 +03:00
Ivan Kravets
13fc8508b3 Bump "uvicorn" dependency to 0.18.* 2022-06-23 18:58:53 +03:00
Ivan Kravets
a76933990c Remove generic targets 2022-06-23 14:20:27 +03:00
Ivan Kravets
7e3e394707 Bump version to 6.0.3rc1 2022-06-22 19:05:05 +03:00
Ivan Kravets
cee3f4d90f Do not resolve debugging serial port by default 2022-06-22 19:03:50 +03:00
Ivan Kravets
c557473cfb Docs: Fix redirect URL 2022-06-22 13:15:32 +03:00
Ivan Kravets
f893fcf135 Bump version to 6.0.3b1 2022-06-20 22:41:02 +03:00
Ivan Kravets
092326cb91 Warn about incompatible Bash version for the Shell Completion // Resolve #4326 2022-06-20 22:40:36 +03:00
Ivan Kravets
92a5c1bac6 Handle UDEV rules and their PID/VID data when searching for serial port 2022-06-20 22:21:28 +03:00
Ivan Kravets
4b2f0eb1d5 Extend CP210X rules 2022-06-20 22:20:47 +03:00
Ivan Kravets
9ae67fdad9 Fixed an issue on Windows OS when flags were wrapped to the temporary file while generating compilation database 2022-06-20 14:49:39 +03:00
Ivan Kravets
5142feba7a Use new unified package API for deprecated pio lib command // Resolve #4198 2022-06-20 14:24:09 +03:00
Ivan Kravets
8cbe7bc7a6 Use new unified package API for deprecated pio platform command // Issue #4198 2022-06-18 17:25:38 +03:00
Ivan Kravets
d8f36b6534 Minor improvements to pkg show layout 2022-06-18 16:59:49 +03:00
Ivan Kravets
58d533a3bb Prefer Black Magic GDB for uploading // Issue #4023 2022-06-18 14:06:24 +03:00
Ivan Kravets
18e130fd12 Bump version to 6.0.3a7 2022-06-17 23:05:47 +03:00
Ivan Kravets
b72c1636f7 Improved a serial port finder for Black Magic Probe // Resolve #4023 2022-06-17 23:05:20 +03:00
Ivan Kravets
f68c18d1e5 Fixed an issue when the build_unflags option was not applied to the ASPPFLAGS scope 2022-06-17 18:58:21 +03:00
Ivan Kravets
db6b8a6dbc Fixed an issue when `build_unflags operation ignores a flag value // Resolve #4309 2022-06-17 14:25:39 +03:00
Ivan Kravets
5afa0a955e PyLint fix 2022-06-17 13:58:26 +03:00
Ivan Kravets
ca3b3717d3 Bump version to 6.0.3a6 2022-06-17 12:31:51 +03:00
Ivan Kravets
d4784c05f5 Documented Stringification – converting a macro argument into a string constant // Resolve #4310 2022-06-17 12:29:09 +03:00
Ivan Kravets
7a01da7039 Added `env.StringifyMacro(value)` helper function for the Advanced Scripting 2022-06-17 12:25:52 +03:00
Ivan Kravets
42690d3fa7 Find serial port using known device HWIDs 2022-06-16 16:58:03 +03:00
Ivan Kravets
50cbc4d4e2 Allowed to Import("projenv") in a library extra script // Resolve #4305 2022-06-16 13:04:38 +03:00
Ivan Kravets
63c2278a83 Bump version to 6.0.3a5 2022-06-16 09:46:04 +03:00
Ivan Kravets
4bccaae945 Fix an issue with serial port finding when board does not have HWIDs // Issue #4323 2022-06-16 09:45:20 +03:00
Ivan Kravets
e12bc9fe5f Do not resolve dependencies from the project "src" folder when the test_build_src option is not enabled 2022-06-15 18:05:55 +03:00
Ivan Kravets
ac63cf0240 Bump version to 6.0.3a4 2022-06-15 15:37:20 +03:00
Ivan Kravets
30709fd0b3 Replaced monitor_flags with independent project configuration options: monitor_parity, monitor_eol, monitor_raw, monitor_echo 2022-06-15 15:36:17 +03:00
Ivan Kravets
6f9985125d Fixed an issue when the monitor filters were not applied in their order // Resolve #4320 2022-06-15 14:30:05 +03:00
Ivan Kravets
743a3e2c02 Improved a serial port finder for a board with predefined HWIDs // Resolve #4308 2022-06-15 12:51:06 +03:00
Ivan Kravets
bd21ff0d3e Fixed an issue when monitor_speed was ignored in configuration file // Resolve #4319 2022-06-14 10:02:23 +03:00
Ivan Kravets
46858fff39 Bump version to 6.0.3a3 2022-06-13 20:19:28 +03:00
Ivan Kravets
854c549e1c Restore original standard streams for device monitor // Issue #3939 2022-06-13 20:19:09 +03:00
Ivan Kravets
4b5bc91abb Merged the Unit Testing “building” stage with “uploading” for the embedded target // Resolve #4307 2022-06-12 12:33:02 +03:00
Ivan Kravets
375c396b7b Minor improvements for pio device monitor command 2022-06-12 12:14:28 +03:00
Ivan Kravets
7aaa9c028b Bump version to 6.0.3a2 2022-06-11 20:56:24 +03:00
Ivan Kravets
7f351bc7c8 Automatically reconnect device monitor if a connection fails // Resolve #3939 2022-06-11 20:55:52 +03:00
Ivan Kravets
c42fe32972 Fix typo in upload_protocol 2022-06-10 17:30:36 +03:00
Ivan Kravets
a6e61a7a5a Restructure "device" module 2022-06-10 14:01:55 +03:00
Ivan Kravets
4bc3e3cf95 Restructure "device" module 2022-06-10 14:01:42 +03:00
Ivan Kravets
4a7a8b8b68 Update tests 2022-06-10 14:00:46 +03:00
Ivan Kravets
51ab0bbd3c Update tests 2022-06-10 13:32:48 +03:00
Ivan Kravets
30937df4e6 Lock "requests" dependency for Python 3.6 2022-06-10 12:46:52 +03:00
Ivan Kravets
b15a4e746a Bump version to 6.0.3a1 2022-06-02 18:09:11 +03:00
Ivan Kravets
1b17234c41 Fixed an issue when a custom "pio test --project-config" was not handled properly // Resolve #4299 2022-06-02 18:05:41 +03:00
Ivan Kravets
26f897cb55 Fix PyLint 2022-06-01 18:29:49 +03:00
Ivan Kravets
99d049a6dd Run deployment on tags 2022-06-01 17:24:02 +03:00
Ivan Kravets
f3c3402b35 Run deployment on tags 2022-06-01 17:21:57 +03:00
Ivan Kravets
55b9c446f1 Merge tag 'v6.0.2' into develop
Bump version to 6.0.2
2022-06-01 16:27:53 +03:00
Ivan Kravets
e3ca0c6f04 Merge branch 'release/v6.0.2' 2022-06-01 16:27:53 +03:00
Ivan Kravets
4ff591bd7e Bump version to 6.0.2 2022-06-01 15:55:42 +03:00
Ivan Kravets
b02335a294 Allow to implement own "FindInoNodes" method // Resolve #4297 2022-06-01 14:11:10 +03:00
Ivan Kravets
cc3ea65faa Fix release branch name 2022-06-01 13:49:52 +03:00
Ivan Kravets
206bb38f54 Move "team" command to the "account" module 2022-06-01 13:16:57 +03:00
Ivan Kravets
10da6bf5c6 Cleanup 2022-06-01 13:16:45 +03:00
Ivan Kravets
22860cd4e5 Rename "helpers" to "validate" 2022-06-01 12:57:23 +03:00
Ivan Kravets
0b8a595288 Move "access" command to the registry module 2022-06-01 12:46:57 +03:00
Ivan Kravets
7e7856e44c Restructure "registry" modules 2022-06-01 12:35:55 +03:00
Ivan Kravets
b104b840c4 Move "org" command to the account module 2022-06-01 12:28:41 +03:00
Ivan Kravets
32386bec18 Make "get_project_watch_lib_dirs" public for IDEs 2022-06-01 12:11:26 +03:00
Ivan Kravets
db366b3163 Fix test 2022-06-01 12:10:57 +03:00
Ivan Kravets
472c80159d Do not export common libdeps_dir 2022-05-31 21:59:24 +03:00
Ivan Kravets
4a95148cd0 Do not modify existing directory 2022-05-31 20:37:44 +03:00
Ivan Kravets
11a43b2693 Regroup "system" commands 2022-05-31 17:31:21 +03:00
Ivan Kravets
12fb02db6e Use "cli" to the top commands 2022-05-31 17:30:41 +03:00
Ivan Kravets
52f8e98eed Move "run" command to the root 2022-05-31 17:20:56 +03:00
Ivan Kravets
dcc63da2ef Move "check" command to the root 2022-05-31 17:16:55 +03:00
Ivan Kravets
756bb07d1a Move "home" command to the root 2022-05-31 17:14:52 +03:00
Ivan Kravets
d2be7033e9 Move "remote" command to the root 2022-05-31 17:12:59 +03:00
Ivan Kravets
27ccdc76a0 Move "system" command to the root 2022-05-31 17:09:22 +03:00
Ivan Kravets
dcecd5f922 Refactor handling of CLI commands 2022-05-31 17:07:56 +03:00
Ivan Kravets
506a08c7cf Fix tests 2022-05-31 14:04:49 +03:00
Ivan Kravets
e2892d5d4c Bump version to 6.0.2rc2 2022-05-30 22:23:36 +03:00
Ivan Kravets
0ce7885833 Fix module import 2022-05-30 22:23:06 +03:00
Ivan Kravets
6b7e8ebe97 Bump version to 6.0.2rc1 2022-05-30 21:04:19 +03:00
Ivan Kravets
6e5aee5ef3 Rename "registry" module to the "client" 2022-05-30 21:02:59 +03:00
Ivan Kravets
4aebf8c9d7 Refactor account module 2022-05-30 21:00:22 +03:00
Ivan Kravets
1f75430fab Move registry client to the package module 2022-05-30 20:36:18 +03:00
Ivan Kravets
2564b9eb78 Move http module to the root 2022-05-30 20:29:35 +03:00
Ivan Kravets
cf558036d0 Sync docs 2022-05-30 20:22:48 +03:00
Ivan Kravets
b568eb68d6 Docs: refactor installation guide and FAQ 2022-05-30 18:53:53 +03:00
Ivan Kravets
19006378a8 Sync docs 2022-05-30 14:27:45 +03:00
Ivan Kravets
a19c4dbcda Show a warning when testing an empty project without a test suite // Resolve #4278 2022-05-28 22:09:14 +03:00
Ivan Kravets
22a0a20666 Update deps 2022-05-28 22:07:44 +03:00
Ivan Kravets
440bb1e6f4 Bump version to 6.0.2b1 2022-05-26 22:30:20 +03:00
Ivan Kravets
87dffa36b8 Improved support for user inputs 2022-05-26 22:29:51 +03:00
Ivan Kravets
bd052d0ce0 Show a warning when testing an empty project without a test suite // Resolve #4278 2022-05-26 19:55:23 +03:00
Ivan Kravets
73dd29c59c Follow symbolic links during searching for the unit test suites // Resolve #4288 2022-05-26 19:18:21 +03:00
Ivan Kravets
460a983ab2 Do not export empty scopes to the build environment 2022-05-26 19:15:15 +03:00
Ivan Kravets
ea94f65159 Minor improvements 2022-05-26 19:11:33 +03:00
Ivan Kravets
6f6460fd4e Minor improvements 2022-05-26 19:10:58 +03:00
Ivan Kravets
5f812409d4 Fixed an issue with debugging assembly files without preprocessor (".s") 2022-05-25 19:23:24 +03:00
Sebastian Guarino
87f2e86928 Fix filter argument used in remote agent (#4291)
* Fix filter argument used in remote agent

* Linting

* Renamed reserved variable name to filter_
2022-05-25 14:54:08 +03:00
Ivan Kravets
626640cc05 Accurate information about broken test suites in PIO Core 5.0 // Resolve #4279 2022-05-20 21:10:10 +03:00
Ivan Kravets
f5e0ccecc3 Docs: Sync dev-platforms 2022-05-20 14:44:54 +03:00
Ivan Kravets
598769fe1b Bump version to 6.0.2a2 2022-05-20 10:57:24 +03:00
Ivan Kravets
f7e24f2093 Drop "test_verbosity_level" configuration option // Issue #4276 2022-05-20 10:56:42 +03:00
Ivan Kravets
9b141bf5a8 Control Unit Testing verbosity with a new test_verbosity_level configuration option // Resolve #4276 2022-05-19 21:23:30 +03:00
Ivan Kravets
9d2adb37f3 Sync examples 2022-05-19 19:32:08 +03:00
Ivan Kravets
97e2d24cd1 Use Python 3.9 for CI examples 2022-05-19 19:18:38 +03:00
Ivan Kravets
720732eba6 Fix env section location 2022-05-19 19:16:52 +03:00
Ivan Kravets
37c6f20747 Test only popular dev-platforms 2022-05-19 19:10:54 +03:00
Ivan Kravets
e27c1c39e4 Remove debug messages 2022-05-19 18:38:17 +03:00
Ivan Kravets
1e000027c7 Fix master branch 2022-05-19 18:32:27 +03:00
Ivan Kravets
e3fea07596 Add deployment workflow 2022-05-19 18:23:06 +03:00
Ivan Kravets
06ed9ba77d Fixed an issue when "build_src_flags" were applied outside project scope // Resolve #4277 2022-05-19 17:55:27 +03:00
Ivan Kravets
f4d9769450 Move ino2cpp tests to the misc folder 2022-05-19 14:36:24 +03:00
Valerii Koval
9da7c42be4 Exclude ESPHome from projects CI on Windows 2022-05-19 14:31:00 +03:00
Ivan Kravets
3419558265 Use private Github Actions environment 2022-05-19 13:29:48 +03:00
Ivan Kravets
61383f9b08 Pass extra envs to the tox 2022-05-19 12:18:08 +03:00
Ivan Kravets
be0acaed40 Cleanup CI configs 2022-05-19 12:02:52 +03:00
Ivan Kravets
0c4c4ac657 Use globals() instead of sys.modules 2022-05-18 23:14:15 +03:00
Ivan Kravets
bb8b115a0b Fix projects CI workflow 2022-05-18 22:29:40 +03:00
Ivan Kravets
2e2735a49c Typo fix 2022-05-18 22:28:05 +03:00
Ivan Kravets
7badd54c89 Exclude "esphome" from testing projects for macOS and Windows 2022-05-18 22:23:09 +03:00
Ivan Kravets
4dfc561551 Dynamically import legacy platform module 2022-05-18 22:18:53 +03:00
Ivan Kravets
3c2afeba89 Fix account related tests 2022-05-18 22:18:15 +03:00
Ivan Kravets
d2d46f4aea Ignore "DeprecationWarning: the load_module() method is deprecated and slated for removal in Python 3.12" SCons warning 2022-05-18 18:47:27 +03:00
Ivan Kravets
ccc7d9c9a4 Update CI badges 2022-05-18 16:17:20 +03:00
Ivan Kravets
45fcb40a5c Dynamically load refactored dev-platform module 2022-05-18 16:16:51 +03:00
Valerii Koval
1585b829be Add CI workflow for popular PlatformIO projects (#4273)
* Add CI workflow for popular PlatformIO projects

* Run projects CI on each commit

* Run mega2560 env for Marlin project

* Run projects CI on several OS with Python 3.9

* Use the latest version of 3rd party actions

Co-authored-by: Ivan Kravets <me@ikravets.com>
2022-05-18 15:54:54 +03:00
Ivan Kravets
0ceae62701 Better informing about deprecated commands 2022-05-17 21:11:29 +03:00
Ivan Kravets
f2bdb17c55 Bump version to 6.0.2a1 2022-05-17 19:47:33 +03:00
Ivan Kravets
83b00ac80c Remove pio update test 2022-05-17 19:47:15 +03:00
Ivan Kravets
a76e445ed9 Merge branch 'release/v6.0.1' 2022-05-17 19:23:31 +03:00
Ivan Kravets
edff591c90 Merge tag 'v6.0.1' into develop
Bump version to 6.0.1
2022-05-17 19:23:31 +03:00
Ivan Kravets
cb7148d018 Bump version to 6.0.1 2022-05-17 19:23:00 +03:00
Ivan Kravets
38afa07dbe Use Marshmallow v3.14.1 for Python 3.6 2022-05-17 19:10:54 +03:00
Ivan Kravets
92073a4ccd Deprecate "pio update", "pio lib", and "pio platform" commands 2022-05-17 18:57:40 +03:00
Ivan Kravets
abf6304818 Fixed an issue when using "Interpolation of Values" and merging str+int options // Resolve #4271 2022-05-17 16:03:33 +03:00
Ivan Kravets
9a86175701 Bump version to 6.0.1b1 2022-05-17 13:34:03 +03:00
Ivan Kravets
b764a2220f Improved support for the renamed configuration options // Resolve #4270 2022-05-17 13:33:25 +03:00
Ivan Kravets
3776233233 Rename "shared" module to the "public" 2022-05-16 16:56:01 +03:00
Ivan Kravets
0d92e8fc17 Bump version to 6.0.0a1 2022-05-16 14:46:52 +03:00
Ivan Kravets
40422eac2e Fixed an issue when calling built-in pio device monitor filter 2022-05-16 14:46:37 +03:00
Ivan Kravets
0fb4b1e109 Merge tag 'v6.0.0' into develop
Bump version to 6.0.0
2022-05-16 14:22:08 +03:00
Ivan Kravets
44ecc7c666 Merge branch 'release/v6.0.0' 2022-05-16 14:22:07 +03:00
Ivan Kravets
26d659c433 Bump version to 6.0.0 2022-05-16 14:21:57 +03:00
Ivan Kravets
58c4145809 Refactor library management docs 2022-05-16 14:18:45 +03:00
Ivan Kravets
fe08ce7795 Implement shared API 2022-05-16 11:39:18 +03:00
Ivan Kravets
9163e9e67d Rename pio project data to the pio project metadata command 2022-05-15 16:57:27 +03:00
Ivan Kravets
7acae6461e Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2022-05-15 15:35:07 +03:00
John Belmonte
e7a172b8dd qtcreator: add project-update makefile target (#4267)
* qtcreator: add project-update makefile target

* add prompt and delete .pio/

* formatting

* forced rm

* remove workaround of deleting .pio/
2022-05-15 15:34:57 +03:00
Ivan Kravets
b90e89a791 no message 2022-05-15 14:54:07 +03:00
John Belmonte
db11244f49 qtcreator IDE gitignore tweaks (#4266)
* add .gitignore to project files
  * exclude qtc_clangd
  * don't exclude user project config file
2022-05-15 13:52:59 +03:00
Ivan Kravets
54f0748201 Cache a build metadata only for debugging // Resolve #4267 2022-05-15 13:52:11 +03:00
Ivan Kravets
575f0ae300 Bump version to 6.0.0rc3 2022-05-15 13:47:32 +03:00
Ivan Kravets
7a100fb0b0 Use device finder for automatic detection of upload port 2022-05-15 13:46:44 +03:00
Ivan Kravets
d01d314f47 Pick the last USB device port 2022-05-15 13:13:45 +03:00
Ivan Kravets
e5e2210768 Improved automatic detection of a testing serial port // Resolve #4076 2022-05-14 23:30:36 +03:00
Ivan Kravets
d22b479bd3 Regroup device command 2022-05-14 18:21:44 +03:00
Ivan Kravets
19853b0b66 Implement config.get_default_env() 2022-05-14 17:55:36 +03:00
Ivan Kravets
ce62514a17 Resolve project dependencies with pio project init command 2022-05-14 16:31:08 +03:00
Ivan Kravets
4a4ba5594b Rename "load_project_ide_data" to the "load_build_metadata" 2022-05-14 16:30:20 +03:00
Ivan Kravets
af5a820862 Rename "load_project_ide_data" to the "load_build_metadata" 2022-05-14 16:29:41 +03:00
Ivan Kravets
40e4e38e0c Do not override CWD when executing a package command 2022-05-14 16:23:36 +03:00
Ivan Kravets
cb1c825747 Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2022-05-14 15:27:13 +03:00
John Belmonte
8c27754045 qtcreator IDE template now generates a "generic" Qt project (#4262)
* Create qtcreator-generic IDE template.

* Fix case of #define in qtcreator-generic template .config file.

* follow directory move

* * fix includes output
  * fixup -mlong-calls for clang
  * add Makefile to files output

* fix escaping in config output

* Makefile improvements:
  * support any platformio run target
  * remove platformio deprecated -f option
  * remove explicit default target (first is always default)

* replace qtcreator rather than making another IDE target

Co-authored-by: Donna Whisnant <dewhisna@users.noreply.github.com>
2022-05-14 15:26:04 +03:00
Ivan Kravets
3247e661e9 Regroup "pio project" command 2022-05-14 13:41:20 +03:00
Ivan Kravets
7c93167d52 Docs: Document double hyphen for "pio debug" // Resolve #4260 2022-05-13 21:04:44 +03:00
Ivan Kravets
79b2bfdefe Fix an issue with multiple symbol definitions when framework uses own Unity // Resolve #4259 2022-05-12 15:34:50 +03:00
Ivan Kravets
de7d710943 Look for custom "unity_config.h" only in the "test" dir 2022-05-12 14:17:45 +03:00
Ivan Kravets
b88a29e652 Bump version to 6.0.0rc2 2022-05-12 13:41:45 +03:00
Ivan Kravets
ed0b12dcf9 Improve project config parser to resolve renamed options // Issue #4259 2022-05-12 13:24:27 +03:00
Ivan Kravets
280bede0e9 Bump version to 6.0.0rc1 2022-05-10 20:22:36 +03:00
Ivan Kravets
e6938f8f39 List available project tests with a new "pio test --list-tests" option 2022-05-10 20:21:49 +03:00
Ivan Kravets
6d705172f5 Docs: Extend migration guide with Unit Testing solution 2022-05-10 19:18:36 +03:00
Ivan Kravets
8fff7084db Rename pio test --output-{format} options to --{format}-output 2022-05-10 18:25:26 +03:00
Ivan Kravets
e75bf27b5f Add "-pthread" to the LINKFLAGS 2022-05-10 17:23:03 +03:00
Ivan Kravets
2c99607d3d Pass "-pthread" flag to GoogleTest only on Unix OS 2022-05-10 16:46:48 +03:00
Ivan Kravets
c09af13b7f Add "-pthread" flag for GoogleTest 2022-05-10 16:13:30 +03:00
Ivan Kravets
ee6b498ca9 Optimize unit testing report CLI 2022-05-10 15:25:30 +03:00
Ivan Kravets
65f2f02d93 Add support for GoogleTest testing and mocking framework // Resolve #3572 2022-05-10 14:30:02 +03:00
Ivan Kravets
960edb5611 Use full testing program path on Windows 2022-05-10 11:59:59 +03:00
Ivan Kravets
cda7a97e67 Do not automatically generate JSON report 2022-05-09 22:32:16 +03:00
Ivan Kravets
c520700276 Export testcase file & line to JUnit XML 2022-05-09 19:20:33 +03:00
Ivan Kravets
a7654a6098 Move Unity code parts to the Unity runner 2022-05-09 18:58:43 +03:00
Ivan Kravets
814679522a Do not override embedded std flag 2022-05-09 18:49:15 +03:00
Ivan Kravets
4249349c2b Add hint about verbose output 2022-05-09 18:40:46 +03:00
Ivan Kravets
d065646d3e Update SPDX license list to v3.17 2022-05-09 10:08:08 +03:00
Ivan Kravets
0cf7aeeec9 Fix test on Github Actions 2022-05-08 14:42:07 +03:00
Ivan Kravets
277ccdafb6 Bump version to 6.0.0b1 2022-05-07 17:58:42 +03:00
Ivan Kravets
5b00f6fb95 Skip "test_doctest_framework" from Github Actions / Windows 2022-05-07 17:55:32 +03:00
Ivan Kravets
3f46a97b6b Fix LDF lib resolving 2022-05-07 16:44:11 +03:00
Ivan Kravets
3989979ca3 Pass extra arguments to the native program with a new "pio run --program-arg" option // Resolve #4246 2022-05-07 16:22:05 +03:00
Ivan Kravets
50eda82e27 Fix test 2022-05-07 14:09:11 +03:00
Ivan Kravets
daa3481862 Pass extra arguments to the testing program with a new "pio test --program-arg" option // Resolve # 3132 2022-05-07 13:31:19 +03:00
Ivan Kravets
2d94000dd5 Rename source.file to source.file name and report project folder 2022-05-07 13:24:27 +03:00
Ivan Kravets
e3eb155d76 Improve doctest results parser 2022-05-07 13:23:03 +03:00
Ivan Kravets
f95e23118c Fix test 2022-05-06 21:57:39 +03:00
Ivan Kravets
82778473fe New: "doctest" testing framework // Resolve #4240 2022-05-06 20:00:23 +03:00
Ivan Kravets
dae3b9665b Implement TestCase.humanize 2022-05-06 19:56:39 +03:00
Ivan Kravets
f19058df65 Try to resolve paths if the common part is not found 2022-05-06 19:40:00 +03:00
Ivan Kravets
3c7bec7c61 Exclude SVG files by default 2022-05-06 19:39:21 +03:00
Ivan Kravets
c4388a6904 Fixed an issue when LDF ignores build_src_flags in the “deep+” mode // Resolve #4253 2022-05-06 10:31:34 +03:00
Ivan Kravets
6d1e637518 Add support for Semihosting and Unit Testing // Resolve #3516 2022-05-05 17:36:15 +03:00
Ivan Kravets
bbd56d6eb0 Document using QEMU, Renode, SimAVR simulators with Unit Testing // Resolve #4238 2022-05-05 15:33:39 +03:00
Ivan Kravets
0b317ef04b Implement buffering for the testing output 2022-05-05 13:02:27 +03:00
Ivan Kravets
c0cfbe2ce0 Using hardware Simulators for Unit Testing // Issue #4238 2022-05-04 23:20:37 +03:00
Ivan Kravets
3ed5d41df5 Strip ANSI codes from Unity output 2022-05-04 18:56:57 +03:00
Ivan Kravets
517ee6532f Move "strip_ansi_codes" to the util 2022-05-04 18:55:34 +03:00
Ivan Kravets
653f22f85b Fix issue with nested interpolation 2022-05-04 14:52:11 +03:00
Ivan Kravets
38906478d3 Professional collaborative platform for safety-critical and declarative embedded development 2022-05-03 22:09:25 +03:00
Ivan Kravets
e81d83b8c2 Added support for a Custom Unity Library // Resolve #3980 2022-05-03 21:47:20 +03:00
Ivan Kravets
b12d9f62b9 Show list of failed tests in the summary // Resolve #4251 2022-05-03 19:30:15 +03:00
Ivan Kravets
0849e5faad Rename "src_filter" and "src_build_flags" options // Resolve #4245 2022-05-03 18:39:49 +03:00
Ivan Kravets
1a4419059d Added support for "socket://" and "rfc2217://" protocols using "test_port" option // Resolve #4229 2022-05-03 18:11:23 +03:00
Ivan Kravets
4ef1333abc Refactor test runner mixins to the test output readers 2022-05-03 15:21:53 +03:00
Ivan Kravets
2b11f64ef1 New Custom Testing Framework 2022-05-03 14:30:15 +03:00
Ivan Kravets
5b98f432f2 Update deps 2022-05-03 14:25:29 +03:00
Ivan Kravets
76779e6af4 Sync docs 2022-05-01 23:00:25 +03:00
Ivan Kravets
738d537266 Docs: Sync Intel MCS51 dev-platform 2022-05-01 20:10:25 +03:00
Ivan Kravets
327d5990d6 Docs: Minor improvements 2022-04-29 21:51:35 +03:00
Ivan Kravets
16021d0df7 Added support for "Test Hierarchies" // Issue #4135 2022-04-29 20:46:43 +03:00
Ivan Kravets
b37a74dfd9 Refactor Unit Testing documentation 2022-04-29 20:46:04 +03:00
Ivan Kravets
d02f02731f Rename the "test_build_project_src" project configuration option to "test_build_src" 2022-04-29 20:44:28 +03:00
Ivan Kravets
4295c54c67 Sync docs and examples 2022-04-29 14:50:15 +03:00
Ivan Kravets
fb1e4fa02b Add "--filter" option to the pio remote test command 2022-04-28 22:02:16 +03:00
Sebastian Guarino
62b8a63b80 Add --filter to remote test (#4244) 2022-04-28 18:25:43 +03:00
Valerii Koval
ab3c832f5e Pylint fix 2022-04-27 21:15:08 +03:00
Valerii Koval
d380e7ea01 Update Cppcheck and PVS-Studio tools to the latest available 2022-04-27 20:47:13 +03:00
Valerii Koval
e69fd5e682 Minor improvements to check tools
- Better handling of unusual macro for PVS-Studio
- Fail the analysis if Cppcheck exited with an internal error
2022-04-27 20:45:21 +03:00
Valerii Koval
285f19e132 Properly handle cases when path to a file with a defect is unknown
Resolves #4237
2022-04-27 20:40:55 +03:00
Ivan Kravets
4151f53e14 Rename unit testing module to "test" 2022-04-26 15:09:51 +03:00
Ivan Kravets
5895fb9faf Bump version to 6.0.0a2 2022-04-25 22:11:50 +03:00
Ivan Kravets
19e22d74f3 Fix unit testing case 2022-04-25 15:30:54 +03:00
Ivan Kravets
26ed6a5548 Implement required setUp/tearDown functions for the latest Unity testing framework 2022-04-25 13:23:33 +03:00
Ivan Kravets
05dd7dd811 Revert back showing test cases status before 2022-04-24 21:08:49 +03:00
Ivan Kravets
8b694f3734 Unity: show test case status before stdout 2022-04-24 11:28:07 +03:00
Ivan Kravets
c9026a1b9c Generate reports in JUnit and JSON formats // Resolve #2891 2022-04-23 19:19:25 +03:00
Ivan Kravets
9b221a06c8 Unity: Avoid "weak" attributes on Windows 2022-04-23 11:05:28 +03:00
Ivan Kravets
f88904e246 Export "ConfigureDebugFlags" to build env (bakward compatibility with Zephyr build script) 2022-04-22 18:14:28 +03:00
Ivan Kravets
e3533dcb01 Added support for test hierarchies (nested test suites) // Resolve #4135 2022-04-22 15:19:12 +03:00
Ivan Kravets
8edb5ffe20 Use unsigned long for unityOutputStart 2022-04-22 10:55:59 +03:00
Ivan Kravets
90e6cd7b46 Fixed an issue when command line parameters do not override values // Resolve #3845 2022-04-21 20:23:30 +03:00
Ivan Kravets
1fa73fb632 Typo fixes 2022-04-21 20:22:57 +03:00
Ivan Kravets
a615af233a Provide more information when the native program crashed on a host (errored with a negative return code) // Resolve #3429 2022-04-21 19:32:12 +03:00
Ivan Kravets
4817e13823 PyLint fixes 2022-04-21 19:30:55 +03:00
Ivan Kravets
ee43b86742 Introduce a new PlatformIO Unit Testing engine 2022-04-21 18:11:49 +03:00
Ivan Kravets
93bfc57dea Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2022-04-21 17:12:31 +03:00
Ivan Kravets
a568a5c356 Keep recursive for the glob 2022-04-21 17:10:38 +03:00
Valerii Koval
0b21977e48 Sync docs 2022-04-21 17:07:21 +03:00
Ivan Kravets
2f7668aef5 Improve src matcher for the symbolic links 2022-04-21 16:31:40 +03:00
Ivan Kravets
72fa6eebba Switch to FS JSON loader 2022-04-21 16:30:55 +03:00
Ivan Kravets
2f6a417168 Move test 2022-04-20 18:54:40 +03:00
Ivan Kravets
faa63727ab Revert back to title() 2022-04-20 18:48:26 +03:00
Ivan Kravets
a2b1a0a0a7 Use capitalize instead of title 2022-04-20 18:36:28 +03:00
Ivan Kravets
0d7bc09c49 Cache DL requests 2022-04-20 18:33:46 +03:00
Ivan Kravets
f57ca747a9 Add support for DL mirrors 2022-04-20 18:03:55 +03:00
Ivan Kravets
624421e4b0 Memoize dev-platform instance cross the clonned build envs 2022-04-19 13:51:43 +03:00
Ivan Kravets
943c6bc59c Move INO converter to a separate tool 2022-04-19 11:36:05 +03:00
Ivan Kravets
9ce0b0e25b Use builtin "title()" 2022-04-19 11:33:56 +03:00
Ivan Kravets
df3a13fc61 Move MISSING to the compat 2022-04-19 11:32:36 +03:00
Ivan Kravets
5a0a215bfc Use PY3 super() zero-argument syntax 2022-04-15 14:44:30 +03:00
Ivan Kravets
eaff7f307c Avoid RecursionError for circular_dependencies // Resolve #4228 2022-04-15 14:17:21 +03:00
Ivan Kravets
8d63591ce8 Extend "library.json" with an example for passing flags to library dependencies // Resolve #1941 2022-04-13 18:55:44 +03:00
Ivan Kravets
0e3aa29689 Introduce PlatformIO Core 6.0 2022-04-13 15:32:05 +03:00
Ivan Kravets
a56b19ff65 Improve pio exec command on Windows 2022-04-13 13:58:31 +03:00
Ivan Kravets
62b7ec271f Keep PY2 for backward compatibility with ESP8266/ESP32 // Resolve #4226 2022-04-13 12:51:13 +03:00
Ivan Kravets
5515bef3d7 Add backward compatibility with ESP-IDF build script // Resolve #4225 2022-04-13 12:47:17 +03:00
Ivan Kravets
092f5de231 Fix removing temporary debugging data on Windows 2022-04-12 18:17:38 +03:00
Ivan Kravets
81fdd75aac Report problematic file before publishing package to the registry 2022-04-12 12:30:49 +03:00
Ivan Kravets
f63b2f79e0 Fixed an issue when GCC preprocessor was applied to the ".s" assembly files on case-sensitive OS such as Window OS // Resolve #3917 2022-04-10 19:21:03 +03:00
Ivan Kravets
0501d55c8f Fixed an issue with calling an extra script located outside a project // Resolve #4220 2022-04-10 19:09:29 +03:00
Ivan Kravets
fe6f51369e Autoinstall dev-platform for the "clean" target 2022-04-10 13:56:44 +03:00
Ivan Kravets
8f454c7e9c Bump version to 5.3.0b5 2022-04-09 20:31:40 +03:00
Ivan Kravets
965feccfdc Extended Interpolation of Values with "${this}" pattern // Resolve #3953 2022-04-09 20:31:06 +03:00
Ivan Kravets
5e18f9bbda Finally removed all tracks to the Python 2.7 2022-04-09 17:46:21 +03:00
Ivan Kravets
541fcbf015 Added a new build variable (COMPILATIONDB_INCLUDE_TOOLCHAIN) to include toolchain paths in the compilation database // Resolve #3735 2022-04-09 12:53:22 +03:00
Ivan Kravets
16f5374474 Typo fix 2022-04-08 21:58:29 +03:00
Ivan Kravets
b414745aa1 Fixed an issue when LDF ignores the project "lib_deps" while resolving library dependencies // Resolve #3598 2022-04-08 18:37:16 +03:00
Ivan Kravets
696d95bf1b Black formatter 2022-04-08 18:36:43 +03:00
Ivan Kravets
1269ce064a Improved detection of a package type from the tarball archive // Resolve #3828 2022-04-08 13:58:40 +03:00
Max Prokhorov
9097d455db Avoid working with detached / non-existent git branches when checking for updates (#4217)
* Avoid working with detached / non-existent git branches when checking for updates

b/c we can't use `pull` anyway in that situation
Otherwise, ask for the specific branch via `refs/heads/{branch}` and
also fail when it is not available

* Update vcsclient.py

Co-authored-by: Ivan Kravets <me@ikravets.com>
2022-04-08 13:15:35 +03:00
Ivan Kravets
1615159014 Fix test 2022-04-08 12:03:31 +03:00
Ivan Kravets
e4e1e72c30 Bump version to 5.3.0b4 2022-04-07 23:10:35 +03:00
Ivan Kravets
43329b7748 Minor improvements for symlink support // Issue #3348 2022-04-07 23:03:40 +03:00
Ivan Kravets
2280865936 Resovle symlink based on the saved cwd 2022-04-05 09:11:10 +03:00
Ivan Kravets
fb2f3c8836 Resovle symlink based on the saved cwd 2022-04-05 09:07:44 +03:00
Ivan Kravets
e2f21212b7 Added support for symbolic links allowing pointing the local source folder to the Package Manager // Resolve #3348 2022-04-04 23:14:19 +03:00
Ivan Kravets
d7597d0992 Cache downloads cleanup 2022-04-04 22:45:25 +03:00
Ivan Kravets
c21876ebe3 Typo fix in class name 2022-04-04 22:22:22 +03:00
Ivan Kravets
76bea5b7a7 Cache downloads cleanup 2022-04-04 22:21:06 +03:00
Ivan Kravets
a03d82ff1a Replace package meta URL with URI 2022-04-04 14:18:11 +03:00
Ivan Kravets
f555656c92 Bump version to 5.3.0b3 2022-04-03 23:18:01 +03:00
Ivan Kravets
f289ebd1f3 Revert back lib deps tree to ascii chars 2022-04-03 23:17:29 +03:00
Ivan Kravets
41b3646012 Bump version to 5.3.0b2 2022-04-03 19:54:03 +03:00
Ivan Kravets
8de5db4b48 Added support for “scripts” in package manifest // Resolve #485 2022-04-03 19:53:34 +03:00
Ivan Kravets
d8be12dcdd PyLint fix 2022-04-03 10:54:23 +03:00
Ivan Kravets
71f9401e23 Fixed an issue when manually removed dependencies were not uninstalled from the storage // Resolve #3076 2022-04-02 22:30:35 +03:00
Ivan Kravets
cdd63dec65 Do not process package that was installed into the "env" storage // Resolve #2910 2022-04-02 16:38:54 +03:00
Ivan Kravets
279fdfc47a Show project dependency licenses when building in the verbose mode 2022-04-02 16:28:40 +03:00
Ivan Kravets
feda42f18f Added support for multi-licensed packages in library.json using SPDX Expressions // Resolve #4037 2022-04-02 14:19:24 +03:00
Ivan Kravets
d86f7fc25e Added ability to override a tool version using the "platform_packages" option // Resolve #3798 2022-04-01 22:05:30 +03:00
Ivan Kravets
e4fb675d5f Install only missed dependencies for the private libraries // Resolve #2910 2022-04-01 17:25:40 +03:00
Ivan Kravets
25e786e6a5 Docs: Sync with dev-platforms 2022-04-01 14:29:38 +03:00
Ivan Kravets
fd01e98cb1 Fix an issue with automatic installation of debug dependencies 2022-04-01 13:47:07 +03:00
Ivan Kravets
2a88cdb8df Bump version to 5.3.0b1 2022-03-31 19:26:21 +03:00
Ivan Kravets
be8f842061 Automatically install dependencies of the local (private) libraries // Resolve #2910 2022-03-31 19:25:44 +03:00
Ivan Kravets
fcb81ae074 Update docs with the new Package Specifications // Resolve #3373 2022-03-31 15:44:16 +03:00
Ivan Kravets
7d9c018b44 Implement Click logging handler for package manager 2022-03-30 21:40:59 +03:00
Ivan Kravets
a6e12532f8 Implement pio pkg search command // Issue #3373 2022-03-30 17:32:05 +03:00
Ivan Kravets
bd202f55ce Rename search "filters" to "qualifiers" 2022-03-30 14:43:02 +03:00
Ivan Kravets
f7b5a7bed8 Added support for the custom Clang-Tidy configuration file // issue #4186 2022-03-30 12:01:17 +03:00
Zach Zodkoy
6123d6f9bf Don't append --checks=* when the --config or --config-file flags are set (#4210)
Appending --checks=* causes clang-tidy to ignore the flags --config
and --config-file, which breaks the ability to use a clang-tidy file
2022-03-30 11:47:14 +03:00
Ivan Kravets
6c8173d1aa Implement pio pkg show command // Issue #3373 2022-03-29 16:39:48 +03:00
Ivan Kravets
d2f857d176 Lock "click" dependency for Python 3.6 2022-03-28 20:56:23 +03:00
Ivan Kravets
1e2afafbc4 Use parse_datetime API 2022-03-28 18:18:51 +03:00
Ivan Kravets
927c5c5e36 Do not install any dependencies on the "clean" target 2022-03-28 00:05:20 +03:00
Ivan Kravets
b2ea96b4a7 Resolve package path 2022-03-27 22:34:43 +03:00
Ivan Kravets
6afb53dd7d PyLint fixes 2022-03-27 22:34:22 +03:00
Ivan Kravets
d7477833d6 PyLint fixes 2022-03-24 14:29:32 +02:00
Ivan Kravets
7624645626 Implement pio pkg list command // Issue #3373 2022-03-24 14:17:18 +02:00
Ivan Kravets
53753c0127 Do not install dependencies that are built-in libraries 2022-03-23 18:01:23 +02:00
Ivan Kravets
95604ff66a Minor enhancements 2022-03-23 18:00:31 +02:00
Ivan Kravets
99e0d1071a Add package METAVAR for CLI 2022-03-23 17:57:18 +02:00
Ivan Kravets
13aacbcc05 Dump only required toolchains 2022-03-23 17:56:15 +02:00
Ivan Kravets
b137b25169 Enhance library dependency tree 2022-03-23 17:55:27 +02:00
Ivan Kravets
b44fb101c4 Remove deprecated code 2022-03-21 18:38:36 +02:00
Ivan Kravets
accc8ac254 Add test for "pio pkg outdated" command 2022-03-21 16:00:29 +02:00
Ivan Kravets
435a526140 Implement pio pkg update command // Issue #3373 2022-03-20 15:40:44 +02:00
Ivan Kravets
346580d955 Do not warn about unknown packages if they are built-in libraries 2022-03-19 18:13:29 +02:00
Ivan Kravets
81f343dbe8 Cleanup dev-platform package installer 2022-03-19 18:12:36 +02:00
Ivan Kravets
fa443f2e5f Strict PackageItem comparison 2022-03-19 18:08:34 +02:00
Ivan Kravets
a25a86e42f Init dev-platform with autoinstallation 2022-03-19 18:07:19 +02:00
Ivan Kravets
1ffa924483 Fix test 2022-03-16 18:17:21 +02:00
Ivan Kravets
463a16a68f Implement "pio pkg uninstall" command // Issue #3373 2022-03-16 16:23:09 +02:00
Ivan Kravets
d2adca8d68 Minor improvements 2022-03-16 16:18:59 +02:00
Ivan Kravets
057bf89894 Sync "asrmicro650x" dev-platform 2022-03-16 12:36:22 +02:00
Ivan Kravets
c9037982d7 Save tool deps into the "platformio.ini" // Issue #3373 2022-03-14 13:37:47 +02:00
Ivan Kravets
ce1264564f Ensure default libs are saved 2022-03-14 12:31:48 +02:00
Ivan Kravets
61ffab376d Split code 2022-03-14 12:18:05 +02:00
Ivan Kravets
f3bcaae4e4 Update deps 2022-03-13 17:54:13 +02:00
Ivan Kravets
2201214717 Allow to skip saving of package dependencies to the "platformio.ini" // Issue #3373 2022-03-09 19:07:11 +02:00
Ivan Kravets
eba4231cdc Move test 2022-03-09 19:01:37 +02:00
Ivan Kravets
de0a810fcf Update "wsproto" dependencies to the "1.1.*" 2022-03-09 14:18:09 +02:00
Ivan Kravets
644fc36c32 Revert back to using TOX tmp dir for PyTest 2022-03-08 18:29:54 +02:00
Ivan Kravets
41144bffeb Reset custom project config per command 2022-03-08 18:00:10 +02:00
Ivan Kravets
c84709dd9d Switch to the new "pio pkg install" command 2022-03-08 15:57:25 +02:00
Ivan Kravets
f28651eaf7 Ensure package dependencies are installed // Resolve #2573 2022-03-08 14:59:12 +02:00
Ivan Kravets
9e40eb992e Implement unified "pio pkg install" CLI // Issue #3373 2022-03-08 14:58:01 +02:00
Ivan Kravets
f445cb7895 Ignore Python3 "__pycache__" binaries 2022-03-06 16:00:01 +02:00
Volodymyr Shymanskyy
dfc0ecdf69 #StandWithUkraine (#4195) 2022-03-06 13:20:54 +02:00
Ivan Kravets
6f11f812f8 Ignore files according to the patterns declared in ".gitignore" when using pio package pack // Resolve #4188 2022-02-23 18:46:53 +02:00
Ivan Kravets
4191a9bc3c Fixed issue linked to package refactoring // Resolve #4189 2022-02-23 13:37:02 +02:00
Ivan Kravets
f2fbdafe64 Use the latest PIO Remote dependencies on non-ARM platforms // Issue #3865 2022-02-22 13:36:11 +02:00
Ivan Kravets
22a037b213 Better handling of the failed tests using "Unit Testing" solution 2022-02-22 13:02:10 +02:00
Ivan Kravets
dbe3ab6c97 Docs: Fix platformio.ini contents for Zephyr and Nordic nRF52-DK tutorial 2022-02-21 19:27:05 +02:00
Ivan Kravets
6bed610af3 Check for invalid version with leading zeros 2022-02-21 18:02:56 +02:00
Ivan Kravets
4d9547066b Show package size before publishing to the registry 2022-02-21 15:00:13 +02:00
Ivan Kravets
54c18ae0c6 Fix test on Win 2022-02-19 21:10:57 +02:00
Ivan Kravets
e49fb9f0d0 Minor Py.Test fixes 2022-02-19 20:45:37 +02:00
Ivan Kravets
33da2af31e Improve pio pkg exec test 2022-02-19 19:22:40 +02:00
Ivan Kravets
bcb3678055 Add test for pio pkg exec command 2022-02-18 21:03:12 +02:00
Ivan Kravets
28da2d245b Handle "BlockingIOError" when locking file resource 2022-02-18 18:51:03 +02:00
Ivan Kravets
e6864adfb6 Minor improvements 2022-02-18 18:34:50 +02:00
Ivan Kravets
8562319638 Do not handle built-in libraries when using package manager 2022-02-18 18:34:24 +02:00
Ivan Kravets
6be17cec37 Added support for dependencies declared in a "tool" type package 2022-02-18 17:51:07 +02:00
Ivan Kravets
f34e6e9c4c Port package management "print_message" to the Python logging system 2022-02-18 12:57:30 +02:00
Ivan Kravets
e8051838a3 Dropped support for "pythonPackages" field in "platform.json" manifest in favor of "Extra Python Dependencies" 2022-02-17 17:25:21 +02:00
Ivan Kravets
f1f5497d8d Fix test 2022-02-16 22:33:16 +02:00
Ivan Kravets
1b44ba4ce0 Dropped automatic updates of global libraries and development platforms // Resolve#4179 2022-02-16 21:53:18 +02:00
Ivan Kravets
a4d2dc856c Do not check for "system prune" for newest PlatformIO Core installation 2022-02-16 21:08:13 +02:00
Ivan Kravets
7964d1c2bf Docs: Add community book "Developing IoT Projects with ESP32" 2022-02-15 20:49:26 +02:00
Ivan Kravets
5df5dd155f Bump version to 5.3.0a3 2022-02-12 23:14:16 +02:00
Ivan Kravets
89cce21161 Move "pio exec" command to "pio pkg exec" // Issue #4163 2022-02-12 23:13:17 +02:00
Ivan Kravets
0bdef36e2a pio pkg outdated - check for project outdated packages // Issue #3373 2022-02-12 23:06:10 +02:00
Ivan Kravets
e549a07901 Typo fix 2022-02-12 23:01:20 +02:00
Ivan Kravets
98603dad66 Configure platform instance with project packages using "configure_project_packages" API 2022-02-12 21:59:27 +02:00
Ivan Kravets
c37fbda7a8 Bump version to 5.3.0a2 2022-02-11 22:42:50 +02:00
Ivan Kravets
34ea4d8f41 Move "debug" command to its main module 2022-02-11 22:42:02 +02:00
Ivan Kravets
452a76105f Update command titles 2022-02-11 22:33:33 +02:00
Ivan Kravets
4982676ca8 Rename "package" command to "pkg" 2022-02-11 22:24:37 +02:00
Ivan Kravets
83d115acca Ensure that platform directory path is string or bytes 2022-02-11 22:22:20 +02:00
Ivan Kravets
86bd0f7c37 Show current working directory, not a path to platformio.ini 2022-02-11 22:21:44 +02:00
Ivan Kravets
83fe00a0cf Revert "Run library extra script only at a build process" (breaks mbed framework) // Issue #3915 2022-02-11 17:00:33 +02:00
Ivan Kravets
526abc6a9f Improved PIO Remote setup on credit-card sized computers (Raspberry Pi, BeagleBon, etc) // Resolve #3865 2022-02-11 14:42:17 +02:00
Ivan Kravets
63feda6efc Simplify dependency on "zeroconf" package // Resolve #4177 2022-02-11 12:15:47 +02:00
Ivan Kravets
c9b3dedbb0 Merge tag 'v5.2.5' into develop
Bump version to 5.2.5

# Conflicts:
#	HISTORY.rst
#	docs
#	platformio/__init__.py
2022-02-10 21:02:47 +02:00
Ivan Kravets
dae8dfe1fc Merge branch 'release/v5.2.5' 2022-02-10 20:59:25 +02:00
Ivan Kravets
100def7609 Bump version to 5.2.5 2022-02-10 20:59:16 +02:00
Ivan Kravets
8594012fa1 Update deps 2022-02-10 20:55:38 +02:00
Ivan Kravets
27400f66a9 Strip the path to userhome dir on Linux // Resolve #4173 Issue #4158 2022-02-10 20:55:31 +02:00
Ivan Kravets
bb1e590222 Update SPDX License List to 3.16 2022-02-10 20:55:18 +02:00
Kalle Bracht
a4b414010d Removing inconsistent dot at README.rst, HISTORY.rst and CONTRIBUTING.md (#4172)
* Removing inconsistent dot at README list

* Removing inconsistent dot at HISTORY file

* Removing inconsistent dot at CONTRIBUTING file
2022-02-10 20:55:08 +02:00
Ivan Kravets
1d72a96654 Merge tag 'v5.2.5' into develop
Bump version to 5.2.5

# Conflicts:
#	docs
#	platformio/__init__.py
2022-02-10 20:52:16 +02:00
Maciej Augustyniak
9b85ed86a9 fix: Added udev rule for FireBeetle-ESP32. (#4168) 2022-02-10 20:50:55 +02:00
Ivan Kravets
e36066a9a2 Move package's related commands to "package" sub-folder 2022-02-10 15:22:20 +02:00
Ivan Kravets
8082158a16 Update deps 2022-02-08 17:40:50 +02:00
Ivan Kravets
1a8567a6da Sync docs 2022-02-08 17:33:58 +02:00
Ivan Kravets
b17cbe30e2 Strip the path to userhome dir on Linux // Resolve #4173 Issue #4158 2022-02-08 17:21:13 +02:00
Ivan Kravets
8aadc88dd5 Update SPDX License List to 3.16 2022-02-07 13:46:47 +02:00
Kalle Bracht
f3d26fae64 Removing inconsistent dot at README.rst, HISTORY.rst and CONTRIBUTING.md (#4172)
* Removing inconsistent dot at README list

* Removing inconsistent dot at HISTORY file

* Removing inconsistent dot at CONTRIBUTING file
2022-02-07 13:45:56 +02:00
Ivan Kravets
828d6f5baf Fixed a "module 'asyncio' has no attribute 'run'" error when launching PIO Home using Python 3.6 // Resolve #4169 2022-02-05 20:00:37 +02:00
Maciej Augustyniak
2003806481 fix: Added udev rule for FireBeetle-ESP32. (#4168) 2022-02-05 13:13:43 +02:00
Ivan Kravets
362823c1e1 Bump version to 5.2.5b1 2022-02-04 19:15:55 +02:00
Ivan Kravets
9c10e00234 Run command from a PlatformIO package with a new pio exec command // Resolve #4163 2022-02-04 19:15:31 +02:00
Ivan Kravets
a4cef2fbd8 Bump version to 5.2.5a7 2022-02-03 15:33:30 +02:00
Ivan Kravets
e5fca99b52 Run library extra script only at a build process // Resolve #3915 2022-02-03 15:33:03 +02:00
Ivan Kravets
f4c692eed2 Bump PIO Home to 3.4.1 2022-02-02 17:42:28 +02:00
Ivan Kravets
2e0688db5f Fix test 2022-02-02 12:42:31 +02:00
Ivan Kravets
ac2b358f87 Docs: generate docs from the registry 2022-02-01 21:56:53 +02:00
Ivan Kravets
251a2c9fa4 Docs: link packages with the registry 2022-02-01 15:38:15 +02:00
Ivan Kravets
0064d4b2c5 Docs: remove deprecated links to "boards" page 2022-02-01 15:01:58 +02:00
Ivan Kravets
ebbac6b483 Use "black" profile 2022-02-01 15:00:47 +02:00
Ivan Kravets
d5373a62f4 Docs: Sync dev-platforms 2022-01-28 14:24:25 +02:00
Ivan Kravets
681b91a6a4 Update deps 2022-01-23 14:17:22 +02:00
CommanderRedYT
8c66352994 Fixed wrong path (#4158)
* Fixed wrong path

On linux, "Documents" doesn't have to be the right folder. It depends on the language selected when installing the operating system.

* Refactor code

* Update HISTORY.rst

Co-authored-by: Ivan Kravets <me@ikravets.com>
2022-01-20 12:19:30 +02:00
Ivan Kravets
4e1ec1215a Bump version to 5.2.5a6 2022-01-19 17:16:44 +02:00
Ivan Kravets
6981894060 Minor updates 2022-01-19 17:16:23 +02:00
Ivan Kravets
57c92e877c Respect disabling debugging server from platformio.ini 2022-01-19 16:53:31 +02:00
Ivan Kravets
e8c0b8504a Ignore annoying "ms-vscode.cpptools-extension-pack" for VSCode and C/C++ files 2022-01-15 22:27:30 +02:00
Ivan Kravets
93bbe8f2a3 Update deps 2022-01-15 15:00:55 +02:00
Ivan Kravets
c78bb1f572 Docs: Remove icons from navbar 2022-01-11 14:11:32 +02:00
Scott Lahteine
7256102785 Unix line-endings for extensions.json (#4153) 2022-01-09 13:58:39 +02:00
Ivan Kravets
fc907c568d Improved checking of available Internet connection for IPv6-only workstations // Issue #4151 2022-01-08 15:08:39 +02:00
Ivan Kravets
9e078ff4d7 Sync docs 2022-01-08 15:00:35 +02:00
Alexey Vazhnov
5658e7f718 _internet_on: try IPv4, if not acceptable — try IPv6 (#4151)
* _internet_on: try IPv4, if not acceptable — try IPv6

* _internet_on: replace IPv4 `socket.socket` + IPv6 `socket.socket` with one universal `socket.create_connection`
2022-01-08 14:59:47 +02:00
Ivan Kravets
111eb55a9f Docs: Update "platformio.ini" examples 2022-01-05 15:00:41 +02:00
Ivan Kravets
0630ec5503 Bump version to 5.2.5a5 2022-01-04 17:18:14 +02:00
Ivan Kravets
38cc493eb7 Minor improvements 2022-01-04 17:17:51 +02:00
Ivan Kravets
254507c3a3 Escape custom request arguments 2022-01-04 15:02:48 +02:00
Ivan Kravets
7cdcc9099b Escape custom request arguments 2022-01-04 14:53:34 +02:00
Ivan Kravets
fb046c43ea Require authorization for package downloading 2022-01-04 14:46:51 +02:00
Ivan Kravets
73ddf80fc1 Refactor authentication part for clients 2022-01-04 14:45:14 +02:00
Ivan Kravets
a5a224ac6f Sync docs 2022-01-03 13:05:53 +02:00
Ivan Kravets
c56dfda833 Minor fixes 2022-01-02 23:08:21 +02:00
Ivan Kravets
6081f9ff1b Switch to the universal Twisted 2022-01-02 23:08:12 +02:00
Ivan Kravets
f3c7d71b3b Sync docs 2022-01-02 19:46:52 +02:00
Ivan Kravets
5748bf9549 Extend packing filters 2021-12-29 15:03:43 +02:00
Ivan Kravets
84a0a6a418 Update deps 2021-12-24 18:14:29 +02:00
Ivan Kravets
1ee9f183cc Fix test 2021-12-24 18:14:18 +02:00
Ivan Kravets
55e8523925 Improve docs for "dependencies" field of library.json 2021-12-24 15:04:54 +02:00
Ivan Kravets
c9efe24959 Switch to the new registry 2021-12-22 22:36:32 +02:00
Ivan Kravets
69aff39205 Warn about package publishing time 2021-12-20 20:57:18 +02:00
Ivan Kravets
f6e9e15253 Bump version to 5.2.5a4 2021-12-20 19:28:28 +02:00
Ivan Kravets
b7f685ed62 Fix a bug with expired account session 2021-12-20 19:27:56 +02:00
Ivan Kravets
6e03eff303 Handle base AccountError 2021-12-20 19:05:12 +02:00
Ivan Kravets
3e0b95e1e1 Fix tests 2021-12-18 14:17:22 +02:00
Ivan Kravets
a32997ceba Bump version to 5.2.5a3 2021-12-18 13:54:09 +02:00
Ivan Kravets
63674d85e8 Ignore private packages if user not authorized 2021-12-18 13:53:54 +02:00
Ivan Kravets
56848ece7a Bump version to 5.2.5a2 2021-12-18 13:45:51 +02:00
Ivan Kravets
449722f08c Improved support for private packages in PlatformIO Registry 2021-12-18 13:45:26 +02:00
Ivan Kravets
949b4562c7 Packaging: exclude extras from Arduino libraries 2021-12-15 13:46:30 +02:00
Ivan Kravets
75f68c8be1 Bump version to 5.2.5a1 2021-12-15 12:46:28 +02:00
Ivan Kravets
1b117712cf Merge branch 'release/v5.2.4' 2021-12-15 12:19:59 +02:00
Ivan Kravets
11356af502 Merge tag 'v5.2.4' into develop
Bump version to 5.2.4
2021-12-15 12:19:59 +02:00
Ivan Kravets
9dbdf7fc8d Bump version to 5.2.4 2021-12-15 12:19:51 +02:00
Ivan Kravets
dec38273b6 Cleanup code 2021-12-15 11:59:19 +02:00
Ivan Kravets
5098f5f420 Minor improvements // Issue #3865 2021-12-14 22:55:48 +02:00
Ivan Kravets
d32fd72d13 Bump version to 5.2.4rc1 2021-12-14 22:38:57 +02:00
Ivan Kravets
a4692d5457 Improved PIO Remote setup on credit-card sized computers (Raspberry Pi, BeagleBon, etc) // Resolve #3865 2021-12-14 22:38:31 +02:00
Ivan Kravets
24ea7aaede Update title to PlatformIO Core 2021-12-14 22:37:42 +02:00
Ivan Kravets
b7f10982c3 Update PIO Remote deps // Issue #3865 2021-12-14 21:14:11 +02:00
Ivan Kravets
8f28d1ad43 Update uvicorn to 0.16 2021-12-08 18:45:43 +02:00
Ivan Kravets
d5db2f0eb7 Apply formatting 2021-12-08 18:45:29 +02:00
Ivan Kravets
fe69f3de04 Bump version to 5.2.4b4 2021-12-08 18:40:37 +02:00
Ivan Kravets
5534394b06 Fixed an issue with wrong detecting Windows architecture when Python 32bit is used // Resolve #4134 2021-12-08 18:40:07 +02:00
Ivan Kravets
24fc2f7e14 Sync docs 2021-12-08 18:38:16 +02:00
valeros
5b23c9a294 Add basic test for CLion integration 2021-12-08 13:48:35 +02:00
Ivan Kravets
7338a02b48 Do not pack Python bytecode by default 2021-12-07 15:05:42 +02:00
Ivan Kravets
8555e83cb1 Sync docs 2021-12-07 15:05:25 +02:00
Ivan Kravets
39494d18bf Revert "Revert "Lock "cryptography" to RUST-less 3.3.2 version""
This reverts commit 24e63e7a02.
2021-12-06 20:59:31 +02:00
Ivan Kravets
aab42c3cff Skip library.properties "paragraph" if total len >= 1000 2021-12-03 20:05:37 +02:00
Ivan Kravets
f5a23c3817 Bump version to 5.2.4b3 2021-12-03 17:02:05 +02:00
Ivan Kravets
b3eb81c3b4 Typo fix 2021-12-03 17:01:42 +02:00
Ivan Kravets
4f4c88aca9 Use SCons vars for deprecated variables 2021-12-02 22:16:37 +02:00
valeros
c3ad3ebb57 Properly replace Home Directory in CLion template on Windows
Issue #4071
2021-12-02 20:56:18 +02:00
valeros
f13734dda4 Convert Home Directory path into a cmake-style path on Windows
Resolve #4071
2021-12-02 20:05:35 +02:00
Ivan Kravets
24e63e7a02 Revert "Lock "cryptography" to RUST-less 3.3.2 version"
This reverts commit 3828e6d15e.
2021-12-02 19:30:19 +02:00
Ivan Kravets
a163048396 Bump version to 5.2.4b2 2021-12-02 16:34:35 +02:00
Ivan Kravets
55f8471aff Improved tab completion support for Bash, ZSH, and Fish shells // Resolve #4114 2021-12-02 16:34:05 +02:00
Ivan Kravets
04e9f38e0e Check for default core dir in run-time (solves issue with tests) 2021-12-02 15:06:58 +02:00
Ivan Kravets
90972e9ce0 Sync docs 2021-12-02 14:55:48 +02:00
Ivan Kravets
6e8f60a27a Bump version to 5.2.4b1 2021-12-02 14:20:46 +02:00
Ivan Kravets
014090c407 Fixed an issue when referencing "*_dir" option from a custom project configuration environment // Resolve #4110 2021-12-02 14:19:54 +02:00
Ivan Kravets
e40b251c06 Fixed a bug when the system environment variable does not override a project configuration option // Resolve #4125 2021-12-02 13:13:07 +02:00
Ivan Kravets
414a194c9d Do not claim that library.properties packages is compatible with any dev-platform if "architectures" field is not defined 2021-11-29 20:02:53 +02:00
Ivan Kravets
7bffe3993d Update deps 2021-11-29 20:01:27 +02:00
Ivan Kravets
3828e6d15e Lock "cryptography" to RUST-less 3.3.2 version 2021-11-29 14:31:38 +02:00
Ivan Kravets
85c582bc93 Use "/v3//search" endpoint when searching for packages in registry 2021-11-27 15:00:10 +02:00
Ivan Kravets
ea1c9dec12 Typo fix 2021-11-26 14:21:06 +02:00
Ivan Kravets
6753121a6a Better cleanup package manifest fields 2021-11-26 14:13:06 +02:00
Ivan Kravets
f63d899c42 Ignore duplicated manifest values 2021-11-25 22:35:44 +02:00
Ivan Kravets
7219c9f806 Ignore duplicated manifest values 2021-11-25 22:19:47 +02:00
Ivan Kravets
df2f1d10fd Sync docs 2021-11-25 22:19:01 +02:00
Ivan Kravets
3f71067b67 Update zeroconf deps to 0.37.* 2021-11-22 22:08:57 +02:00
Ivan Kravets
8dc68a01fd Do not print empty errors 2021-11-22 22:08:10 +02:00
Ivan Kravets
9e0ded958c Bump version to 5.2.4a4 2021-11-18 17:56:18 +02:00
Ivan Kravets
68243aa95b Added support for a new "headers" field in "library.json" 2021-11-18 17:55:35 +02:00
Ivan Kravets
507df1f507 Extend platform manifest test with a package owner 2021-11-18 13:31:49 +02:00
Ivan Kravets
1800c29b44 Upgraded build engine to the SCons 4.3 2021-11-18 13:17:26 +02:00
Ivan Kravets
0343548f6e Sync docs 2021-11-18 13:14:55 +02:00
valeros
5cb5c9713e Wrap the path to PlatformIO core in the NetBeans project template
This fixes a possible issue when the path to PlatformIO contains a whitespace

Resolve #4096
2021-11-15 19:22:41 +02:00
Ivan Kravets
5e2c5c793f SPDX License List v3.15 2021-11-15 11:28:57 +02:00
Ivan Kravets
3022cb6955 Bump version to 5.2.4a3 2021-11-12 15:17:55 +02:00
Ivan Kravets
4687665ff3 Improved support for projects located on a network share // Resolve #3417 , Resolve #3926 , Resolve #4102 2021-11-12 15:17:25 +02:00
Ivan Kravets
001f075a49 Bump version to 5.2.4a2 2021-11-09 22:49:21 +02:00
Ivan Kravets
7d78e4a60a Fixed an issue with the CLion project generator when a macro contains a space // Resolve #4102 2021-11-09 22:49:00 +02:00
Pedro Barreto
2786bfbeb8 Escape spaces in CLion CMakeListsPrivate template - FIXES #4085 (#4105)
This fix adds spaces to the regex substitutions on CMakeListsPrivate.txt add_definitions.

Fixes #4102
2021-11-09 22:45:12 +02:00
Ivan Kravets
d3049a8d62 Fix test 2021-11-08 20:08:18 +02:00
Ivan Kravets
831a2582ed Sync docs 2021-11-08 19:31:49 +02:00
Ivan Kravets
0919019123 Bump version to 5.2.4a1 2021-11-05 23:19:22 +02:00
Ivan Kravets
7dd9c99c91 Merge tag 'v5.2.3' into develop
Bump version to 5.2.3
2021-11-05 17:31:41 +02:00
Ivan Kravets
326c24911a Merge branch 'release/v5.2.3' 2021-11-05 17:31:40 +02:00
Ivan Kravets
133fa1495b Bump version to 5.2.3 2021-11-05 17:31:23 +02:00
Ivan Kravets
7c040ed99f Normalize Windows path with Python's pathlib 2021-11-05 17:21:15 +02:00
Ivan Kravets
f88a2de8a9 Filter duplicated recent projects on Windows 2021-11-05 17:05:30 +02:00
Ivan Kravets
a24ec8b07a Grammar fixes 2021-11-05 16:57:44 +02:00
Ivan Kravets
d6ad6f96e8 Bump version to 5.2.3rc1 2021-11-05 16:29:18 +02:00
Ivan Kravets
411764854b Add support for custom device monitor filters located in package folders // Issue #3924 2021-11-05 16:28:49 +02:00
Ivan Kravets
973f77012f Fixed an issue when VSCode's debugger does not honor default environment // Resolve #4098 2021-11-05 14:46:57 +02:00
Maximilian Gerhardt
1d80da2559 Add "inc" as sign that it's the root of the library (#4093)
* Add "inc" as sign that it's the root of the library

* Add "inc" and "Inc"

Co-authored-by: Ivan Kravets <me@ikravets.com>
2021-11-05 14:16:36 +02:00
Ivan Kravets
00d298935a Bump version to 5.2.3b5 2021-11-05 12:58:12 +02:00
Ivan Kravets
4a9a478243 Refactor PIO Home IDE RPC 2021-11-05 12:57:09 +02:00
Ivan Kravets
9040bbb75a Update deps 2021-11-05 12:56:39 +02:00
Ivan Kravets
abcc4c0a12 Bump version to 5.2.3b4 2021-11-02 20:06:08 +02:00
Ivan Kravets
ceb3a19b81 Automatically synchronize active projects between IDE and PlatformIO Home 2021-11-02 20:05:40 +02:00
Ivan Kravets
2a2f7825cc Sync docs 2021-11-01 16:21:47 +02:00
Ivan Kravets
a0e9f6a92d Docs: Sync dev-platforms 2021-11-01 15:57:17 +02:00
Ivan Kravets
dbc73f5086 Use Rust-less "cryptography" dependency for PIO Remote 2021-10-30 14:30:30 +03:00
Ivan Kravets
78a67b754e Docs: Extend a project configuration example with the common "[env]" section 2021-10-26 16:01:50 +03:00
Ivan Kravets
de4b02eaf1 Remove unused module 2021-10-26 15:52:16 +03:00
Ivan Kravets
751c82fd29 Bump version to 5.2.3b3 2021-10-26 15:42:05 +03:00
Ivan Kravets
8c8a94fc71 Run config option validation even in raw mode 2021-10-26 15:41:41 +03:00
Ivan Kravets
1174958e8b Add project.helpers.get_project_all_lib_dirs API (used by platformio-node-helpers) 2021-10-26 14:36:18 +03:00
Ivan Kravets
6399de7a66 Removed deprecated project.helpers API 2021-10-26 14:35:28 +03:00
Ivan Kravets
c0f2275b61 Restore ProjectConfig.get_optional_dir API, "platformio-node-helpers" depends on it 2021-10-26 14:34:32 +03:00
Ivan Kravets
256a9ee45d Revert "Pass system STDIN stream to SCons subprocess"
This reverts commit d7b7d2de6e.
2021-10-26 13:54:49 +03:00
Ivan Kravets
c835ce780a Fixed "UnicodeEncodeError" when a build output contains non-ASCII characters // Resolve #3971 2021-10-25 22:01:11 +03:00
Ivan Kravets
d7b7d2de6e Pass system STDIN stream to SCons subprocess 2021-10-25 21:12:29 +03:00
Ivan Kravets
1dd0635e5e Use secured bitly 2021-10-25 20:25:23 +03:00
Ivan Kravets
67506511c3 Update token for docs/deploy 2021-10-25 19:45:47 +03:00
Ivan Kravets
3fbb4cde36 Bump version to 5.2.3b2 2021-10-25 18:45:04 +03:00
Ivan Kravets
9aaa80a213 Cast Python warnings to errors when running "pytest" 2021-10-25 18:36:10 +03:00
Ivan Kravets
acb6cbffa0 Add "arduplot" to the "Community Filters" // Resolve #4058 2021-10-25 15:54:06 +03:00
Ivan Kravets
6a70ab74bc Update history 2021-10-25 15:24:24 +03:00
Ivan Kravets
852c252302 Added support for custom device monitor filters // Resolve #3924 2021-10-25 15:18:18 +03:00
Ilia Motornyi
3a670b55b6 Update CMakeLists.txt.tpl (#4089) 2021-10-25 14:56:12 +03:00
Ivan Kravets
d01435f4f2 Bump version to 5.2.3b1 2021-10-25 13:28:57 +03:00
Ivan Kravets
f1638c9cd7 Fixed an issue when PIO Remote device monitor crashes on the first keypress // Resolve #3832 2021-10-25 13:24:36 +03:00
Ivan Kravets
4943504898 Bump version to 5.2.3a3 2021-10-24 23:17:30 +03:00
Ivan Kravets
7d7480c120 Show human-readable message when infinite recursion is detected while processing "Interpolation of Values" // Resolve #3883 2021-10-24 22:21:15 +03:00
Ivan Kravets
78182fea0a Disabled resolving of SCons variables when preprocessing "Interpolation of Values" // Resolve #3933 2021-10-24 21:27:25 +03:00
Ivan Kravets
947e57b5b4 Bump version to 5.2.3a2 2021-10-24 20:00:30 +03:00
Ivan Kravets
e0e4a594e9 Fix conf tests on Windows 2021-10-24 19:59:52 +03:00
Ivan Kravets
4839fe37a3 Improved PlatformIO directory interpolation (${platformio.***_dir}) in “platformio.ini” configuration file // Resolve #3934 2021-10-24 18:19:40 +03:00
Phill Price
9914b7ea38 Typo (#4087)
showed > shown
2021-10-23 13:01:48 +03:00
Ivan Kravets
f86ed97820 Bump version to 5.2.3a1 2021-10-22 19:14:17 +03:00
Ivan Kravets
8d8b0807e2 Fixed an issue when the "$PROJECT_DIR" gets the full path to "platformio.ini", not the directory name // Resolve #4086 2021-10-22 19:13:24 +03:00
Ivan Kravets
e3c6237430 Remove unused files 2021-10-20 23:29:34 +03:00
Ivan Kravets
e964c7fa5c Merge branch 'release/v5.2.2' 2021-10-20 18:44:28 +03:00
Ivan Kravets
f1e84e145c Merge tag 'v5.2.2' into develop
Bump version to 5.2.2
2021-10-20 18:44:28 +03:00
Ivan Kravets
2e2773fa6b Bump version to 5.2.2 2021-10-20 18:44:20 +03:00
Ilia Motornyi
a9c7a27d47 Fix CLion 2021.3 support (#4085)
New CMake behavior crashes CLion with apostrophe symbols in `add_definitions` clause
see https://youtrack.jetbrains.com/issue/CPP-26719
2021-10-20 18:08:22 +03:00
Ivan Kravets
e41ecb19cf Resolve an issue with interrupting a running program 2021-10-20 16:21:48 +03:00
Ivan Kravets
5b091b602f Fixed a “TypeError” issue when extending configuration option in “platformio.ini” with the multi-line default value // Resolve #4082 2021-10-20 15:35:01 +03:00
Ivan Kravets
768681c4f2 Remove debugging code // Resolve #4083 2021-10-19 19:27:20 +03:00
Ivan Kravets
2e4e5c1873 Temporary disable CI for Windows+Python 3.10 2021-10-19 19:26:13 +03:00
Ivan Kravets
4a61806e60 Quote Python versions 2021-10-19 18:52:30 +03:00
Ivan Kravets
883187f9ac Bump version to 5.2.2a1 2021-10-19 18:21:28 +03:00
Ivan Kravets
2d9a5031e9 Test PlatformIO Core on Python 3.10 2021-10-19 18:21:21 +03:00
Ivan Kravets
39c93f6512 Override debugging firmware loading mode using `--load-mode option for pio debug` command 2021-10-19 18:20:01 +03:00
Ivan Kravets
a7905b373e Skip CI for macOS & Py 3.6 2021-10-11 16:00:09 +03:00
Ivan Kravets
a7c82ff9b9 Merge branch 'release/v5.2.1' 2021-10-11 15:07:19 +03:00
Ivan Kravets
5b4b4a4051 Merge tag 'v5.2.1' into develop
Bump version to 5.2.1
2021-10-11 15:07:19 +03:00
Ivan Kravets
c348fec609 Bump version to 5.2.1 2021-10-11 15:07:04 +03:00
Ivan Kravets
4af17356f3 Handle ".hpp" files when looking for a library root 2021-10-11 15:01:42 +03:00
Ivan Kravets
384e5052bc Bump version to 5.2.1rc2 2021-10-10 14:09:59 +03:00
Ivan Kravets
a5adae1491 Skip broken Click 8.0.2 release // Resolve #4078 2021-10-10 14:09:17 +03:00
Ivan Kravets
fe62b810db Bump version to 5.2.1rc1 2021-10-08 19:03:12 +03:00
Ivan Kravets
ee78496058 Clean a build environment and installed library dependencies using a new `cleanall` target // Resolve #4062 2021-10-08 19:02:45 +03:00
Ivan Kravets
8afe4bae87 Typo fix 2021-10-08 15:31:26 +03:00
Ivan Kravets
b04bb2b740 Fix Click's "DeprecationWarning: 'resultcallback' has been renamed to 'result_callback'" // Resolve #4075 2021-10-08 15:18:34 +03:00
Ivan Kravets
3d46f0d72f Drop support for Click < 7.1.2 2021-10-08 15:18:19 +03:00
Ivan Kravets
a65d973660 Extend library root signs with "include" and "src" dirs // Resolve #4073 2021-10-08 15:00:05 +03:00
Ivan Kravets
df83d90c06 Handle upper-cased "Include" & "Src" folders 2021-10-08 14:58:41 +03:00
Ivan Kravets
a1d55f2529 Ignore telemetry on "idedata" target 2021-10-08 14:40:23 +03:00
valeros
aa097f3fd6 Update Cppcheck to v2.6.0 // Resolve #3942 2021-10-07 16:43:06 +03:00
Ivan Kravets
e0b72202fd Bump version to 5.2.1b4 2021-09-29 19:21:55 +03:00
Ivan Kravets
e8769fff7d Improved handling of a library root based on "Conan" or "CMake" build systems // Resolve #3887 2021-09-29 19:21:31 +03:00
Ivan Kravets
ed33652534 Handle "test" folder as a part of CLion project // Resolve #4005 2021-09-29 15:44:52 +03:00
cpavot
d1c1f972a6 Propagate agent option to remote device monitor command (#4065)
Signed-off-by: Christophe PAVOT <christophe.pavot@wiifor.com>
2021-09-29 14:47:11 +03:00
Valerii Koval
6008275aae Properly handle in-progress C++ standards when invoking Cppcheck // Resolve #3944 (#4070) 2021-09-29 14:46:02 +03:00
Ivan Kravets
edf8bb3945 Bump version to 5.2.1b3 2021-09-27 22:59:58 +03:00
Ivan Kravets
dd7d133263 Dump "embedded_result.output" 2021-09-27 22:59:36 +03:00
Ivan Kravets
b6f783674b Allowed to override a default library builder via a new `builder field in a build group of library.json` // Resolve #3957 2021-09-26 15:27:41 +03:00
Valerii Koval
eab70fae3b Properly handle "--keep-build-dir" option in platformio ci command (#4061)
This fixes #4011 and possible "FileExists" errors when the "platformio ci"
command by safely copying sources to the build folder
2021-09-23 23:26:42 +03:00
Ivan Kravets
fed40ef104 Add debug information when a test fails on Win/Py3.8 2021-09-17 21:06:08 +03:00
Ivan Kravets
6d087f5a38 Bump version to 5.2.1b2 2021-09-16 22:07:01 +03:00
Ivan Kravets
0edcf33547 Use "ubuntu-18.04" for project examples (CI) 2021-09-16 22:06:45 +03:00
Ivan Kravets
443417b0f4 PyLint fix 2021-09-16 21:56:09 +03:00
Ivan Kravets
369e994b0d Check for "build.mcu" and "build.cpu" when looking for precompiled library // Issue #405 2021-09-16 21:51:53 +03:00
Ivan Kravets
55469327c6 Bump version to 5.2.1b1 2021-09-16 21:16:21 +03:00
Ivan Kravets
27f326673c 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 // Resolve #405 2021-09-16 21:13:54 +03:00
Ivan Kravets
e6fd766fff Bump version to 5.2.1a1 2021-09-14 13:03:47 +03:00
Ivan Kravets
7da3ccfacb Merge tag 'v5.2.0' into develop
Bump version to 5.2.0
2021-09-13 19:00:10 +03:00
Ivan Kravets
624d6b3b0b Merge branch 'release/v5.2.0' 2021-09-13 19:00:09 +03:00
Ivan Kravets
9528083a66 Bump version to 5.2.0 2021-09-13 18:59:53 +03:00
Ivan Kravets
55408f6ccb Fixed an issue when PlatformIO archives a library that does not contain C/C++ source files // Resolve #4019 2021-09-13 14:56:24 +03:00
Ivan Kravets
dce5a39b10 Process "precompiled" and "ldflags" properties of the "library.properties" manifest // Resolve #3994 2021-09-13 14:48:48 +03:00
Ivan Kravets
03a23876a7 Fixed an issue when PlatformIO archives a library that does not contain C/C++ source files // Resolve #4019 2021-09-13 14:04:33 +03:00
Ivan Kravets
775357dd94 Better error handling if git is not installed // Resolve #4013 2021-09-13 13:31:53 +03:00
Dmitry Antyneskul
d10cbb2823 Fix link to clang-tidy (#4049) 2021-09-13 12:36:56 +03:00
valeros
63a2465bac Update check tools to the latest available // Resolve #4041 2021-09-10 18:11:48 +03:00
Ivan Kravets
d97ed52e91 Sync docs 2021-09-07 15:17:59 +03:00
Ivan Kravets
e1dc12c14d Docs: Document "platformio-ide.pioHomeServerHttpHost" setting for VSCode 2021-09-02 12:47:17 +03:00
Ivan Kravets
7c755d4e2d Sync docs 2021-08-31 16:23:24 +03:00
Ivan Kravets
55b786d9f0 Use byte-mode for writing binary file 2021-08-28 13:21:46 +03:00
Ivan Kravets
131f4be4ea Fix PyLint's "use-dict-literal" and "use-list-literal" 2021-08-28 13:14:40 +03:00
Ivan Kravets
d819617d2b Specify encoding for "open()" functions 2021-08-28 13:10:07 +03:00
Ivan Kravets
b9219a2b62 Update "zeroconf" deps to 0.36 2021-08-28 12:31:02 +03:00
Ivan Kravets
554e378dd6 Sync docs 2021-08-28 12:30:38 +03:00
Ivan Kravets
cc11402bc9 Sync docs 2021-08-14 15:41:44 +03:00
Ivan Kravets
40220f92c1 Sync docs 2021-08-14 15:25:25 +03:00
Ivan Kravets
8c4d9021c2 Update deps 2021-08-14 12:53:49 +03:00
Ivan Kravets
efefb02d86 Sync docs 2021-08-14 12:53:30 +03:00
Ivan Kravets
3ee281aaf9 Update SPDX License List to 3.14 2021-08-09 17:46:56 +03:00
Ivan Kravets
097b6d5097 PyLint fixes 2021-08-05 18:13:22 +03:00
Ivan Kravets
6cdaf05f98 Sync docs 2021-08-05 18:13:00 +03:00
Ivan Kravets
3be0f58c30 Sync docs 2021-08-04 14:58:54 +03:00
Ivan Kravets
f3489a3b01 Sync docs 2021-08-02 13:52:06 +03:00
Ivan Kravets
173dbeb24a Bump version to 5.2.0b1 2021-08-02 13:11:23 +03:00
Ivan Kravets
0607b86818 Upgraded build engine to the SCons 4.2 2021-08-02 13:10:37 +03:00
Valerii Koval
1282a65bcb Update Arduino udev rule to include latest Portenta board
Resolves #4014
2021-08-02 12:12:52 +03:00
Ivan Kravets
45d3207dfe Docs: Sync dev-platforms 2021-07-31 18:48:08 +03:00
Ivan Kravets
76b46f59e9 Fix lib test 2021-07-30 20:13:53 +03:00
Ivan Kravets
19fa108f61 Docs: Add "Copy" button to CODE blocks 2021-07-30 17:32:22 +03:00
Ivan Kravets
2372d06591 Sync docs 2021-07-26 19:26:33 +03:00
Ivan Kravets
7015375892 Docs: Revert "html_favicon" path 2021-07-23 15:32:02 +03:00
Ivan Kravets
e9bf2b361f Update deps and sync docs 2021-07-23 15:05:01 +03:00
Ivan Kravets
51b790b767 Bump version to 5.2.0a9 2021-07-12 15:06:42 +03:00
Ivan Kravets
ac84431361 Take into account package's "system" when checking for duplicates 2021-07-12 15:06:06 +03:00
Mikhail
7dc8463da9 Fix charmap error (#3998)
* Fix charmap error

Fix charmap error on cyrilic in platformio.ini file #3493

* Update config.py

Co-authored-by: Ivan Kravets <me@ikravets.com>
2021-07-07 18:25:55 +03:00
Ivan Kravets
71ae579bc0 PyLint fix 2021-07-05 16:06:02 +03:00
Ivan Kravets
5036d25b60 Enable Python version auto-detection for Black formatter 2021-07-05 13:31:23 +03:00
Ivan Kravets
ff6d169862 Fix PyLint for v2.9.3 2021-07-05 13:30:37 +03:00
Otto Winter
dde8898aae Bump zeroconf to 0.32.* (#3991) 2021-07-05 12:57:30 +03:00
Ivan Kravets
72cc23ef46 Fix PyLint warning with "No exception type(s) specified (bare-except)" 2021-06-29 18:25:20 +03:00
Ivan Kravets
5390b4ed42 Add Github token for Slack notification 2021-06-29 18:24:47 +03:00
Ivan Kravets
17c7d90d52 Sync docs 2021-06-29 18:11:08 +03:00
Ivan Kravets
5c3b5be613 Fix TypeError: 'NoneType' object is not callable 2021-06-29 18:07:45 +03:00
Ivan Kravets
5ab7769745 Bump version to 5.2.0a8 2021-06-24 16:43:00 +03:00
Ivan Kravets
05374d1145 Match buffered data from debugging server 2021-06-24 16:42:45 +03:00
Ivan Kravets
311e10f91e Ensure all patterns are replaces in debug init script 2021-06-24 16:00:13 +03:00
Ivan Kravets
2b94791387 Bump version to 5.2.0a7 2021-06-22 14:28:40 +03:00
Ivan Kravets
fbcae11cd0 Fix project generator 2021-06-22 14:28:04 +03:00
Ivan Kravets
0d6eff2a9a Syn docs 2021-06-22 14:27:33 +03:00
Ivan Kravets
6a9b7fdb6d Update SPDX License List to 3.13 2021-06-03 16:32:53 +03:00
Ivan Kravets
e8f703648a Docs: Use Python 3 for CI integration 2021-06-01 18:24:17 +03:00
Ivan Kravets
710f82de0f Up uvicorn to 0.14 & click to 8.0 2021-06-01 17:59:18 +03:00
Ivan Kravets
bee35acfa6 Sync docs 2021-06-01 17:56:55 +03:00
Ivan Kravets
90fdaf80e4 Sync docs 2021-05-31 18:25:54 +03:00
Ivan Kravets
27feb1ddd7 Added support for Click 8.0; updated other deps 2021-05-19 19:43:41 +03:00
Ivan Kravets
2be7e0f7e6 Docs: Promote PlatformIO Labs blog posts 2021-05-13 15:28:09 +03:00
Valerii Koval
186ab70bf9 Add udev rule for Raspberry Pi Pico boards 2021-05-10 11:38:05 +03:00
valeros
0fa9006e45 Sync docs: CircleCI updates 2021-05-03 22:34:43 +03:00
Ivan Kravets
60c83bae93 Docs: Sync dev-platforms 2021-05-01 13:44:28 +03:00
Ivan Kravets
553c398c8e Show package "system" info before publishing 2021-04-30 18:06:35 +03:00
Ivan Kravets
1c90bb383f Sync docs 2021-04-29 19:46:17 +03:00
Ivan Kravets
4281225b02 Sync docs 2021-04-29 19:24:44 +03:00
Ivan Kravets
14dc9c6c43 Sync docs 2021-04-29 18:38:44 +03:00
Ivan Kravets
c9e10b1a3e Fix issue with broken redirect 2021-04-29 14:43:27 +03:00
Ivan Kravets
915c850760 Docs: Fix JS redirect URL 2021-04-29 12:47:57 +03:00
valeros
2c3f430203 Tidy up Docs CI 2021-04-28 20:59:01 +03:00
valeros
1a152ed7fa Add deploy step to CI configuration 2021-04-28 20:18:23 +03:00
Ivan Kravets
5953480807 Docs: Fix broken link for RTD page 2021-04-28 20:16:01 +03:00
Ivan Kravets
b5c1a195be Fix PyLint issues: consider-using-with 2021-04-28 19:59:37 +03:00
Ivan Kravets
310cc086c6 Docs: Minor fixes to "redirect" page generator 2021-04-28 19:59:12 +03:00
Ivan Kravets
61d6cd3c18 Apply black formatter 2021-04-28 19:58:50 +03:00
Ivan Kravets
cccabf5330 Add missed "sphinx-notfound-page" package for docs 2021-04-28 13:19:49 +03:00
Ivan Kravets
6f33460afd Remove debugging code 2021-04-28 13:17:22 +03:00
Ivan Kravets
603d524aaf Refactor docs to be deployed as a static content 2021-04-28 13:10:19 +03:00
Ivan Kravets
eb2cd001b6 Use private "_idedata" target when fetching data for debugging 2021-04-24 18:01:35 +03:00
Ivan Kravets
b5b57790be Validate package manifest when packing archive or publishing a package 2021-04-23 22:02:07 +03:00
Ivan Kravets
286f4ef961 Bump version to 5.2.0a6 2021-04-21 20:52:27 +03:00
Ivan Kravets
ad28d1906c Improve a package publishing process 2021-04-21 20:51:54 +03:00
Ivan Kravets
dfdccac67d Remove unnecessary "ensure_python3()" blocks 2021-04-20 20:28:49 +03:00
Ivan Kravets
b8c2752237 Dccs: Add information how to avoid extra script running when IDE fetches metadata 2021-04-16 13:36:53 +03:00
Ivan Kravets
834c7b0def Bump version to 5.2.0a5 2021-04-12 22:38:56 +03:00
Ivan Kravets
5bfe70142e Switch to project directory before starting debugging process 2021-04-12 22:38:21 +03:00
Ivan Kravets
b35c5a22bb Fix a broken support for custom configuration file for pio debug command // Resolve #3922 2021-04-11 22:21:01 +03:00
Ivan Kravets
eecc825c90 PyLint 2021-04-11 22:20:09 +03:00
valeros
3823c22dad Update Release Notes 2021-04-07 21:30:06 +03:00
Valerii Koval
551bd3dbfe Explicitly specify PROGSUFFIX when compiling final binary (#3918)
Resolves #3906
2021-04-02 17:09:38 +03:00
Ivan Kravets
7e9956963a Remove a note with using pio ci for uploading // Resolve #3903 2021-04-02 15:23:34 +03:00
Ivan Kravets
80c24a1993 Fixed an issue when "main.cpp" was generated for a new project for 8-bit development platforms // Resolve #3872 2021-04-02 15:19:18 +03:00
Ivan Kravets
66091bae24 Disable GDB "startup-with-shell" only on Unix platform 2021-04-02 14:44:38 +03:00
Ivan Kravets
73d4f10f4b Bump version to 5.2.0a4 2021-04-01 21:16:42 +03:00
Ivan Kravets
ee7ea77fc3 Fixed an error "Unknown development platform" when running unit tests on a clean machine // Resolve #3901 2021-04-01 21:15:14 +03:00
Ivan Kravets
32e1cbe2a3 Provide solution for issue #3417 2021-03-31 18:28:06 +03:00
Ivan Kravets
3539724843 Update "zeroconf" dependency to 0.29 2021-03-31 17:33:26 +03:00
Ivan Kravets
940b25f158 Sync docs & examples 2021-03-31 17:32:57 +03:00
Ivan Kravets
37e601e5b5 Ensure that a serial port is ready before running unit tests on a remote target // Resolve #3742 2021-03-24 19:07:40 +02:00
Ivan Kravets
0230374709 Document new VSCode settings: activateProjectOnTextEditorChange & autoOpenPlatformIOIniFile 2021-03-24 13:04:20 +02:00
valeros
86db237e5d Update Cppcheck and PVS-Studio packages // Resolve #3898 2021-03-23 21:17:32 +02:00
Ivan Kravets
1542b1cebb Bump version to 5.2.0a3 2021-03-20 10:32:14 +02:00
Ivan Kravets
990071af5c Fix issue with missed compat.path_to_unicode // Resolve #3894 2021-03-20 10:31:55 +02:00
Ivan Kravets
f543e00307 Bump version to 5.2.0a2 2021-03-19 20:26:26 +02:00
Ivan Kravets
34b4f8265a Debug unit tests created with PlatformIO Unit Testing solution // Resolve #948 2021-03-19 20:25:30 +02:00
Ivan Kravets
a366d1af2a Use "target remote" for mpsdebug 2021-03-19 18:26:09 +02:00
Ivan Kravets
ebe5785a91 Allow overriding default debugging flags from dev-platform 2021-03-19 17:11:25 +02:00
Ivan Kravets
887d46725b Debug native (desktop) application on a host machine // Resolve #980 2021-03-19 17:02:11 +02:00
Ivan Kravets
a326b718f2 Handle legacy $LOAD_CMD "init_cmds" 2021-03-19 16:09:38 +02:00
Ivan Kravets
c14b298cb9 Fixed an issue with silent hanging when a custom debug server is not found // Resolve #3756 2021-03-19 15:55:42 +02:00
Ivan Kravets
9cca8f3f55 Split debugging client to base and GDB // Resolve #3757 2021-03-19 15:47:20 +02:00
Ivan Kravets
f5cee56740 Fix issue when disabling "debug_init_break" did not work 2021-03-19 14:09:43 +02:00
Ivan Kravets
972d183d85 Use a cached build configuration 2021-03-19 13:46:54 +02:00
Ivan Kravets
eebdf04357 Load "idedata" configuration from a dumped file 2021-03-19 13:46:27 +02:00
Ivan Kravets
9ede20a367 Disable checking for "__PLATFORMIO_BUILD_DEBUG__" that is not available in g2 mode 2021-03-19 13:10:29 +02:00
Ivan Kravets
b0c3e22a52 Configure a custom pattern to determine when debugging server is started with a new debug_server_ready_pattern option 2021-03-19 12:30:16 +02:00
Ivan Kravets
a78db17784 Drop support for Python 2 2021-03-19 00:21:44 +02:00
Ivan Kravets
dbb9998f69 Refactor debugging configuration, add support for server_ready_pattern // Resolve #3401 2021-03-18 23:42:54 +02:00
Ivan Kravets
2745dbd124 PyLint fix 2021-03-17 23:14:22 +02:00
Ivan Kravets
c0357daf01 Remove Python 2 code 2021-03-17 21:08:06 +02:00
Ivan Kravets
064fa6027d Bump version to 5.2.0a1 2021-03-17 20:07:26 +02:00
Ivan Kravets
779e02a05e Use "connect_read_pipe" on Unix 2021-03-17 20:06:52 +02:00
Ivan Kravets
e222d0356a Merge branch 'feature/debug-async' into develop 2021-03-17 18:25:47 +02:00
Ivan Kravets
d2ae333bb8 Merge branch 'release/v5.1.1' 2021-03-17 18:17:46 +02:00
Ivan Kravets
764c42a810 Merge tag 'v5.1.1' into develop
Bump version to 5.1.1
2021-03-17 18:17:46 +02:00
Ivan Kravets
18b18f1c3d Bump version to 5.1.1 2021-03-17 18:17:40 +02:00
Ivan Kravets
b54a8b40a4 Refactor Unified Debugger to native Python Asynchronous I/O stack // Resolve #3793 , Resolve #3595 2021-03-17 17:42:11 +02:00
Ivan Kravets
edf724d20d Sync docs 2021-03-15 17:01:44 +02:00
Ivan Kravets
622a190a61 Avoid "rustup" when building cryptography for contrib-pysite // Resolve #3865 2021-03-15 17:00:16 +02:00
Ivan Kravets
5b4a78ba20 Bump version to 5.1.1b1 2021-03-11 14:49:20 +02:00
valeros
44b85f6e4b Switch Cppcheck to analyze project per file // Issue #3797
Cppcheck doesn't provide a proper report when one of the files in the check list is broken.
If we run the analysis on a per-file basis, then Cppcheck will be able report at least defects
from valid source files.
2021-03-11 13:49:27 +02:00
Valerii Koval
7f1f760645 Preserve user-specified debug configurations in VSCode integration (#3878)
* Preserve user-specified debug configurations in VSCode integration

Issue #3824

* Tidy up Python code
2021-03-10 14:54:52 +02:00
Ivan Kravets
54d8c96c30 Update SPDX license list to 3.12 2021-03-09 22:01:58 +02:00
Ivan Kravets
c6ab7827e7 Fixed incorrect size of unnecessary data // Resolve #3830 2021-03-09 19:26:22 +02:00
Ivan Kravets
ae26079e2e Fixed an issue when code inspection fails with "Bad JSON" // Resolve #3790 2021-03-09 19:20:30 +02:00
valeros
3e993156f2 Suppress printing unnecessary info in silent mode // Resolve #3837 2021-03-08 12:16:53 +02:00
valeros
3b2fafd789 Add new test for check command and project with whitespace 2021-03-04 22:27:00 +02:00
GovorovViva64
72ebaddcb8 Handle possible whitespaces in project path for PVS-Studio (#3849) 2021-03-04 22:22:09 +02:00
Ivan Kravets
5a9950cc19 Sync docs 2021-03-04 18:52:12 +02:00
Ivan Kravets
cf29d7e400 Typo fix 2021-03-04 18:52:02 +02:00
Ivan Kravets
244dba3614 JFrog shutdowns Bintray 2021-03-03 21:31:42 +02:00
Ivan Kravets
21886517e1 Bump version to 5.1.1a3 2021-03-01 17:59:58 +02:00
Ivan Kravets
3996236729 Report detailed server error to PIO Home frontend 2021-03-01 17:59:40 +02:00
Ivan Kravets
560cb3ac82 Sync docs 2021-02-27 19:57:40 +02:00
Ivan Kravets
81c7e23ae9 Bump version to 5.1.1a2 2021-02-27 19:44:11 +02:00
Ivan Kravets
0b8bd6d4fc Migrate to Async JSON-RPC package 2021-02-27 19:43:43 +02:00
Ivan Kravets
7c271c8207 Better detecting of native dev-platform for unit testing // Resolve #3851 2021-02-27 18:53:26 +02:00
Ivan Kravets
58947d91a6 PyLint fixes 2021-02-27 17:13:30 +02:00
Ivan Kravets
20096be990 Sync docs 2021-02-26 13:39:13 +02:00
Ivan Kravets
7c8508b651 Fixed an issue with device monitor when the “send_on_enter” filter didn’t send EOL chars // Resolve #3787 2021-02-10 14:43:50 +02:00
Ivan Kravets
b56d0fdd9b Sync docs & examples 2021-02-10 14:43:12 +02:00
Ivan Kravets
d0cc06f766 Move isort setttings to "tox.ini" 2021-02-06 16:56:44 +02:00
Ivan Kravets
d8d2b215d1 Minor improvement 2021-02-03 23:11:47 +02:00
Ivan Kravets
c478d383b4 Sync docs 2021-02-03 23:10:01 +02:00
Ivan Kravets
e01cd1c037 Bump version to 5.1.1a1 2021-02-01 13:01:31 +02:00
Ivan Kravets
e63019c469 Fixed a "The command line is too long" issue with a linking process on Windows // Resolve #3827 2021-02-01 12:52:00 +02:00
Ivan Kravets
90a325a1b2 Merge branch 'release/v5.1.0' 2021-01-28 19:23:14 +02:00
Ivan Kravets
698594525f Merge tag 'v5.1.0' into develop
Bump version to 5.1.0
2021-01-28 19:23:14 +02:00
Ivan Kravets
fd540148f3 Bump version to 5.1.0 2021-01-28 19:23:06 +02:00
Ivan Kravets
078a024931 Configure default debug_speed 2021-01-28 13:52:11 +02:00
Ivan Kravets
f8193b2419 Bump version to 5.1.0rc3 2021-01-27 23:06:42 +02:00
Ivan Kravets
808ba603c5 Fixed an issue when "pio device monitor –eol" and “send_on_enter” filter do not work properly // Resolve #3787 2021-01-27 23:06:18 +02:00
Ivan Kravets
61d70fa688 Include Unity framework for IDE data only if there are tests in project 2021-01-27 22:40:19 +02:00
Ivan Kravets
493a33e754 Drop support for Python 2 2021-01-27 22:25:42 +02:00
Ivan Kravets
bd75c3e559 Bump version to 5.1.0rc2 2021-01-27 20:58:13 +02:00
Ivan Kravets
cb9e72a879 Dump build flags using SCons.Subst.SUBST_CMD 2021-01-27 20:57:53 +02:00
Ivan Kravets
9d2fd4982f Cleanup code 2021-01-27 20:40:25 +02:00
Ivan Kravets
eed9a0e376 Merge branch 'feature/3792-maxleng-cmd' into develop 2021-01-27 20:30:39 +02:00
Ivan Kravets
d77dbb2cca Use "TEMPFILEARGESCFUNC" for GCC workaround on Windows 2021-01-27 20:30:28 +02:00
Ivan Kravets
7810946484 Use project build folder for tempfile workaround with command maxlen 2021-01-27 18:47:54 +02:00
Ivan Kravets
e2906e3be5 Refactored a workaround for a maximum command line character limitation // Resolve #3792 2021-01-27 16:10:13 +02:00
Ivan Kravets
0a8b66ee95 Configure a custom debug adapter speed using a new debug_speed option // Resolve #3799 2021-01-26 21:21:41 +02:00
Ivan Kravets
8ff270c5f7 Skip non-existing package when checking for update// Resolve #3818 2021-01-26 17:05:37 +02:00
Ivan Kravets
4012a86cac Fixed a "ValueError: Invalid simple block" when uninstalling a package with a custom name and external source // Resolve #3816 2021-01-26 16:15:11 +02:00
Ivan Kravets
dd4fff3a79 Bump version to 5.1.0rc1 2021-01-25 23:50:41 +02:00
Ivan Kravets
0ed99b7687 Added a new `--session-id option to pio home` // Resolve #3397 2021-01-25 23:44:26 +02:00
Ivan Kravets
2c389ae11e Added new check_prune_system_threshold setting 2021-01-24 17:21:22 +02:00
Ivan Kravets
15ff8f9d2a Bump version to 5.0.5b5 2021-01-24 15:58:07 +02:00
Ivan Kravets
bd4d3b914b Revert "lib_compat_mode" changes // Resolve #3811 Resolve #3806 2021-01-24 15:49:56 +02:00
Ivan Kravets
59b02120b6 New options for system prune command: remove unnecessary core and development platform packages // Resolve #923 2021-01-23 23:20:53 +02:00
Ivan Kravets
92655c30c1 Disabled automatic removal of unnecessary development platform packages // Resolve #3708 , Resolve #/3770 2021-01-23 22:34:48 +02:00
Ivan Kravets
484567f242 Project's "lib_compat_mode" has higher priority than "library.json" 2021-01-23 15:54:52 +02:00
Ivan Kravets
ef6e70a38b Fixed an issue when unnecessary packages were removed in `update --dry-run` mode // Resolve #3809 2021-01-23 15:24:32 +02:00
Ivan Kravets
e695e30a9b Fixed an issue with compiler driver for ".ccls" language server // Resolve #3808 2021-01-23 14:44:53 +02:00
Ivan Kravets
65e67b64bd Remove unnecessary dependencies from contrib-pysite 2021-01-22 22:55:45 +02:00
Ivan Kravets
ddbe339541 Update to iSort 5.0 2021-01-22 22:55:02 +02:00
Ivan Kravets
b2c0e6a8c2 Sync docs 2021-01-22 22:46:09 +02:00
Ivan Kravets
f9384ded27 Fixed an issue when “strict” compatibility mode was not used for a library with custom “platforms” field in library.json manifest // Resolve #3806 2021-01-22 22:45:36 +02:00
Ivan Kravets
4488f25ce0 Bump version to 5.0.5b4 2021-01-20 23:26:22 +02:00
Ivan Kravets
52b22b5784 Fixed a "UnicodeDecodeError: 'utf-8' codec can't decode byte" // Resolve #3804 , Resolve #3417 2021-01-20 20:45:23 +02:00
Ivan Kravets
5a356140d6 Sync examples and docs 2021-01-20 20:44:43 +02:00
Ivan Kravets
e79de0108c Upgraded build engine to the SCons 4.1 2021-01-20 16:15:05 +02:00
Ivan Kravets
985f31877c Automatically install tool-unity when there are tests and "idedata" target is called 2021-01-20 15:14:45 +02:00
Ivan Kravets
11a71b7fbb Bump version to 5.0.5b3 2021-01-20 14:37:19 +02:00
Ivan Kravets
7f26c11c9d Fix an issue with "coroutine' object has no attribute 'addCallback'" 2021-01-20 14:36:45 +02:00
Ivan Kravets
9b93fcd947 Do not install tool-unity for even non-test proejct 2021-01-20 14:27:03 +02:00
Ivan Kravets
733ca5174b Bump version to 5.0.5b2 2021-01-18 21:19:57 +02:00
Ivan Kravets
bd897d780b Implement "__shutdown__" endpoint for PIO Home server 2021-01-18 21:19:15 +02:00
Ivan Kravets
429065d2b9 Legacy support for PIO Home "__shutdown__" query request 2021-01-18 20:53:19 +02:00
Ivan Kravets
b90734f1e2 List multicast DNS services only when PY3 2021-01-18 20:51:50 +02:00
Ivan Kravets
db97a7d9d3 Bump version to 5.0.5b1 2021-01-18 18:21:27 +02:00
Ivan Kravets
6ff67aeadf Significantly speedup PlatformIO Home loading time by migrating to native Python 3 Asynchronous I/O 2021-01-18 18:20:26 +02:00
Ivan Kravets
dd7d282d17 Improved listing of multicast DNS services 2021-01-18 18:17:10 +02:00
Ivan Kravets
4e637ae58a Drop Python 2 from PIO Core test 2021-01-18 18:15:15 +02:00
sephalon
1ec2e55322 Add udev rule for Atmel AVR Dragon (#3786) 2021-01-04 13:46:09 +02:00
Ivan Kravets
556eb3f8c1 Docs: Update "Wiring Connections" section for ST-Link debugging probe 2020-12-31 13:47:05 +02:00
Ivan Kravets
76b49ebc95 Increase timeout to 60sec when starting debug server and "ready_pattern" is used 2020-12-30 14:38:18 +02:00
Ivan Kravets
e82443a302 Bump version to 5.0.5a1 2020-12-30 14:29:41 +02:00
Ivan Kravets
5de86a6416 Check for debug server's "ready_pattern" in "stderr" 2020-12-30 14:29:19 +02:00
Ivan Kravets
3f3c8cabb8 Merge branch 'release/v5.0.4' 2020-12-30 13:23:11 +02:00
Ivan Kravets
cd59aa9afb Merge tag 'v5.0.4' into develop
Bump version to 5.0.4
2020-12-30 13:23:11 +02:00
Ivan Kravets
34e12e575b Bump version to 5.0.4 2020-12-30 13:23:04 +02:00
Ivan Kravets
4c8c261ab4 Raise an exception when trying to pack a package from tar.gz on Windows // Resolve #3776 2020-12-28 20:12:53 +02:00
Ivan Kravets
099bb3b9ff Sync dev-platforms: docs + examples 2020-12-28 13:51:34 +02:00
Ivan Kravets
c623a6aacc Fixed an issue with package publishing on Windows when Unix permissions are not preserved // Resolve // #3776 2020-12-28 13:08:12 +02:00
Ivan Kravets
ce7356794d Test examples from the official dev-platforms 2020-12-26 21:43:41 +02:00
Ivan Kravets
523494f9cf Ignore CI tests from tokisaki dev-platform 2020-12-26 20:18:15 +02:00
Ivan Kravets
0edc867d45 Bump version to 5.0.4rc1 2020-12-26 16:10:44 +02:00
Ivan Kravets
ce4c45a075 Show a warning message about deprecated support for Python 2 and Python 3.5 2020-12-26 16:10:07 +02:00
valeros
e29941e3eb Update release notes with check tools updates 2020-12-22 21:30:01 +02:00
valeros
86ce3595f6 Update check tools packages // Resolve #3758
Updated tools: Cppcheck v2.3, PVS-Studio v7.11
2020-12-22 00:44:09 +02:00
valeros
6e958b8415 Handle possible issues when check tool cannot be executed // Resolve #3753
Now, each tool individually decides under what conditions the check is considered failed.
2020-12-22 00:21:32 +02:00
Ivan Kravets
d485703768 Use "Updating to X.Y.Z" instead of "Outdated" when doing a real package updating 2020-12-11 17:53:48 +02:00
Ivan Kravets
109e2107d1 Sync docs 2020-12-11 16:14:08 +02:00
Ivan Kravets
3469905365 Decode subprocess output only for byte-strings 2020-12-02 15:15:17 +02:00
Ivan Kravets
75b3846f8f Sync docs & examples 2020-12-02 15:15:02 +02:00
Ivan Kravets
a9ec38208c Bump version to 5.0.4b1 2020-11-30 20:24:45 +02:00
Ivan Kravets
c38b9a4144 Fixed a "git-sh-setup: file not found" error when installing project dependencies from Git VCS // Resolve #3740 2020-11-30 20:23:30 +02:00
Ivan Kravets
b6128aeaa1 Apply formatting 2020-11-22 22:32:03 +02:00
Ivan Kravets
881782be05 Allow spaces and dots in example's name ([package manifest) 2020-11-22 21:42:25 +02:00
Ivan Kravets
0c05930501 Sync docs 2020-11-22 21:41:47 +02:00
Ivan Kravets
b96f2a19b5 Bump version to 5.0.4a2 2020-11-14 20:10:45 +02:00
Ivan Kravets
c1906714ee Give a constant "PlatformIO" name for the C/C++ configuration 2020-11-14 20:10:22 +02:00
Ivan Kravets
32181d1bd2 Improved `.ccls` configuration file for Emacs, Vim, and Sublime Text integrations // Issue #3735 2020-11-14 19:55:24 +02:00
Ivan Kravets
7dfb413d87 Typo fix 2020-11-12 21:42:53 +02:00
Ivan Kravets
7934a96ad1 Added "Core" suffix when showing PlatformIO Core version using `pio --version` command 2020-11-12 20:42:27 +02:00
Ivan Kravets
abddbf9c7d Bump version to 5.0.4a1 2020-11-12 18:56:55 +02:00
Ivan Kravets
77e66241f7 Do not provide "intelliSenseMode" option when generating configuration for VSCode C/C++ extension 2020-11-12 18:56:34 +02:00
Ivan Kravets
4b3f2e19a4 Merge branch 'release/v5.0.3' 2020-11-12 17:57:30 +02:00
Ivan Kravets
b29c6485a8 Merge tag 'v5.0.3' into develop
Bump version to 5.0.3
2020-11-12 17:57:30 +02:00
Ivan Kravets
f4dba7a68c Bump version to 5.0.3 2020-11-12 17:56:12 +02:00
Ivan Kravets
2817408db3 Fixed an issue when pio package pack ignores some folders // Resolve #3730 2020-11-12 16:06:54 +02:00
Ivan Kravets
9ff3c758eb Fix tests 2020-11-12 15:35:37 +02:00
Ivan Kravets
3dcc189740 Use custom Pre-Debug task only for multi-env project 2020-11-12 15:35:19 +02:00
Ivan Kravets
4a12d1954e Fixed an issue when the package manager tries to install a built-in library from the registry // Resolve #3662 2020-11-12 15:27:34 +02:00
Ivan Kravets
e4d645110a Merge branch 'develop' of https://github.com/platformio/platformio-core into develop
# Conflicts:
#	HISTORY.rst
2020-11-12 15:25:51 +02:00
valeros
01a32067d5 Print ignored environments and test suites in only in verbose mode
Resolve #3726
2020-11-12 15:22:47 +02:00
Ivan Kravets
fc5ce4739c Added an error selector for Sublime Text build runner // Resolve #3733 2020-11-12 15:05:01 +02:00
Ivan Kravets
ae7b8f9ecf Fix tests 2020-11-11 20:52:23 +02:00
Ivan Kravets
0f5d2d6821 Sync docs 2020-11-11 19:44:39 +02:00
Ivan Kravets
48eca22a00 Force VSCode's intelliSenseMode to "gcc-x64" when GCC toolchain is used 2020-11-11 14:19:58 +02:00
Ivan Kravets
5e164493a8 Sync docs 2020-11-09 11:39:26 +02:00
Ivan Kravets
ead99208f2 Increase example name in manifest to 255 chars 2020-11-09 11:38:46 +02:00
Ivan Kravets
4f5ad05792 Docs: Document "Introducing Strict SSL/TLS" in migration 2020-11-04 14:07:40 +02:00
Ivan Kravets
bc52e72605 Bump version to 5.0.3a2 2020-11-03 15:11:52 +02:00
Ivan Kravets
038674835a Workaround for a broken locale 2020-11-02 12:27:17 +02:00
Ivan Kravets
00f21c17ca Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2020-11-01 21:06:47 +02:00
Ivan Kravets
818a1508a0 Docs: Use native ProjectConfig in the advanced scripting examples 2020-11-01 21:06:23 +02:00
Ivan Kravets
2d9480a6a7 Support for GitPod environment 2020-11-01 21:05:03 +02:00
valeros
0bec4e25c8 Add support for C++ language standard in QtCreator template
Resolve #3719
2020-11-01 19:03:14 +02:00
Ivan Kravets
950a540df4 Bump version to 5.0.3a1 2020-10-31 19:07:45 +02:00
Ivan Kravets
2e66c5f807 Generate a working "projectEnvName" for PlatformIO IDE's debugger for VSCode 2020-10-31 19:07:04 +02:00
Ivan Kravets
7033c2616b Docs: Add info how to access PlatformIO Core CLI in VSCode 2020-10-31 12:44:37 +02:00
Ivan Kravets
7292024ee6 Merge branch 'release/v5.0.2' 2020-10-30 18:10:54 +02:00
Ivan Kravets
8d4cde4534 Merge tag 'v5.0.2' into develop
Bump version to 5.0.2
2020-10-30 18:10:54 +02:00
Ivan Kravets
d6df6cbb5d Bump version to 5.0.2 2020-10-30 18:10:47 +02:00
Ivan Kravets
344e94d8a1 Bump version to 5.0.2rc2 2020-10-30 17:51:02 +02:00
Ivan Kravets
5cf73a9165 Remove all hooks when dumping data to JSON and Python 3 is used 2020-10-30 17:50:43 +02:00
Ivan Kravets
96b1a1c79c Fixed an issue with a "wrong" timestamp in device monitor output using "time" filter // Resolve #3712 2020-10-30 14:11:27 +02:00
Ivan Kravets
0bbe7f8c73 Sync docs 2020-10-29 23:48:44 +02:00
Ivan Kravets
e333bb1cca Tests: skip dev-plalform without examples 2020-10-29 23:42:15 +02:00
Ivan Kravets
454cd8d784 Bump version to 5.0.2rc1 2020-10-29 23:18:39 +02:00
Ivan Kravets
743a43ae17 Fixed an issue when multiple pio lib install command with the same local library results in duplicates in `lib_deps` // Resolve #3715 2020-10-29 23:17:47 +02:00
Ivan Kravets
5a1b0e19b2 Initialize a new project or update existing passing working environment name and its options // Resolve #3686 2020-10-29 22:59:48 +02:00
Ivan Kravets
da6cde5cbd Sync docs 2020-10-29 18:09:08 +02:00
Ivan Kravets
5ea864da39 Add py39 env 2020-10-29 18:08:58 +02:00
Ivan Kravets
175448deda Fix tests on PY2 2020-10-29 14:37:50 +02:00
valeros
16f90dd821 Ignore possible empty defines when exporting IDE data // Resolve #3690 2020-10-29 12:22:26 +02:00
Ivan Kravets
9efac669e6 Bump version to 5.0.2b5 2020-10-28 22:53:29 +02:00
Ivan Kravets
adf9ba29df Fixed an issue when "pio package publish" command removes original archive after submitting to the registry // Resolve #3716 2020-10-28 22:52:48 +02:00
Ivan Kravets
cacddb9abb Support package packing on the Python 3+ only 2020-10-28 22:33:24 +02:00
Ivan Kravets
edbe213410 Sync docs 2020-10-28 22:32:48 +02:00
Ivan Kravets
891f78be37 Use "ensure_python3" util 2020-10-28 22:32:27 +02:00
Ivan Kravets
175be346a8 Extend package filters 2020-10-28 20:57:26 +02:00
Ivan Kravets
9ae981614f Add pack/sdist target 2020-10-28 20:56:53 +02:00
Ivan Kravets
16f5f3ef46 Do not pack binary files and docs to the package source archive 2020-10-28 14:18:09 +02:00
Ivan Kravets
2cd19b0273 Bump version to 5.0.2b4 2020-10-27 23:00:33 +02:00
Ivan Kravets
e158e54a26 Fix issue with data decoding when calling PIO Core via PIO Home 2020-10-27 22:57:51 +02:00
Ivan Kravets
63a6fe9133 Improved "core.call" RPC for PlatformIO Home // Resolve #3671 2020-10-27 21:07:02 +02:00
Ivan Kravets
779eaee310 Bump version to 5.0.2b3 2020-10-26 22:25:47 +02:00
Ivan Kravets
0ecfe8105f Docs: Unify CLI commands to use "pio" short version command 2020-10-26 22:24:05 +02:00
Ivan Kravets
b8cc867ba4 Allow dev-platform to provide extra debug configuration using BsePlatform::configure_debug_options API 2020-10-26 18:24:46 +02:00
Ivan Kravets
7230556d1b Move extra IDE data to "extra" section 2020-10-26 18:23:28 +02:00
Ivan Kravets
afd79f4655 Improve initiating manifest parser from a package archive 2020-10-22 19:08:20 +03:00
Ivan Kravets
5d87fb8757 Add "Articles" section to Zephyr RTOS 2020-10-22 19:07:44 +03:00
Ivan Kravets
23e9596506 Automatically build PlatformIO Core extra Python dependencies on a host machine if they are missed in the registry // Resolve #3700 2020-10-20 21:06:53 +03:00
Ivan Kravets
428f46fafe Typo test 2020-10-16 17:05:19 +03:00
Ivan Kravets
ee847e03a6 Fix an issue with "'NoneType' object has no attribute 'status_code'" 2020-10-16 14:23:10 +03:00
Ivan Kravets
a870981266 Docs: Fix custom "platform_packages" for ESP8266/32 2020-10-14 23:21:59 +03:00
Ivan Kravets
411bf1107d Disable "lattice_ice40" examples for macOS 2020-10-14 22:33:04 +03:00
Ivan Kravets
5b74c8a942 Minor fixes 2020-10-14 19:53:30 +03:00
Ivan Kravets
a24bab0a27 Fix badge 2020-10-14 17:55:45 +03:00
Ivan Kravets
1cb7764b0e Highlight PlatformIO Labs Technology 2020-10-14 17:53:41 +03:00
Ivan Kravets
d835f52a18 Sync docs 2020-10-10 20:48:56 +03:00
Michele Campeotto
9c20ab81cb fix quoting of defines in ccls template (#3692) 2020-10-02 13:28:02 +03:00
Ivan Kravets
14de3e79c5 Sync docs 2020-09-26 22:52:43 +03:00
Ivan Kravets
21c12030d5 Bump version to 5.0.2b2 2020-09-19 19:30:40 +03:00
Ivan Kravets
2370e16f1b Fixed an "AssertionError: ensure_dir_exists" when checking library updates from simultaneous subprocesses // Resolve #3677 2020-09-19 19:29:51 +03:00
Ivan Kravets
a384411a28 Bump version to 5.0.2b1 2020-09-17 20:41:10 +03:00
Ivan Kravets
1e0ca8f79c Fixed an issue with GCC linker when "native" dev-platform is used in pair with library dependencies // Resolve #3669 2020-09-17 20:40:11 +03:00
Ivan Kravets
2b5e590819 Docs: Explain how to install custom Python packages // Resolve #3673 2020-09-17 19:21:12 +03:00
Ivan Kravets
bf57b777bf Docs: Update docs for PlatformIO IDE 2.0 for VSCode 2020-09-16 19:33:55 +03:00
valeros
f656d19ed5 Docs: Added new section about Arduino STM32L0 core 2020-09-14 22:31:11 +03:00
Ivan Kravets
eb09af06ed Bump version to 5.0.2a2 2020-09-12 23:21:33 +03:00
Ivan Kravets
687c339f20 Fixed a "PermissionError: [WinError 5]" on Windows when external repository is used with lib_deps option // Resolve #3664 2020-09-12 23:20:46 +03:00
Ivan Kravets
7bc170a53e Fixed an issue with "KeyError: 'versions'" when dependency does not exist in the registry // Resolve #3666 2020-09-11 21:16:18 +03:00
Ivan Kravets
65297c24d4 Merge branch 'release/v5.0.1' 2020-09-10 17:46:56 +03:00
Ivan Kravets
ea21f3fba0 Merge tag 'v5.0.1' into develop
Bump version to 5.0.1
2020-09-10 17:46:56 +03:00
Ivan Kravets
b515a004d3 Bump version to 5.0.1 2020-09-10 17:46:49 +03:00
Ivan Kravets
7d3fc1ec1a Catch exception if folder already exists 2020-09-09 18:38:55 +03:00
Ivan Kravets
6987d6c1c6 Fixed an issue when can not remove update or remove external dev-platform using PlatformIO Home // Resolve #3663 2020-09-09 17:53:04 +03:00
Ivan Kravets
de2b5ea905 Bump version to 5.0.1b1 2020-09-09 16:27:47 +03:00
Ivan Kravets
f946a0bc08 Reformat code with black==20.8b1 2020-09-09 16:27:36 +03:00
Ivan Kravets
4f47ca5742 Fixed an issue with "Invalid simple block (semantic_version)" from library dependency that refs to an external source (repository, ZIP/Tar archives) // Resolve #3658 2020-09-09 16:13:39 +03:00
Ivan Kravets
54b51fc2fd Merge branch 'develop' of https://github.com/platformio/platformio-core into develop
# Conflicts:
#	HISTORY.rst
2020-09-09 14:38:29 +03:00
Ivan Kravets
1f284e853d Fixed an issue when the package manager tries to install a built-in library from the registry // Resolve #3662 2020-09-09 14:36:01 +03:00
valeros
2a30ad0fdf Allow in-progress language standards in IDE templates // Resolve #3653
Note: VS Code only supports finalized names
2020-09-09 13:56:00 +03:00
Ivan Kravets
c454ae336d Added support for "owner" requirement when declaring `dependencies using library.json` 2020-09-09 13:10:42 +03:00
Ivan Kravets
cd59c829e0 Fixed an issue when pio package unpublish command crashes // Resolve #3660 2020-09-09 12:17:09 +03:00
Ivan Kravets
429f416b38 Generate current date for a custom contrib-pysite package 2020-09-07 16:38:20 +03:00
Ivan Kravets
0a881d582d Docs: Add info how to list publish packages 2020-09-07 16:37:37 +03:00
Ivan Kravets
65b1029216 Host SPDX licenses on Bintray, Github is blocked in multiple countries 2020-09-07 13:16:08 +03:00
Ivan Kravets
c7758fd30e Docs: Minor fixes 2020-09-06 21:06:16 +03:00
Ivan Kravets
46f300d62f Docs: Add "Publishing" section to the instruction on how to create own dev-platform 2020-09-06 21:00:45 +03:00
Ivan Kravets
4234dfb6f9 Fixed an issue with "ImportError: cannot import name '_get_backend' from 'cryptography.hazmat.backends'" when using Remote Development // Resolve #3652 2020-09-06 18:37:27 +03:00
Ivan Kravets
9695720343 Bump version to 5.0.1a1 2020-09-04 22:48:21 +03:00
Ivan Kravets
1f28056459 Fixed an issue when using a custom git/ssh package with platform_packages // Resolve #3624 2020-09-04 22:47:49 +03:00
Jake
7dacceef04 Exclude tests from python package (#3650) 2020-09-04 18:55:30 +03:00
Ivan Kravets
39883e8d68 Docs: Document "--without-testing" option for pio test command 2020-09-04 18:39:52 +03:00
Ivan Kravets
949ef2c48a Merge tag 'v5.0.0' into develop
Bump version to 5.0.0
2020-09-03 14:43:11 +03:00
Ivan Kravets
ada3f8b270 Merge branch 'release/v5.0.0' 2020-09-03 14:43:10 +03:00
Ivan Kravets
cf4b835b0c Bump version to 5.0.0 2020-09-03 14:42:59 +03:00
Ivan Kravets
fec4569ada Docs: Update docs with new owner-based dependency form 2020-09-03 14:37:24 +03:00
Ivan Kravets
083edc4c76 Refactor to os.path 2020-09-02 20:52:11 +03:00
Ivan Kravets
fe4112a2a3 Follow SemVer complaint version constraints when checking library updates // Resolve #1281 2020-09-02 20:36:56 +03:00
Dirk Mueller
c8ea64edab Fix link to FAQ sections (#3642)
* Fix link to FAQ sections

Use consistently the same host and url and fix one unmatched anchor.

* Update HISTORY.rst

Co-authored-by: Ivan Kravets <me@ikravets.com>
2020-09-02 19:13:20 +03:00
Ivan Kravets
6e5198f373 Minor improvements 2020-09-02 18:49:00 +03:00
Ivan Kravets
44c2b65372 Show ignored project environments only in the verbose mode // Resolve #3641 2020-09-02 17:31:32 +03:00
Ivan Kravets
5cc21511ad Show owner name for packages 2020-09-02 16:07:16 +03:00
valeros
2edd7ae649 Update PVS-Studio to the latest v7.09 2020-08-31 15:40:25 +03:00
Ivan Kravets
7a49a74135 Bump version to 5.0.0b3 2020-08-28 21:55:55 +03:00
Ivan Kravets
be487019f5 Fix a broken handling multi-configuration project // Resolve #3615 2020-08-28 21:54:47 +03:00
Ivan Kravets
5dee0a31e6 Do not test for package owner if resource is external 2020-08-28 21:40:17 +03:00
Ivan Kravets
9f2c134e44 Do not detach a new package even if it comes from external source 2020-08-28 21:24:48 +03:00
Ivan Kravets
cdbb837948 Minor fixes 2020-08-28 18:45:52 +03:00
Ivan Kravets
80c1774a19 Docs: PlatformIO Core 5.0: new commands, migration guide, other improvements 2020-08-28 14:08:26 +03:00
valeros
1aaa9b6707 Update changelog with static analysis section 2020-08-26 17:44:01 +03:00
Ivan Kravets
4a7f578649 Sync docs and history 2020-08-26 15:40:24 +03:00
Ivan Kravets
d59416431d Parse npm-like "repository" data from a package manifest // Resolve #3637 2020-08-26 15:40:03 +03:00
Ivan Kravets
8625fdc571 Minor imperovements 2020-08-26 14:51:53 +03:00
Ivan Kravets
3c91e3c1e1 Move build dir to the disk root (should fix issue with long path for Zephyr RTOS on WIndows) 2020-08-26 14:51:01 +03:00
Ivan Kravets
1560fb724c Bump version to 5.0.0b2 2020-08-26 06:40:46 +03:00
Ivan Kravets
0db39ccfbd Automatically accept PIO. Core 4.0 compatible dev-platforms 2020-08-26 06:40:22 +03:00
Ivan Kravets
5086b96ede Bump version to 5.0.0b1 2020-08-25 22:22:35 +03:00
Ivan Kravets
210cd76042 Rename "idedata" sub-command to "data" 2020-08-25 22:01:22 +03:00
Ivan Kravets
f77978a295 Apply formatting 2020-08-25 22:01:08 +03:00
Valerii Koval
3e72f098fe Updates for PIO Check (#3640)
* Update check tools to the latest versions

* Use language standard when exporting defines to check tools

* Buffer Cppcheck output to detect multiline messages

* Add new test for PIO Check

* Pass include paths to Clang-Tidy as individual compiler arguments

Clang-tidy doesn't support response files which can exceed command
length limitations on Windows

* Simplify tests for PIO Check

* Update history

* Sync changelog
2020-08-25 21:19:21 +03:00
Ivan Kravets
b9fe493336 Sync docs 2020-08-25 19:18:26 +03:00
Ivan Kravets
79bfac29ba Update history and sync docs 2020-08-25 18:57:20 +03:00
Ivan Kravets
2ea80d91f8 Minor fixes 2020-08-25 15:55:17 +03:00
Ivan Kravets
fa90251714 Fixed an issue when Unit Testing engine fails with a custom project configuration file // Resolve #3583 2020-08-25 14:35:01 +03:00
Ivan Kravets
ff19109787 Fix test 2020-08-25 14:34:03 +03:00
Ivan Kravets
091ba4346d Bump version to 4.4.0b6 2020-08-24 23:11:43 +03:00
Ivan Kravets
e43176e33a Typo fix 2020-08-24 23:11:24 +03:00
Ivan Kravets
655e2856d1 Bump version to 4.4.0b5 2020-08-24 23:05:01 +03:00
Ivan Kravets
c6a37ef880 Get real path of just installed core-package 2020-08-24 23:04:17 +03:00
Ivan Kravets
6af2bad123 Make PIO Core 4.0 automatically compatible with dev-platforms for PIO Core 2.0 & 3.0 // Resolve #3638 2020-08-24 22:56:31 +03:00
Ivan Kravets
3e7e9e2b3d Remove unused data using a new `pio system prune // Resolve #3522 2020-08-24 15:22:05 +03:00
Ivan Kravets
13db51a556 Install/Uninstall dependencies only for library-type packages // Resolve #3637 2020-08-24 15:10:38 +03:00
Ivan Kravets
d6d95e05e8 Rename "fs.format_filesize" to "fs.humanize_file_size" 2020-08-24 15:09:37 +03:00
Ivan Kravets
b44bc80bd1 PyLint fix for PY2 2020-08-23 21:41:53 +03:00
Ivan Kravets
f39c9fb597 Bump version to 4.4.0b4 2020-08-23 21:07:40 +03:00
Ivan Kravets
24f85a337f Fix "AttributeError: module 'platformio.exception' has no attribute 'InternetIsOffline'" 2020-08-23 21:07:14 +03:00
Ivan Kravets
a069bae1fb Fix a bug with package updating when version is not in SemVer format // Resolve #3635 2020-08-23 15:26:58 +03:00
Ivan Kravets
1c8aca2f6a Check ALL possible version for the first matched package 2020-08-23 15:25:03 +03:00
Ivan Kravets
620241e067 Move package "version" related things to "platformio.package.version" module 2020-08-23 15:24:31 +03:00
Ivan Kravets
da179cb33f Enhance configuration variables 2020-08-23 14:29:31 +03:00
Ivan Kravets
8ea10a18d3 Bump version to 4.4.0b3 2020-08-23 13:22:38 +03:00
Ivan Kravets
e2bb81bae4 Restore legacy util.cd API 2020-08-23 13:22:11 +03:00
Ivan Kravets
dcf91c49ac Remove debug code 2020-08-22 22:56:26 +03:00
Ivan Kravets
c2caf8b839 Bump version to 4.4.0b2 2020-08-22 22:53:41 +03:00
Ivan Kravets
95151062f5 Implement mirroring for HTTP client 2020-08-22 22:52:29 +03:00
Ivan Kravets
7e4bfb1959 Move CacheContent API to "cache.py" module 2020-08-22 20:05:14 +03:00
Ivan Kravets
abae9c7e77 Cache base registry requests 2020-08-22 17:52:12 +03:00
Ivan Kravets
102aa5f22b Port legacy API requests to the new registry client 2020-08-22 17:49:29 +03:00
Ivan Kravets
d92c1d3442 Refactor HTTP related operations 2020-08-22 17:48:49 +03:00
Ivan Kravets
aa186382a8 Upgraded to SCons 4.0 2020-08-22 14:22:37 +03:00
Ivan Kravets
70366d34b9 Sync docs 2020-08-22 13:57:18 +03:00
Ivan Kravets
49b70f44ca Ignore legacy tmp pkg folders 2020-08-22 13:56:57 +03:00
Ivan Kravets
f79fb4190e Sync docs 2020-08-21 14:25:59 +03:00
Ivan Kravets
d980194600 Bump version to 4.4.0b1 2020-08-17 15:34:02 +03:00
Ivan Kravets
fb6e1fd33c PyLint fixes 2020-08-17 15:33:08 +03:00
Ivan Kravets
6f7fc638c7 Fix PyLint errors in tests 2020-08-17 12:56:57 +03:00
Ivan Kravets
2459e85c1d Fix a bug with the custom platform packages // Resolve #3628 2020-08-17 12:13:25 +03:00
Ivan Kravets
74e27a2edc Enable "cyclic reference" for GCC linker only for the embedded dev-platforms // Resolve #3570 2020-08-16 20:26:59 +03:00
Ivan Kravets
808852f4cc Set default timeout for http requests // Resolve #3623 2020-08-16 20:21:30 +03:00
Ivan Kravets
67e6d177b4 Minor fixes for dev-platform factory 2020-08-16 18:48:05 +03:00
Ivan Kravets
04694b4126 Switch legacy platform manager to the new 2020-08-15 23:11:01 +03:00
Ivan Kravets
bb6fb3fdf8 Fix bug with parsing detached packages 2020-08-15 15:24:35 +03:00
Ivan Kravets
4ec64f8980 Fix a test for examples 2020-08-14 17:00:18 +03:00
Ivan Kravets
332874cd4b Fix relative import of platform module on Py27 2020-08-14 16:48:12 +03:00
Ivan Kravets
276ca61cde Refactor dev-platform API 2020-08-14 16:39:15 +03:00
Ivan Kravets
5f3ad70190 Rename meta.PackageSourceItem or PackageItem 2020-08-14 16:38:46 +03:00
Ivan Kravets
ff8ec43a28 Ensure tool-type package is compatible with a host system 2020-08-13 21:46:46 +03:00
Ivan Kravets
ecc369c2f8 Minor fixes 2020-08-13 20:19:27 +03:00
Ivan Kravets
26fdd0a62c Bump version to 4.4.0a8 2020-08-13 18:30:33 +03:00
Ivan Kravets
64ff6a0ff5 Switch legacy core package manager to the new 2020-08-13 18:30:04 +03:00
Ivan Kravets
fd7dba1d74 Package Manifest: increase package author.name field to the 100 chars 2020-08-13 17:50:44 +03:00
Ivan Kravets
38ec517200 Update history 2020-08-12 21:09:42 +03:00
Ivan Kravets
20a74d1654 Merge branch 'feature/pkg-next' into develop 2020-08-12 20:09:18 +03:00
Ivan Kravets
d5451756fd Minor improvements 2020-08-12 20:09:10 +03:00
Ivan Kravets
893ca1b328 Switch library manager to the new package manager 2020-08-12 13:27:05 +03:00
Ivan Kravets
2dd69e21c0 Implement package removing with dependencies 2020-08-01 20:17:07 +03:00
Ivan Kravets
a01b3a2473 Do not raise exception when package is not found (404), return None 2020-08-01 19:58:59 +03:00
Ivan Kravets
6ac538fba4 Remove unused import 2020-08-01 15:49:10 +03:00
Ivan Kravets
41c2d64ef0 Fix "PermissionError: [WinError 32] The process cannot access the file" on Windows 2020-08-01 15:36:28 +03:00
Ivan Kravets
a1970bbfe3 Allow a forced package installation with removing existing package 2020-08-01 14:38:28 +03:00
Ivan Kravets
d329aef876 Initial version of a new package manager 2020-07-31 15:42:26 +03:00
Valerii Koval
abc0489ac6 Update changelog 2020-07-28 15:59:02 +03:00
Valerii Koval
2bc47f4e97 PyLint fix 2020-07-28 15:55:25 +03:00
Valerii Koval
933a09f981 Update unit testing support for mbed framework
- Take into account Mbed OS6 API changes
- RawSerial is used with Mbed OS 5 since Serial doesn't support putc with baremetal profile
2020-07-28 15:22:36 +03:00
Valerii Koval
adc2d5fe7c Update VSCode template
Starting with cpptools v0.29 escaped paths in compilerArgs field don't work on Windows.
2020-07-28 15:10:52 +03:00
Ivan Kravets
def149a29e Use updated registry API 2020-07-25 17:13:05 +03:00
Ivan Kravets
39cb23813f Allow ignoring "platforms" and "frameworks" fields in "library.json" and treat a library as compatible with all 2020-07-25 11:51:47 +03:00
Ivan Kravets
85f5a6a84a Bump version to 4.4.0a7 2020-07-24 21:00:58 +03:00
Ivan Kravets
6ace5668b8 Update the registry publish endpoints 2020-07-24 20:57:18 +03:00
Ivan Kravets
c193a4ceb7 Handle proxy environment variables in lower case // Resolve #3606 2020-07-23 19:07:29 +03:00
Ivan Kravets
1abc110f8a Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2020-07-23 17:57:00 +03:00
Ivan Kravets
73740aea89 Sync docs and examples 2020-07-23 17:56:41 +03:00
Valerii Koval
83110975fa Docs: Sync 2020-07-23 17:42:46 +03:00
Ivan Kravets
881c5ea308 Remove unused code 2020-07-23 17:37:23 +03:00
Ivan Kravets
22f1b94062 Bump version to 4.4.0a6 2020-07-21 12:42:26 +03:00
Ivan Kravets
ea30d94324 Automatically enable LDF dependency chain+ mode (evaluates C/C++ Preprocessor conditional syntax) for Arduino library when “library.properties” has “depends” field // Resolve #3607 2020-07-21 12:41:38 +03:00
Ivan Kravets
1ed462a29a PyLint fix 2020-07-16 01:00:38 +03:00
Ivan Kravets
a2efd7f7c5 Bump version to 4.4.0a5 2020-07-15 23:18:07 +03:00
Ivan Kravets
ca33058637 New commands for the registry package management (pack, publish, unpublish) 2020-07-15 23:16:46 +03:00
Ivan Kravets
a6f143d1ca Dump data intended for IDE extensions/plugins using a new platformio project idedata command 2020-07-15 14:20:29 +03:00
Ivan Kravets
1368fa4c3b Implement new fields (id, ownername, url, requirements) for PackageSpec API 2020-07-14 21:07:09 +03:00
Ivan Kravets
cca3099d13 Ensure that module.json keywords are lowercased 2020-07-14 18:55:29 +03:00
Ivan Kravets
368c66727b Fix issue with package packing when re-map is used and manifest is missed in "include" (copy it now) 2020-07-12 22:39:32 +03:00
Ivan Kravets
a688edbdf1 Fix an issue with manifest parser when "new_from_archive" API is used 2020-07-09 21:53:46 +03:00
Ivan Kravets
e570aadd72 Docs: Sync 2020-07-09 17:17:34 +03:00
Ivan Kravets
f85cf61d68 Revert back max length of author name to 50 chars 2020-07-08 23:23:14 +03:00
Ivan Kravets
f27c71a0d4 Increase author name length to 100 chars for manifest 2020-07-08 22:56:14 +03:00
Ivan Kravets
940682255d Lock Python's isort package to isort<5 2020-07-08 22:16:52 +03:00
Ivan Kravets
a00722bef4 Ignore maintainer's broken email in library.properties manifest 2020-07-08 21:53:28 +03:00
Ivan Kravets
84132d9459 Fix tests 2020-07-08 21:52:34 +03:00
Ivan Kravets
42fd284560 Improve parsing "author" field of library.properties manfiest 2020-07-08 20:21:10 +03:00
Ivan Kravets
40d6847c96 Add option to pass a custom path where to save package archive 2020-07-08 13:46:36 +03:00
Ivan Kravets
abd3f8b3b5 Docs: Remove legacy library dependency syntax for github 2020-07-07 22:53:01 +03:00
Ivan Kravets
3c986ed681 Remove recursively .pio folders when packing a package 2020-07-07 16:28:51 +03:00
Ivan Kravets
8b24b0f657 Sync docs & examples 2020-07-06 23:37:28 +03:00
Ivan Kravets
0f8042eeb4 Implement PackagePacker.get_archive_name API 2020-07-06 15:57:49 +03:00
Ivan Kravets
f97632202b Fix issue with KeyError 2020-07-06 15:57:10 +03:00
Ivan Kravets
a79e933c37 Ignore author's broken email in a package manifest 2020-07-06 14:22:35 +03:00
Ivan Kravets
ef53bcf601 Ignore empty fields in library.properties manifest 2020-07-06 14:17:00 +03:00
Ivan Kravets
08a87f3a21 Do not allow [;.<>] chars for a package name 2020-07-03 19:14:58 +03:00
Ivan Kravets
b3dabb221d Allow "+" in a package name 2020-07-03 16:07:36 +03:00
Rosen Stoyanov
899a6734ee Add .ccls to .gitignore (vim and emacs) (#3576)
* Add .ccls to .gitignore (vim)

* Add .ccls to .gitignore (emacs)
2020-06-30 21:48:44 +03:00
Ivan Kravets
7f48c8c14e Fix PyLint for PY 2.7 2020-06-30 15:06:40 +03:00
Ivan Kravets
2c24e9eff6 Fall back to latin-1 encoding when failed with UTF-8 while parsing manifest 2020-06-30 14:28:37 +03:00
Ivan Kravets
5cdca9d490 Optimize tests 2020-06-29 21:14:34 +03:00
Valerii Koval
1ac6c50334 Update multi-environment test for PIO test command 2020-06-29 20:52:15 +03:00
Valerii Koval
4cbad399f7 Remove mbed framework from several tests 2020-06-29 19:22:22 +03:00
Ivan Kravets
2b8aebbdf9 Extend test for parsing package manifest when "system" is used as a list 2020-06-29 15:06:21 +03:00
Ivan Kravets
e9a15b4e9b Parse package.json manifest keywords 2020-06-27 21:42:13 +03:00
Ivan Kravets
dd18abcac3 Fix tests 2020-06-27 12:59:12 +03:00
Ivan Kravets
b046f21e0d Fix "RuntimeError: dictionary keys changed during iteration" when parsing "library.json" dependencies 2020-06-27 12:46:04 +03:00
Ivan Kravets
29fb803be1 Enable PIO Core tests on Python 3.8 2020-06-27 12:36:57 +03:00
Ivan Kravets
bc2eb0d79f Parse dev-platform keywords 2020-06-26 19:49:25 +03:00
Ivan Kravets
0bec1f1585 Extend system info with "file system" and "locale" encodings 2020-06-26 18:38:17 +03:00
Ivan Kravets
a1ec3e0a22 Remove "vendor_url" and "docs_url" from Platform API 2020-06-25 23:23:55 +03:00
Ivan Kravets
7bc22353cc Docs: Sync dev-platforms 2020-06-25 18:04:04 +03:00
Ivan Kravets
efc2242046 Remove empty data from board information 2020-06-25 14:51:53 +03:00
Ivan Kravets
5dadb8749e Change slogan to "PlatformIO is a professional collaborative platform for embedded development" 2020-06-23 12:33:00 +03:00
Ivan Kravets
82735dd571 Fixed an issue with improper processing of source files added via multiple Build Middlewares // Resolve #3531 2020-06-23 11:46:00 +03:00
Ivan Kravets
9fb4cde2a5 Do not generate ".travis.yml" for a new project, let the user have a choice 2020-06-23 11:26:22 +03:00
Ivan Kravets
164ae2bcbc Extend system info with Python and PIO Core executables // Issue #3521 2020-06-23 11:20:29 +03:00
Ivan Kravets
a172a17c81 Bump version to 4.4.0a4 2020-06-22 23:09:28 +03:00
Ivan Kravets
5ee90f4e61 Display system-wide information using platformio system info command // Resolve #3521 2020-06-22 23:04:36 +03:00
Ivan Kravets
3aae791bee Change slogan to "collaborative platform" 2020-06-22 20:02:43 +03:00
Ivan Kravets
9f05519ccd List available project targets with a new "platformio run –list-targets" command // Resolve #3544 2020-06-22 19:53:31 +03:00
Ivan Kravets
f19491f909 Docs: Sync articles 2020-06-22 17:55:02 +03:00
Ivan Kravets
967a856061 Do not allow ":" and "/" chars in a package name 2020-06-22 15:25:02 +03:00
Valerii Koval
87d5997b46 Add a test that ensures setUp and tearDown functions can be compiled 2020-06-22 14:42:45 +03:00
Valerii Koval
c20a1f24cd Don't print relative paths with double-dot 2020-06-18 20:36:59 +03:00
Shahrustam
260c36727c fix pio access urn format 2020-06-17 23:56:22 +03:00
ShahRustam
03d9965758 Replace urn with prn (#3565)
* Replace urn with prn

* fix

* fix text
2020-06-17 23:46:50 +03:00
ShahRustam
e853d61e16 Add orgname filter for access list (#3564)
* add orgname filter for access list

* fix

* fix namings
2020-06-17 18:55:40 +03:00
ShahRustam
42e8ea29ff CLI to manage access level on PlatformIO resources. Resolve #3534 (#3563) 2020-06-17 13:53:53 +03:00
ShahRustam
1e90c821dc Disable package upload test (#3562) 2020-06-17 00:24:55 +03:00
Ivan Kravets
cad0ae0113 Update slogan to "No more vendor lock-in!" 2020-06-16 15:06:04 +03:00
Valerii Koval
21f3dd11f4 Fix printing relative paths on Windows // Resolve #3542
Fixes "ValueError" when running "clean" target if "build_dir"
points to a folder on a different logical drive
2020-06-16 12:27:49 +03:00
Ivan Kravets
a9c13aa20e Implement "ManifestParserFactory.new_from_archive" API 2020-06-15 22:05:59 +03:00
Ivan Kravets
d3fd115743 Black format 2020-06-15 22:05:28 +03:00
Valerii Koval
df0e6016bb Handle possible NodeList in source files when processing Middlewares // Resolve #3531
env.Object() returns a list of objects that breaks the processing of
subsequent middlewares since we only expected File nodes.
2020-06-15 21:25:24 +03:00
Ivan Kravets
cb70e51016 Update changelog for Custom Targets 2020-06-13 16:21:15 +03:00
Ivan Kravets
cf2fa37e56 Bump version to 4.4.0a3 2020-06-13 13:18:54 +03:00
Ivan Kravets
28d9f25f9a Added a new "-e, --environment" option to "platformio project init" command 2020-06-12 23:47:12 +03:00
Valerii Koval
fdb83c24be Clean autogenerated files before running tests // Resolve #3523
Fixes possible conflicts between auxiliary test transport files when
project contains multiple environments with different platforms
2020-06-11 23:53:52 +03:00
Ivan Kravets
660b57cdd3 Update PIO Home front-end to 3.2.3 2020-06-11 21:16:06 +03:00
ShahRustam
405dcda824 Feature/update account tests (#3556)
* update account tests

* change second user

* refactoring

* clean

* fix tests email receiving

* fix
2020-06-11 16:02:38 +03:00
Valerii Koval
266612bbdf Run CI on pull requests 2020-06-11 15:27:51 +03:00
Ivan Kravets
2722e27415 Sync docs 2020-06-11 15:15:46 +03:00
Valerii Koval
f571ad9d47 Sync docs 2020-06-11 11:03:48 +03:00
Ivan Kravets
ef8a9835b0 Bump version to 4.4.0a2 2020-06-10 14:26:48 +03:00
Ivan Kravets
b71b939307 Rename "AddSystemTarget" to "AddPlatformTarget" 2020-06-10 14:25:53 +03:00
Shahrustam
9e3ba11e8a skip account tests 2020-06-10 12:36:07 +03:00
Shahrustam
91e9406304 cleaning 2020-06-10 12:22:28 +03:00
Shahrustam
0d8272890c merge account, org and team tests into one file 2020-06-10 12:02:34 +03:00
ShahRustam
a182cca5e9 tests fix (#3555)
* replace timestamp with randint in tests

* replace pop3 with imap
2020-06-10 11:07:19 +03:00
Valerii Koval
e6fbd6acf1 Remove debug code 2020-06-09 23:26:49 +03:00
Ivan Kravets
062a82c89e Sync docs 2020-06-09 20:59:23 +03:00
Ivan Kravets
89cc6f9bf3 Bump version to 4.4.0a1 2020-06-09 18:44:49 +03:00
Ivan Kravets
3c8e0b17a7 Added support for custom targets 2020-06-09 18:43:50 +03:00
Shahrustam
e0023bb908 increase tests email receiving time 2020-06-09 17:05:11 +03:00
ShahRustam
a5547491ed Add account and org destroy commands. Fix tests (#3552)
* Add account and org destroy commands. Fix tests

* fix tests

* fix

* fix texts
2020-06-09 15:50:37 +03:00
Ivan Kravets
78546e9246 Docs: Add "TensorFlow, Meet The ESP32" to articles list 2020-06-08 19:26:48 +03:00
Ivan Kravets
7457ef043b Docs: Sync ASR Micro dev-platform 2020-06-08 12:00:19 +03:00
Ivan Kravets
e0e97a3629 Cache the latest news in PIO Home for 180 days 2020-06-05 18:29:11 +03:00
Ivan Kravets
f5e6820903 Bump version to 4.3.5a2 2020-06-05 14:18:24 +03:00
Ivan Kravets
27fd3b0b14 Improve detecting if PlatformIO Core is run in container 2020-06-05 14:17:19 +03:00
Valerii Koval
ced244d30a Sync docs 2020-06-05 11:30:15 +03:00
Ivan Kravets
6fa7cb4af5 Add new dev-platform "ASR Microelectronics ASR605x" 2020-06-04 22:59:05 +03:00
ShahRustam
94cb808285 CLI to manage teams. Resolve #3533 (#3547)
* CLI to manage teams.Minor fixes. Resolve #3533

* fix teams tests

* disable org and team tests

* minor fixes. fix error texts

* fix split compatibility
2020-06-04 19:31:30 +03:00
Ivan Kravets
42df3c9c3f Sync docs 2020-06-04 15:27:46 +03:00
Ivan Kravets
0c4c113b0a Fix account shpw command when PLATFORMIO_AUTH_TOKEN is used 2020-06-04 14:09:42 +03:00
Ivan Kravets
3c1b08daab Ignore empty PLATFORMIO_AUTH_TOKEN 2020-06-04 13:57:56 +03:00
Ivan Kravets
d7f4eb5955 Minor grammar fix 2020-06-03 22:40:37 +03:00
Ivan Kravets
87b5fbd237 More cosmetic changes to Org CLI 2020-06-03 22:34:37 +03:00
Ivan Kravets
6c97cc6192 Cosmetic changes to Org CLI 2020-06-03 22:22:13 +03:00
Ivan Kravets
cbcd3f7c4d Fix cmd.org test 2020-06-03 21:40:03 +03:00
Ivan Kravets
f7dceb782c Fix PY2.7 when PermissionError is not avialable 2020-06-03 21:24:01 +03:00
ShahRustam
140fff9c23 CLI to manage organizations. Resolve #3532 (#3540)
* CLI to manage organizations. Resolve #3532

* fix tests

* fix test

* add org owner test

* fix org test

* fix invalid username/orgname error text

* refactor auth request in clients

* fix

* fix send auth request

* fix regexp

* remove duplicated code. minor fixes.

* Remove space

Co-authored-by: Ivan Kravets <me@ikravets.com>
2020-06-03 17:41:30 +03:00
Ivan Kravets
8c586dc360 Sync docs 2020-06-03 17:16:59 +03:00
Ivan Kravets
fe52f60389 Bypass PermissionError when cleaning the cache 2020-06-03 14:33:53 +03:00
Ivan Kravets
9064fcbc77 Sync docs 2020-06-03 14:33:03 +03:00
Ivan Kravets
9a1d2970cc Sync docs 2020-05-30 01:10:04 +03:00
Ivan Kravets
26ba6e4756 Add new option to package publishing CLI which allows to disable email notiication 2020-05-28 17:06:36 +03:00
Ivan Kravets
ae58cc74bd Rename checksum header to X-PIO-Content-SHA256 2020-05-28 16:08:37 +03:00
Ivan Kravets
37e795d539 Send package checksum when publishing 2020-05-28 16:07:20 +03:00
Ivan Kravets
49960b257d Implement fs.calculate_file_hashsum 2020-05-28 16:07:02 +03:00
Shahrustam
25a421402b fix package type detector 2020-05-28 12:49:32 +03:00
Shahrustam
8e72c48319 fix datetime validation in package publish command 2020-05-27 22:30:16 +03:00
Ivan Kravets
c1965b607b Add binary stream to package publishing request 2020-05-27 17:27:05 +03:00
Ivan Kravets
d38f5aca5c Fix metavar for package CLI 2020-05-27 16:20:02 +03:00
Ivan Kravets
c06859aa9f Add package type to unpublish command 2020-05-27 14:30:27 +03:00
ShahRustam
e706a2cfe2 Refactor pio account client. Resolve #3525 (#3529) 2020-05-27 13:39:58 +03:00
Ivan Kravets
0c301b2f5d Fix order of arguments 2020-05-27 01:14:07 +03:00
Ivan Kravets
deb12972fb Implement "package unpublish" CLI 2020-05-27 01:10:35 +03:00
Ivan Kravets
8346b9822d Implement "package pack" command 2020-05-26 22:17:55 +03:00
Ivan Kravets
19cdc7d34a Initial support for package publishing in to the registry 2020-05-26 22:01:32 +03:00
Ivan Kravets
49cc5d606b Sync docs 2020-05-26 21:58:58 +03:00
Ivan Kravets
58470e8911 PY2 lint fix 2020-05-26 14:30:43 +03:00
Ivan Kravets
38699cca8f Bump version to 4.3.5a1 2020-05-26 14:26:42 +03:00
Ivan Kravets
0eb8895959 Add support for “globstar/**” (recursive) pattern 2020-05-26 14:25:28 +03:00
Ivan Kravets
99d4e0c390 Merge branch 'release/v4.3.4' 2020-05-23 20:35:59 +03:00
Ivan Kravets
6d32aeb310 Merge tag 'v4.3.4' into develop
Bump version to 4.3.4	81843087	Ivan Kravets <me@ikravets.com>	23 May 2020, 20:33
Bump version to 4.3.4
2020-05-23 20:35:59 +03:00
Ivan Kravets
8184308755 Bump version to 4.3.4 2020-05-23 20:33:13 +03:00
Ivan Kravets
b68953b733 Bump version to 4.3.4b1 2020-05-23 20:01:25 +03:00
Ivan Kravets
7dce494ad6 Rename "misc" command to "system", do not append completion code for Fish shell // Resolve 3435 2020-05-23 20:00:56 +03:00
Valerii Koval
4921bf8b6a PyLint fix 2020-05-22 14:22:41 +03:00
Valerii Koval
32cb0d6e4d Handle possible issue on Python 2.x when writing to thread buffer
The problem happens when value has type "unicode" that shouldn't be decoded
2020-05-22 14:17:17 +03:00
Ivan Kravets
e2c5a3c498 Add Python 3.8 for Tox 2020-05-22 14:12:27 +03:00
Ivan Kravets
ec34a65cff Bump version to 4.3.4a5 2020-05-21 15:40:38 +03:00
Ivan Kravets
9296615dbf Merge branch 'develop' of https://github.com/platformio/platformio-core into develop 2020-05-21 15:39:59 +03:00
Ivan Kravets
56795940b9 Sync teensy dev-platform 2020-05-21 15:39:24 +03:00
Valerii Koval
09a5952248 Add new record to history log
Mention issues about permission error on Windows when cloning
package from Git repository
2020-05-20 21:51:13 +03:00
Valerii Koval
735435306d Copy and remove cloned package instead of moving // Resolve #2844, Resolve #3328
On Windows, it’s not possible to move a file which is used by another
process (e.g. Git extension in VSCode)
2020-05-20 21:32:55 +03:00
Ivan Kravets
bdd57bf356 Ensure that copytree preserves symlinks 2020-05-20 20:57:55 +03:00
Valerii Koval
8840b28968 Handle possible issue on Python 2.x when writing to thread buffer
The problem happens when value has type "unicode" that shouldn't be decoded
2020-05-20 17:04:50 +03:00
Valerii Koval
e31591a35e Print warning about an issue with mapped network drives on Windows // Issue #3417
Starting with Python 3.8 paths to mapped network drives are resolved
to their real path in the system, e.g.: "Z:\path" becomes "\\path" which
causes weird errors in the default terminal with a message that UNC
paths are not supported
2020-05-19 22:37:05 +03:00
Ivan Kravets
457a218723 Sync docs 2020-05-19 13:27:54 +03:00
Ivan Kravets
9724660dda Update SPDX licenses to 3.9 2020-05-19 13:27:44 +03:00
ShahRustam
eac6c1c552 Handle error when internet is offline. Resolve # 3503 (#3505)
* Handle error when internet is offline.

* Fix

* minor fix
2020-05-17 22:44:27 +03:00
Ivan Kravets
54d73e834b Github Actions: Checkout submodules recursive 2020-05-14 18:08:51 +03:00
Ivan Kravets
099e3c7198 Use original MongoDB license for "compilation_db.py" 2020-05-13 00:48:11 +03:00
Ivan Kravets
96a68c6b14 Docs: Sync Atmel AVR dev-platform 2020-05-11 22:10:32 +03:00
Valerii Koval
2a0a1247e3 Revert "Add initialization config for new simavr tool"
This reverts commit 16966a4957.
2020-05-11 18:21:48 +03:00
Valerii Koval
7555d66748 Revert "Add special debug port for simavr tool"
This reverts commit 7b43444d81.
2020-05-11 18:21:26 +03:00
Ivan Kravets
c76940f7ce PyLint fix 2020-05-10 19:11:06 +03:00
Ivan Kravets
b2ed027bc3 Bump version to 4.3.4a4 2020-05-10 18:36:16 +03:00
Ivan Kravets
01a1981ca1 Added PlatformIO CLI Shell Completion for Fish, Zsh, Bash, and PowerShell // Resolve #3435 2020-05-10 18:35:50 +03:00
Ivan Kravets
03228c528e Bump version to 4.3.4a3 2020-05-09 16:36:05 +03:00
ShahRustam
ac510c1553 fix summary caching (#3500) 2020-05-09 16:35:21 +03:00
ShahRustam
a1ff5e1a4f Save summary data to local session. (#3497)
* Save summary data to local session.

* naming

* fix account summary test

* add ttl for summary cache

* refactoring get_account_info

* fix
2020-05-08 21:34:52 +03:00
Valerii Koval
7b43444d81 Add special debug port for simavr tool 2020-05-08 12:31:48 +03:00
Valerii Koval
16966a4957 Add initialization config for new simavr tool 2020-05-08 01:14:15 +03:00
ShahRustam
7e7a6d7807 Skip account tests if env variables not presented (#3494)
* added skip if env variables not presented. fix exception texts

* fix texts

* fix texts
2020-05-06 19:25:24 +03:00
Ivan Kravets
f32dbeeb6d Bump version to 4.3.4a2 2020-05-06 12:30:41 +03:00
Ivan Kravets
f78ffaded0 Remove local PIO Account session from PIO Remote when token is broken 2020-05-06 12:29:01 +03:00
Ivan Kravets
8480ebde89 Rename "authenticating" to "authorizing" wording for PIO Account 2020-05-06 12:27:29 +03:00
Ivan Kravets
44ee7d6a6b Docs: Sync ESP8266 dev-platform 2020-05-04 15:50:11 +03:00
ShahRustam
2ab47b7968 Remove account state item if refreshing token failed (#3487) 2020-05-04 13:14:52 +03:00
Ivan Kravets
7181b7632b Docs: Increase content width 2020-05-03 11:06:26 +03:00
Ivan Kravets
b82eaca45e Enable caching for PIP when building contrib-pysite 2020-05-02 15:29:24 +03:00
Ivan Kravets
fd04f31c5f Update link to CLA provider 2020-05-01 23:37:38 +03:00
Ivan Kravets
75abe8a0af Sync docs 2020-05-01 23:36:29 +03:00
Ivan Kravets
f7995ce49a PyLint fix 2020-04-29 12:56:54 +03:00
Ivan Kravets
2c2309acac Bump version to 4.3.4a1 2020-04-29 12:41:56 +03:00
Ivan Kravets
5f79ab34f5 Automatically build `contrib-pysite` package on a target machine when pre-built package is not compatible // Resolve #3482 2020-04-29 12:40:04 +03:00
Ivan Kravets
5bcbee7423 Merge branch 'release/v4.3.3' 2020-04-28 18:06:53 +03:00
Ivan Kravets
961049cf9b Merge tag 'v4.3.3' into develop
Bump version to 4.3.3
2020-04-28 18:06:53 +03:00
Ivan Kravets
72e7492a78 Bump version to 4.3.3 2020-04-28 18:06:46 +03:00
Ivan Kravets
5e4b4bbacd Fix "UnicodeDecodeError: 'utf-8' codec can't decode byte" when non-Latin chars are used in project path // Resolve #3481 2020-04-28 18:05:08 +03:00
Ivan Kravets
a64d368de2 Merge branch 'release/v4.3.2' 2020-04-28 13:27:23 +03:00
Ivan Kravets
6146b58520 Merge tag 'v4.3.2' into develop
Bump version to 4.3.2
2020-04-28 13:27:23 +03:00
Ivan Kravets
f35e6e99af Bump version to 4.3.2 2020-04-28 13:25:52 +03:00
Ivan Kravets
5d8440fdd1 PyLint fixes 2020-04-28 12:48:15 +03:00
Ivan Kravets
d1b394b20a Bump version to 4.3.2rc2 2020-04-27 23:42:22 +03:00
Ivan Kravets
520d6decac Nominate some exceptions to UserSideException 2020-04-27 23:42:02 +03:00
Ivan Kravets
4a251f0ab0 Fix JSONDecodeError when bottle.SimpleTemplate is used 2020-04-27 23:41:36 +03:00
Ivan Kravets
c215abb50c Bump version to 4.3.2rc1 2020-04-26 19:46:33 +03:00
Ivan Kravets
31ca47837d Disable build cache for Github Actions 2020-04-26 12:58:32 +03:00
Ivan Kravets
560699fc6b Apply formatting 2020-04-26 12:58:05 +03:00
Valerii Koval
51ec94f78c Add new test for PIO Check with --skip-packages option 2020-04-26 01:38:25 +03:00
Valerii Koval
ac1210fbea Add -imacros files to forcedInclude field in VSCode template 2020-04-26 00:35:22 +03:00
Valerii Koval
c03f93521b Refactor PIO Check feature (#3478)
* Add new option --skip-packages for check command

Check tools might fail if they're not able to preprocess source
files, for example, Cppcheck uses a custom preprocessor that is
not able to parse complex preprocessor code in zephyr framework).
Instead user can specify this option to skip headers included from
packages and only check project sources.

* Fix toolchain built-in include paths order
C++ and fixed directories should have higher priority

* Refactor check feature

The main purpose is to prepare a more comprehensive build environment.
It's crucial for cppcheck to be able to check complex frameworks like
zephyr, esp-idf, etc. Also detect a special case when cppcheck fails to check
the entire project (e.g. a syntax error due to custom preprocessor)

* Add new test for check feature

Tests ststm32 platform all tools and the main frameworks

* Update check tools to the latest available versions

* Test check tools and Zephyr framework only with Python 3

* Tidy up code

* Add history entry
2020-04-26 00:10:41 +03:00
Ivan Kravets
62ede23b0e Bump version to 4.3.2b1 2020-04-25 15:48:55 +03:00
Ivan Kravets
60f28599d9 Echo what is typed when "send_on_enter" device monitor filter is used // Resolve #3452 2020-04-25 15:48:37 +03:00
Ivan Kravets
629f23c4f3 Bump version to 4.3.2a4 2020-04-25 13:20:56 +03:00
Ivan Kravets
27db344739 Bump version to 4.3.2a3 2020-04-25 13:15:55 +03:00
Ivan Kravets
777a47fd99 Minor improvements 2020-04-25 13:14:54 +03:00
Ivan Kravets
e913159cb4 Sync docs 2020-04-24 21:48:57 +03:00
Ivan Kravets
b285c3137a Extend remote hosts with PlatformIO when checking internet connection 2020-04-24 16:25:02 +03:00
Ivan Kravets
f0576ddcd9 Docs: Fix incorrect type for library.json "libCompatMode" field 2020-04-24 13:14:03 +03:00
Shahrustam
6e2cc333f2 disable pio account change password and username update tests 2020-04-24 11:57:17 +03:00
ShahRustam
18c7c5a9be Refactor pio account tests. (#3473) 2020-04-24 11:25:09 +03:00
Ivan Kravets
01945716d3 Sync docs 2020-04-24 00:43:32 +03:00
ShahRustam
2f5b231dc3 Disable pio account tests (#3472)
* minor fix pio account test

* disable pio account change password and username update tests
2020-04-24 00:13:46 +03:00
Shahrustam
75c1aafaef fix pio account tests 2020-04-23 20:45:51 +03:00
ShahRustam
b9714d0ac1 Add pio account tests (#3470)
* add pio account tests

* update tests
2020-04-23 16:05:00 +03:00
Ivan Kravets
5774654582 Switch to Github Actions (#3471) 2020-04-23 16:04:15 +03:00
ShahRustam
0a46b8ab6a add login with code method for account client. add new account rpc handler. (#3468) 2020-04-21 22:44:32 +03:00
Valerii Koval
a556573a4f Move env dependent directories to appropriate CMAKE_BUILD_TYPE // Issue #3460
This will allow to dynamically populate list of sources depending on
selected environment. At the same time "src" and "lib" folders remain
common for all environments
2020-04-21 22:01:07 +03:00
Valerii Koval
fd91819b2c Fix missing include paths for check tools
Includes are now split by scopes and imported as a dictionary
2020-04-21 19:26:00 +03:00
Valerii Koval
24c04057e9 CLion: Add paths to libraries specified via lib_extra_dirs option (#3463)
* Add paths to libraries specified via lib_extra_dirs option

Besides, global folders in SRC_LIST seem a bit unnecessary
since there might be unused libraries in these folders

* Refactor processing of includes when exporting IDE/Editor projects

Split includes according to their source. That will help export includes in a more flexible way.
For example some IDEs don't need include paths from toolchains

* Add new record to history log

* Typo fix
2020-04-21 17:37:55 +03:00
Ivan Kravets
2960b73da5 Fix an issue when PIO Remote agent was not reconnected automatically 2020-04-21 12:32:03 +03:00
Ivan Kravets
c4645a9a96 Sync docs 2020-04-21 10:43:34 +03:00
Ivan Kravets
877e84ea1d Bump version to 4.3.2a2 2020-04-19 20:05:21 +03:00
Ivan Kravets
cb1058c693 New PIO Account with "username" and profile support 2020-04-19 20:03:46 +03:00
Ivan Kravets
be6bf5052e Open source PIO Remote client 2020-04-19 19:26:56 +03:00
ShahRustam
7780003d01 New Account Management System (#3443)
* add login for PIO account to account cli

* Remove PyJWT lib. Fixes.

* Add password change for account

* Refactoring. Add Account Client.

* Fixes.

* http -> https.

* adding error handling for expired session.

* Change broker requests from json to form-data.

* Add pio accoint register command. fixes

* Fixes.

* Fixes.

* Add username and password validation

* fixes

* Add token, forgot commands to pio account

* fix domain

* add update command for pio account

* fixes

* refactor profile update output

* lint

* Update exception text.

* Fix logout

* Add custom user-agent for pio account

* add profile show command. minor fixes.

* Fix pio account show output format.

* Move account related exceptions

* cleaning

* minor fix

* Remove try except for account command authenticated/non-authenticated errors

* fix profile update cli command

* rename first name and last name vars to 'firstname' and 'lastname'
2020-04-19 19:06:06 +03:00
Ivan Kravets
445ca937fd Sync docs 2020-04-18 22:40:27 +03:00
Ivan Kravets
1f4aff7f27 Sync docs 2020-04-16 16:07:02 +03:00
valeros
788351a0cd Fixed an incorrect node path used for pattern matching when processing middleware nodes 2020-04-13 16:41:03 +03:00
Ivan Kravets
5ba7753bfa Sync docs 2020-04-12 17:43:27 +03:00
Ivan Kravets
ae57829190 Generate user agent based on PIO Core environment 2020-04-10 17:59:58 +03:00
Ivan Kravets
030ddf4ea1 Apply black formatting 2020-04-10 17:08:16 +03:00
Ivan Kravets
ccc43633b7 Support for a new dev-platform NXP i.MX RT 2020-04-10 13:14:10 +03:00
Ivan Kravets
aba2ea9746 Temporary disable "infineonxmc" from CI due to a broken dev-platform 2020-04-09 12:44:52 +03:00
Valerii Koval
d5ebbb99a7 Dynamically choose extension for file with unit test transports (#3454)
C file should be used by default as only Arduino and mbed require C++ files.
There might be a lot of legacy projects so custom transport is also set to use C++.
2020-04-09 12:02:38 +03:00
Ivan Kravets
a636a60e00 Sort examples 2020-04-08 22:34:04 +03:00
Ivan Kravets
ad7e3f83aa Fix tests/commands/test_init.py 2020-04-08 17:18:59 +03:00
valeros
baa7aab1d7 Specify C++ as the language for .ino files when preprocessing them for PVS-Studio // Resolve #3450 2020-04-07 11:35:17 +03:00
Ivan Kravets
2e320c01b3 Fix test 2020-04-06 18:19:34 +03:00
Ivan Kravets
3cd6c618a4 Docs: Sync STM32 dev-platform 2020-04-06 16:56:05 +03:00
Ivan Kravets
5ea759bc3e Document PIO Core: Integration with custom applications (extensions, plugins) 2020-04-05 19:48:50 +03:00
Ivan Kravets
11cb3a1bf7 Docs: Add info about stm32pio tool for STM32Cube framework 2020-04-04 00:45:45 +03:00
Ivan Kravets
7412cf586b Update docs for Zephyr RTOS 2.2 2020-04-02 00:59:35 +03:00
Ivan Kravets
f976cf7ae5 Docs: Extend tutorials list 2020-03-30 17:15:18 +03:00
Ivan Kravets
e92b498b68 Fixed an issue when saving libraries in new project results in error "No option 'lib_deps' in section" // Resolve #3442 2020-03-27 13:34:14 +02:00
Ivan Kravets
1b0810ec87 Docs: Fix broken link for creating dev-platform // Resolve #123 2020-03-26 22:31:15 +02:00
Ivan Kravets
45e523a468 Docs: Sync with Atmel SAM dev-platform 2020-03-25 17:01:12 +02:00
Ivan Kravets
d42481d196 Sync docs 2020-03-24 18:03:23 +02:00
Ivan Kravets
11c946bfe4 Sync Espressif 32 dev-platform 2020-03-23 19:52:57 +02:00
Ivan Kravets
589d6f9e12 Docs: Sync Espressif 32 dev-platform 2020-03-23 19:35:18 +02:00
Ivan Kravets
79b3a232fc Move debug client and server implementations to "process" folder 2020-03-21 22:00:14 +02:00
Ivan Kravets
f95230b86e Fixed UnicodeDecodeError on Windows when network drive (NAS) is used // Resolve #3417 2020-03-21 21:53:42 +02:00
Ivan Kravets
fc9a16aa81 Merge branch 'feature/issue-3417-unicodeerror-nas' into develop 2020-03-21 21:44:13 +02:00
Ivan Kravets
81a4d28918 Docs: Remove duplicate demo image of PlatformIO for CLion 2020-03-21 16:39:17 +02:00
Ivan Kravets
fd137fe054 Bump version to 4.3.2a1 2020-03-21 13:28:31 +02:00
Ivan Kravets
efd3b244e1 Force PIPE reader to UTF-8 on Windows // Issue #3417 2020-03-21 13:27:46 +02:00
Richard Coleman
dbeaaf270c fix typo in URL (#3432) 2020-03-21 00:02:50 +02:00
Ivan Kravets
32642b7ec8 Fix broken link to Renode in history 2020-03-20 17:16:49 +02:00
Ivan Kravets
096c2f6165 Typo fix in docs 2020-03-20 17:11:31 +02:00
Ivan Kravets
91ae8b4cc7 Fixed typo in history 2020-03-20 15:15:30 +02:00
Ivan Kravets
cc52890d45 Merge branch 'release/v4.3.1' 2020-03-20 15:13:46 +02:00
Ivan Kravets
5a12f1f56e Merge tag 'v4.3.1' into develop
Bump version to 4.3.1
2020-03-20 15:13:46 +02:00
Ivan Kravets
b7b9ee5a80 Bump version to 4.3.1 2020-03-20 15:13:40 +02:00
Ivan Kravets
97a0cbdd18 Skip Click 7.1 and 7.1.1 on Windows due to broken releases 2020-03-20 15:11:14 +02:00
Ivan Kravets
b8f43732fe Docs: update What's PlatformIO and PIO IDE pages 2020-03-20 14:44:24 +02:00
Ivan Kravets
658b3df123 Fixed an TypeError "super(type, obj): obj must be an instance or subtype of type" when device monitor is used with a custom dev-platform filter // Resolve #3431 2020-03-20 13:56:30 +02:00
Ivan Kravets
d32312e738 Fixed an issue when lib_archive = no was not honored in "platformio.ini" 2020-03-20 13:34:35 +02:00
Ivan Kravets
20023f8d8a Bump version to 4.3.1a1 2020-03-20 13:02:11 +02:00
Ivan Kravets
6b2ff04bbf Fixed an error "SyntaxError: 'return' with argument inside generator" for PIO Unified Debugger when Python 2.7 is used 2020-03-20 13:01:33 +02:00
Ivan Kravets
d80a9c820d Merge branch 'release/v4.3.0' 2020-03-19 22:38:05 +02:00
Ivan Kravets
4b62af1675 Merge tag 'v4.3.0' into develop
Bump version to 4.3.0
2020-03-19 22:38:05 +02:00
Ivan Kravets
6414e1d9e3 Bump version to 4.3.0 2020-03-19 22:37:16 +02:00
Ivan Kravets
a55f04dc28 Warn that can't allocate socket for PIO Home 2020-03-19 22:36:55 +02:00
Ivan Kravets
2d68e28a70 Fix auto-ready logic for debugging server 2020-03-19 21:33:23 +02:00
Ivan Kravets
4c2a157dce Bump version to 4.3.0rc1 2020-03-19 19:28:13 +02:00
Ivan Kravets
d9647dec95 Add support for debugging server "ready_pattern" 2020-03-19 19:17:54 +02:00
Ivan Kravets
15647c81f0 New standalone (1-script) PlatformIO Core Installer 2020-03-19 18:26:30 +02:00
Ivan Kravets
24a0d9123e Update history with initial support for Renode 2020-03-19 17:04:05 +02:00
Ivan Kravets
720c29350d Add docs for Renode debugging tool // Issue #3401 2020-03-19 16:58:18 +02:00
valeros
aa939b07b1 Update default init config for Renode 2020-03-19 16:17:51 +02:00
Ivan Kravets
0e3c3abf73 GDB init commands for Renode simulation framework // Issue #3401 2020-03-19 15:16:55 +02:00
Ivan Kravets
a8606f4efa Refactor debug GDB initial configurations 2020-03-19 14:49:25 +02:00
ShahRustam
475f898222 Replace installer script with a new one // Resolve #3420 (#3428)
* Replace installer script with a new one. Resolve #3420

* temp file name fix

* get-platformio.py script update.

* small fix
2020-03-19 13:26:51 +02:00
Ivan Kravets
69f5fdf8e1 Remove debug code 2020-03-19 01:05:12 +02:00
Ivan Kravets
fe1ad35cad Merge branch 'feature/issue-3401-renode-support' into develop 2020-03-19 00:50:21 +02:00
Ivan Kravets
352a0b7377 Wait for an output from debug server 2020-03-19 00:46:23 +02:00
Ivan Kravets
52689bc5e8 Wait until debug server is ready 2020-03-19 00:19:59 +02:00
Ivan Kravets
3dd3ea1c35 Show a hexadecimal representation of the data (code point of each character) with `hexlify` filter 2020-03-18 18:55:54 +02:00
Ivan Kravets
fff33d8c29 Do not send CR+NL for "send_on_enter" device monitor filter 2020-03-18 17:25:40 +02:00
Ivan Kravets
db9829a11e Sync docs 2020-03-18 00:36:07 +02:00
Ivan Kravets
9a1b5d869d Bump version to 4.3.0b2 2020-03-18 00:13:03 +02:00
Ivan Kravets
605cd36e27 Send a text to device on ENTER with `send_on_enter` filter // Resolve #926 2020-03-18 00:09:40 +02:00
Ivan Kravets
24a23b67dd Fix formatting issue 2020-03-17 23:10:06 +02:00
Ivan Kravets
0df72411a0 Device Monitor Filter API, implement "time" and "log2file" filters // Resolve #981 Resolve #670 2020-03-17 23:08:57 +02:00
Ivan Kravets
5a72033622 Fixed an issue when unknown transport is used for PIO Unit Testing // Resolve #3422 2020-03-17 17:42:54 +02:00
Ivan Kravets
4e6095ca13 Update docs and history 2020-03-17 17:39:11 +02:00
Matthew Mirvish
f81b0b2a84 Ensure all commands in compilation_commands.json use absolute paths. (#3415)
* Fix resolving of absolute path for toolchain

By placing the `where_is_program` call into this function, all references to the compiler will be made absolute, instead of just ones in the top environment. Previously, all references to the compiler for user source code would not use the full path in the compilation database, which broke `clangd`'s detection of system includes.

* Linting issue
2020-03-17 16:30:28 +02:00
Ivan Kravets
314f634e16 Docs: Improvements for CLion docs. 2020-03-15 00:41:16 +02:00
Ivan Kravets
ba040ba2ba Docs: Workaround for ReadTheDocs bug 2020-03-14 20:32:42 +02:00
Ivan Kravets
a22ed40256 Added initial support for an official "PlatformIO for CLion IDE" plugin // Resolve #2201 2020-03-14 19:31:00 +02:00
Ivan Kravets
58a4ff8246 Skip broken Click 7.1 & 7.1.1, see Click's issue #1501 2020-03-14 12:18:00 +02:00
Ivan Kravets
9a5ebfb642 Bump version to 4.3.0b1 2020-03-12 15:10:25 +02:00
Ivan Kravets
5d0faaa5a8 Refactor docs structure 2020-03-12 15:09:20 +02:00
Ivan Kravets
108b892e30 Control device monitor output with filters and text transformations 2020-03-12 14:28:54 +02:00
Ivan Kravets
0ff37c9999 Implement universal "get_object_members" helper 2020-03-12 14:24:20 +02:00
Vojtěch Boček
8c3de609ab Add ESP crash trace decoding to monitor (#3383)
* Implement mechanism for adding platform filters into miniterm

Updates platformio/platform-espressif8266#31

* DeviceMonitorFilter: fixes for Windows and Python2
2020-03-11 13:22:01 +02:00
valeros
073efef2a1 Explicitly use Python-x64 with Appveyor CI 2020-03-10 15:54:01 +02:00
Ilia Motornyi
b9fd97dae4 Changes required for CLion PlatformIO plugin (#3298) 2020-03-09 15:47:41 +02:00
Ivan Kravets
60a7af6a8c Docs: Update recent articles 2020-03-09 14:58:35 +02:00
Ivan Kravets
0f02b3b653 Improved support for Arduino "library.properties" `depends` field 2020-03-07 17:44:28 +02:00
Ivan Kravets
620335631f Bump version to 4.2.2b1 2020-03-06 22:08:38 +02:00
Ivan Kravets
3ef96cb215 Minor fixes 2020-03-06 00:43:57 +02:00
Ivan Kravets
59e1c88726 Fixed an issue when `"libArchive": false` in "library.json" does not work // Resolve #3403 2020-03-06 00:37:48 +02:00
Ivan Kravets
3a27fbc883 Fixed an issue when Python 2 does not keep encoding when converting .INO file // Resolve #3393 2020-03-05 23:52:46 +02:00
Ivan Kravets
ce6b96ea84 Use native open/io.open for file contents reading/writing 2020-03-05 23:52:13 +02:00
Ivan Kravets
3275bb59bf Fix test 2020-03-04 18:14:51 +02:00
Ivan Kravets
fbb62fa8a6 Bump version to 4.2.2a3 2020-03-03 23:10:54 +02:00
Ivan Kravets
261c46d4ef Add support for Arm Mbed "module.json" `dependencies` field // Resolve #3400 2020-03-03 23:10:19 +02:00
Ivan Kravets
0c0ceb2caa Sync docs 2020-03-03 23:03:14 +02:00
Ivan Kravets
de60f20c21 Sync docs 2020-03-03 14:59:03 +02:00
valeros
314fe7d309 Initial support for menuconfig target 2020-03-03 00:58:07 +02:00
Ivan Kravets
a271143c52 Sync docs 2020-03-02 23:25:28 +02:00
Ivan Kravets
2d4a3db250 Fixed an issue with expanding $WORKSPACE_DIR for library manager 2020-02-29 23:08:08 +02:00
Ivan Kravets
7fba6f78d6 Bump version to 4.2.2a2 2020-02-29 21:59:58 +02:00
Ivan Kravets
eee12b9b66 Fixed an issue "the JSON object must be str, not 'bytes'" when PIO Home is used with Python 3.5 // Resolve #3396 2020-02-29 21:59:10 +02:00
Ivan Kravets
d3e151feeb Sync docs 2020-02-29 18:44:37 +02:00
Ivan Kravets
dd1fe74956 PyLint fix 2020-02-21 15:44:55 +02:00
Ivan Kravets
49aed34325 Rename PIO Plus to Professional 2020-02-21 15:44:24 +02:00
Ivan Kravets
81ba2a5a74 Sync docs 2020-02-20 18:22:12 +02:00
Ivan Kravets
1c87f83463 Parse package dependencies declared as a list of strings 2020-02-18 21:55:01 +02:00
Ivan Kravets
e15f227c48 Docs: Sync Atmel SAM dev-platform 2020-02-18 14:45:54 +02:00
Ivan Kravets
ea5f2742f8 Bump version to 4.2.2a1 2020-02-18 00:05:20 +02:00
Ivan Kravets
9fd0943b75 Fixed an issue when quitting from PlatformIO IDE does not shutdown PIO Home server 2020-02-18 00:03:23 +02:00
Ivan Kravets
80acd52fc2 Merge branch 'release/v4.2.1' 2020-02-17 14:25:27 +02:00
Ivan Kravets
b8312d545c Merge tag 'v4.2.1' into develop
Bump version to 4.2.1
2020-02-17 14:25:27 +02:00
Ivan Kravets
82f36a1ac3 Bump version to 4.2.1 2020-02-17 14:25:20 +02:00
Ivan Kravets
9f7c827572 Resolve absolute path of toolchain when generating compilation database 2020-02-17 13:52:25 +02:00
Ivan Kravets
6328206e78 Fixed an issue when generating of compilation database "compile_commands.json" does not work with Python 2.7 // Resolve #3378 2020-02-17 13:05:01 +02:00
Valerii Koval
154be7fa81 Improve VSCode template structure (#3385)
* Switch to click argument parser

* Typo fix

* Tidy up VSCode template

Co-authored-by: Ivan Kravets <me@ikravets.com>
2020-02-17 12:19:00 +02:00
Ivan Kravets
b8c9eee8af Force docs to HTTPS 2020-02-16 21:25:30 +02:00
Ivan Kravets
43664672fc Bump version to 4.2.1a3 2020-02-14 22:59:16 +02:00
Ivan Kravets
5cc9a328ab Fixed an issue when Library Dependency Finder (LDF) ignores custom "libLDFMode" and "libCompatMode" options in library.json 2020-02-14 22:57:51 +02:00
Ivan Kravets
6556c37e58 Bump version to 4.2.1a2 2020-02-14 20:57:40 +02:00
valeros
292049199a Add new record to history log 2020-02-14 17:24:52 +02:00
valeros
ed4452b115 Get rid of direct imports 2020-02-14 17:09:48 +02:00
valeros
fbfbf340c1 Add "forceInclude" field to VSCode template
VScode doesn't recognize header files included via "-include" flag in "compilerArgs" field.
Instead, absolute paths to these files should be specified in a special section "forceInclude".
2020-02-14 16:43:20 +02:00
Ivan Kravets
a57ea79bf8 Froze "marshmallow" dependency to 2.X for Python 2 // Resolve #3380 2020-02-14 13:49:41 +02:00
Ivan Kravets
22e8e02f3d Automatically rebuild contrib-pysite package when import fails // Resolve #3313 2020-02-13 22:06:46 +02:00
Ivan Kravets
a10625a052 Automatically rebuild contrib-pysite package when import fails // Issue #3313 2020-02-13 15:53:42 +02:00
Ivan Kravets
42020e2498 Bump version to 4.2.1a1 2020-02-13 13:35:38 +02:00
Ivan Kravets
36a2228220 Fixed "TypeError: unsupported operand type(s)" when system environment variable is used by project configuration parser // Resolve #3377 2020-02-13 13:34:34 +02:00
Ivan Kravets
206054b35f Docs: Sync dev-platforms 2020-02-12 23:58:39 +02:00
Ivan Kravets
b87048020d Add warning that overriding board data will not work for device monitor command // Issue #3349 2020-02-12 21:08:08 +02:00
Ivan Kravets
f7d4bf5fa8 Merge branch 'release/v4.2.0' 2020-02-12 16:42:13 +02:00
Ivan Kravets
f0bf531e1b Merge tag 'v4.2.0' into develop
Bump version to 4.2.0
2020-02-12 16:42:13 +02:00
Ivan Kravets
176cf17f9f Bump version to 4.2.0 2020-02-12 16:42:06 +02:00
Ivan Kravets
b41262a20e Fix broken "init" command 2020-02-12 16:34:38 +02:00
Ivan Kravets
d0a6861369 Fix "TypeError: TypeError: write() argument 1 must be unicode" when generating project on Windows/Python 2 2020-02-12 15:14:58 +02:00
Ivan Kravets
0bc872eafd Remap command before calling Click 2020-02-12 13:47:42 +02:00
Ivan Kravets
edc2d10574 Update SPDX License List to 3.8 2020-02-11 18:59:35 +02:00
Ivan Kravets
a033e2d1fe Docs: Update supported upload/debug protocols by Nuclei dev-platform 2020-02-11 18:37:48 +02:00
Ivan Kravets
c0aefe4c62 Add support for Nuclei RISC-V Processor development platform // Resolve #3340 2020-02-10 18:52:31 +02:00
Ivan Kravets
86069ab7c6 Typo fix 2020-02-08 21:37:18 +02:00
Ivan Kravets
86f2dde6f3 Do not overwrite a custom items in VSCode's "extensions.json" // Resolve #3374 2020-02-08 21:36:32 +02:00
Ivan Kravets
96f60aab66 Bump version to 4.2.0rc2 2020-02-08 20:35:43 +02:00
Ivan Kravets
2763853d8d Fixed an issue when no error is raised if referred parameter (interpolation) is missing in a project configuration file // Resolve #3279 2020-02-08 19:10:48 +02:00
Ivan Kravets
a78b461d45 Code formatting 2020-02-08 19:10:15 +02:00
Ivan Kravets
2fa20b5c52 Typo fix 2020-02-07 11:28:32 +02:00
Valerii Koval
0b0b63aa7d Update templates for Atom, VSCode, CLion (#3371)
* Wrap flags with whitespace chars when exporting data for IDEs

* Update IDEs templates

Take into account compiler flags that can contain whitespace characters (e.g. -iprefix)

* Update template for VSCode

* Add history record
2020-02-07 11:26:45 +02:00
valeros
fe174e35c8 Suppress warnings from packages dir instead of core dir for CppCheck 2020-02-06 23:48:13 +02:00
Ivan Kravets
88e40e28fc Bump version to 4.2.0rc1 2020-02-06 23:33:27 +02:00
Ivan Kravets
73ce3c94e9 Initial support for `Project Manager // Resolve #3335 2020-02-06 23:32:43 +02:00
valeros
d2033aacea Remove the entire folder with temp files used by pvs-studio tool 2020-02-06 23:21:27 +02:00
Mark Harfouche
dfb47a089b Add license file to sdist using MANIFEST.in (#3325) 2020-02-06 17:48:08 +02:00
Ivan Kravets
81960ce051 Fix test 2020-02-06 17:41:35 +02:00
Ivan Kravets
2ecceb8ed2 Generate absolute path for compilation DB item 2020-02-06 17:30:55 +02:00
Ivan Kravets
00a9a2c04d Generate `compilation database "compile_commands.json" // Resolve #2990 2020-02-06 17:19:48 +02:00
Valerii Koval
7716fe1d1c Autodetect monitor port for boards with specified HWIDs // Resolves #3349 (#3369)
* Autodetect serial port for boards with specified hwids

* Add new record to history log
2020-02-05 22:33:05 +02:00
Ivan Kravets
09b3df5520 Fixed a "UnicodeDecodeError" when listing built-in libraries on macOS with Python 2.7 // Resolve #3370 2020-02-05 22:25:06 +02:00
Ivan Kravets
ee2e4896d2 Fixed an issue when Project Inspector crashes when flash use > 100% // Resolve #3368 2020-02-05 18:15:44 +02:00
Ivan Kravets
390f1935d6 Fix parsing dependency in a legacy format 2020-02-05 15:43:39 +02:00
Ivan Kravets
365c3eaf4b Fixed an issue when invalid CLI command does not return non-zero exit code 2020-02-05 15:31:32 +02:00
Ivan Kravets
b83121a951 Fix package parser test 2020-02-05 14:34:40 +02:00
Ivan Kravets
efe8e599fd Added support for Arduino's library.properties `depends` field // Resolve #2781 2020-02-05 00:04:16 +02:00
valeros
bc69259dd1 Update tool-unity package to v2.5.0 // Resolve #3362 2020-01-31 15:10:45 +02:00
Ivan Kravets
607e8eb477 Improve detecting of active Internet connection // Resolve #3359 2020-01-29 18:54:30 +02:00
Ivan Kravets
139171a79f Sync docs 2020-01-29 18:53:33 +02:00
Ivan Kravets
848e525919 Bumo PIO Home to 3.1.0-rc.2 2020-01-26 00:31:55 +02:00
Ivan Kravets
b805822eea Remove debug code 2020-01-25 20:51:20 +02:00
Ivan Kravets
13e9306753 Bump version to 4.1.1b9 2020-01-25 20:50:26 +02:00
Ivan Kravets
880d5bb8b0 Fix project saving 2020-01-25 20:47:10 +02:00
Ivan Kravets
f9de23b16f Bump version to 4.1.1b8 2020-01-25 15:48:14 +02:00
Ivan Kravets
e5aa71e4e1 Fix config saving when PY2 is used 2020-01-25 15:47:45 +02:00
Ivan Kravets
ba441ca77c Remove double blank lines when saving project config // Resolve #3293 2020-01-24 22:15:33 +02:00
Ivan Kravets
decf482367 Use io.DEFAULT_BUFFER_SIZE as default chunk size 2020-01-24 22:05:24 +02:00
Ivan Kravets
253e4b13b5 Disable buffering file calculating checksum for downloaded file 2020-01-24 21:40:12 +02:00
Ivan Kravets
04ca6621f1 Verify downloaded package checksum with native Python's hashlib and support all OS 2020-01-24 20:43:05 +02:00
Ivan Kravets
20334772b5 Install a dev-platform with ALL declared packages using a new `--with-all-packages` option // Resolve #3345 2020-01-24 20:20:56 +02:00
Ivan Kravets
a62bc3846e Update IPs when checking for Internet 2020-01-24 19:50:55 +02:00
Ivan Kravets
3b092f28c3 Added support for "pythonPackages" in platform.json 2020-01-24 19:47:47 +02:00
Ivan Kravets
2de46f545f Formatter 2020-01-24 19:47:20 +02:00
Ivan Kravets
8fce660afa Add notice about VID:PID pairs // Resolve #3349 2020-01-24 14:47:23 +02:00
Ivan Kravets
dbeffe426f Update docs for CI 2020-01-23 22:48:22 +02:00
Ivan Kravets
d4c42bd546 Added support for `PVS-Studio static code analyzer 2020-01-23 20:51:34 +02:00
Ivan Kravets
fad5d1d744 Sync docs 2020-01-23 14:06:36 +02:00
Valerii Koval
46a9c1b6b2 Add initial support for PVS-Studio check tool (#3357)
* Add initial support for PVS-Studio check tool

* Enable all available PVS-Studio analyzers by default

* Add tests for PVS-Studio check tool

* Improve handling check tool extra flags that contain colon symbol
2020-01-23 12:57:54 +02:00
Max Prokhorov
5ac1e9454f pio-test: pass --verbose to the run command context (#3338)
* pio-test: pass --verbose to the run command context

* restore old output behavior
2020-01-23 12:56:08 +02:00
Ivan Kravets
17f9d57207 Control debug flags and optimization level with a new "debug_build_flags" option 2020-01-22 22:20:24 +02:00
Valerii Koval
5bdec19f31 Add new debug_build_flags option (#3355)
This will allow users to override default debug flags for example in cases when
the final binary built in debug mode is too large to be loaded on target
2020-01-22 20:41:42 +02:00
Ivan Kravets
90b80083e8 Sync docs 2020-01-22 12:58:16 +02:00
Ivan Kravets
8d02e8b8f7 Docs: Update FAQ for installing Python 2020-01-16 11:55:58 +02:00
Ivan Kravets
7e41841a74 Allow to call Downloader API in silent mode 2020-01-11 15:23:36 +02:00
Ivan Kravets
0f296e7e37 Skip broken example definitions in package manifest 2020-01-10 21:28:19 +02:00
Ivan Kravets
9c32ff278c Sync docs 2020-01-09 23:32:55 +02:00
Ivan Kravets
60139035d8 Include hidden files by default in a package 2020-01-05 18:29:19 +02:00
Ivan Kravets
5ab34436ec Cleanup package file name when packing 2020-01-04 23:48:06 +02:00
Ivan Kravets
178080fd12 Improve boards search 2020-01-04 13:53:08 +02:00
Ivan Kravets
915b9145f6 Filter boards by ID+Name 2020-01-04 11:46:25 +02:00
Ivan Kravets
6020faf970 Docs: Add "v" suffix to SparkFun RISC-V board ids 2020-01-04 11:38:13 +02:00
Ivan Kravets
ec82fc82a2 Support packages with nested folders and with a custom "root" 2020-01-03 22:55:56 +02:00
Ivan Kravets
8d7b775875 Implement package packer 2020-01-03 15:52:54 +02:00
Ivan Kravets
682114d6f1 Bump version to 4.1.1b7 2019-12-31 20:11:14 +02:00
Ivan Kravets
0ac5cd6789 Skip empty "export" values when parsing library.json manifest 2019-12-31 10:21:20 +02:00
Ivan Kravets
209040fdc1 Initial support for Zephyr framework // Issue #1613 2019-12-30 14:11:27 +02:00
Ivan Kravets
643f290057 Fix issue with library.properties manifest parser when author email is not specified 2019-12-29 17:43:50 +02:00
Ivan Kravets
ea0b462d0b PyLint fixes 2019-12-29 14:18:43 +02:00
Ivan Kravets
442a7e3576 Made package ManifestSchema compatible with marshmallow >= 3 // Resolve #3296 2019-12-29 13:13:04 +02:00
Ivan Kravets
f7385e8e88 Bump version to 4.1.1b6 2019-12-25 00:44:01 +02:00
Ivan Kravets
20a10c7fc5 Fixed an issue "Import of non-existent variable 'projenv''" // Resolve #3315 2019-12-24 23:43:21 +02:00
Ivan Kravets
2f05040081 Fixed an issue with LDF when header files not found if "libdeps_dir" is within a subdirectory of "lib_extra_dirs" // Resolve #3311 2019-12-24 14:36:44 +02:00
Ivan Kravets
7e0fb43dbe Normalise repository url when parsing package manifest 2019-12-22 23:45:12 +02:00
Ivan Kravets
26e7069099 Fixed default PIO Unified Debugger configuration for J-Link probe 2019-12-22 12:33:08 +02:00
Ivan Kravets
7d90c468ae Updated SCons tool to 3.1.2 2019-12-22 01:27:51 +02:00
Ivan Kravets
f9494c940e Add support for "downloadUrl" in package manifest 2019-12-20 20:20:09 +02:00
Ivan Kravets
135ef8701c Better representation of dependent packages 2019-12-20 01:19:23 +02:00
Ivan Kravets
1bd6e898ad Fix tests 2019-12-18 14:03:10 +02:00
Ivan Kravets
b15ddc00a5 Pass extra files with compiler options to VSCode IntelliSense tool 2019-12-17 22:40:28 +02:00
Ivan Kravets
b4088a6d00 Drop support for Samsung Artik dev/platform // Resolve #3309 2019-12-17 22:39:15 +02:00
Ivan Kravets
c57f68aee3 Change order between board/framework for configuration file 2019-12-17 15:22:02 +02:00
Ivan Kravets
31eed6c5e5 Improve detecting of a run PIO Home Server 2019-12-09 14:47:00 -08:00
Ivan Kravets
09852dcada Sync docs 2019-12-09 14:46:28 -08:00
Ivan Kravets
5768fcd429 Inform that PlatformIO Home server is already started in another process 2019-12-02 19:34:19 +02:00
Ivan Kravets
d901cc875a Minor improvements for docs 2019-12-02 19:28:21 +02:00
Ivan Kravets
4f1ccfe58f Bump version to 4.1.1b5 2019-11-28 18:58:09 +02:00
Ivan Kravets
f852f9fa89 Small refacoring 2019-11-28 18:23:00 +02:00
Ivan Kravets
5c388d4271 Fix issue with invalid checking used port for PIO Home server 2019-11-28 18:14:53 +02:00
Ivan Kravets
f9cae60225 Fix tests 2019-11-28 18:14:10 +02:00
Ivan Kravets
49ceadc6ad Move exceptions to their components 2019-11-28 16:15:54 +02:00
Ivan Kravets
47469e8759 Fix issue when None value is passed to config.set 2019-11-27 18:08:32 +02:00
Ivan Kravets
742f60b48d Bump version to 4.1.1b4 2019-11-26 18:00:33 +02:00
Ivan Kravets
0615ff6dd8 Docs: Change "Global/Local scope" configuration to "Common/Environment" 2019-11-26 17:40:09 +02:00
Ivan Kravets
2fbe33bca0 Move "Board" Options to "Platform 2019-11-26 14:44:54 +02:00
Ivan Kravets
fdd73552ea Docs for Zephyr // Issue #1613 2019-11-26 14:44:29 +02:00
Ivan Kravets
17b4f0b4dd Docs: Sync Atmel AVR dev/platform 2019-11-25 13:56:33 +02:00
Ivan Kravets
f87322591d Bump version to 4.1.1b3 2019-11-22 20:49:44 +02:00
Ivan Kravets
47099190f4 Bump PIO Home version to 3.1.0-beta.2 2019-11-22 20:49:09 +02:00
Ivan Kravets
9cf777b4e5 Fixed an issue with "start-group/end-group" linker flags on Native development platform // Resolve #3282 2019-11-21 14:19:32 +02:00
valeros
8675d3fa46 Use proper CMake variables for setting compilation flags 2019-11-21 00:39:05 +02:00
Ivan Kravets
2b9d8dba5f Bump version to 4.1.1b2 2019-11-20 23:32:19 +02:00
Ivan Kravets
b37814976c Fix project generator for CLion 2019-11-20 23:31:35 +02:00
Ivan Kravets
895aa0cb34 Update PlatformIO slogan 2019-11-19 20:01:50 +02:00
Ivan Kravets
18a9866a02 An example with custom debug flags in advanced scripting 2019-11-19 19:56:10 +02:00
Ivan Kravets
88ead0aed1 Catch all debug errors when killing debug server 2019-11-19 18:55:21 +02:00
Ivan Kravets
f19c7dc575 Support for Atmel megaAVR 2019-11-18 17:59:19 +02:00
Ivan Kravets
7eab5d567e Fix CLion generator when one env is used 2019-11-17 00:35:56 +02:00
Ivan Kravets
5b1c6daa2a Fix a space in config header 2019-11-16 23:09:18 +02:00
Ivan Kravets
464e1a509f Add PIO Home "os.get_file_mtime" RPC method 2019-11-16 22:57:56 +02:00
Ivan Kravets
c1394b290d Fix issue with unknown dev/platform when symlink is used 2019-11-16 22:43:25 +02:00
Ivan Kravets
0029c7fe09 Advanced Serial Monitor with UI 2019-11-16 17:45:57 +02:00
Ivan Kravets
e9f9871c1e Show to user the last exception when can't install a package 2019-11-16 17:25:27 +02:00
Ivan Kravets
d1b46c838e Revert back "Flash" instead of "ROM" 2019-11-16 14:09:16 +02:00
Ivan Kravets
a7b9187234 Bump version to 4.1.1b1 2019-11-15 20:05:52 +02:00
Ivan Kravets
c7202154de Project Manager and Project Configuration UI for "platformio.ini" 2019-11-15 20:05:09 +02:00
Ivan Kravets
6809da0353 Replace os.path.abspath by realpath 2019-11-15 16:02:15 +02:00
Ivan Kravets
fbdcbf17c7 Rename Data/Flash to RAM/ROM 2019-11-15 15:52:39 +02:00
Ivan Kravets
44a9de6dcb Pass -m and -i flags to VSCode Intellisense analyzer 2019-11-15 15:11:13 +02:00
Ivan Kravets
a077081e46 Init generic C/C++ SCons tools by default 2019-11-15 15:10:43 +02:00
Ivan Kravets
728fd7f5b9 Catch exception when can not get a default locale 2019-11-13 16:48:04 +02:00
Ivan Kravets
053160a6eb Sync docs 2019-11-13 16:47:39 +02:00
Ivan Kravets
9bbaba3d59 Bump version to 4.1.1a2 2019-11-13 15:35:32 +02:00
Ivan Kravets
b1577d101c Update PIO Home to 3.0.1 2019-11-13 15:32:57 +02:00
Ivan Kravets
53e6cf3e4a Drop support for "project_dirs" argument to Project RPC 2019-11-13 15:32:14 +02:00
Ivan Kravets
a9f9f4ef04 Fixed an issue when `env.BoardConfig()` does not work for custom boards in extra scripts of libraries // Resolve #3264 2019-11-12 23:52:43 +02:00
Ivan Kravets
15f142fc70 Ensure content cache key does not contain path separators 2019-11-12 23:48:39 +02:00
Ivan Kravets
6e9429dbbf Split BuildProgram into ProcessProgramDeps and ProcessProjectDeps 2019-11-12 18:52:25 +02:00
Ivan Kravets
be628051a7 Fix typo 2019-11-12 18:35:07 +02:00
Ivan Kravets
f0eb177a8e Check if directory exists before fetching project info 2019-11-12 18:32:10 +02:00
Ivan Kravets
7c481291dc Warn about about broken library manifest when scanning dependencies // Resolve #3268 2019-11-12 18:14:06 +02:00
Ivan Kravets
f1d20f591a Sync docs 2019-11-12 13:41:54 +02:00
Ivan Kravets
c6a8e03367 Fixed an issue when `env.BoardConfig()` does not work for custom boards in extra scripts of libraries // Resolve #3264 2019-11-12 13:41:39 +02:00
Ivan Kravets
cbb7869da1 Fixed an issue with the broken latest news for PIO Home 2019-11-12 13:09:35 +02:00
Ivan Kravets
1f796ca0e5 Bump version to 4.1.1a1 2019-11-11 23:22:17 +02:00
Ivan Kravets
703b29a05e Fixed missed descriptions for project options 2019-11-11 23:19:47 +02:00
Ivan Kravets
56ceee220b Fix invalid build status for unit test when remote is used 2019-11-11 22:48:29 +02:00
Ivan Kravets
0328037b49 Handle project configuration (monitor, test, and upload options) for PIO Remote commands // Resolve #2591 2019-11-11 22:38:16 +02:00
Ivan Kravets
3c796ca7c8 Cosmetic fixes 2019-11-08 17:40:11 +02:00
Ivan Kravets
e6e14be528 Fix framework name shakti-sdk 2019-11-07 16:58:57 +02:00
Ivan Kravets
f42d1a89f2 Merge tag 'v4.1.0' into develop
Bump version to 4.1.0
2019-11-07 16:54:21 +02:00
Ivan Kravets
5a89388fb0 Merge branch 'release/v4.1.0' 2019-11-07 16:54:20 +02:00
Ivan Kravets
d043412e0f Bump version to 4.1.0 2019-11-07 16:54:12 +02:00
Ivan Kravets
71168b1a5f Replace IoT with Embedded 2019-11-07 16:49:34 +02:00
Ivan Kravets
95c1b0214c Rename "check_pattern" to "check_patterns" 2019-11-07 15:24:47 +02:00
Ivan Kravets
2408c0a4c7 Fix incorrect info about build_type 2019-11-06 23:53:38 +02:00
Ivan Kravets
4b3f593df9 Bump version to 4.1.0rc9 2019-11-06 23:24:49 +02:00
Ivan Kravets
67aea4db3f Fix issue with GDB/MI Stream Records for PIO Debugger 2019-11-06 22:30:58 +02:00
Ivan Kravets
6b44a8ae75 Use BuildAsyncPipe only if TTY stream 2019-11-06 22:25:14 +02:00
Ivan Kravets
70f4fa2665 Remove platformio.description if none value is passed 2019-11-06 20:06:30 +02:00
valeros
17ff3250c9 Export uppercased driver name in sizedata report on Windows 2019-11-06 12:34:43 +02:00
Ivan Kravets
2cce47a13d Fix "pio_reset_run_target" for JLink debug probe 2019-11-06 12:20:42 +02:00
Ivan Kravets
c1f62f8ead Bump version to 4.1.0rc8 2019-11-06 01:01:07 +02:00
Ivan Kravets
e0c174b9b6 Improve PIO Home Misc RPC 2019-11-06 00:48:28 +02:00
Ivan Kravets
e5ec4de3a4 Extend PIO Home RPC with "project.config_update_description(path, text)" method 2019-11-06 00:05:17 +02:00
Ivan Kravets
bcf09964ab Better formatting for multi-line values in config option 2019-11-06 00:03:08 +02:00
Ivan Kravets
f3992f8e53 Create dummy target for CLION 2019-11-05 15:59:06 +02:00
Ivan Kravets
66cc557d2f Export SVD Path to CLion 2019-11-05 15:16:50 +02:00
Ivan Kravets
9786b3e1b9 Fix CLion integration when project name contains a space 2019-11-05 15:16:35 +02:00
Ivan Kravets
30bc691c95 Fix test with a missed library 2019-11-05 12:08:29 +02:00
Ivan Kravets
83110326f4 Rename "check_pattern" option 2019-11-05 12:02:12 +02:00
valeros
182835fabf Rename check_patterns option to check_pattern 2019-11-05 11:36:20 +02:00
Ivan Kravets
7345d3ea19 Improve dump of config data 2019-11-05 00:17:39 +02:00
Ivan Kravets
3f4aa320c2 Sync docs 2019-11-04 21:52:42 +02:00
valeros
dfd853fa87 Update tests for check command with a new flag "pattern" that supersedes "filter" 2019-11-04 21:34:39 +02:00
Ivan Kravets
3289e84b21 Refactor PIO Check from "check_filters" to "check_patterns" 2019-11-04 18:22:28 +02:00
Ivan Kravets
39639d45fe Bump version to 4.1.0rc7 2019-11-04 15:36:45 +02:00
Ivan Kravets
b45abf67a5 Fix broken debug configuration 2019-11-04 15:36:23 +02:00
Ivan Kravets
e57871cab7 Print a building mode 2019-11-03 22:22:40 +02:00
Ivan Kravets
484ea15959 Bump version to 4.1.0rc6 2019-11-02 23:14:16 +02:00
Ivan Kravets
40109263f0 Fix initial debug configuration for J-Link 2019-11-02 23:09:56 +02:00
Ivan Kravets
b45261c3dc Change initial debug configuration to: reset/halt, load, init break points 2019-11-02 22:56:11 +02:00
Ivan Kravets
73bcf18498 Fix broken debugger 2019-11-02 22:54:57 +02:00
Ivan Kravets
0dcc6f350d Bump version to 4.1.0rc5 2019-11-02 19:49:34 +02:00
Ivan Kravets
0488cc4086 Typo fix 2019-11-02 19:48:41 +02:00
Ivan Kravets
7784743cb1 Switch to default values from project configuration options 2019-11-02 19:44:28 +02:00
Ivan Kravets
0a4bc1d4e3 Add "description" for project config options, configure "default" values 2019-11-02 19:41:39 +02:00
Ivan Kravets
3630084a64 Docs: Sync Kendryte K210 dev/platform 2019-11-01 18:53:00 +02:00
Ivan Kravets
53c561e895 Bump version to 4.1.0rc4 2019-11-01 18:33:21 +02:00
Ivan Kravets
88db253515 Ignore duplicate library storages 2019-11-01 18:28:20 +02:00
Ivan Kravets
da928efb43 Added "--shutdown-timeout" option to PIO Home Server 2019-11-01 14:40:03 +02:00
Ivan Kravets
cd3d638337 Disable parsing of extra configs for PIO Home Project RPC load/dump methods 2019-11-01 12:05:13 +02:00
Ivan Kravets
3de2d84e2b Fixed an issue with a GCC Linter for PlatformIO IDE for Atom // Resolve #3218 2019-10-31 22:42:22 +02:00
Ivan Kravets
1d5d09feab Fixed an issue when Project Config Parser does not remove in-line comments when Python 3 is used // Remove #3213 2019-10-31 22:04:57 +02:00
Ivan Kravets
2c2b419685 Docs: Sync nRF52 dev/platform 2019-10-31 18:52:26 +02:00
Ivan Kravets
a7f8838d9a Format code 2019-10-31 18:52:13 +02:00
Ivan Kravets
a18f8b2a4c Use default values from project options 2019-10-31 15:28:02 +02:00
Ivan Kravets
9b65a091da Export config dump/load and schema to PIO Home Project.RPC 2019-10-31 15:27:34 +02:00
Ivan Kravets
8ccf9d2e53 Implement project config "update" with "clear" option 2019-10-31 15:26:34 +02:00
Ivan Kravets
cd6137bdb0 Bump version to 4.1.0rc3 2019-10-31 00:43:44 +02:00
Ivan Kravets
6d69c25a2f Use locale encoding to decode subprocess output // Resolve #2890 2019-10-30 20:43:37 +02:00
Ivan Kravets
7b6bab7f4e Update memory usage banner 2019-10-30 20:40:26 +02:00
Ivan Kravets
257a8c63d2 Sync docs 2019-10-30 20:28:38 +02:00
Ivan Kravets
3146ab5d12 Allow export project config data as Tuple 2019-10-30 19:09:32 +02:00
Ivan Kravets
2d4722477e Automatically shutdown PIO Home server when no clients for 1 hour 2019-10-30 18:58:49 +02:00
valeros
d815daed29 Allow specifying defect level that will cause failure 2019-10-30 13:38:46 +02:00
valeros
c4e7674585 Don't pass header files to Cppcheck 2019-10-30 12:23:33 +02:00
Ivan Kravets
94f565db84 Show warning about restart IDE to affect PIO Home changes 2019-10-29 18:11:09 +02:00
Ivan Kravets
6e03aa3a3d Bump version to 4.1.0rc2 2019-10-29 18:03:07 +02:00
Ivan Kravets
737c29b510 Update PIO Home to 3.0.0-beta.2 2019-10-29 18:02:32 +02:00
Ivan Kravets
0222c56c4d Use file system encoding when decoding subprocess output // Resolve #2890 2019-10-29 17:43:48 +02:00
Ivan Kravets
8d0584aa59 Add new IDE RPC "open_text_document" method for PIO Home 2019-10-29 17:37:09 +02:00
Ivan Kravets
7dbeab11a5 Add new OS.RPC "open_file" method for PIO Home 2019-10-29 17:36:36 +02:00
Ivan Kravets
7cad06ea18 Minor test fixes 2019-10-29 17:12:18 +02:00
Ivan Kravets
3236fb6b3d Return file+line for sizedata instead of "location" 2019-10-29 17:01:20 +02:00
valeros
0194e09410 Use simple abspath to get absolute path to file with defect 2019-10-28 18:37:14 +02:00
valeros
187e30d055 Export full path to file with defect 2019-10-28 18:30:22 +02:00
valeros
39a7062503 Fix types of defect fields column and line 2019-10-28 18:12:39 +02:00
Ivan Kravets
4ff7c868ef Sync docs 2019-10-28 16:34:26 +02:00
valeros
5573c3871c Allow cppcheck suppress individual defects by default 2019-10-28 13:38:46 +02:00
valeros
d620579247 Fix tests for check command according to updated exit codes 2019-10-25 21:04:30 +03:00
valeros
48651286b6 Automatically detect C++ standard version when invoking cppcheck 2019-10-25 20:59:36 +03:00
valeros
0e7a2b3141 Automatically detect source files language when invoking cppcheck 2019-10-25 20:08:04 +03:00
Ivan Kravets
f3b8ae4224 Bump version to 4.1.0rc1 2019-10-25 20:02:01 +03:00
Ivan Kravets
a2451a716d PIO Home 3.0 with Project Inspect 2019-10-25 20:01:31 +03:00
Ivan Kravets
2e5dabb913 Fix issue with custom board_ options 2019-10-25 19:33:22 +03:00
valeros
4e43e7d3c3 Fix code formatting 2019-10-25 17:43:52 +03:00
Ivan Kravets
49acf4bdb9 Minimum supported version of PIO Plus Core is 2.5.8 2019-10-25 17:27:51 +03:00
valeros
f3d8c30f95 Skip ignored environments when exporting check report in JSON format 2019-10-25 15:50:19 +03:00
valeros
4486a85d4c Introduce new flag --fail-on-defect to pio check 2019-10-25 15:40:50 +03:00
Ivan Kravets
8a6892bf3c Fixed an issue with invalid encoding when generating project for Visual Studio // Issue #3183 2019-10-25 14:33:22 +03:00
valeros
087a8f6dd0 Fix Visual Studio template files encoding // Resolve #3183 2019-10-25 14:27:47 +03:00
Ivan Kravets
5e681ec03c ProjectRPC.config_call accepts first argument as dict/kwargs for Config.init 2019-10-25 14:01:46 +03:00
Ivan Kravets
784a5cd349 Add support for "Build Middlewares" 2019-10-25 00:33:04 +03:00
valeros
5345dd2674 Give a proper name to method that converts defect item to dict 2019-10-24 21:35:04 +03:00
valeros
8127fd9960 Export correct stats for each check tool 2019-10-24 20:44:34 +03:00
Ivan Kravets
3177aaf591 Fixed an issue when booleans in "platformio.ini" are not parsed properly // Resolve #3022 2019-10-24 19:43:13 +03:00
Ivan Kravets
70b484a2c2 Escape "\" char in GDB console output 2019-10-24 17:34:49 +03:00
Ivan Kravets
ed6c9a08ce Add custom "PLATFORMIO_BUILD_DEBUG" target for CLion 2019-10-24 17:21:02 +03:00
Ivan Kravets
601989c5ff Escape "\" char in GDB console output 2019-10-24 16:56:28 +03:00
Ivan Kravets
234585dc97 Fixed an issue with project generator when `src_build_flags` were not respected // Resolve #3137 2019-10-24 16:39:11 +03:00
Ivan Kravets
2388b2a62b Fixed security issue when extracting items from TAR archive // Issue #2995 2019-10-24 16:24:53 +03:00
Ivan Kravets
69d9438c71 Temporary disable security checking for Tar items 2019-10-24 15:39:41 +03:00
Ivan Kravets
0b500dba54 Handle legacy "system": "all" for package manifest 2019-10-24 15:10:11 +03:00
Ivan Kravets
798b12ce7b Fixed security issue when extracting items from TAR archive // Resolve #2995 2019-10-24 14:55:45 +03:00
Ivan Kravets
334d50c367 Use package parser for package manager and LDF 2019-10-24 13:42:46 +03:00
Ivan Kravets
dd1da95a40 Fix issue when wrong library was picked up by LDF when framework is not declared 2019-10-24 00:28:03 +03:00
Ivan Kravets
6684ac5a57 LDF: Check project include dirs before looking for dependencies 2019-10-23 22:55:02 +03:00
Ivan Kravets
b533d7a1dd LDF: Check global CPPPATH when looking for dependencies 2019-10-23 22:31:26 +03:00
Ivan Kravets
95d1f43799 Sync docs with ST STM32 dev/platform 2019-10-23 18:49:08 +03:00
Ivan Kravets
9c7cc87c5f Move command related modules to "commands" package 2019-10-23 16:05:27 +03:00
valeros
374379ba03 Skip .debug sections when generating memory use report 2019-10-22 21:52:55 +03:00
valeros
56ac577b0a Fix case with empty arguments when generating sizedata report 2019-10-22 12:10:48 +03:00
valeros
941c0f4297 Improve the speed of memory use report generation 2019-10-21 23:26:28 +03:00
Ivan Kravets
f34745bef9 Parse device frequency in int format for size data 2019-10-21 15:57:34 +03:00
Ivan Kravets
9fef7f0ba9 Docs: Sync TI MSP430 dev/platfom 2019-10-21 15:53:25 +03:00
Ivan Kravets
971cd2ca0f Export device info in pair with sizedata 2019-10-21 00:12:04 +03:00
Ivan Kravets
6bf8bec22d Bump version to 4.1.0b5 2019-10-19 12:43:43 +03:00
Ivan Kravets
d771816b02 Automatically change dir to project for RPC "config_call"; add "envs" and "descrption" for project entities 2019-10-19 12:42:43 +03:00
Ivan Kravets
f78a1a7b15 Show encoding error when can't read a file // Issue #2796 2019-10-18 22:00:28 +03:00
Ivan Kravets
77f8414c63 Better explanation about encoding error // Resolve #2796 2019-10-18 15:56:50 +03:00
Ivan Kravets
4d84d03a63 Black 2019-10-18 15:56:41 +03:00
Ivan Kravets
065607b68c Disable PyLint's "import-outside-toplevel" 2019-10-18 15:41:52 +03:00
Ivan Kravets
f5807364e8 Force to "backslashreplace" when UnicodeEncodeError arises when writing file // Issue #2796 2019-10-18 15:20:52 +03:00
Ivan Kravets
92d86192aa Substitute LDSCRIPT with real value 2019-10-18 15:05:11 +03:00
Ivan Kravets
d44c60614d Use direct LDSCRIPT_PATH only if script resolves 2019-10-17 23:40:30 +03:00
Ivan Kravets
19a8326f0f Fix test for package manifest 2019-10-17 21:19:04 +03:00
Ivan Kravets
be9aaf8902 Be compatible with Python 3.8, on Windows skip HOME and check for USERPROFILE 2019-10-17 20:57:40 +03:00
Ivan Kravets
5cfa2b7fdd Fix typo with UnicodeEncodeError // Issue #2796 2019-10-17 19:28:57 +03:00
Ivan Kravets
6218b773fd Better support for file contents writing // Issue #2796 2019-10-17 18:48:59 +03:00
Ivan Kravets
7bcfea13fb Fixed an issue with linking process when `$LDSCRIPT` contains a space in path 2019-10-17 16:52:18 +03:00
Ivan Kravets
89843c0d65 Fix issue with parsing library.properties when export field is used 2019-10-17 15:48:18 +03:00
valeros
31d4a5c72e Add collective stats info about project components to check report 2019-10-17 13:42:00 +03:00
Ivan Kravets
83f25cbc16 Fix tests 2019-10-17 12:38:35 +03:00
Ivan Kravets
27fc19d6b3 Switch to Marshmallow ODM framework 2019-10-17 00:17:16 +03:00
Ivan Kravets
9cfccc5cd4 Minor fixes to manifest parser 2019-10-16 13:58:50 +03:00
Ivan Kravets
9da19fbf54 Use isolated SCons sign DB per Python interpreter 2019-10-16 12:09:53 +03:00
Ivan Kravets
a481a5deda Fix issue with "remote test" // Resolve #3127 2019-10-15 23:30:02 +03:00
Matt McCartney
e8692334f6 Replace deprecated in python3: iteritems with items and basestr with str (#3119) 2019-10-15 22:00:48 +03:00
Ivan Kravets
239befa4ee New Shakti dev/platform 2019-10-15 13:05:56 +03:00
Ivan Kravets
2e9b0066de Capture manifest parser exceptions 2019-10-14 23:36:15 +03:00
Ivan Kravets
55d905a0d0 Add a new RPC method "project.config_call" for Home API 2019-10-12 20:00:12 +03:00
Ivan Kravets
181adb277f Sync docs 2019-10-12 19:58:34 +03:00
Ivan Kravets
82ec0164b0 Update docs on how to install Python 3.7 on Windows 2019-10-10 23:35:59 +03:00
Ivan Kravets
c8354b100e Bump version to 4.1.0b4 2019-10-10 14:51:14 +03:00
Ivan Kravets
4366719ed2 Restore missed project helpers needed by "platformio-node-helpers" 2019-10-10 14:50:34 +03:00
valeros
971eb8e35c Revert back unix style directory separator in sizedata report 2019-10-09 17:37:24 +03:00
valeros
a785c238b1 Use OS-native directory separator in sizedata report 2019-10-09 00:39:57 +03:00
valeros
eda02750ae Export files as list instead of dict for sizedata target 2019-10-08 13:45:36 +03:00
Ivan Kravets
e5d50eb45c Docs: RV-LINK debug tool, sync GDV32 dev/platform 2019-10-08 11:49:04 +03:00
Ivan Kravets
b66bf5f4c0 Ignore symbolic links for package examples 2019-10-07 20:35:01 +03:00
Ivan Kravets
d1c8cc38f2 Cast semver to string when validating version 2019-10-05 23:40:27 +03:00
Ivan Kravets
10bada0bcc ManifestPaser: handle examples from "Examples" folder 2019-10-05 20:21:39 +03:00
Ivan Kravets
5d7e7b1796 DataModel: capture exceptions from failed models in non-strict mode 2019-10-04 23:52:06 +03:00
Ivan Kravets
0f7fe260d1 Docs: Sync ESP32 dev platform 2019-10-04 21:15:37 +03:00
Ivan Kravets
46be56af43 Bump version to 4.1.0b3 2019-10-04 20:51:05 +03:00
Ivan Kravets
dce2655004 Fix broken serial monitor called via run target while uploading // Resolve #3081 2019-10-04 20:50:39 +03:00
Ivan Kravets
36acdd7797 DataModel: allow valid values in non-strict mode for TypeOfList and TypeOfDict 2019-10-04 18:30:48 +03:00
valeros
47e297fecb Use less verbose debug output 2019-10-04 13:27:02 +03:00
valeros
9ce19c7e83 Skip debug sections when calculating sizedata 2019-10-04 10:52:55 +03:00
Ivan Kravets
9954900a0e Return back LINKFLAGS for debug mode 2019-10-03 18:16:55 +03:00
Ivan Kravets
a7855ae664 ManifestParser: init from dir using name of file in remote url if provided 2019-10-03 16:14:51 +03:00
Ivan Kravets
76865a1730 ManifetPatrser fixes (#3080)
* Skip broken examples declaration

* Allow dots in keywords

* Allow "+" in keywords
2019-10-03 14:55:04 +03:00
Ivan Kravets
8febdc19ea ManifestParser: normalize example names 2019-10-03 12:47:41 +03:00
Ivan Kravets
85a814c21a Allow dot in manifest example name 2019-10-03 10:33:11 +03:00
Ivan Kravets
ab5650f84b Use max line length hooks for all systems 2019-10-02 23:46:42 +03:00
Ivan Kravets
77c591ce81 Fix RTD conf 2019-10-02 21:35:13 +03:00
Ivan Kravets
dc067642b2 Fix RTD conf 2019-10-02 21:33:40 +03:00
Ivan Kravets
d0ee0c2919 Sync docs 2019-10-02 21:32:31 +03:00
Ivan Kravets
6d50aa2e25 Remove RTD confs 2019-10-02 20:54:36 +03:00
Ivan Kravets
b68b9794ec Fix docs with "htmlzip" format 2019-10-02 20:51:39 +03:00
Ivan Kravets
e6ea4cb613 PackageManifest: Ignore hidden files for examples 2019-10-02 20:42:01 +03:00
Ivan Kravets
47ba127733 Add ReadTheDocs config 2019-10-02 18:15:17 +03:00
Ivan Kravets
bbd694c5ea ManifestParse: automatically generate examples from package dir 2019-10-02 17:54:59 +03:00
Ivan Kravets
7ba2a7cd3d Bump version to 4.1.0b2 2019-10-02 13:33:12 +03:00
Ivan Kravets
a1ed99962c Better handling of non-dict values passed to DataModel 2019-10-02 12:34:50 +03:00
Ivan Kravets
c2970631a5 Add "--force" for git update // Issue #3060 2019-10-02 12:34:20 +03:00
Ivan Kravets
d38c843574 Fixed an issue when installing a package using custom Git tag and submodules were not updated correctly // Resolve #3060 2019-10-02 11:52:14 +03:00
Ivan Kravets
a2213a1aa4 Change "examples" field in package manifest to ListOf(ExampleModel) 2019-10-02 11:04:29 +03:00
Ivan Kravets
dee2d2c538 Add manifest parsers for platform.json and package.json 2019-10-01 22:03:23 +03:00
Ivan Kravets
fec19849b5 Docs: Add info about ignoring individual parts of mbed framework 2019-10-01 22:02:55 +03:00
Ivan Kravets
5b77adccb1 DataModels: fix issue when traversing using model fields 2019-10-01 18:10:48 +03:00
Ivan Kravets
a82c4666d4 DataModel: add support for DictOfType, extend base manifest with ExampelsModel 2019-10-01 17:37:11 +03:00
Ivan Kravets
df6a8da290 DataModel: add support for silent validation and "get_exceptions" API 2019-10-01 16:13:25 +03:00
Ivan Kravets
39c8996093 Fix docs typos 2019-10-01 16:11:55 +03:00
Ivan Kravets
af1a0f3587 Allow to build a manifest parser from directory 2019-10-01 00:11:31 +03:00
Ivan Kravets
703912fdc9 Strict manifest validation when submitting to Registry, more tests for manifest model 2019-09-30 23:45:03 +03:00
Ivan Kravets
744881da59 Refactor DataModel with a strict type declaration 2019-09-30 19:44:03 +03:00
Ivan Kravets
5f55c18373 Introduce DataModel, package manifest parser and base manifest model 2019-09-30 17:59:06 +03:00
Ivan Kravets
2137eb1794 Do not append debug flags to linker stage 2019-09-30 13:27:34 +03:00
Ivan Kravets
3dcf1784fb Update PIO Remote to 2.5.5 2019-09-27 19:36:49 +03:00
Ivan Kravets
9a3dcd3daa PY2 fix with absolute import 2019-09-27 18:53:58 +03:00
Ivan Kravets
1b74f380a6 Refactor appending of debugging flags 2019-09-27 17:22:21 +03:00
Ivan Kravets
cd2a4ea535 Update copyrights 2019-09-27 17:21:35 +03:00
Ivan Kravets
536a9566da Feature/pio size data (#3056)
* Add initial support for detailed memory usage report

* Tidy up sizedata target

* Add toolchain to environment paths

* Make sizedata target a bit more readable
2019-09-27 14:18:35 +03:00
Ivan Kravets
d2abac9b18 Fixed an issue when configuration file options partly ignored when `--project-conf` // Resolve #3034 (#3055)
* Fixed an issue when configuration file options partly ignored when using custom ``--project-conf`` // Resolve #3034

* Py2 compatible makedirs

* Fix circle dependency

* Fix broken import in test examples

* Fix history

* Remove YAPF markers

* PyLint fix

* Fix invalid project conf path

* Move PIO Core to the root on Windows, issue with long CPPPATHs

* Respect global PLATFORMIO_BUILD_CACHE_DIR env var

* Fix Appveyor paths

* Minor changes
2019-09-27 14:13:53 +03:00
Florian Knodt
94f8afec38 udev: Add GD32V DFU Bootloader (#3032) 2019-09-24 11:02:26 +03:00
Ivan Kravets
3d5c1411c0 Fix PyLint for PY2 2019-09-24 00:28:23 +03:00
Ivan Kravets
9a7e5d86fc Install Black only for Python 3.6+ 2019-09-24 00:21:16 +03:00
Ivan Kravets
ca29b4e370 Fixed "DeprecationWarning: the imp module is deprecated in favour of importlib" PY2/PY3 2019-09-24 00:17:08 +03:00
Ivan Kravets
392fe1cbd0 Move Run to the root 2019-09-24 00:12:21 +03:00
Ivan Kravets
aa955819b0 Move PIO Check to the root 2019-09-23 23:44:42 +03:00
Ivan Kravets
b1f190a7f8 Move PIO Unit Testing to the root 2019-09-23 23:44:28 +03:00
Ivan Kravets
5453df94e4 Move PIO Unified Debugger to the root 2019-09-23 23:27:55 +03:00
Ivan Kravets
7b314b58a4 Move PIO Home to the root of source code 2019-09-23 23:23:11 +03:00
Ivan Kravets
7c41c7c2f3 Introduce Black to automate code formatting 2019-09-23 23:13:48 +03:00
Ivan Kravets
5e144a2c98 Add PIO Check to changelog 2019-09-23 21:57:31 +03:00
Ivan Kravets
61b6eea52c New "--no-ansi" flag for PIO Core 2019-09-23 20:51:02 +03:00
Ivan Kravets
cd8dc24454 Docs: Sync Espressif32 dev/platform 2019-09-18 18:47:55 +03:00
Ivan Kravets
6531dcbc78 Allow to skip checking of unpacked data 2019-09-16 21:38:47 +03:00
Thomas Bleijendaal
123963f760 UTF8 decoding should ignore invalid characters (#3026)
Some boards, like ESP32 based boards, give some unintelligible data when connecting to them via Serial. This is sometimes data that is send with the wrong baud rate (hard baked into the boot loader), or something else. It's hard to prevent this from happening. When a build is uploaded to the ESP board for unit testing, the decoding of the incoming stream should not fail the test due to some garbled content. Since the read data is validated on line 95, any garbage is automatically ignored and only outputted to the console.
2019-09-16 21:02:07 +03:00
Ivan Kravets
08a94b6f7c New article "Arduino In-circuit Debugging with PlatformIO" 2019-09-16 18:58:29 +03:00
Ivan Kravets
43ae62afd8 Sync Aceinna and GD32V dev/platforms. 2019-09-13 16:01:42 +03:00
Ivan Kravets
e08dc5f0d7 Docs: Sync Microchip PIC32 dev/platform 2019-09-10 17:48:47 +03:00
Ivan Kravets
1e26feb566 Bump version to 4.1.0b1 2019-09-09 23:34:44 +03:00
Ivan Kravets
96567dea4d PyLint fix 2019-09-08 23:44:18 +03:00
Ivan Kravets
c720933d34 Refactor PIO Check 2019-09-08 23:33:25 +03:00
Ivan Kravets
f61d03ec8f PIO Check (#2982) 2019-09-08 18:04:41 +03:00
Ivan Kravets
b7bc4401eb Use isolated SCons DB per build environment 2019-09-08 14:01:41 +03:00
Ivan Kravets
7a07a2e63e Generate `.ccls` LSP file for Emacs 2019-09-03 15:31:33 +03:00
Ivan Kravets
2c242944c7 Fixed default PIO Unified Debugger configuration for J-Link probe 2019-09-02 16:48:33 +03:00
Ivan Kravets
6265233903 Optimize udev rules 2019-09-02 16:01:15 +03:00
Ivan Kravets
be3e26c202 Cleanup UDEV rules 2019-09-02 14:24:35 +03:00
Ivan Kravets
9f76293684 Cleanup Segger UDEV rules 2019-09-02 14:13:58 +03:00
Ivan Kravets
1be2e510da Sync nRF52 dev/platform 2019-09-02 12:50:55 +03:00
Ivan Kravets
af049eecc9 Bump version to 4.1.0a1 2019-08-31 23:40:28 +03:00
Ivan Kravets
fe237f15aa Implement "extends" for project configuration // Resolve #2953 2019-08-31 23:39:41 +03:00
Peter
bdce78ba6f Stop ModemManager corrupting Arduino uploads (#2966)
On boards like the Arduino Micro, when in bootloader mode it appears ModemManager interferes with the programming process and result in a catastrophic failure with no end of different errors including, but not limited to:
```
error: programmer did not respond to command: write block
error: butterfly programmer uses avr_write_page() but does not provide a cmd() method.
error: programmer did not respond to command: set addr
```
After this, the device could appear to be completely non-functional, refusing to enumerate or appear for programming, but thankfully a double-reset will usually recover it, but the underlying ModemManager issue will still prevent successful programming. Hence the additional rules. 

This affects not only PlatformIO, but also the Arduino IDE (on linux).
2019-08-31 11:47:32 +03:00
Ivan Kravets
f26e3c42dd Sync docs 2019-08-31 11:40:16 +03:00
Ivan Kravets
92cd03cf2a Sync docs 2019-08-30 18:12:26 +03:00
Ivan Kravets
e7da3d7f5f Bump version to 4.0.4a1 2019-08-30 16:41:17 +03:00
Ivan Kravets
f966eeb604 Fixed an issue with project generator for CLion IDE when 2 environments were used // Resolve #2824 2019-08-30 16:40:44 +03:00
Ivan Kravets
34176f974b Fix generator for CLion when project is empty // Issue #2824 2019-08-30 15:45:21 +03:00
Ivan Kravets
5f044a7948 Merge tag 'v4.0.3' into develop
Bump version to 4.0.3
2019-08-30 15:41:59 +03:00
404 changed files with 36111 additions and 15231 deletions

View File

@@ -1,28 +0,0 @@
build: off
platform:
- x64
environment:
matrix:
- TOXENV: "py27"
PLATFORMIO_BUILD_CACHE_DIR: C:/Temp/PIO_Build_Cache_P2_{build}
- TOXENV: "py36"
PLATFORMIO_BUILD_CACHE_DIR: C:/Temp/PIO_Build_Cache_P3_{build}
install:
- cmd: git submodule update --init --recursive
- cmd: SET PATH=C:\MinGW\bin;%PATH%
- cmd: pip install --force-reinstall tox
test_script:
- cmd: tox
notifications:
- provider: Slack
incoming_webhook:
secure: E9H0SU0Ju7WLDvgxsV8cs3J62T3nTTX7QkEjsczN0Sto/c9hWkVfhc5gGWUkxhlD975cokHByKGJIdwYwCewqOI+7BrcT8U+nlga4Uau7J8=
on_build_success: false
on_build_failure: true
on_build_status_changed: true

52
.github/workflows/core.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Core
on: [push, pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
exclude:
- os: macos-latest
python-version: "3.6"
- os: windows-latest
python-version: "3.10"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Python Lint
if: ${{ matrix.python-version != '3.6' }}
run: |
tox -e lint
- name: Integration Tests
run: |
tox -e testcore
- name: Slack Notification
uses: homoluctus/slatify@master
if: failure()
with:
type: ${{ job.status }}
job_name: '*Core*'
commit: true
url: ${{ secrets.SLACK_BUILD_WEBHOOK }}
token: ${{ secrets.SLACK_GITHUB_TOKEN }}

45
.github/workflows/deployment.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: Deployment
on:
push:
branches:
- "master"
- "release/**"
jobs:
deployment:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Deployment Tests
env:
TEST_EMAIL_LOGIN: ${{ secrets.TEST_EMAIL_LOGIN }}
TEST_EMAIL_PASSWORD: ${{ secrets.TEST_EMAIL_PASSWORD }}
TEST_EMAIL_IMAP_SERVER: ${{ secrets.TEST_EMAIL_IMAP_SERVER }}
run: |
tox -e testcore
- name: Build Python source tarball
run: python setup.py sdist
- name: Publish package to PyPI
if: ${{ github.ref == 'refs/heads/master' }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}

109
.github/workflows/docs.yml vendored Normal file
View File

@@ -0,0 +1,109 @@
name: Docs
on: [push, pull_request]
jobs:
build:
name: Build Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Build docs
run: |
tox -e docs
- name: Slack Notification
uses: homoluctus/slatify@master
if: failure()
with:
type: ${{ job.status }}
job_name: '*Docs*'
commit: true
url: ${{ secrets.SLACK_BUILD_WEBHOOK }}
token: ${{ secrets.SLACK_GITHUB_TOKEN }}
- name: Preserve Docs
if: ${{ github.event_name == 'push' }}
run: |
tar -czvf docs.tar.gz -C docs/_build html rtdpage
- name: Save artifact
if: ${{ github.event_name == 'push' }}
uses: actions/upload-artifact@v2
with:
name: docs
path: ./docs.tar.gz
deploy:
name: Deploy Docs
needs: build
runs-on: ubuntu-latest
env:
DOCS_REPO: platformio/platformio-docs
DOCS_DIR: platformio-docs
LATEST_DOCS_DIR: latest-docs
RELEASE_BUILD: ${{ startsWith(github.ref, 'refs/tags/v') }}
if: ${{ github.event_name == 'push' }}
steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: docs
- name: Unpack artifact
run: |
mkdir ./${{ env.LATEST_DOCS_DIR }}
tar -xzf ./docs.tar.gz -C ./${{ env.LATEST_DOCS_DIR }}
- name: Delete Artifact
uses: geekyeggo/delete-artifact@v1
with:
name: docs
- name: Select Docs type
id: get-destination-dir
run: |
if [[ ${{ env.RELEASE_BUILD }} == true ]]; then
echo "::set-output name=dst_dir::stable"
else
echo "::set-output name=dst_dir::latest"
fi
- name: Checkout latest Docs
continue-on-error: true
uses: actions/checkout@v2
with:
repository: ${{ env.DOCS_REPO }}
path: ${{ env.DOCS_DIR }}
ref: gh-pages
- name: Synchronize Docs
run: |
rm -rf ${{ env.DOCS_DIR }}/.git
rm -rf ${{ env.DOCS_DIR }}/en/${{ steps.get-destination-dir.outputs.dst_dir }}
mkdir -p ${{ env.DOCS_DIR }}/en/${{ steps.get-destination-dir.outputs.dst_dir }}
cp -rf ${{ env.LATEST_DOCS_DIR }}/html/* ${{ env.DOCS_DIR }}/en/${{ steps.get-destination-dir.outputs.dst_dir }}
if [[ ${{ env.RELEASE_BUILD }} == false ]]; then
rm -rf ${{ env.DOCS_DIR }}/page
mkdir -p ${{ env.DOCS_DIR }}/page
cp -rf ${{ env.LATEST_DOCS_DIR }}/rtdpage/* ${{ env.DOCS_DIR }}/page
fi
- name: Validate Docs
run: |
if [ -z "$(ls -A ${{ env.DOCS_DIR }})" ]; then
echo "Docs folder is empty. Aborting!"
exit 1
fi
- name: Deploy to Github Pages
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.DEPLOY_GH_DOCS_TOKEN }}
external_repository: ${{ env.DOCS_REPO }}
publish_dir: ./${{ env.DOCS_DIR }}
commit_message: Sync Docs

63
.github/workflows/examples.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Examples
on: [push, pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
env:
PIO_INSTALL_DEVPLATFORM_OWNERNAMES: "platformio"
PIO_INSTALL_DEVPLATFORM_NAMES: "aceinna_imu,atmelavr,atmelmegaavr,atmelsam,espressif32,espressif8266,nordicnrf52,raspberrypi,ststm32,teensy"
steps:
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Run on Linux
if: startsWith(matrix.os, 'ubuntu')
run: |
# Free space
sudo apt clean
docker rmi $(docker image ls -aq)
df -h
tox -e testexamples
- name: Run on macOS
if: startsWith(matrix.os, 'macos')
run: |
df -h
tox -e testexamples
- name: Run on Windows
if: startsWith(matrix.os, 'windows')
env:
PLATFORMIO_CORE_DIR: C:/pio
PLATFORMIO_WORKSPACE_DIR: C:/pio-workspace/$PROJECT_HASH
run: |
tox -e testexamples
- name: Slack Notification
uses: homoluctus/slatify@master
if: failure()
with:
type: ${{ job.status }}
job_name: '*Examples*'
commit: true
url: ${{ secrets.SLACK_BUILD_WEBHOOK }}
token: ${{ secrets.SLACK_GITHUB_TOKEN }}

69
.github/workflows/projects.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
name: Projects
on: [push, pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
project:
- marlin:
repository: "MarlinFirmware/Marlin"
folder: "Marlin"
config_dir: "Marlin"
env_name: "mega2560"
# - esphome:
# repository: "esphome/esphome"
# folder: "esphome"
# config_dir: "esphome"
# env_name: "esp32-arduino"
- smartknob:
repository: "scottbez1/smartknob"
folder: "smartknob"
config_dir: "smartknob/firmware"
env_name: "view"
- espurna:
repository: "xoseperez/espurna"
folder: "espurna"
config_dir: "espurna/code"
env_name: "nodemcu-lolin"
- OpenMQTTGateway:
repository: "1technophile/OpenMQTTGateway"
folder: "OpenMQTTGateway"
config_dir: "OpenMQTTGateway"
env_name: "esp32-m5atom"
os: [ubuntu-latest, windows-latest, macos-latest]
exclude:
- os: windows-latest
project: {"esphome": "", "repository": "esphome/esphome", "folder": "esphome", "config_dir": "esphome", "env_name": "esp32-arduino"}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: 3.9
- name: Install PlatformIO
run: pip install -U .
- name: Check out ${{ matrix.project.repository }}
uses: actions/checkout@v2
with:
submodules: "recursive"
repository: ${{ matrix.project.repository }}
path: ${{ matrix.project.folder }}
- name: Install ESPHome dependencies
# Requires esptool package as it's used in a custom prescript
if: ${{ contains(matrix.project.repository, 'esphome') }}
run: pip install esptool==3.*
- name: Compile ${{ matrix.project.repository }}
run: pio run -d ${{ matrix.project.config_dir }} -e ${{ matrix.project.env_name }}

2
.gitignore vendored
View File

@@ -1,6 +1,6 @@
*.egg-info
*.pyc
.pioenvs
__pycache__
.tox
docs/_build
dist

View File

@@ -1,3 +0,0 @@
[settings]
line_length=79
known_third_party=bottle,click,pytest,requests,SCons,semantic_version,serial,twisted,autobahn,jsonrpc,tabulate

View File

@@ -1,12 +1,11 @@
[REPORTS]
output-format=colorized
[MESSAGES CONTROL]
disable=
missing-docstring,
ungrouped-imports,
invalid-name,
cyclic-import,
duplicate-code,
superfluous-parens,
invalid-name,
too-few-public-methods,
useless-object-inheritance,
useless-import-alias,
fixme
consider-using-f-string,
cyclic-import

View File

@@ -1,3 +0,0 @@
[style]
blank_line_before_nested_class_or_def = true
allow_multiline_lambdas = true

View File

@@ -1,39 +0,0 @@
language: python
matrix:
include:
- os: linux
sudo: false
python: 2.7
env: TOX_ENV=docs
- os: linux
sudo: required
python: 2.7
env: TOX_ENV=py27 PLATFORMIO_BUILD_CACHE_DIR=$(mktemp -d)
- os: linux
sudo: required
python: 3.6
env: TOX_ENV=py36 PLATFORMIO_BUILD_CACHE_DIR=$(mktemp -d)
- os: osx
language: generic
env: TOX_ENV=skipexamples
install:
- git submodule update --init --recursive
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -fsSL https://bootstrap.pypa.io/get-pip.py | sudo python; fi
- pip install -U tox
# ChipKIT issue: install 32-bit support for GCC PIC32
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libc6-i386; fi
script:
- tox -e $TOX_ENV
notifications:
email: false
slack:
rooms:
secure: JD6VGfN4+SLU2CwDdiIOr1VgwD+zbYUCE/srwyGuHavnjIkPItkl6T6Bn8Y4VrU6ysbuKotfdV2TAJJ82ivFbY8BvZBc7FBcYp/AGQ4FaCCV5ySv8RDAcQgdE12oaGzMdODiLqsB85f65zOlAFa+htaXyEiRTcotn6Y2hupatrI=
on_failure: always
on_success: change

View File

@@ -1,21 +1,21 @@
Contributing
------------
To get started, <a href="https://www.clahub.com/agreements/platformio/platformio-core">sign the Contributor License Agreement</a>.
To get started, <a href="https://cla-assistant.io/platformio/platformio-core">sign the Contributor License Agreement</a>.
1. Fork the repository on GitHub.
1. Fork the repository on GitHub
2. Clone repository `git clone --recursive https://github.com/YourGithubUsername/platformio-core.git`
3. Run `pip install tox`
4. Go to the root of project where is located `tox.ini` and run `tox -e py27`
4. Go to the root of project where is located `tox.ini` and run `tox -e py37`
5. Activate current development environment:
* Windows: `.tox\py27\Scripts\activate`
* Bash/ZSH: `source .tox/py27/bin/activate`
* Fish: `source .tox/py27/bin/activate.fish`
* Windows: `.tox\py37\Scripts\activate`
* Bash/ZSH: `source .tox/py37/bin/activate`
* Fish: `source .tox/py37/bin/activate.fish`
6. Make changes to code, documentation, etc.
7. Lint source code `make lint`
7. Lint source code `make before-commit`
8. Run the tests `make test`
9. Build documentation `tox -e docs` (creates a directory _build under docs where you can find the html)
10. Commit changes to your forked repository
11. Submit a Pull Request on GitHub.
11. Submit a Pull Request on GitHub

File diff suppressed because it is too large Load Diff

1
MANIFEST.in Normal file
View File

@@ -0,0 +1 @@
include LICENSE

View File

@@ -1,17 +1,19 @@
lint:
pylint --rcfile=./.pylintrc ./tests
pylint --rcfile=./.pylintrc ./platformio
isort:
isort -rc ./platformio
isort -rc ./tests
isort ./platformio
isort ./tests
yapf:
yapf --recursive --in-place platformio/
format:
black ./platformio
black ./tests
test:
py.test --verbose --capture=no --exitfirst -n 3 --dist=loadscope tests --ignore tests/test_examples.py --ignore tests/test_pkgmanifest.py
py.test --verbose --exitfirst -n 6 --dist=loadscope tests --ignore tests/test_examples.py
before-commit: isort yapf lint test
before-commit: isort format lint
clean-docs:
rm -rf docs/_build
@@ -26,8 +28,11 @@ clean: clean-docs
profile:
# Usage $ > make PIOARGS="boards" profile
python -m cProfile -o .tox/.tmp/cprofile.prof $(shell which platformio) ${PIOARGS}
python -m cProfile -o .tox/.tmp/cprofile.prof -m platformio ${PIOARGS}
snakeviz .tox/.tmp/cprofile.prof
pack:
python setup.py sdist
publish:
python setup.py sdist upload

View File

@@ -1,127 +1,83 @@
PlatformIO
==========
.. image:: https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg
:target: https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md
:alt: SWUbanner
.. image:: https://travis-ci.org/platformio/platformio-core.svg?branch=develop
:target: https://travis-ci.org/platformio/platformio-core
:alt: Travis.CI Build Status
.. image:: https://ci.appveyor.com/api/projects/status/unnpw0n3c5k14btn/branch/develop?svg=true
:target: https://ci.appveyor.com/project/ivankravets/platformio-core
:alt: AppVeyor.CI Build Status
PlatformIO Core
===============
.. image:: https://github.com/platformio/platformio-core/workflows/Core/badge.svg
:target: https://docs.platformio.org/en/latest/core/index.html
:alt: CI Build for PlatformIO Core
.. image:: https://github.com/platformio/platformio-core/workflows/Docs/badge.svg
:target: https://docs.platformio.org?utm_source=github&utm_medium=core
:alt: CI Build for Docs
.. image:: https://github.com/platformio/platformio-core/workflows/Examples/badge.svg
:target: https://github.com/platformio/platformio-examples
:alt: CI Build for dev-platform examples
.. image:: https://github.com/platformio/platformio-core/workflows/Projects/badge.svg
:target: https://docs.platformio.org/en/latest/tutorials/index.html#projects
:alt: CI Build for the Community Projects
.. image:: https://img.shields.io/pypi/v/platformio.svg
:target: https://pypi.python.org/pypi/platformio/
:alt: Latest Version
.. image:: https://img.shields.io/badge/license-Apache%202.0-blue.svg
:target: https://pypi.python.org/pypi/platformio/
:alt: License
.. image:: https://img.shields.io/badge/PlatformIO-Community-orange.svg
:alt: Community Forums
:target: https://community.platformio.org?utm_source=github&utm_medium=core
.. image:: https://img.shields.io/badge/PlatformIO-Labs-orange.svg
:alt: PlatformIO Labs
:target: https://piolabs.com/?utm_source=github&utm_medium=core
**Quick Links:** `Web <https://platformio.org?utm_source=github&utm_medium=core>`_ |
**Quick Links:** `Homepage <https://platformio.org?utm_source=github&utm_medium=core>`_ |
`PlatformIO IDE <https://platformio.org/platformio-ide?utm_source=github&utm_medium=core>`_ |
`Registry <https://registry.platformio.org?utm_source=github&utm_medium=core>`_ |
`Project Examples <https://github.com/platformio/platformio-examples/>`__ |
`Docs <https://docs.platformio.org?utm_source=github&utm_medium=core>`_ |
`Donate <https://platformio.org/donate?utm_source=github&utm_medium=core>`_ |
`Contact Us <https://platformio.org/contact?utm_source=github&utm_medium=core>`_
`Contact Us <https://piolabs.com/?utm_source=github&utm_medium=core>`_
**Social:** `Twitter <https://twitter.com/PlatformIO_Org>`_ |
`LinkedIn <https://www.linkedin.com/company/platformio/>`_ |
**Social:** `LinkedIn <https://www.linkedin.com/company/platformio/>`_ |
`Twitter <https://twitter.com/PlatformIO_Org>`_ |
`Facebook <https://www.facebook.com/platformio>`_ |
`Hackaday <https://hackaday.io/project/7980-platformio>`_ |
`Bintray <https://bintray.com/platformio>`_ |
`Community <https://community.platformio.org?utm_source=github&utm_medium=core>`_
`Community Forums <https://community.platformio.org?utm_source=github&utm_medium=core>`_
.. image:: https://raw.githubusercontent.com/platformio/platformio-web/develop/app/images/platformio-ide-laptop.png
:target: https://platformio.org?utm_source=github&utm_medium=core
`PlatformIO <https://platformio.org?utm_source=github&utm_medium=core>`_ is an open source ecosystem for IoT
development. Cross-platform IDE and unified debugger. Remote unit testing and
firmware updates.
`PlatformIO <https://platformio.org>`_ is a professional collaborative platform for embedded development.
**A place where Developers and Teams have true Freedom! No more vendor lock-in!**
* Open source, maximum permissive Apache 2.0 license
* Cross-platform IDE and Unified Debugger
* Static Code Analyzer and Remote Unit Testing
* Multi-platform and Multi-architecture Build System
* Firmware File Explorer and Memory Inspection
Get Started
-----------
* `What is PlatformIO? <https://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=core>`_
Open Source
-----------
* `PlatformIO IDE <https://platformio.org/platformio-ide?utm_source=github&utm_medium=core>`_
* `PlatformIO Core (CLI) <https://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=core>`_
* `Library Management <https://docs.platformio.org/page/librarymanager/index.html?utm_source=github&utm_medium=core>`_
* `Project Examples <https://github.com/platformio/platformio-examples?utm_source=github&utm_medium=core>`__
* `Desktop IDEs Integration <https://docs.platformio.org/page/ide.html?utm_source=github&utm_medium=core>`_
* `Continuous Integration <https://docs.platformio.org/page/ci/index.html?utm_source=github&utm_medium=core>`_
* `Advanced Scripting API <https://docs.platformio.org/page/projectconf/advanced_scripting.html?utm_source=github&utm_medium=core>`_
PIO Plus
--------
Solutions
---------
* `PIO Remote <https://docs.platformio.org/page/plus/pio-remote.html?utm_source=github&utm_medium=core>`_
* `PIO Unified Debugger <https://docs.platformio.org/page/plus/debugging.html?utm_source=github&utm_medium=core>`_
* `PIO Unit Testing <https://docs.platformio.org/en/latest/plus/unit-testing.html?utm_source=github&utm_medium=core>`_
* `Cloud IDEs Integration <https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=core#solution-pio-delivery>`_
* `Integration Services <https://platformio.org/pricing?utm_source=github&utm_medium=core#enterprise-features>`_
* `Library Management <https://docs.platformio.org/en/latest/librarymanager/index.html?utm_source=github&utm_medium=core>`_
* `Desktop IDEs Integration <https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=core>`_
* `Continuous Integration <https://docs.platformio.org/en/latest/ci/index.html?utm_source=github&utm_medium=core>`_
**Advanced**
* `Debugging <https://docs.platformio.org/en/latest/plus/debugging.html?utm_source=github&utm_medium=core>`_
* `Unit Testing <https://docs.platformio.org/en/latest/advanced/unit-testing/index.html?utm_source=github&utm_medium=core>`_
* `Static Code Analysis <https://docs.platformio.org/en/latest/plus/pio-check.html?utm_source=github&utm_medium=core>`_
* `Remote Development <https://docs.platformio.org/en/latest/plus/pio-remote.html?utm_source=github&utm_medium=core>`_
Registry
--------
* `Libraries <https://platformio.org/lib?utm_source=github&utm_medium=core>`_
* `Development Platforms <https://platformio.org/platforms?utm_source=github&utm_medium=core>`_
* `Frameworks <https://platformio.org/frameworks?utm_source=github&utm_medium=core>`_
* `Embedded Boards <https://platformio.org/boards?utm_source=github&utm_medium=core>`_
Development Platforms
---------------------
* `Aceinna IMU <https://platformio.org/platforms/aceinna_imu?utm_source=github&utm_medium=core>`_
* `Atmel AVR <https://platformio.org/platforms/atmelavr?utm_source=github&utm_medium=core>`_
* `Atmel SAM <https://platformio.org/platforms/atmelsam?utm_source=github&utm_medium=core>`_
* `Espressif 32 <https://platformio.org/platforms/espressif32?utm_source=github&utm_medium=core>`_
* `Espressif 8266 <https://platformio.org/platforms/espressif8266?utm_source=github&utm_medium=core>`_
* `Freescale Kinetis <https://platformio.org/platforms/freescalekinetis?utm_source=github&utm_medium=core>`_
* `Infineon XMC <https://platformio.org/platforms/infineonxmc?utm_source=github&utm_medium=core>`_
* `Intel ARC32 <https://platformio.org/platforms/intel_arc32?utm_source=github&utm_medium=core>`_
* `Intel MCS-51 (8051) <https://platformio.org/platforms/intel_mcs51?utm_source=github&utm_medium=core>`_
* `Kendryte K210 <https://platformio.org/platforms/kendryte210?utm_source=github&utm_medium=core>`_
* `Lattice iCE40 <https://platformio.org/platforms/lattice_ice40?utm_source=github&utm_medium=core>`_
* `Maxim 32 <https://platformio.org/platforms/maxim32?utm_source=github&utm_medium=core>`_
* `Microchip PIC32 <https://platformio.org/platforms/microchippic32?utm_source=github&utm_medium=core>`_
* `Nordic nRF51 <https://platformio.org/platforms/nordicnrf51?utm_source=github&utm_medium=core>`_
* `Nordic nRF52 <https://platformio.org/platforms/nordicnrf52?utm_source=github&utm_medium=core>`_
* `NXP LPC <https://platformio.org/platforms/nxplpc?utm_source=github&utm_medium=core>`_
* `RISC-V <https://platformio.org/platforms/riscv?utm_source=github&utm_medium=core>`_
* `RISC-V GAP <https://platformio.org/platforms/riscv_gap?utm_source=github&utm_medium=core>`_
* `Samsung ARTIK <https://platformio.org/platforms/samsung_artik?utm_source=github&utm_medium=core>`_
* `Silicon Labs EFM32 <https://platformio.org/platforms/siliconlabsefm32?utm_source=github&utm_medium=core>`_
* `ST STM32 <https://platformio.org/platforms/ststm32?utm_source=github&utm_medium=core>`_
* `ST STM8 <https://platformio.org/platforms/ststm8?utm_source=github&utm_medium=core>`_
* `Teensy <https://platformio.org/platforms/teensy?utm_source=github&utm_medium=core>`_
* `TI MSP430 <https://platformio.org/platforms/timsp430?utm_source=github&utm_medium=core>`_
* `TI Tiva <https://platformio.org/platforms/titiva?utm_source=github&utm_medium=core>`_
* `WIZNet W7500 <https://platformio.org/platforms/wiznet7500?utm_source=github&utm_medium=core>`_
Frameworks
----------
* `Arduino <https://platformio.org/frameworks/arduino?utm_source=github&utm_medium=core>`_
* `ARTIK SDK <https://platformio.org/frameworks/artik-sdk?utm_source=github&utm_medium=core>`_
* `CMSIS <https://platformio.org/frameworks/cmsis?utm_source=github&utm_medium=core>`_
* `Energia <https://platformio.org/frameworks/energia?utm_source=github&utm_medium=core>`_
* `ESP-IDF <https://platformio.org/frameworks/espidf?utm_source=github&utm_medium=core>`_
* `ESP8266 Non-OS SDK <https://platformio.org/frameworks/esp8266-nonos-sdk?utm_source=github&utm_medium=core>`_
* `ESP8266 RTOS SDK <https://platformio.org/frameworks/esp8266-rtos-sdk?utm_source=github&utm_medium=core>`_
* `Freedom E SDK <https://platformio.org/frameworks/freedom-e-sdk?utm_source=github&utm_medium=core>`_
* `Kendryte Standalone SDK <https://platformio.org/frameworks/kendryte-standalone-sdk?utm_source=github&utm_medium=core>`_
* `libOpenCM3 <https://platformio.org/frameworks/libopencm3?utm_source=github&utm_medium=core>`_
* `mbed <https://platformio.org/frameworks/mbed?utm_source=github&utm_medium=core>`_
* `PULP OS <https://platformio.org/frameworks/pulp-os?utm_source=github&utm_medium=core>`_
* `Pumbaa <https://platformio.org/frameworks/pumbaa?utm_source=github&utm_medium=core>`_
* `Simba <https://platformio.org/frameworks/simba?utm_source=github&utm_medium=core>`_
* `SPL <https://platformio.org/frameworks/spl?utm_source=github&utm_medium=core>`_
* `STM32Cube <https://platformio.org/frameworks/stm32cube?utm_source=github&utm_medium=core>`_
* `Tizen RT <https://platformio.org/frameworks/tizenrt?utm_source=github&utm_medium=core>`_
* `WiringPi <https://platformio.org/frameworks/wiringpi?utm_source=github&utm_medium=core>`_
* `Libraries <https://registry.platformio.org/search?t=library&utm_source=github&utm_medium=core>`_
* `Development Platforms <https://registry.platformio.org/search?t=platform&utm_source=github&utm_medium=core>`_
* `Development Tools <https://registry.platformio.org/search?t=tool&utm_source=github&utm_medium=core>`_
Contributing
------------
@@ -135,7 +91,6 @@ Share minimal diagnostics and usage information to help us make PlatformIO bette
It is enabled by default. For more information see:
* `Telemetry Setting <https://docs.platformio.org/en/latest/userguide/cmd_settings.html?utm_source=github&utm_medium=core#enable-telemetry>`_
* `SSL Setting <https://docs.platformio.org/en/latest/userguide/cmd_settings.html?utm_source=github&utm_medium=core#strict-ssl>`_
License
-------

2
docs

Submodule docs updated: 704ff85c7d...beb6d196ea

View File

@@ -12,22 +12,51 @@
# See the License for the specific language governing permissions and
# limitations under the License.
VERSION = (4, 0, 3)
import sys
VERSION = (6, 1, 3)
__version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio"
__description__ = (
"An open source ecosystem for IoT development. "
"Cross-platform IDE and unified debugger. "
"Remote unit testing and firmware updates. "
"Arduino, ARM mbed, Espressif (ESP8266/ESP32), STM32, PIC32, nRF51/nRF52, "
"FPGA, CMSIS, SPL, AVR, Samsung ARTIK, libOpenCM3")
"A professional collaborative platform for embedded development. "
"Cross-platform IDE and Unified Debugger. "
"Static Code Analyzer and Remote Unit Testing. "
"Multi-platform and Multi-architecture Build System. "
"Firmware File Explorer and Memory Inspection. "
"IoT, Arduino, CMSIS, ESP-IDF, FreeRTOS, libOpenCM3, mbedOS, Pulp OS, SPL, "
"STM32Cube, Zephyr RTOS, ARM, AVR, Espressif (ESP8266/ESP32), FPGA, "
"MCS-51 (8051), MSP430, Nordic (nRF51/nRF52), NXP i.MX RT, PIC32, RISC-V, "
"STMicroelectronics (STM8/STM32), Teensy"
)
__url__ = "https://platformio.org"
__author__ = "PlatformIO"
__email__ = "contact@platformio.org"
__author__ = "PlatformIO Labs"
__email__ = "contact@piolabs.com"
__license__ = "Apache Software License"
__copyright__ = "Copyright 2014-present PlatformIO"
__copyright__ = "Copyright 2014-present PlatformIO Labs"
__apiurl__ = "https://api.platformio.org"
__accounts_api__ = "https://api.accounts.platformio.org"
__registry_mirror_hosts__ = [
"registry.platformio.org",
"registry.nm1.platformio.org",
]
__pioremote_endpoint__ = "ssl:host=remote.platformio.org:port=4413"
__default_requests_timeout__ = (10, None) # (connect, read)
__core_packages__ = {
"contrib-piohome": "~3.4.2",
"contrib-pysite": "~2.%d%d.0" % (sys.version_info.major, sys.version_info.minor),
"tool-scons": "~4.40300.0",
"tool-cppcheck": "~1.270.0",
"tool-clangtidy": "~1.120001.0",
"tool-pvs-studio": "~7.18.0",
}
__check_internet_hosts__ = [
"185.199.110.153", # Github.com
"88.198.170.159", # platformio.org
"github.com",
] + __registry_mirror_hosts__

View File

@@ -18,53 +18,63 @@ from traceback import format_exc
import click
from platformio import __version__, exception, maintenance, util
from platformio.commands import PlatformioCLI
from platformio.compat import CYGWIN
from platformio import __version__, exception, maintenance
from platformio.cli import PlatformioCLI
from platformio.compat import IS_CYGWIN, ensure_python3
@click.command(cls=PlatformioCLI,
context_settings=dict(help_option_names=["-h", "--help"]))
@click.version_option(__version__, prog_name="PlatformIO")
@click.option("--force",
"-f",
is_flag=True,
help="Force to accept any confirmation prompts.")
@click.option("--caller", "-c", help="Caller ID (service).")
@click.command(
cls=PlatformioCLI, context_settings=dict(help_option_names=["-h", "--help"])
)
@click.version_option(__version__, prog_name="PlatformIO Core")
@click.option("--force", "-f", is_flag=True, help="DEPRECATED", hidden=True)
@click.option("--caller", "-c", help="Caller ID (service)")
@click.option("--no-ansi", is_flag=True, help="Do not print ANSI control characters")
@click.pass_context
def cli(ctx, force, caller):
def cli(ctx, force, caller, no_ansi):
try:
if (
no_ansi
or str(
os.getenv("PLATFORMIO_NO_ANSI", os.getenv("PLATFORMIO_DISABLE_COLOR"))
).lower()
== "true"
):
# pylint: disable=protected-access
click._compat.isatty = lambda stream: False
elif (
str(
os.getenv("PLATFORMIO_FORCE_ANSI", os.getenv("PLATFORMIO_FORCE_COLOR"))
).lower()
== "true"
):
# pylint: disable=protected-access
click._compat.isatty = lambda stream: True
except: # pylint: disable=bare-except
pass
maintenance.on_platformio_start(ctx, force, caller)
@cli.resultcallback()
@cli.result_callback()
@click.pass_context
def process_result(ctx, result, force, caller): # pylint: disable=W0613
def process_result(ctx, result, *_, **__):
maintenance.on_platformio_end(ctx, result)
@util.memoized()
def configure():
if CYGWIN:
if IS_CYGWIN:
raise exception.CygwinEnvDetected()
# https://urllib3.readthedocs.org
# /en/latest/security.html#insecureplatformwarning
try:
import urllib3
import urllib3 # pylint: disable=import-outside-toplevel
urllib3.disable_warnings()
except (AttributeError, ImportError):
pass
try:
if str(os.getenv("PLATFORMIO_DISABLE_COLOR", "")).lower() == "true":
# pylint: disable=protected-access
click._compat.isatty = lambda stream: False
elif str(os.getenv("PLATFORMIO_FORCE_COLOR", "")).lower() == "true":
# pylint: disable=protected-access
click._compat.isatty = lambda stream: True
except: # pylint: disable=bare-except
pass
# Handle IOError issue with VSCode's Terminal (Windows)
click_echo_origin = [click.echo, click.secho]
@@ -73,7 +83,8 @@ def configure():
click_echo_origin[origin](*args, **kwargs)
except IOError:
(sys.stderr.write if kwargs.get("err") else sys.stdout.write)(
"%s\n" % (args[0] if args else ""))
"%s\n" % (args[0] if args else "")
)
click.echo = lambda *args, **kwargs: _safe_echo(0, *args, **kwargs)
click.secho = lambda *args, **kwargs: _safe_echo(1, *args, **kwargs)
@@ -86,16 +97,18 @@ def main(argv=None):
assert isinstance(argv, list)
sys.argv = argv
try:
ensure_python3(raise_exception=True)
configure()
cli(None, None, None)
except SystemExit:
pass
except Exception as e: # pylint: disable=broad-except
if not isinstance(e, exception.ReturnErrorCode):
maintenance.on_platformio_exception(e)
cli() # pylint: disable=no-value-for-parameter
except SystemExit as exc:
if exc.code and str(exc.code).isdigit():
exit_code = int(exc.code)
except Exception as exc: # pylint: disable=broad-except
if not isinstance(exc, exception.ReturnErrorCode):
maintenance.on_platformio_exception(exc)
error_str = "Error: "
if isinstance(e, exception.PlatformioException):
error_str += str(e)
if isinstance(exc, exception.PlatformioException):
error_str += str(exc)
else:
error_str += format_exc()
error_str += """
@@ -107,7 +120,7 @@ An unexpected error occurred. Further steps:
`pip install -U platformio` command
* Try to find answer in FAQ Troubleshooting section
https://docs.platformio.org/page/faq.html
https://docs.platformio.org/page/faq/index.html
* Report this problem to the developers
https://github.com/platformio/platformio-core/issues
@@ -115,7 +128,7 @@ An unexpected error occurred. Further steps:
============================================================
"""
click.secho(error_str, fg="red", err=True)
exit_code = int(str(e)) if str(e).isdigit() else 1
exit_code = int(str(exc)) if str(exc).isdigit() else 1
sys.argv = prev_sys_argv
return exit_code

44
platformio/account/cli.py Normal file
View File

@@ -0,0 +1,44 @@
# 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.
import click
from platformio.account.commands.destroy import account_destroy_cmd
from platformio.account.commands.forgot import account_forgot_cmd
from platformio.account.commands.login import account_login_cmd
from platformio.account.commands.logout import account_logout_cmd
from platformio.account.commands.password import account_password_cmd
from platformio.account.commands.register import account_register_cmd
from platformio.account.commands.show import account_show_cmd
from platformio.account.commands.token import account_token_cmd
from platformio.account.commands.update import account_update_cmd
@click.group(
"account",
commands=[
account_destroy_cmd,
account_forgot_cmd,
account_login_cmd,
account_logout_cmd,
account_password_cmd,
account_register_cmd,
account_show_cmd,
account_token_cmd,
account_update_cmd,
],
short_help="Manage PlatformIO account",
)
def cli():
pass

View File

@@ -0,0 +1,356 @@
# 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.
import os
import time
from platformio import __accounts_api__, app
from platformio.exception import PlatformioException
from platformio.http import HTTPClient, HTTPClientError
class AccountError(PlatformioException):
MESSAGE = "{0}"
class AccountNotAuthorized(AccountError):
MESSAGE = "You are not authorized! Please log in to PlatformIO Account."
class AccountAlreadyAuthorized(AccountError):
MESSAGE = "You are already authorized with {0} account."
class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
SUMMARY_CACHE_TTL = 60 * 60 * 24 * 7
def __init__(self):
super().__init__(__accounts_api__)
@staticmethod
def get_refresh_token():
try:
return app.get_state_item("account").get("auth").get("refresh_token")
except Exception as exc:
raise AccountNotAuthorized() from exc
@staticmethod
def delete_local_session():
app.delete_state_item("account")
@staticmethod
def delete_local_state(key):
account = app.get_state_item("account")
if not account or key not in account:
return
del account[key]
app.set_state_item("account", account)
def fetch_json_data(self, *args, **kwargs):
try:
return super().fetch_json_data(*args, **kwargs)
except HTTPClientError as exc:
raise AccountError(exc) from exc
def fetch_authentication_token(self):
if os.environ.get("PLATFORMIO_AUTH_TOKEN"):
return os.environ.get("PLATFORMIO_AUTH_TOKEN")
auth = app.get_state_item("account", {}).get("auth", {})
if auth.get("access_token") and auth.get("access_token_expire"):
if auth.get("access_token_expire") > time.time():
return auth.get("access_token")
if auth.get("refresh_token"):
try:
data = self.fetch_json_data(
"post",
"/v1/login",
headers={
"Authorization": "Bearer %s" % auth.get("refresh_token")
},
)
app.set_state_item("account", data)
return data.get("auth").get("access_token")
except AccountError:
self.delete_local_session()
raise AccountNotAuthorized()
def login(self, username, password):
try:
self.fetch_authentication_token()
except: # pylint:disable=bare-except
pass
else:
raise AccountAlreadyAuthorized(
app.get_state_item("account", {}).get("email", "")
)
data = self.fetch_json_data(
"post",
"/v1/login",
data={"username": username, "password": password},
)
app.set_state_item("account", data)
return data
def login_with_code(self, client_id, code, redirect_uri):
try:
self.fetch_authentication_token()
except: # pylint:disable=bare-except
pass
else:
raise AccountAlreadyAuthorized(
app.get_state_item("account", {}).get("email", "")
)
result = self.fetch_json_data(
"post",
"/v1/login/code",
data={"client_id": client_id, "code": code, "redirect_uri": redirect_uri},
)
app.set_state_item("account", result)
return result
def logout(self):
refresh_token = self.get_refresh_token()
self.delete_local_session()
try:
self.fetch_json_data(
"post",
"/v1/logout",
data={"refresh_token": refresh_token},
)
except AccountError:
pass
return True
def change_password(self, old_password, new_password):
return self.fetch_json_data(
"post",
"/v1/password",
data={"old_password": old_password, "new_password": new_password},
x_with_authorization=True,
)
def registration(
self, username, email, password, firstname, lastname
): # pylint:disable=too-many-arguments
try:
self.fetch_authentication_token()
except: # pylint:disable=bare-except
pass
else:
raise AccountAlreadyAuthorized(
app.get_state_item("account", {}).get("email", "")
)
return self.fetch_json_data(
"post",
"/v1/registration",
data={
"username": username,
"email": email,
"password": password,
"firstname": firstname,
"lastname": lastname,
},
)
def auth_token(self, password, regenerate):
return self.fetch_json_data(
"post",
"/v1/token",
data={"password": password, "regenerate": 1 if regenerate else 0},
x_with_authorization=True,
).get("auth_token")
def forgot_password(self, username):
return self.fetch_json_data(
"post",
"/v1/forgot",
data={"username": username},
)
def get_profile(self):
return self.fetch_json_data(
"get",
"/v1/profile",
x_with_authorization=True,
)
def update_profile(self, profile, current_password):
profile["current_password"] = current_password
self.delete_local_state("summary")
response = self.fetch_json_data(
"put",
"/v1/profile",
data=profile,
x_with_authorization=True,
)
return response
def get_account_info(self, offline=False):
account = app.get_state_item("account") or {}
if (
account.get("summary")
and account["summary"].get("expire_at", 0) > time.time()
):
return account["summary"]
if offline and account.get("email"):
return {
"profile": {
"email": account.get("email"),
"username": account.get("username"),
}
}
result = self.fetch_json_data(
"get",
"/v1/summary",
x_with_authorization=True,
)
account["summary"] = dict(
profile=result.get("profile"),
packages=result.get("packages"),
subscriptions=result.get("subscriptions"),
user_id=result.get("user_id"),
expire_at=int(time.time()) + self.SUMMARY_CACHE_TTL,
)
app.set_state_item("account", account)
return result
def get_logged_username(self):
return self.get_account_info(offline=True).get("profile").get("username")
def destroy_account(self):
return self.fetch_json_data(
"delete",
"/v1/account",
x_with_authorization=True,
)
def create_org(self, orgname, email, displayname):
return self.fetch_json_data(
"post",
"/v1/orgs",
data={"orgname": orgname, "email": email, "displayname": displayname},
x_with_authorization=True,
)
def get_org(self, orgname):
return self.fetch_json_data(
"get",
"/v1/orgs/%s" % orgname,
x_with_authorization=True,
)
def list_orgs(self):
return self.fetch_json_data(
"get",
"/v1/orgs",
x_with_authorization=True,
)
def update_org(self, orgname, data):
return self.fetch_json_data(
"put",
"/v1/orgs/%s" % orgname,
data={k: v for k, v in data.items() if v},
x_with_authorization=True,
)
def destroy_org(self, orgname):
return self.fetch_json_data(
"delete",
"/v1/orgs/%s" % orgname,
x_with_authorization=True,
)
def add_org_owner(self, orgname, username):
return self.fetch_json_data(
"post",
"/v1/orgs/%s/owners" % orgname,
data={"username": username},
x_with_authorization=True,
)
def list_org_owners(self, orgname):
return self.fetch_json_data(
"get",
"/v1/orgs/%s/owners" % orgname,
x_with_authorization=True,
)
def remove_org_owner(self, orgname, username):
return self.fetch_json_data(
"delete",
"/v1/orgs/%s/owners" % orgname,
data={"username": username},
x_with_authorization=True,
)
def create_team(self, orgname, teamname, description):
return self.fetch_json_data(
"post",
"/v1/orgs/%s/teams" % orgname,
data={"name": teamname, "description": description},
x_with_authorization=True,
)
def destroy_team(self, orgname, teamname):
return self.fetch_json_data(
"delete",
"/v1/orgs/%s/teams/%s" % (orgname, teamname),
x_with_authorization=True,
)
def get_team(self, orgname, teamname):
return self.fetch_json_data(
"get",
"/v1/orgs/%s/teams/%s" % (orgname, teamname),
x_with_authorization=True,
)
def list_teams(self, orgname):
return self.fetch_json_data(
"get",
"/v1/orgs/%s/teams" % orgname,
x_with_authorization=True,
)
def update_team(self, orgname, teamname, data):
return self.fetch_json_data(
"put",
"/v1/orgs/%s/teams/%s" % (orgname, teamname),
data={k: v for k, v in data.items() if v},
x_with_authorization=True,
)
def add_team_member(self, orgname, teamname, username):
return self.fetch_json_data(
"post",
"/v1/orgs/%s/teams/%s/members" % (orgname, teamname),
data={"username": username},
x_with_authorization=True,
)
def remove_team_member(self, orgname, teamname, username):
return self.fetch_json_data(
"delete",
"/v1/orgs/%s/teams/%s/members" % (orgname, teamname),
data={"username": username},
x_with_authorization=True,
)

View File

@@ -0,0 +1,37 @@
# 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.
import click
from platformio.account.client import AccountClient, AccountNotAuthorized
@click.command("destroy", short_help="Destroy account")
def account_destroy_cmd():
client = AccountClient()
click.confirm(
"Are you sure you want to delete the %s user account?\n"
"Warning! All linked data will be permanently removed and can not be restored."
% client.get_logged_username(),
abort=True,
)
client.destroy_account()
try:
client.logout()
except AccountNotAuthorized:
pass
click.secho(
"User account has been destroyed.",
fg="green",
)

View File

@@ -0,0 +1,29 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("forgot", short_help="Forgot password")
@click.option("--username", prompt="Username or email")
def account_forgot_cmd(username):
client = AccountClient()
client.forgot_password(username)
click.secho(
"If this account is registered, we will send the "
"further instructions to your email.",
fg="green",
)

View File

@@ -0,0 +1,26 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("login", short_help="Log in to PlatformIO Account")
@click.option("-u", "--username", prompt="Username or email")
@click.option("-p", "--password", prompt=True, hide_input=True)
def account_login_cmd(username, password):
client = AccountClient()
client.login(username, password)
click.secho("Successfully logged in!", fg="green")

View File

@@ -12,10 +12,13 @@
# 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
import click
from platformio.account.client import AccountClient
@click.command("logout", short_help="Log out of PlatformIO Account")
def account_logout_cmd():
client = AccountClient()
client.logout()
click.secho("Successfully logged out!", fg="green")

View File

@@ -0,0 +1,26 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("password", short_help="Change password")
@click.option("--old-password", prompt=True, hide_input=True)
@click.option("--new-password", prompt=True, hide_input=True, confirmation_prompt=True)
def account_password_cmd(old_password, new_password):
client = AccountClient()
client.change_password(old_password, new_password)
click.secho("Password successfully changed!", fg="green")

View File

@@ -0,0 +1,52 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import (
validate_email,
validate_password,
validate_username,
)
@click.command("register", short_help="Create new PlatformIO Account")
@click.option(
"-u",
"--username",
prompt=True,
callback=lambda _, __, value: validate_username(value),
)
@click.option(
"-e", "--email", prompt=True, callback=lambda _, __, value: validate_email(value)
)
@click.option(
"-p",
"--password",
prompt=True,
hide_input=True,
confirmation_prompt=True,
callback=lambda _, __, value: validate_password(value),
)
@click.option("--firstname", prompt=True)
@click.option("--lastname", prompt=True)
def account_register_cmd(username, email, password, firstname, lastname):
client = AccountClient()
client.registration(username, email, password, firstname, lastname)
click.secho(
"An account has been successfully created. "
"Please check your mail to activate your account and verify your email address.",
fg="green",
)

View File

@@ -0,0 +1,116 @@
# 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.
import json
import click
from tabulate import tabulate
from platformio import util
from platformio.account.client import AccountClient
@click.command("show", short_help="PlatformIO Account information")
@click.option("--offline", is_flag=True)
@click.option("--json-output", is_flag=True)
def account_show_cmd(offline, json_output):
client = AccountClient()
info = client.get_account_info(offline)
if json_output:
click.echo(json.dumps(info))
return
click.echo()
if info.get("profile"):
print_profile(info["profile"])
if info.get("packages"):
print_packages(info["packages"])
if info.get("subscriptions"):
print_subscriptions(info["subscriptions"])
click.echo()
def print_profile(profile):
click.secho("Profile", fg="cyan", bold=True)
click.echo("=" * len("Profile"))
data = []
if profile.get("username"):
data.append(("Username:", profile["username"]))
if profile.get("email"):
data.append(("Email:", profile["email"]))
if profile.get("firstname"):
data.append(("First name:", profile["firstname"]))
if profile.get("lastname"):
data.append(("Last name:", profile["lastname"]))
click.echo(tabulate(data, tablefmt="plain"))
def print_packages(packages):
click.echo()
click.secho("Packages", fg="cyan")
click.echo("=" * len("Packages"))
for package in packages:
click.echo()
click.secho(package.get("name"), bold=True)
click.echo("-" * len(package.get("name")))
if package.get("description"):
click.echo(package.get("description"))
data = []
expire = "-"
if "subscription" in package:
expire = util.parse_datetime(
package["subscription"].get("end_at")
or package["subscription"].get("next_bill_at")
).strftime("%Y-%m-%d")
data.append(("Expire:", expire))
services = []
for key in package:
if not key.startswith("service."):
continue
if isinstance(package[key], dict):
services.append(package[key].get("title"))
else:
services.append(package[key])
if services:
data.append(("Services:", ", ".join(services)))
click.echo(tabulate(data, tablefmt="plain"))
def print_subscriptions(subscriptions):
click.echo()
click.secho("Subscriptions", fg="cyan")
click.echo("=" * len("Subscriptions"))
for subscription in subscriptions:
click.echo()
click.secho(subscription.get("product_name"), bold=True)
click.echo("-" * len(subscription.get("product_name")))
data = [("State:", subscription.get("status"))]
begin_at = util.parse_datetime(subscription.get("begin_at")).strftime("%c")
data.append(("Start date:", begin_at or "-"))
end_at = subscription.get("end_at")
if end_at:
end_at = util.parse_datetime(subscription.get("end_at")).strftime("%c")
data.append(("End date:", end_at or "-"))
next_bill_at = subscription.get("next_bill_at")
if next_bill_at:
next_bill_at = util.parse_datetime(
subscription.get("next_bill_at")
).strftime("%c")
data.append(("Next payment:", next_bill_at or "-"))
data.append(
("Edit:", click.style(subscription.get("update_url"), fg="blue") or "-")
)
data.append(
("Cancel:", click.style(subscription.get("cancel_url"), fg="blue") or "-")
)
click.echo(tabulate(data, tablefmt="plain"))

View File

@@ -0,0 +1,32 @@
# 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.
import json
import click
from platformio.account.client import AccountClient
@click.command("token", short_help="Get or regenerate Authentication Token")
@click.option("-p", "--password", prompt=True, hide_input=True)
@click.option("--regenerate", is_flag=True)
@click.option("--json-output", is_flag=True)
def account_token_cmd(password, regenerate, json_output):
client = AccountClient()
auth_token = client.auth_token(password, regenerate)
if json_output:
click.echo(json.dumps({"status": "success", "result": auth_token}))
return
click.secho("Personal Authentication Token: %s" % auth_token, fg="green")

View File

@@ -0,0 +1,59 @@
# 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.
import click
from platformio.account.client import AccountClient, AccountNotAuthorized
from platformio.account.validate import validate_email, validate_username
@click.command("update", short_help="Update profile information")
@click.option("--current-password", prompt=True, hide_input=True)
@click.option("--username")
@click.option("--email")
@click.option("--firstname")
@click.option("--lastname")
def account_update_cmd(current_password, **kwargs):
client = AccountClient()
profile = client.get_profile()
new_profile = profile.copy()
if not any(kwargs.values()):
for field in profile:
new_profile[field] = click.prompt(
field.replace("_", " ").capitalize(), default=profile[field]
)
if field == "email":
validate_email(new_profile[field])
if field == "username":
validate_username(new_profile[field])
else:
new_profile.update({key: value for key, value in kwargs.items() if value})
client.update_profile(new_profile, current_password)
click.secho("Profile successfully updated!", fg="green")
username_changed = new_profile["username"] != profile["username"]
email_changed = new_profile["email"] != profile["email"]
if not username_changed and not email_changed:
return None
try:
client.logout()
except AccountNotAuthorized:
pass
if email_changed:
click.secho(
"Please check your mail to verify your new email address and re-login. ",
fg="yellow",
)
return None
click.secho("Please re-login.", fg="yellow")
return None

View File

@@ -0,0 +1,38 @@
# 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.
import click
from platformio.account.org.commands.add import org_add_cmd
from platformio.account.org.commands.create import org_create_cmd
from platformio.account.org.commands.destroy import org_destroy_cmd
from platformio.account.org.commands.list import org_list_cmd
from platformio.account.org.commands.remove import org_remove_cmd
from platformio.account.org.commands.update import org_update_cmd
@click.group(
"account",
commands=[
org_add_cmd,
org_create_cmd,
org_destroy_cmd,
org_list_cmd,
org_remove_cmd,
org_update_cmd,
],
short_help="Manage organizations",
)
def cli():
pass

View File

@@ -0,0 +1,34 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("add", short_help="Add a new owner to organization")
@click.argument(
"orgname",
)
@click.argument(
"username",
)
def org_add_cmd(orgname, username):
client = AccountClient()
client.add_org_owner(orgname, username)
return click.secho(
"The new owner `%s` has been successfully added to the `%s` organization."
% (username, orgname),
fg="green",
)

View File

@@ -0,0 +1,38 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_email, validate_orgname
@click.command("create", short_help="Create a new organization")
@click.argument(
"orgname",
callback=lambda _, __, value: validate_orgname(value),
)
@click.option(
"--email", callback=lambda _, __, value: validate_email(value) if value else value
)
@click.option(
"--displayname",
)
def org_create_cmd(orgname, email, displayname):
client = AccountClient()
client.create_org(orgname, email, displayname)
return click.secho(
"The organization `%s` has been successfully created." % orgname,
fg="green",
)

View File

@@ -0,0 +1,34 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("destroy", short_help="Destroy organization")
@click.argument("orgname")
def org_destroy_cmd(orgname):
client = AccountClient()
click.confirm(
"Are you sure you want to delete the `%s` organization account?\n"
"Warning! All linked data will be permanently removed and can not be restored."
% orgname,
abort=True,
)
client.destroy_org(orgname)
return click.secho(
"Organization `%s` has been destroyed." % orgname,
fg="green",
)

View File

@@ -0,0 +1,48 @@
# 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.
import json
import click
from tabulate import tabulate
from platformio.account.client import AccountClient
@click.command("list", short_help="List organizations and their members")
@click.option("--json-output", is_flag=True)
def org_list_cmd(json_output):
client = AccountClient()
orgs = client.list_orgs()
if json_output:
return click.echo(json.dumps(orgs))
if not orgs:
return click.echo("You do not have any organization")
for org in orgs:
click.echo()
click.secho(org.get("orgname"), fg="cyan")
click.echo("-" * len(org.get("orgname")))
data = []
if org.get("displayname"):
data.append(("Display Name:", org.get("displayname")))
if org.get("email"):
data.append(("Email:", org.get("email")))
data.append(
(
"Owners:",
", ".join((owner.get("username") for owner in org.get("owners"))),
)
)
click.echo(tabulate(data, tablefmt="plain"))
return click.echo()

View File

@@ -0,0 +1,34 @@
# 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.
import click
from platformio.account.client import AccountClient
@click.command("remove", short_help="Remove an owner from organization")
@click.argument(
"orgname",
)
@click.argument(
"username",
)
def org_remove_cmd(orgname, username):
client = AccountClient()
client.remove_org_owner(orgname, username)
return click.secho(
"The `%s` owner has been successfully removed from the `%s` organization."
% (username, orgname),
fg="green",
)

View File

@@ -0,0 +1,52 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_email, validate_orgname
@click.command("update", short_help="Update organization")
@click.argument("cur_orgname")
@click.option(
"--orgname",
callback=lambda _, __, value: validate_orgname(value),
help="A new orgname",
)
@click.option("--email")
@click.option("--displayname")
def org_update_cmd(cur_orgname, **kwargs):
client = AccountClient()
org = client.get_org(cur_orgname)
del org["owners"]
new_org = org.copy()
if not any(kwargs.values()):
for field in org:
new_org[field] = click.prompt(
field.replace("_", " ").capitalize(), default=org[field]
)
if field == "email":
validate_email(new_org[field])
if field == "orgname":
validate_orgname(new_org[field])
else:
new_org.update(
{key.replace("new_", ""): value for key, value in kwargs.items() if value}
)
client.update_org(cur_orgname, new_org)
return click.secho(
"The organization `%s` has been successfully updated." % cur_orgname,
fg="green",
)

View File

@@ -11,5 +11,3 @@
# 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.
from platformio.commands.run.command import cli

View File

@@ -0,0 +1,38 @@
# 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.
import click
from platformio.account.team.commands.add import team_add_cmd
from platformio.account.team.commands.create import team_create_cmd
from platformio.account.team.commands.destroy import team_destroy_cmd
from platformio.account.team.commands.list import team_list_cmd
from platformio.account.team.commands.remove import team_remove_cmd
from platformio.account.team.commands.update import team_update_cmd
@click.group(
"team",
commands=[
team_add_cmd,
team_create_cmd,
team_destroy_cmd,
team_list_cmd,
team_remove_cmd,
team_update_cmd,
],
short_help="Manage organization teams",
)
def cli():
pass

View File

@@ -11,5 +11,3 @@
# 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.
from platformio.commands.test.command import cli

View File

@@ -0,0 +1,38 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_orgname_teamname
@click.command("add", short_help="Add a new member to team")
@click.argument(
"orgname_teamname",
metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(value),
)
@click.argument(
"username",
)
def team_add_cmd(orgname_teamname, username):
orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient()
client.add_team_member(orgname, teamname, username)
return click.secho(
"The new member %s has been successfully added to the %s team."
% (username, teamname),
fg="green",
)

View File

@@ -0,0 +1,39 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_orgname_teamname
@click.command("create", short_help="Create a new team")
@click.argument(
"orgname_teamname",
metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(
value, teamname_validate=True
),
)
@click.option(
"--description",
)
def team_create_cmd(orgname_teamname, description):
orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient()
client.create_team(orgname, teamname, description)
return click.secho(
"The team %s has been successfully created." % teamname,
fg="green",
)

View File

@@ -0,0 +1,40 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_orgname_teamname
@click.command("destroy", short_help="Destroy a team")
@click.argument(
"orgname_teamname",
metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(value),
)
def team_destroy_cmd(orgname_teamname):
orgname, teamname = orgname_teamname.split(":", 1)
click.confirm(
click.style(
"Are you sure you want to destroy the %s team?" % teamname, fg="yellow"
),
abort=True,
)
client = AccountClient()
client.destroy_team(orgname, teamname)
return click.secho(
"The team %s has been successfully destroyed." % teamname,
fg="green",
)

View File

@@ -0,0 +1,59 @@
# 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.
import json
import click
from tabulate import tabulate
from platformio.account.client import AccountClient
@click.command("list", short_help="List teams")
@click.argument("orgname", required=False)
@click.option("--json-output", is_flag=True)
def team_list_cmd(orgname, json_output):
client = AccountClient()
data = {}
if not orgname:
for item in client.list_orgs():
teams = client.list_teams(item.get("orgname"))
data[item.get("orgname")] = teams
else:
teams = client.list_teams(orgname)
data[orgname] = teams
if json_output:
return click.echo(json.dumps(data[orgname] if orgname else data))
if not any(data.values()):
return click.secho("You do not have any teams.", fg="yellow")
for org_name, teams in data.items():
for team in teams:
click.echo()
click.secho("%s:%s" % (org_name, team.get("name")), fg="cyan")
click.echo("-" * len("%s:%s" % (org_name, team.get("name"))))
table_data = []
if team.get("description"):
table_data.append(("Description:", team.get("description")))
table_data.append(
(
"Members:",
", ".join(
(member.get("username") for member in team.get("members"))
)
if team.get("members")
else "-",
)
)
click.echo(tabulate(table_data, tablefmt="plain"))
return click.echo()

View File

@@ -0,0 +1,36 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_orgname_teamname
@click.command("remove", short_help="Remove a member from team")
@click.argument(
"orgname_teamname",
metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(value),
)
@click.argument("username")
def team_remove_cmd(orgname_teamname, username):
orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient()
client.remove_team_member(orgname, teamname, username)
return click.secho(
"The %s member has been successfully removed from the %s team."
% (username, teamname),
fg="green",
)

View File

@@ -0,0 +1,55 @@
# 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.
import click
from platformio.account.client import AccountClient
from platformio.account.validate import validate_orgname_teamname, validate_teamname
@click.command("update", short_help="Update team")
@click.argument(
"orgname_teamname",
metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(value),
)
@click.option(
"--name",
callback=lambda _, __, value: validate_teamname(value),
help="A new team name",
)
@click.option(
"--description",
)
def team_update_cmd(orgname_teamname, **kwargs):
orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient()
team = client.get_team(orgname, teamname)
del team["id"]
del team["members"]
new_team = team.copy()
if not any(kwargs.values()):
for field in team:
new_team[field] = click.prompt(
field.replace("_", " ").capitalize(), default=team[field]
)
if field == "name":
validate_teamname(new_team[field])
else:
new_team.update({key: value for key, value in kwargs.items() if value})
client.update_team(orgname, teamname, new_team)
return click.secho(
"The team %s has been successfully updated." % teamname,
fg="green",
)

View File

@@ -0,0 +1,79 @@
# 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.
import re
import click
def validate_username(value, field="username"):
value = str(value).strip()
if not re.match(r"^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,37}$", value, flags=re.I):
raise click.BadParameter(
"Invalid %s format. "
"%s must contain only alphanumeric characters "
"or single hyphens, cannot begin or end with a hyphen, "
"and must not be longer than 38 characters."
% (field.lower(), field.capitalize())
)
return value
def validate_email(value):
value = str(value).strip()
if not re.match(r"^[a-z\d_\.\+\-]+@[a-z\d\-]+\.[a-z\d\-\.]+$", value, flags=re.I):
raise click.BadParameter("Invalid email address")
return value
def validate_password(value):
value = str(value).strip()
if not re.match(r"^(?=.*[a-z])(?=.*\d).{8,}$", value):
raise click.BadParameter(
"Invalid password format. "
"Password must contain at least 8 characters"
" including a number and a lowercase letter"
)
return value
def validate_orgname(value):
return validate_username(value, "Organization name")
def validate_orgname_teamname(value, teamname_validate=False):
if ":" not in value:
raise click.BadParameter(
"Please specify organization and team name in the next"
" format - orgname:teamname. For example, mycompany:DreamTeam"
)
teamname = str(value.strip().split(":", 1)[1])
if teamname_validate:
validate_teamname(teamname)
return value
def validate_teamname(value):
if not value:
return value
value = str(value).strip()
if not re.match(r"^[a-z\d](?:[a-z\d]|[\-_ ](?=[a-z\d])){0,19}$", value, flags=re.I):
raise click.BadParameter(
"Invalid team name format. "
"Team name must only contain alphanumeric characters, "
"single hyphens, underscores, spaces. It can not "
"begin or end with a hyphen or a underscore and must"
" not be longer than 20 characters."
)
return value

View File

@@ -12,97 +12,73 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import codecs
from __future__ import absolute_import
import getpass
import hashlib
import json
import os
import platform
import socket
import uuid
from os import environ, getenv, listdir, remove
from os.path import abspath, dirname, expanduser, isdir, isfile, join
from time import time
import requests
from platformio import exception, fs, lockfile
from platformio.compat import (WINDOWS, dump_json_to_unicode,
hashlib_encode_data)
from platformio.proc import is_ci
from platformio.project.helpers import (get_project_cache_dir,
get_project_core_dir)
def get_default_projects_dir():
docs_dir = join(expanduser("~"), "Documents")
try:
assert WINDOWS
import ctypes.wintypes
buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
ctypes.windll.shell32.SHGetFolderPathW(None, 5, None, 0, buf)
docs_dir = buf.value
except: # pylint: disable=bare-except
pass
return join(docs_dir, "PlatformIO", "Projects")
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.config import ProjectConfig
from platformio.project.helpers import get_default_projects_dir
def projects_dir_validate(projects_dir):
assert isdir(projects_dir)
return abspath(projects_dir)
assert os.path.isdir(projects_dir)
return os.path.abspath(projects_dir)
DEFAULT_SETTINGS = {
"auto_update_libraries": {
"description": "Automatically update libraries (Yes/No)",
"value": False
},
"auto_update_platforms": {
"description": "Automatically update platforms (Yes/No)",
"value": False
},
"check_libraries_interval": {
"description": "Check for the library updates interval (days)",
"value": 7
},
"check_platformio_interval": {
"description": "Check for the new PlatformIO interval (days)",
"value": 3
"description": "Check for the new PlatformIO Core interval (days)",
"value": 7,
},
"check_platforms_interval": {
"description": "Check for the platform updates interval (days)",
"value": 7
"check_prune_system_threshold": {
"description": "Check for pruning unnecessary data threshold (megabytes)",
"value": 1024,
},
"enable_cache": {
"description": "Enable caching for API requests and Library Manager",
"value": True
},
"strict_ssl": {
"description": "Strict SSL for PlatformIO Services",
"value": False
"description": "Enable caching for HTTP API requests",
"value": True,
},
"enable_telemetry": {
"description":
("Telemetry service <http://bit.ly/pio-telemetry> (Yes/No)"),
"value": True
"description": ("Telemetry service <https://bit.ly/pio-telemetry> (Yes/No)"),
"value": True,
},
"force_verbose": {
"description": "Force verbose output when processing environments",
"value": False
"value": False,
},
"projects_dir": {
"description": "Default location for PlatformIO projects (PIO Home)",
"description": "Default location for PlatformIO projects (PlatformIO Home)",
"value": get_default_projects_dir(),
"validator": projects_dir_validate
"validator": projects_dir_validate,
},
}
SESSION_VARS = {"command_ctx": None, "force_option": False, "caller_id": None}
SESSION_VARS = {
"command_ctx": None,
"force_option": False,
"caller_id": None,
"custom_project_conf": None,
}
class State(object):
class State:
def __init__(self, path=None, lock=False):
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
@@ -110,31 +86,37 @@ 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 (AssertionError, ValueError, UnicodeDecodeError,
exception.InvalidJSONFile):
except (
AssertionError,
ValueError,
UnicodeDecodeError,
exception.InvalidJSONFile,
):
self._storage = {}
return self
def __exit__(self, type_, value, traceback):
if self.modified:
try:
with open(self.path, "w") as fp:
fp.write(dump_json_to_unicode(self._storage))
except IOError:
raise exception.HomeDirPermissionsError(get_project_core_dir())
with open(self.path, mode="w", encoding="utf8") as fp:
fp.write(json.dumps(self._storage))
except IOError as exc:
raise exception.HomeDirPermissionsError(
os.path.dirname(self.path)
) from exc
self._unlock_state_file()
def _lock_state_file(self):
if not self.lock:
return
self._lockfile = lockfile.LockFile(self.path)
self._lockfile = LockFile(self.path)
try:
self._lockfile.acquire()
except IOError:
raise exception.HomeDirPermissionsError(dirname(self.path))
except IOError as exc:
raise exception.HomeDirPermissionsError(os.path.dirname(self.path)) from exc
def _unlock_state_file(self):
if hasattr(self, "_lockfile") and self._lockfile:
@@ -148,6 +130,9 @@ class State(object):
def as_dict(self):
return self._storage
def keys(self):
return self._storage.keys()
def get(self, key, default=True):
return self._storage.get(key, default)
@@ -173,143 +158,6 @@ class State(object):
return item in self._storage
class ContentCache(object):
def __init__(self, cache_dir=None):
self.cache_dir = None
self._db_path = None
self._lockfile = None
self.cache_dir = cache_dir or get_project_cache_dir()
self._db_path = join(self.cache_dir, "db.data")
def __enter__(self):
self.delete()
return self
def __exit__(self, type_, value, traceback):
pass
def _lock_dbindex(self):
if not self.cache_dir:
os.makedirs(self.cache_dir)
self._lockfile = lockfile.LockFile(self.cache_dir)
try:
self._lockfile.acquire()
except: # pylint: disable=bare-except
return False
return True
def _unlock_dbindex(self):
if self._lockfile:
self._lockfile.release()
return True
def get_cache_path(self, key):
key = str(key)
assert len(key) > 3
return join(self.cache_dir, key[-2:], key)
@staticmethod
def key_from_args(*args):
h = hashlib.md5()
for arg in args:
if arg:
h.update(hashlib_encode_data(arg))
return h.hexdigest()
def get(self, key):
cache_path = self.get_cache_path(key)
if not isfile(cache_path):
return None
with codecs.open(cache_path, "rb", encoding="utf8") as fp:
return fp.read()
def set(self, key, data, valid):
if not get_setting("enable_cache"):
return False
cache_path = self.get_cache_path(key)
if isfile(cache_path):
self.delete(key)
if not data:
return False
if not isdir(self.cache_dir):
os.makedirs(self.cache_dir)
tdmap = {"s": 1, "m": 60, "h": 3600, "d": 86400}
assert valid.endswith(tuple(tdmap))
expire_time = int(time() + tdmap[valid[-1]] * int(valid[:-1]))
if not self._lock_dbindex():
return False
if not isdir(dirname(cache_path)):
os.makedirs(dirname(cache_path))
try:
with codecs.open(cache_path, "wb", encoding="utf8") as fp:
fp.write(data)
with open(self._db_path, "a") as fp:
fp.write("%s=%s\n" % (str(expire_time), cache_path))
except UnicodeError:
if isfile(cache_path):
try:
remove(cache_path)
except OSError:
pass
return self._unlock_dbindex()
def delete(self, keys=None):
""" Keys=None, delete expired items """
if not isfile(self._db_path):
return None
if not keys:
keys = []
if not isinstance(keys, list):
keys = [keys]
paths_for_delete = [self.get_cache_path(k) for k in keys]
found = False
newlines = []
with open(self._db_path) as fp:
for line in fp.readlines():
line = line.strip()
if "=" not in line:
continue
expire, path = line.split("=")
try:
if time() < int(expire) and isfile(path) and \
path not in paths_for_delete:
newlines.append(line)
continue
except ValueError:
pass
found = True
if isfile(path):
try:
remove(path)
if not listdir(dirname(path)):
fs.rmtree(dirname(path))
except OSError:
pass
if found and self._lock_dbindex():
with open(self._db_path, "w") as fp:
fp.write("\n".join(newlines) + "\n")
self._unlock_dbindex()
return True
def clean(self):
if not self.cache_dir or not isdir(self.cache_dir):
return
fs.rmtree(self.cache_dir)
def clean_cache():
with ContentCache() as cc:
cc.clean()
def sanitize_setting(name, value):
if name not in DEFAULT_SETTINGS:
raise exception.InvalidSettingName(name)
@@ -317,14 +165,14 @@ def sanitize_setting(name, value):
defdata = DEFAULT_SETTINGS[name]
try:
if "validator" in defdata:
value = defdata['validator'](value)
elif isinstance(defdata['value'], bool):
value = defdata["validator"](value)
elif isinstance(defdata["value"], bool):
if not isinstance(value, bool):
value = str(value).lower() in ("true", "yes", "y", "1")
elif isinstance(defdata['value'], int):
elif isinstance(defdata["value"], int):
value = int(value)
except Exception:
raise exception.InvalidSettingValue(value, name)
except Exception as exc:
raise exception.InvalidSettingValue(value, name) from exc
return value
@@ -347,28 +195,28 @@ def delete_state_item(name):
def get_setting(name):
_env_name = "PLATFORMIO_SETTING_%s" % name.upper()
if _env_name in environ:
return sanitize_setting(name, getenv(_env_name))
if _env_name in os.environ:
return sanitize_setting(name, os.getenv(_env_name))
with State() as state:
if "settings" in state and name in state['settings']:
return state['settings'][name]
if "settings" in state and name in state["settings"]:
return state["settings"][name]
return DEFAULT_SETTINGS[name]['value']
return DEFAULT_SETTINGS[name]["value"]
def set_setting(name, value):
with State(lock=True) as state:
if "settings" not in state:
state['settings'] = {}
state['settings'][name] = sanitize_setting(name, value)
state["settings"] = {}
state["settings"][name] = sanitize_setting(name, value)
state.modified = True
def reset_settings():
with State(lock=True) as state:
if "settings" in state:
del state['settings']
del state["settings"]
def get_session_var(name, default=None):
@@ -381,11 +229,13 @@ def set_session_var(name, value):
def is_disabled_progressbar():
return any([
get_session_var("force_option"),
is_ci(),
getenv("PLATFORMIO_DISABLE_PROGRESSBAR") == "true"
])
return any(
[
get_session_var("force_option"),
proc.is_ci(),
os.getenv("PLATFORMIO_DISABLE_PROGRESSBAR") == "true",
]
)
def get_cid():
@@ -393,19 +243,43 @@ def get_cid():
if cid:
return cid
uid = None
if getenv("C9_UID"):
uid = getenv("C9_UID")
elif getenv("CHE_API", getenv("CHE_API_ENDPOINT")):
try:
uid = requests.get("{api}/user?token={token}".format(
api=getenv("CHE_API", getenv("CHE_API_ENDPOINT")),
token=getenv("USER_TOKEN"))).json().get("id")
except: # pylint: disable=bare-except
pass
if os.getenv("GITHUB_USER"):
uid = os.getenv("GITHUB_USER")
elif os.getenv("GITPOD_GIT_USER_NAME"):
uid = os.getenv("GITPOD_GIT_USER_NAME")
if not uid:
uid = uuid.getnode()
cid = uuid.UUID(bytes=hashlib.md5(hashlib_encode_data(uid)).digest())
cid = str(cid)
if WINDOWS or os.getuid() > 0: # yapf: disable pylint: disable=no-member
if IS_WINDOWS or os.getuid() > 0: # pylint: disable=no-member
set_state_item("cid", cid)
return cid
def get_user_agent():
data = [
"PlatformIO/%s" % __version__,
"CI/%d" % int(proc.is_ci()),
"Container/%d" % int(proc.is_container()),
]
if get_session_var("caller_id"):
data.append("Caller/%s" % get_session_var("caller_id"))
if os.getenv("PLATFORMIO_IDE"):
data.append("IDE/%s" % os.getenv("PLATFORMIO_IDE"))
data.append("Python/%s" % platform.python_version())
data.append("Platform/%s" % platform.platform())
return " ".join(data)
def get_host_id():
h = hashlib.sha1(hashlib_encode_data(get_cid()))
try:
username = getpass.getuser()
h.update(hashlib_encode_data(username))
except: # pylint: disable=bare-except
pass
return h.hexdigest()
def get_host_name():
return str(socket.gethostname())[:255]

View File

@@ -12,8 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from os import environ, makedirs
from os.path import isdir, join
import json
import os
import sys
from time import time
import click
@@ -27,11 +28,10 @@ from SCons.Script import DefaultEnvironment # pylint: disable=import-error
from SCons.Script import Import # pylint: disable=import-error
from SCons.Script import Variables # pylint: disable=import-error
from platformio import fs
from platformio.compat import PY2, dump_json_to_unicode
from platformio.managers.platform import PlatformBase
from platformio import app, compat, fs
from platformio.platform.base import PlatformBase
from platformio.proc import get_pythonexe_path
from platformio.project import helpers as project_helpers
from platformio.project.helpers import get_project_dir
AllowSubstExceptions(NameError)
@@ -43,50 +43,61 @@ clivars.AddVariables(
("PROJECT_CONFIG",),
("PIOENV",),
("PIOTEST_RUNNING_NAME",),
("UPLOAD_PORT",)
) # yapf: disable
("UPLOAD_PORT",),
("PROGRAM_ARGS",),
)
DEFAULT_ENV_OPTIONS = dict(
tools=[
"ar", "gas", "gcc", "g++", "gnulink", "platformio", "pioplatform",
"pioproject", "piowinhooks", "piolib", "pioupload", "piomisc", "pioide"
"ar",
"cc",
"c++",
"link",
"piohooks",
"pioasm",
"platformio",
"pioproject",
"pioplatform",
"piotest",
"piotarget",
"piolib",
"pioupload",
"piosize",
"pioino",
"piomisc",
"piointegration",
"piomaxlen",
],
toolpath=[join(fs.get_source_dir(), "builder", "tools")],
toolpath=[os.path.join(fs.get_source_dir(), "builder", "tools")],
variables=clivars,
# Propagating External Environment
ENV=environ,
ENV=os.environ,
UNIX_TIME=int(time()),
PROJECT_DIR=project_helpers.get_project_dir(),
PROJECTCORE_DIR=project_helpers.get_project_core_dir(),
PROJECTPACKAGES_DIR=project_helpers.get_project_packages_dir(),
PROJECTWORKSPACE_DIR=project_helpers.get_project_workspace_dir(),
PROJECTLIBDEPS_DIR=project_helpers.get_project_libdeps_dir(),
PROJECTINCLUDE_DIR=project_helpers.get_project_include_dir(),
PROJECTSRC_DIR=project_helpers.get_project_src_dir(),
PROJECTTEST_DIR=project_helpers.get_project_test_dir(),
PROJECTDATA_DIR=project_helpers.get_project_data_dir(),
PROJECTBUILD_DIR=project_helpers.get_project_build_dir(),
BUILDCACHE_DIR=project_helpers.get_project_optional_dir("build_cache_dir"),
BUILD_DIR=join("$PROJECTBUILD_DIR", "$PIOENV"),
BUILDSRC_DIR=join("$BUILD_DIR", "src"),
BUILDTEST_DIR=join("$BUILD_DIR", "test"),
BUILD_DIR=os.path.join("$PROJECT_BUILD_DIR", "$PIOENV"),
BUILD_SRC_DIR=os.path.join("$BUILD_DIR", "src"),
BUILD_TEST_DIR=os.path.join("$BUILD_DIR", "test"),
COMPILATIONDB_PATH=os.path.join("$PROJECT_DIR", "compile_commands.json"),
LIBPATH=["$BUILD_DIR"],
LIBSOURCE_DIRS=[
project_helpers.get_project_lib_dir(),
join("$PROJECTLIBDEPS_DIR", "$PIOENV"),
project_helpers.get_project_global_lib_dir()
],
PROGNAME="program",
PROG_PATH=join("$BUILD_DIR", "$PROGNAME$PROGSUFFIX"),
PYTHONEXE=get_pythonexe_path())
PROGPATH=os.path.join("$BUILD_DIR", "$PROGNAME$PROGSUFFIX"),
PROG_PATH="$PROGPATH", # deprecated
PYTHONEXE=get_pythonexe_path(),
IDE_EXTRA_DATA={},
)
# Declare command verbose messages
command_strings = dict(
ARCOM="Archiving",
LINKCOM="Linking",
RANLIBCOM="Indexing",
ASCOM="Compiling",
ASPPCOM="Compiling",
CCCOM="Compiling",
CXXCOM="Compiling",
)
if not int(ARGUMENTS.get("PIOVERBOSE", 0)):
DEFAULT_ENV_OPTIONS['ARCOMSTR'] = "Archiving $TARGET"
DEFAULT_ENV_OPTIONS['LINKCOMSTR'] = "Linking $TARGET"
DEFAULT_ENV_OPTIONS['RANLIBCOMSTR'] = "Indexing $TARGET"
for k in ("ASCOMSTR", "ASPPCOMSTR", "CCCOMSTR", "CXXCOMSTR"):
DEFAULT_ENV_OPTIONS[k] = "Compiling $TARGET"
for name, value in command_strings.items():
DEFAULT_ENV_OPTIONS["%sSTR" % name] = "%s $TARGET" % (value)
env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS)
@@ -94,31 +105,82 @@ env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS)
env.Replace(
**{
key: PlatformBase.decode_scons_arg(env[key])
for key in list(clivars.keys()) if key in env
})
for key in list(clivars.keys())
if key in env
}
)
if env.subst("$BUILDCACHE_DIR"):
if not isdir(env.subst("$BUILDCACHE_DIR")):
makedirs(env.subst("$BUILDCACHE_DIR"))
env.CacheDir("$BUILDCACHE_DIR")
# Setup project optional directories
config = env.GetProjectConfig()
app.set_session_var("custom_project_conf", config.path)
env.Replace(
PROJECT_DIR=get_project_dir(),
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="$PROJECT_SRC_DIR", # legacy for dev/platform
PROJECT_TEST_DIR=config.get("platformio", "test_dir"),
PROJECT_DATA_DIR=config.get("platformio", "data_dir"),
PROJECTDATA_DIR="$PROJECT_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("platformio", "lib_dir"),
os.path.join("$PROJECT_LIBDEPS_DIR", "$PIOENV"),
config.get("platformio", "globallib_dir"),
],
)
if int(ARGUMENTS.get("ISATTY", 0)):
# pylint: disable=protected-access
click._compat.isatty = lambda stream: True
if env.GetOption('clean'):
env.PioClean(env.subst("$BUILD_DIR"))
if compat.IS_WINDOWS and sys.version_info >= (3, 8) and os.getcwd().startswith("\\\\"):
click.secho("!!! WARNING !!!\t\t" * 3, fg="red")
click.secho(
"Your project is located on a mapped network drive but the "
"current command-line shell does not support the UNC paths.",
fg="yellow",
)
click.secho(
"Please move your project to a physical drive or check this workaround: "
"https://bit.ly/3kuU5mP\n",
fg="yellow",
)
if env.subst("$BUILD_CACHE_DIR"):
if not os.path.isdir(env.subst("$BUILD_CACHE_DIR")):
os.makedirs(env.subst("$BUILD_CACHE_DIR"))
env.CacheDir("$BUILD_CACHE_DIR")
is_clean_all = "cleanall" in COMMAND_LINE_TARGETS
if env.GetOption("clean") or is_clean_all:
env.PioClean(is_clean_all)
env.Exit(0)
elif not int(ARGUMENTS.get("PIOVERBOSE", 0)):
print("Verbose mode can be enabled via `-v, --verbose` option")
if not int(ARGUMENTS.get("PIOVERBOSE", 0)):
click.echo("Verbose mode can be enabled via `-v, --verbose` option")
# Dynamically load dependent tools
if "compiledb" in COMMAND_LINE_TARGETS:
env.Tool("compilation_db")
if not os.path.isdir(env.subst("$BUILD_DIR")):
os.makedirs(env.subst("$BUILD_DIR"))
env.LoadProjectOptions()
env.LoadPioPlatform()
env.SConscriptChdir(0)
env.SConsignFile(
join("$PROJECTBUILD_DIR",
".sconsign.dblite" if PY2 else ".sconsign3.dblite"))
os.path.join(
"$BUILD_DIR", ".sconsign%d%d" % (sys.version_info[0], sys.version_info[1])
)
)
for item in env.GetExtraScripts("pre"):
env.SConscript(item, exports="env")
@@ -136,32 +198,63 @@ for item in env.GetExtraScripts("post"):
##############################################################################
# Checking program size
if env.get("SIZETOOL") and "nobuild" not in COMMAND_LINE_TARGETS:
env.Depends(["upload", "program"], "checkprogsize")
if env.get("SIZETOOL") and not (
set(["nobuild", "sizedata"]) & set(COMMAND_LINE_TARGETS)
):
env.Depends("upload", "checkprogsize")
# Replace platform's "size" target with our
_new_targets = [t for t in DEFAULT_TARGETS if str(t) != "size"]
Default(None)
Default(_new_targets)
Default("checkprogsize")
# Print configured protocols
env.AddPreAction(["upload", "program"],
env.VerboseAction(
lambda source, target, env: env.PrintUploadInfo(),
"Configuring upload protocol..."))
if "compiledb" in COMMAND_LINE_TARGETS:
env.Alias("compiledb", env.CompilationDatabase("$COMPILATIONDB_PATH"))
AlwaysBuild(env.Alias("debug", DEFAULT_TARGETS))
# Print configured protocols
env.AddPreAction(
"upload",
env.VerboseAction(
lambda source, target, env: env.PrintUploadInfo(),
"Configuring upload protocol...",
),
)
AlwaysBuild(env.Alias("__debug", DEFAULT_TARGETS))
AlwaysBuild(env.Alias("__test", DEFAULT_TARGETS))
env.ProcessDelayedActions()
##############################################################################
if "envdump" in COMMAND_LINE_TARGETS:
print(env.Dump())
click.echo(env.Dump())
env.Exit(0)
if "idedata" in COMMAND_LINE_TARGETS:
Import("projenv")
print("\n%s\n" % dump_json_to_unicode(
env.DumpIDEData(projenv) # pylint: disable=undefined-variable
))
if env.IsIntegrationDump():
projenv = None
try:
Import("projenv")
except: # pylint: disable=bare-except
projenv = env
data = projenv.DumpIntegrationData(env)
# dump to file for the further reading by project.helpers.load_build_metadata
with open(
projenv.subst(os.path.join("$BUILD_DIR", "idedata.json")),
mode="w",
encoding="utf8",
) as fp:
json.dump(data, fp)
click.echo("\n%s\n" % json.dumps(data)) # pylint: disable=undefined-variable
env.Exit(0)
if "sizedata" in COMMAND_LINE_TARGETS:
AlwaysBuild(
env.Alias(
"sizedata",
DEFAULT_TARGETS,
env.VerboseAction(env.DumpSizeData, "Generating memory usage report..."),
)
)
Default("sizedata")

View File

@@ -0,0 +1,226 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
# Copyright 2020 MongoDB Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# pylint: disable=unused-argument, protected-access, unused-variable, import-error
# Original: https://github.com/mongodb/mongo/blob/master/site_scons/site_tools/compilation_db.py
from __future__ import absolute_import
import itertools
import json
import os
import SCons
from platformio.builder.tools.platformio import SRC_ASM_EXT, SRC_C_EXT, SRC_CXX_EXT
from platformio.proc import where_is_program
# Implements the ability for SCons to emit a compilation database for the MongoDB project. See
# http://clang.llvm.org/docs/JSONCompilationDatabase.html for details on what a compilation
# database is, and why you might want one. The only user visible entry point here is
# 'env.CompilationDatabase'. This method takes an optional 'target' to name the file that
# should hold the compilation database, otherwise, the file defaults to compile_commands.json,
# which is the name that most clang tools search for by default.
# Is there a better way to do this than this global? Right now this exists so that the
# emitter we add can record all of the things it emits, so that the scanner for the top level
# compilation database can access the complete list, and also so that the writer has easy
# access to write all of the files. But it seems clunky. How can the emitter and the scanner
# communicate more gracefully?
__COMPILATION_DB_ENTRIES = []
# We make no effort to avoid rebuilding the entries. Someday, perhaps we could and even
# integrate with the cache, but there doesn't seem to be much call for it.
class __CompilationDbNode(SCons.Node.Python.Value):
def __init__(self, value):
SCons.Node.Python.Value.__init__(self, value)
self.Decider(changed_since_last_build_node)
def changed_since_last_build_node(*args, **kwargs):
"""Dummy decider to force always building"""
return True
def makeEmitCompilationDbEntry(comstr):
"""
Effectively this creates a lambda function to capture:
* command line
* source
* target
:param comstr: unevaluated command line
:return: an emitter which has captured the above
"""
user_action = SCons.Action.Action(comstr)
def EmitCompilationDbEntry(target, source, env):
"""
This emitter will be added to each c/c++ object build to capture the info needed
for clang tools
:param target: target node(s)
:param source: source node(s)
:param env: Environment for use building this node
:return: target(s), source(s)
"""
# Resolve absolute path of toolchain
for cmd in ("CC", "CXX", "AS"):
if cmd not in env:
continue
if os.path.isabs(env[cmd]):
continue
env[cmd] = where_is_program(
env.subst("$%s" % cmd), env.subst("${ENV['PATH']}")
)
dbtarget = __CompilationDbNode(source)
entry = env.__COMPILATIONDB_Entry(
target=dbtarget,
source=[],
__COMPILATIONDB_UTARGET=target,
__COMPILATIONDB_USOURCE=source,
__COMPILATIONDB_UACTION=user_action,
__COMPILATIONDB_ENV=env,
)
# Technically, these next two lines should not be required: it should be fine to
# cache the entries. However, they don't seem to update properly. Since they are quick
# to re-generate disable caching and sidestep this problem.
env.AlwaysBuild(entry)
env.NoCache(entry)
__COMPILATION_DB_ENTRIES.append(dbtarget)
return target, source
return EmitCompilationDbEntry
def CompilationDbEntryAction(target, source, env, **kw):
"""
Create a dictionary with evaluated command line, target, source
and store that info as an attribute on the target
(Which has been stored in __COMPILATION_DB_ENTRIES array
:param target: target node(s)
:param source: source node(s)
:param env: Environment for use building this node
:param kw:
:return: None
"""
command = env["__COMPILATIONDB_UACTION"].strfunction(
target=env["__COMPILATIONDB_UTARGET"],
source=env["__COMPILATIONDB_USOURCE"],
env=env["__COMPILATIONDB_ENV"],
)
entry = {
"directory": env.Dir("#").abspath,
"command": command,
"file": str(env["__COMPILATIONDB_USOURCE"][0]),
}
target[0].write(entry)
def WriteCompilationDb(target, source, env):
entries = []
for s in __COMPILATION_DB_ENTRIES:
item = s.read()
item["file"] = os.path.abspath(item["file"])
entries.append(item)
with open(str(target[0]), mode="w", encoding="utf8") as target_file:
json.dump(
entries, target_file, sort_keys=True, indent=4, separators=(",", ": ")
)
def ScanCompilationDb(node, env, path):
return __COMPILATION_DB_ENTRIES
def generate(env, **kwargs):
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
env["COMPILATIONDB_COMSTR"] = kwargs.get(
"COMPILATIONDB_COMSTR", "Building compilation database $TARGET"
)
components_by_suffix = itertools.chain(
itertools.product(
[".%s" % ext for ext in SRC_C_EXT],
[
(static_obj, SCons.Defaults.StaticObjectEmitter, "$CCCOM"),
(shared_obj, SCons.Defaults.SharedObjectEmitter, "$SHCCCOM"),
],
),
itertools.product(
[".%s" % ext for ext in SRC_CXX_EXT],
[
(static_obj, SCons.Defaults.StaticObjectEmitter, "$CXXCOM"),
(shared_obj, SCons.Defaults.SharedObjectEmitter, "$SHCXXCOM"),
],
),
itertools.product(
[".%s" % ext for ext in SRC_ASM_EXT],
[(static_obj, SCons.Defaults.StaticObjectEmitter, "$ASCOM")],
),
)
for entry in components_by_suffix:
suffix = entry[0]
builder, base_emitter, command = entry[1]
# Assumes a dictionary emitter
emitter = builder.emitter[suffix]
builder.emitter[suffix] = SCons.Builder.ListEmitter(
[emitter, makeEmitCompilationDbEntry(command)]
)
env["BUILDERS"]["__COMPILATIONDB_Entry"] = SCons.Builder.Builder(
action=SCons.Action.Action(CompilationDbEntryAction, None),
)
env["BUILDERS"]["__COMPILATIONDB_Database"] = SCons.Builder.Builder(
action=SCons.Action.Action(WriteCompilationDb, "$COMPILATIONDB_COMSTR"),
target_scanner=SCons.Scanner.Scanner(
function=ScanCompilationDb, node_class=None
),
)
def CompilationDatabase(env, target):
result = env.__COMPILATIONDB_Database(target=target, source=[])
env.AlwaysBuild(result)
env.NoCache(result)
return result
env.AddMethod(CompilationDatabase, "CompilationDatabase")
def exists(env):
return True

View File

@@ -12,14 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from platformio.commands.update import cli as cmd_update
from __future__ import absolute_import
import SCons.Tool.asm # pylint: disable=import-error
#
# Resolve https://github.com/platformio/platformio-core/issues/3917
# Avoid forcing .S to bare assembly on Windows OS
#
if ".S" in SCons.Tool.asm.ASSuffixes:
SCons.Tool.asm.ASSuffixes.remove(".S")
if ".S" not in SCons.Tool.asm.ASPPSuffixes:
SCons.Tool.asm.ASPPSuffixes.append(".S")
def test_update(clirunner, validate_cliresult):
matches = ("Platform Manager", "Up-to-date", "Library Manager")
result = clirunner.invoke(cmd_update, ["--only-check"])
validate_cliresult(result)
assert all([m in result.output for m in matches])
result = clirunner.invoke(cmd_update)
validate_cliresult(result)
assert all([m in result.output for m in matches])
generate = SCons.Tool.asm.generate
exists = SCons.Tool.asm.exists

View File

@@ -0,0 +1,52 @@
# 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.
from __future__ import absolute_import
def AddActionWrapper(handler):
def wraps(env, files, action):
if not isinstance(files, (list, tuple, set)):
files = [files]
known_nodes = []
unknown_files = []
for item in files:
nodes = env.arg2nodes(item, env.fs.Entry)
if nodes and nodes[0].exists():
known_nodes.extend(nodes)
else:
unknown_files.append(item)
if unknown_files:
env.Append(**{"_PIO_DELAYED_ACTIONS": [(handler, unknown_files, action)]})
if known_nodes:
return handler(known_nodes, action)
return []
return wraps
def ProcessDelayedActions(env):
for func, nodes, action in env.get("_PIO_DELAYED_ACTIONS", []):
func(nodes, action)
def generate(env):
env.Replace(**{"_PIO_DELAYED_ACTIONS": []})
env.AddMethod(AddActionWrapper(env.AddPreAction), "AddPreAction")
env.AddMethod(AddActionWrapper(env.AddPostAction), "AddPostAction")
env.AddMethod(ProcessDelayedActions)
def exists(_):
return True

View File

@@ -1,197 +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.
from __future__ import absolute_import
from glob import glob
from os import environ
from os.path import abspath, isfile, join
from SCons.Defaults import processDefines # pylint: disable=import-error
from platformio.compat import glob_escape
from platformio.managers.core import get_core_package_dir
from platformio.proc import exec_command, where_is_program
def _dump_includes(env, projenv):
includes = []
for item in projenv.get("CPPPATH", []):
includes.append(projenv.subst(item))
# installed libs
for lb in env.GetLibBuilders():
includes.extend(lb.get_include_dirs())
# includes from toolchains
p = env.PioPlatform()
for name in p.get_installed_packages():
if p.get_package_type(name) != "toolchain":
continue
toolchain_dir = glob_escape(p.get_package_dir(name))
toolchain_incglobs = [
join(toolchain_dir, "*", "include*"),
join(toolchain_dir, "*", "include", "c++", "*"),
join(toolchain_dir, "*", "include", "c++", "*", "*-*-*"),
join(toolchain_dir, "lib", "gcc", "*", "*", "include*")
]
for g in toolchain_incglobs:
includes.extend(glob(g))
unity_dir = get_core_package_dir("tool-unity")
if unity_dir:
includes.append(unity_dir)
includes.extend(
[env.subst("$PROJECTINCLUDE_DIR"),
env.subst("$PROJECTSRC_DIR")])
# remove duplicates
result = []
for item in includes:
if item not in result:
result.append(abspath(item))
return result
def _get_gcc_defines(env):
items = []
try:
sysenv = environ.copy()
sysenv['PATH'] = str(env['ENV']['PATH'])
result = exec_command("echo | %s -dM -E -" % env.subst("$CC"),
env=sysenv,
shell=True)
except OSError:
return items
if result['returncode'] != 0:
return items
for line in result['out'].split("\n"):
tokens = line.strip().split(" ", 2)
if not tokens or tokens[0] != "#define":
continue
if len(tokens) > 2:
items.append("%s=%s" % (tokens[1], tokens[2]))
else:
items.append(tokens[1])
return items
def _dump_defines(env):
defines = []
# global symbols
for item in processDefines(env.get("CPPDEFINES", [])):
defines.append(env.subst(item).replace('\\', ''))
# special symbol for Atmel AVR MCU
if env['PIOPLATFORM'] == "atmelavr":
board_mcu = env.get("BOARD_MCU")
if not board_mcu and "BOARD" in env:
board_mcu = env.BoardConfig().get("build.mcu")
if board_mcu:
defines.append(
str("__AVR_%s__" % board_mcu.upper().replace(
"ATMEGA", "ATmega").replace("ATTINY", "ATtiny")))
# built-in GCC marcos
# if env.GetCompilerType() == "gcc":
# defines.extend(_get_gcc_defines(env))
return defines
def _get_svd_path(env):
svd_path = env.GetProjectOption("debug_svd_path")
if svd_path:
return abspath(svd_path)
if "BOARD" not in env:
return None
try:
svd_path = env.BoardConfig().get("debug.svd_path")
assert svd_path
except (AssertionError, KeyError):
return None
# custom path to SVD file
if isfile(svd_path):
return svd_path
# default file from ./platform/misc/svd folder
p = env.PioPlatform()
if isfile(join(p.get_dir(), "misc", "svd", svd_path)):
return abspath(join(p.get_dir(), "misc", "svd", svd_path))
return None
def DumpIDEData(env, projenv):
LINTCCOM = "$CFLAGS $CCFLAGS $CPPFLAGS"
LINTCXXCOM = "$CXXFLAGS $CCFLAGS $CPPFLAGS"
data = {
"env_name":
env['PIOENV'],
"libsource_dirs": [env.subst(l) for l in env.GetLibSourceDirs()],
"defines":
_dump_defines(env),
"includes":
_dump_includes(env, projenv),
"cc_flags":
env.subst(LINTCCOM),
"cxx_flags":
env.subst(LINTCXXCOM),
"cc_path":
where_is_program(env.subst("$CC"), env.subst("${ENV['PATH']}")),
"cxx_path":
where_is_program(env.subst("$CXX"), env.subst("${ENV['PATH']}")),
"gdb_path":
where_is_program(env.subst("$GDB"), env.subst("${ENV['PATH']}")),
"prog_path":
env.subst("$PROG_PATH"),
"flash_extra_images": [{
"offset": item[0],
"path": env.subst(item[1])
} for item in env.get("FLASH_EXTRA_IMAGES", [])],
"svd_path":
_get_svd_path(env),
"compiler_type":
env.GetCompilerType()
}
env_ = env.Clone()
# https://github.com/platformio/platformio-atom-ide/issues/34
_new_defines = []
for item in processDefines(env_.get("CPPDEFINES", [])):
item = item.replace('\\"', '"')
if " " in item:
_new_defines.append(item.replace(" ", "\\\\ "))
else:
_new_defines.append(item)
env_.Replace(CPPDEFINES=_new_defines)
data.update({
"cc_flags": env_.subst(LINTCCOM),
"cxx_flags": env_.subst(LINTCXXCOM)
})
return data
def exists(_):
return True
def generate(env):
env.AddMethod(DumpIDEData)
return env

View File

@@ -0,0 +1,259 @@
# 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.
from __future__ import absolute_import
import atexit
import glob
import io
import os
import re
import tempfile
import click
from platformio.compat import get_filesystem_encoding, get_locale_encoding
class InoToCPPConverter:
PROTOTYPE_RE = re.compile(
r"""^(
(?:template\<.*\>\s*)? # template
([a-z_\d\&]+\*?\s+){1,2} # return type
([a-z_\d]+\s*) # name of prototype
\([a-z_,\.\*\&\[\]\s\d]*\) # arguments
)\s*(\{|;) # must end with `{` or `;`
""",
re.X | re.M | re.I,
)
DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I)
PROTOPTRS_TPLRE = r"\([^&\(]*&(%s)[^\)]*\)"
def __init__(self, env):
self.env = env
self._main_ino = None
self._safe_encoding = None
def read_safe_contents(self, path):
error_reported = False
for encoding in (
"utf-8",
None,
get_filesystem_encoding(),
get_locale_encoding(),
"latin-1",
):
try:
with io.open(path, encoding=encoding) as fp:
contents = fp.read()
self._safe_encoding = encoding
return contents
except UnicodeDecodeError:
if not error_reported:
error_reported = True
click.secho(
"Unicode decode error has occurred, please remove invalid "
"(non-ASCII or non-UTF8) characters from %s file or convert it to UTF-8"
% path,
fg="yellow",
err=True,
)
return ""
def write_safe_contents(self, path, contents):
with io.open(
path, "w", encoding=self._safe_encoding, errors="backslashreplace"
) as fp:
return fp.write(contents)
def is_main_node(self, contents):
return self.DETECTMAIN_RE.search(contents)
def convert(self, nodes):
contents = self.merge(nodes)
if not contents:
return None
return self.process(contents)
def merge(self, nodes):
assert nodes
lines = []
for node in nodes:
contents = self.read_safe_contents(node.get_path())
_lines = ['# 1 "%s"' % node.get_path().replace("\\", "/"), contents]
if self.is_main_node(contents):
lines = _lines + lines
self._main_ino = node.get_path()
else:
lines.extend(_lines)
if not self._main_ino:
self._main_ino = nodes[0].get_path()
return "\n".join(["#include <Arduino.h>"] + lines) if lines else None
def process(self, contents):
out_file = self._main_ino + ".cpp"
assert self._gcc_preprocess(contents, out_file)
contents = self.read_safe_contents(out_file)
contents = self._join_multiline_strings(contents)
self.write_safe_contents(out_file, self.append_prototypes(contents))
return out_file
def _gcc_preprocess(self, contents, out_file):
tmp_path = tempfile.mkstemp()[1]
self.write_safe_contents(tmp_path, contents)
self.env.Execute(
self.env.VerboseAction(
'$CXX -o "{0}" -x c++ -fpreprocessed -dD -E "{1}"'.format(
out_file, tmp_path
),
"Converting " + os.path.basename(out_file[:-4]),
)
)
atexit.register(_delete_file, tmp_path)
return os.path.isfile(out_file)
def _join_multiline_strings(self, contents):
if "\\\n" not in contents:
return contents
newlines = []
linenum = 0
stropen = False
for line in contents.split("\n"):
_linenum = self._parse_preproc_line_num(line)
if _linenum is not None:
linenum = _linenum
else:
linenum += 1
if line.endswith("\\"):
if line.startswith('"'):
stropen = True
newlines.append(line[:-1])
continue
if stropen:
newlines[len(newlines) - 1] += line[:-1]
continue
elif stropen and line.endswith(('",', '";')):
newlines[len(newlines) - 1] += line
stropen = False
newlines.append(
'#line %d "%s"' % (linenum, self._main_ino.replace("\\", "/"))
)
continue
newlines.append(line)
return "\n".join(newlines)
@staticmethod
def _parse_preproc_line_num(line):
if not line.startswith("#"):
return None
tokens = line.split(" ", 3)
if len(tokens) > 2 and tokens[1].isdigit():
return int(tokens[1])
return None
def _parse_prototypes(self, contents):
prototypes = []
reserved_keywords = set(["if", "else", "while"])
for match in self.PROTOTYPE_RE.finditer(contents):
if (
set([match.group(2).strip(), match.group(3).strip()])
& reserved_keywords
):
continue
prototypes.append(match)
return prototypes
def _get_total_lines(self, contents):
total = 0
if contents.endswith("\n"):
contents = contents[:-1]
for line in contents.split("\n")[::-1]:
linenum = self._parse_preproc_line_num(line)
if linenum is not None:
return total + linenum
total += 1
return total
def append_prototypes(self, contents):
prototypes = self._parse_prototypes(contents) or []
# skip already declared prototypes
declared = set(m.group(1).strip() for m in prototypes if m.group(4) == ";")
prototypes = [m for m in prototypes if m.group(1).strip() not in declared]
if not prototypes:
return contents
prototype_names = set(m.group(3).strip() for m in prototypes)
split_pos = prototypes[0].start()
match_ptrs = re.search(
self.PROTOPTRS_TPLRE % ("|".join(prototype_names)),
contents[:split_pos],
re.M,
)
if match_ptrs:
split_pos = contents.rfind("\n", 0, match_ptrs.start()) + 1
result = []
result.append(contents[:split_pos].strip())
result.append("%s;" % ";\n".join([m.group(1) for m in prototypes]))
result.append(
'#line %d "%s"'
% (
self._get_total_lines(contents[:split_pos]),
self._main_ino.replace("\\", "/"),
)
)
result.append(contents[split_pos:].strip())
return "\n".join(result)
def FindInoNodes(env):
src_dir = glob.escape(env.subst("$PROJECT_SRC_DIR"))
return env.Glob(os.path.join(src_dir, "*.ino")) + env.Glob(
os.path.join(src_dir, "*.pde")
)
def ConvertInoToCpp(env):
ino_nodes = env.FindInoNodes()
if not ino_nodes:
return
c = InoToCPPConverter(env)
out_file = c.convert(ino_nodes)
atexit.register(_delete_file, out_file)
def _delete_file(path):
try:
if os.path.isfile(path):
os.remove(path)
except: # pylint: disable=bare-except
pass
def generate(env):
env.AddMethod(FindInoNodes)
env.AddMethod(ConvertInoToCpp)
def exists(_):
return True

View File

@@ -0,0 +1,204 @@
# 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.
from __future__ import absolute_import
import glob
import os
import SCons.Defaults # pylint: disable=import-error
import SCons.Subst # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from platformio.proc import exec_command, where_is_program
def IsIntegrationDump(_):
return set(["_idedata", "idedata"]) & set(COMMAND_LINE_TARGETS)
def DumpIntegrationIncludes(env):
result = dict(build=[], compatlib=[], toolchain=[])
result["build"].extend(
[
env.subst("$PROJECT_INCLUDE_DIR"),
env.subst("$PROJECT_SRC_DIR"),
]
)
result["build"].extend(
[os.path.abspath(env.subst(item)) for item in env.get("CPPPATH", [])]
)
# installed libs
for lb in env.GetLibBuilders():
result["compatlib"].extend(
[os.path.abspath(inc) for inc in lb.get_include_dirs()]
)
# includes from toolchains
p = env.PioPlatform()
for pkg in p.get_installed_packages(with_optional=False):
if p.get_package_type(pkg.metadata.name) != "toolchain":
continue
toolchain_dir = glob.escape(pkg.path)
toolchain_incglobs = [
os.path.join(toolchain_dir, "*", "include", "c++", "*"),
os.path.join(toolchain_dir, "*", "include", "c++", "*", "*-*-*"),
os.path.join(toolchain_dir, "lib", "gcc", "*", "*", "include*"),
os.path.join(toolchain_dir, "*", "include*"),
]
for g in toolchain_incglobs:
result["toolchain"].extend([os.path.abspath(inc) for inc in glob.glob(g)])
return result
def get_gcc_defines(env):
items = []
try:
sysenv = os.environ.copy()
sysenv["PATH"] = str(env["ENV"]["PATH"])
result = exec_command(
"echo | %s -dM -E -" % env.subst("$CC"), env=sysenv, shell=True
)
except OSError:
return items
if result["returncode"] != 0:
return items
for line in result["out"].split("\n"):
tokens = line.strip().split(" ", 2)
if not tokens or tokens[0] != "#define":
continue
if len(tokens) > 2:
items.append("%s=%s" % (tokens[1], tokens[2]))
else:
items.append(tokens[1])
return items
def dump_defines(env):
defines = []
# global symbols
for item in SCons.Defaults.processDefines(env.get("CPPDEFINES", [])):
item = item.strip()
if item:
defines.append(env.subst(item).replace("\\", ""))
# special symbol for Atmel AVR MCU
if env["PIOPLATFORM"] == "atmelavr":
board_mcu = env.get("BOARD_MCU")
if not board_mcu and "BOARD" in env:
board_mcu = env.BoardConfig().get("build.mcu")
if board_mcu:
defines.append(
str(
"__AVR_%s__"
% board_mcu.upper()
.replace("ATMEGA", "ATmega")
.replace("ATTINY", "ATtiny")
)
)
# built-in GCC marcos
# if env.GetCompilerType() == "gcc":
# defines.extend(get_gcc_defines(env))
return defines
def dump_svd_path(env):
svd_path = env.GetProjectOption("debug_svd_path")
if svd_path:
return os.path.abspath(svd_path)
if "BOARD" not in env:
return None
try:
svd_path = env.BoardConfig().get("debug.svd_path")
assert svd_path
except (AssertionError, KeyError):
return None
# custom path to SVD file
if os.path.isfile(svd_path):
return svd_path
# default file from ./platform/misc/svd folder
p = env.PioPlatform()
if os.path.isfile(os.path.join(p.get_dir(), "misc", "svd", svd_path)):
return os.path.abspath(os.path.join(p.get_dir(), "misc", "svd", svd_path))
return None
def _subst_cmd(env, cmd):
args = env.subst_list(cmd, SCons.Subst.SUBST_CMD)[0]
return " ".join([SCons.Subst.quote_spaces(arg) for arg in args])
def DumpIntegrationData(env, globalenv):
"""env here is `projenv`"""
data = {
"env_name": env["PIOENV"],
"libsource_dirs": [env.subst(item) for item in env.GetLibSourceDirs()],
"defines": dump_defines(env),
"includes": env.DumpIntegrationIncludes(),
"cc_path": where_is_program(env.subst("$CC"), env.subst("${ENV['PATH']}")),
"cxx_path": where_is_program(env.subst("$CXX"), env.subst("${ENV['PATH']}")),
"gdb_path": where_is_program(env.subst("$GDB"), env.subst("${ENV['PATH']}")),
"prog_path": env.subst("$PROG_PATH"),
"svd_path": dump_svd_path(env),
"compiler_type": env.GetCompilerType(),
"targets": globalenv.DumpTargets(),
"extra": dict(
flash_images=[
{"offset": item[0], "path": env.subst(item[1])}
for item in env.get("FLASH_EXTRA_IMAGES", [])
]
),
}
data["extra"].update(
env.get("INTEGRATION_EXTRA_DATA", env.get("IDE_EXTRA_DATA", {}))
)
env_ = env.Clone()
# https://github.com/platformio/platformio-atom-ide/issues/34
_new_defines = []
for item in SCons.Defaults.processDefines(env_.get("CPPDEFINES", [])):
item = item.replace('\\"', '"')
if " " in item:
_new_defines.append(item.replace(" ", "\\\\ "))
else:
_new_defines.append(item)
env_.Replace(CPPDEFINES=_new_defines)
# export C/C++ build flags
data.update(
{
"cc_flags": _subst_cmd(env_, "$CFLAGS $CCFLAGS $CPPFLAGS"),
"cxx_flags": _subst_cmd(env_, "$CXXFLAGS $CCFLAGS $CPPFLAGS"),
}
)
return data
def exists(_):
return True
def generate(env):
env.AddMethod(IsIntegrationDump)
env.AddMethod(DumpIntegrationIncludes)
env.AddMethod(DumpIntegrationData)
return env

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
# 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.
from __future__ import absolute_import
import hashlib
import os
import re
from SCons.Platform import TempFileMunge # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from SCons.Subst import quote_spaces # pylint: disable=import-error
from platformio.compat import IS_WINDOWS, hashlib_encode_data
# There are the next limits depending on a platform:
# - Windows = 8192
# - Unix = 131072
# We need ~512 characters for compiler and temporary file paths
MAX_LINE_LENGTH = (8192 if IS_WINDOWS else 131072) - 512
WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)")
def tempfile_arg_esc_func(arg):
arg = quote_spaces(arg)
if not IS_WINDOWS:
return arg
# GCC requires double Windows slashes, let's use UNIX separator
return WINPATHSEP_RE.sub(r"/\1", arg)
def long_sources_hook(env, sources):
_sources = str(sources).replace("\\", "/")
if len(str(_sources)) < MAX_LINE_LENGTH:
return sources
# fix space in paths
data = []
for line in _sources.split(".o "):
line = line.strip()
if not line.endswith(".o"):
line += ".o"
data.append('"%s"' % line)
return '@"%s"' % _file_long_data(env, " ".join(data))
def _file_long_data(env, data):
build_dir = env.subst("$BUILD_DIR")
if not os.path.isdir(build_dir):
os.makedirs(build_dir)
tmp_file = os.path.join(
build_dir, "longcmd-%s" % hashlib.md5(hashlib_encode_data(data)).hexdigest()
)
if os.path.isfile(tmp_file):
return tmp_file
with open(tmp_file, mode="w", encoding="utf8") as fp:
fp.write(data)
return tmp_file
def exists(env):
return "compiledb" not in COMMAND_LINE_TARGETS and not env.IsIntegrationDump()
def generate(env):
if not exists(env):
return env
kwargs = dict(
_long_sources_hook=long_sources_hook,
TEMPFILE=TempFileMunge,
MAXLINELENGTH=MAX_LINE_LENGTH,
TEMPFILEARGESCFUNC=tempfile_arg_esc_func,
TEMPFILESUFFIX=".tmp",
TEMPFILEDIR="$BUILD_DIR",
)
for name in ("LINKCOM", "ASCOM", "ASPPCOM", "CCCOM", "CXXCOM"):
kwargs[name] = "${TEMPFILE('%s','$%sSTR')}" % (env.get(name), name)
kwargs["ARCOM"] = env.get("ARCOM", "").replace(
"$SOURCES", "${_long_sources_hook(__env__, SOURCES)}"
)
env.Replace(**kwargs)
return env

View File

@@ -14,213 +14,26 @@
from __future__ import absolute_import
import atexit
import re
import os
import sys
from os import environ, remove, walk
from os.path import basename, isdir, isfile, join, realpath, relpath, sep
from tempfile import mkstemp
from SCons.Action import Action # pylint: disable=import-error
from SCons.Script import ARGUMENTS # pylint: disable=import-error
from platformio import fs, util
from platformio.compat import get_file_contents, glob_escape
from platformio.managers.core import get_core_package_dir
from platformio.proc import exec_command
class InoToCPPConverter(object):
PROTOTYPE_RE = re.compile(
r"""^(
(?:template\<.*\>\s*)? # template
([a-z_\d\&]+\*?\s+){1,2} # return type
([a-z_\d]+\s*) # name of prototype
\([a-z_,\.\*\&\[\]\s\d]*\) # arguments
)\s*(\{|;) # must end with `{` or `;`
""", re.X | re.M | re.I)
DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I)
PROTOPTRS_TPLRE = r"\([^&\(]*&(%s)[^\)]*\)"
def __init__(self, env):
self.env = env
self._main_ino = None
def is_main_node(self, contents):
return self.DETECTMAIN_RE.search(contents)
def convert(self, nodes):
contents = self.merge(nodes)
if not contents:
return None
return self.process(contents)
def merge(self, nodes):
assert nodes
lines = []
for node in nodes:
contents = get_file_contents(node.get_path())
_lines = [
'# 1 "%s"' % node.get_path().replace("\\", "/"), contents
]
if self.is_main_node(contents):
lines = _lines + lines
self._main_ino = node.get_path()
else:
lines.extend(_lines)
if not self._main_ino:
self._main_ino = nodes[0].get_path()
return "\n".join(["#include <Arduino.h>"] + lines) if lines else None
def process(self, contents):
out_file = self._main_ino + ".cpp"
assert self._gcc_preprocess(contents, out_file)
contents = get_file_contents(out_file)
contents = self._join_multiline_strings(contents)
with open(out_file, "w") as fp:
fp.write(self.append_prototypes(contents))
return out_file
def _gcc_preprocess(self, contents, out_file):
tmp_path = mkstemp()[1]
with open(tmp_path, "w") as fp:
fp.write(contents)
self.env.Execute(
self.env.VerboseAction(
'$CXX -o "{0}" -x c++ -fpreprocessed -dD -E "{1}"'.format(
out_file, tmp_path),
"Converting " + basename(out_file[:-4])))
atexit.register(_delete_file, tmp_path)
return isfile(out_file)
def _join_multiline_strings(self, contents):
if "\\\n" not in contents:
return contents
newlines = []
linenum = 0
stropen = False
for line in contents.split("\n"):
_linenum = self._parse_preproc_line_num(line)
if _linenum is not None:
linenum = _linenum
else:
linenum += 1
if line.endswith("\\"):
if line.startswith('"'):
stropen = True
newlines.append(line[:-1])
continue
elif stropen:
newlines[len(newlines) - 1] += line[:-1]
continue
elif stropen and line.endswith(('",', '";')):
newlines[len(newlines) - 1] += line
stropen = False
newlines.append('#line %d "%s"' %
(linenum, self._main_ino.replace("\\", "/")))
continue
newlines.append(line)
return "\n".join(newlines)
@staticmethod
def _parse_preproc_line_num(line):
if not line.startswith("#"):
return None
tokens = line.split(" ", 3)
if len(tokens) > 2 and tokens[1].isdigit():
return int(tokens[1])
return None
def _parse_prototypes(self, contents):
prototypes = []
reserved_keywords = set(["if", "else", "while"])
for match in self.PROTOTYPE_RE.finditer(contents):
if (set([match.group(2).strip(),
match.group(3).strip()]) & reserved_keywords):
continue
prototypes.append(match)
return prototypes
def _get_total_lines(self, contents):
total = 0
if contents.endswith("\n"):
contents = contents[:-1]
for line in contents.split("\n")[::-1]:
linenum = self._parse_preproc_line_num(line)
if linenum is not None:
return total + linenum
total += 1
return total
def append_prototypes(self, contents):
prototypes = self._parse_prototypes(contents) or []
# skip already declared prototypes
declared = set(
m.group(1).strip() for m in prototypes if m.group(4) == ";")
prototypes = [
m for m in prototypes if m.group(1).strip() not in declared
]
if not prototypes:
return contents
prototype_names = set(m.group(3).strip() for m in prototypes)
split_pos = prototypes[0].start()
match_ptrs = re.search(
self.PROTOPTRS_TPLRE % ("|".join(prototype_names)),
contents[:split_pos], re.M)
if match_ptrs:
split_pos = contents.rfind("\n", 0, match_ptrs.start()) + 1
result = []
result.append(contents[:split_pos].strip())
result.append("%s;" % ";\n".join([m.group(1) for m in prototypes]))
result.append('#line %d "%s"' % (self._get_total_lines(
contents[:split_pos]), self._main_ino.replace("\\", "/")))
result.append(contents[split_pos:].strip())
return "\n".join(result)
def ConvertInoToCpp(env):
src_dir = glob_escape(env.subst("$PROJECTSRC_DIR"))
ino_nodes = (env.Glob(join(src_dir, "*.ino")) +
env.Glob(join(src_dir, "*.pde")))
if not ino_nodes:
return
c = InoToCPPConverter(env)
out_file = c.convert(ino_nodes)
atexit.register(_delete_file, out_file)
def _delete_file(path):
try:
if isfile(path):
remove(path)
except: # pylint: disable=bare-except
pass
@util.memoized()
def _get_compiler_type(env):
def GetCompilerType(env):
if env.subst("$CC").endswith("-gcc"):
return "gcc"
try:
sysenv = environ.copy()
sysenv['PATH'] = str(env['ENV']['PATH'])
sysenv = os.environ.copy()
sysenv["PATH"] = str(env["ENV"]["PATH"])
result = exec_command([env.subst("$CC"), "-v"], env=sysenv)
except OSError:
return None
if result['returncode'] != 0:
if result["returncode"] != 0:
return None
output = "".join([result['out'], result['err']]).lower()
output = "".join([result["out"], result["err"]]).lower()
if "clang" in output and "LLVM" in output:
return "clang"
if "gcc" in output:
@@ -228,16 +41,11 @@ def _get_compiler_type(env):
return None
def GetCompilerType(env):
return _get_compiler_type(env)
def GetActualLDScript(env):
def _lookup_in_ldpath(script):
for d in env.get("LIBPATH", []):
path = join(env.subst(d), script)
if isfile(path):
path = os.path.join(env.subst(d), script)
if os.path.isfile(path):
return path
return None
@@ -248,7 +56,7 @@ def GetActualLDScript(env):
if f == "-T":
script_in_next = True
continue
elif script_in_next:
if script_in_next:
script_in_next = False
raw_script = f
elif f.startswith("-Wl,-T"):
@@ -256,7 +64,7 @@ def GetActualLDScript(env):
else:
continue
script = env.subst(raw_script.replace('"', "").strip())
if isfile(script):
if os.path.isfile(script):
return script
path = _lookup_in_ldpath(script)
if path:
@@ -264,12 +72,13 @@ def GetActualLDScript(env):
if script:
sys.stderr.write(
"Error: Could not find '%s' LD script in LDPATH '%s'\n" %
(script, env.subst("$LIBPATH")))
"Error: Could not find '%s' LD script in LDPATH '%s'\n"
% (script, env.subst("$LIBPATH"))
)
env.Exit(1)
if not script and "LDSCRIPT_PATH" in env:
path = _lookup_in_ldpath(env['LDSCRIPT_PATH'])
path = _lookup_in_ldpath(env["LDSCRIPT_PATH"])
if path:
return path
@@ -277,51 +86,43 @@ def GetActualLDScript(env):
env.Exit(1)
def VerboseAction(_, act, actstr):
if int(ARGUMENTS.get("PIOVERBOSE", 0)):
return act
return Action(act, actstr)
def ConfigureDebugTarget(env):
def _cleanup_debug_flags(scope):
if scope not in env:
return
unflags = ["-Os", "-g"]
for level in [0, 1, 2, 3]:
for flag in ("O", "g", "ggdb"):
unflags.append("-%s%d" % (flag, level))
env[scope] = [f for f in env.get(scope, []) if f not in unflags]
env.Append(CPPDEFINES=["__PLATFORMIO_BUILD_DEBUG__"])
def PioClean(env, clean_dir):
if not isdir(clean_dir):
print("Build environment is clean")
env.Exit(0)
clean_rel_path = relpath(clean_dir)
for root, _, files in walk(clean_dir):
for f in files:
dst = join(root, f)
remove(dst)
print("Removed %s" %
(dst if clean_rel_path.startswith(".") else relpath(dst)))
print("Done cleaning")
fs.rmtree(clean_dir)
env.Exit(0)
for scope in ("ASFLAGS", "CCFLAGS", "LINKFLAGS"):
_cleanup_debug_flags(scope)
debug_flags = env.ParseFlags(
env.get("PIODEBUGFLAGS")
if env.get("PIODEBUGFLAGS")
and not env.GetProjectOptions(as_dict=True).get("debug_build_flags")
else env.GetProjectOption("debug_build_flags")
)
def ProcessDebug(env):
if not env.subst("$PIODEBUGFLAGS"):
env.Replace(PIODEBUGFLAGS=["-Og", "-g3", "-ggdb3"])
env.Append(BUILD_FLAGS=list(env['PIODEBUGFLAGS']) +
["-D__PLATFORMIO_BUILD_DEBUG__"])
unflags = ["-Os"]
for level in [0, 1, 2]:
for flag in ("O", "g", "ggdb"):
unflags.append("-%s%d" % (flag, level))
env.Append(BUILD_UNFLAGS=unflags)
env.MergeFlags(debug_flags)
optimization_flags = [
f for f in debug_flags.get("CCFLAGS", []) if f.startswith(("-O", "-g"))
]
def ProcessTest(env):
env.Append(CPPDEFINES=["UNIT_TEST", "UNITY_INCLUDE_CONFIG_H"],
CPPPATH=[join("$BUILD_DIR", "UnityTestLib")])
unitylib = env.BuildLibrary(join("$BUILD_DIR", "UnityTestLib"),
get_core_package_dir("tool-unity"))
env.Prepend(LIBS=[unitylib])
src_filter = ["+<*.cpp>", "+<*.c>"]
if "PIOTEST_RUNNING_NAME" in env:
src_filter.append("+<%s%s>" % (env['PIOTEST_RUNNING_NAME'], sep))
env.Replace(PIOTEST_SRC_FILTER=src_filter)
if optimization_flags:
env.AppendUnique(
ASFLAGS=[
# skip -O flags for assembler
f
for f in optimization_flags
if f.startswith("-g")
],
LINKFLAGS=optimization_flags,
)
def GetExtraScripts(env, scope):
@@ -330,24 +131,21 @@ def GetExtraScripts(env, scope):
if scope == "post" and ":" not in item:
items.append(item)
elif item.startswith("%s:" % scope):
items.append(item[len(scope) + 1:])
items.append(item[len(scope) + 1 :])
if not items:
return items
with fs.cd(env.subst("$PROJECT_DIR")):
return [realpath(item) for item in items]
return [os.path.abspath(env.subst(item)) for item in items]
def generate(env):
env.AddMethod(GetCompilerType)
env.AddMethod(GetActualLDScript)
env.AddMethod(ConfigureDebugTarget)
env.AddMethod(GetExtraScripts)
# bakward-compatibility with Zephyr build script
env.AddMethod(ConfigureDebugTarget, "ConfigureDebugFlags")
def exists(_):
return True
def generate(env):
env.AddMethod(ConvertInoToCpp)
env.AddMethod(GetCompilerType)
env.AddMethod(GetActualLDScript)
env.AddMethod(VerboseAction)
env.AddMethod(PioClean)
env.AddMethod(ProcessDebug)
env.AddMethod(ProcessTest)
env.AddMethod(GetExtraScripts)
return env

View File

@@ -14,79 +14,88 @@
from __future__ import absolute_import
import os
import sys
from os.path import isdir, isfile, join
from SCons.Script import ARGUMENTS # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from SCons.Script import DefaultEnvironment # pylint: disable=import-error
from platformio import exception, fs, util
from platformio.compat import WINDOWS
from platformio.managers.platform import PlatformFactory
from platformio import fs, util
from platformio.compat import IS_MACOS, IS_WINDOWS
from platformio.package.meta import PackageItem
from platformio.package.version import get_original_version
from platformio.platform.exception import UnknownBoard
from platformio.platform.factory import PlatformFactory
from platformio.project.config import ProjectOptions
# pylint: disable=too-many-branches, too-many-locals
@util.memoized()
def PioPlatform(env):
variables = env.GetProjectOptions(as_dict=True)
if "framework" in variables:
# support PIO Core 3.0 dev/platforms
variables['pioframework'] = variables['framework']
p = PlatformFactory.newPlatform(env['PLATFORM_MANIFEST'])
p.configure_default_packages(variables, COMMAND_LINE_TARGETS)
def _PioPlatform():
env = DefaultEnvironment()
p = PlatformFactory.new(os.path.dirname(env["PLATFORM_MANIFEST"]))
p.configure_project_packages(env["PIOENV"], COMMAND_LINE_TARGETS)
return p
def PioPlatform(_):
return _PioPlatform()
def BoardConfig(env, board=None):
p = env.PioPlatform()
try:
board = board or env.get("BOARD")
assert board, "BoardConfig: Board is not defined"
config = p.board_config(board)
except (AssertionError, exception.UnknownBoard) as e:
sys.stderr.write("Error: %s\n" % str(e))
env.Exit(1)
return config
with fs.cd(env.subst("$PROJECT_DIR")):
try:
p = env.PioPlatform()
board = board or env.get("BOARD")
assert board, "BoardConfig: Board is not defined"
return p.board_config(board)
except (AssertionError, UnknownBoard) as exc:
sys.stderr.write("Error: %s\n" % str(exc))
env.Exit(1)
return None
def GetFrameworkScript(env, framework):
p = env.PioPlatform()
assert p.frameworks and framework in p.frameworks
script_path = env.subst(p.frameworks[framework]['script'])
if not isfile(script_path):
script_path = join(p.get_dir(), script_path)
script_path = env.subst(p.frameworks[framework]["script"])
if not os.path.isfile(script_path):
script_path = os.path.join(p.get_dir(), script_path)
return script_path
def LoadPioPlatform(env):
p = env.PioPlatform()
installed_packages = p.get_installed_packages()
# Ensure real platform name
env['PIOPLATFORM'] = p.name
env["PIOPLATFORM"] = p.name
# Add toolchains and uploaders to $PATH and $*_LIBRARY_PATH
systype = util.get_systype()
for name in installed_packages:
type_ = p.get_package_type(name)
for pkg in p.get_installed_packages():
type_ = p.get_package_type(pkg.metadata.name)
if type_ not in ("toolchain", "uploader", "debugger"):
continue
pkg_dir = p.get_package_dir(name)
env.PrependENVPath(
"PATH",
join(pkg_dir, "bin") if isdir(join(pkg_dir, "bin")) else pkg_dir)
if (not WINDOWS and isdir(join(pkg_dir, "lib"))
and type_ != "toolchain"):
os.path.join(pkg.path, "bin")
if os.path.isdir(os.path.join(pkg.path, "bin"))
else pkg.path,
)
if (
not IS_WINDOWS
and os.path.isdir(os.path.join(pkg.path, "lib"))
and type_ != "toolchain"
):
env.PrependENVPath(
"DYLD_LIBRARY_PATH"
if "darwin" in systype else "LD_LIBRARY_PATH",
join(pkg_dir, "lib"))
"DYLD_LIBRARY_PATH" if IS_MACOS else "LD_LIBRARY_PATH",
os.path.join(pkg.path, "lib"),
)
# Platform specific LD Scripts
if isdir(join(p.get_dir(), "ldscripts")):
env.Prepend(LIBPATH=[join(p.get_dir(), "ldscripts")])
if os.path.isdir(os.path.join(p.get_dir(), "ldscripts")):
env.Prepend(LIBPATH=[os.path.join(p.get_dir(), "ldscripts")])
if "BOARD" not in env:
return
@@ -94,16 +103,27 @@ def LoadPioPlatform(env):
# update board manifest with overridden data from INI config
board_config = env.BoardConfig()
for option, value in env.GetProjectOptions():
if option.startswith("board_"):
board_config.update(option.lower()[6:], value)
if not option.startswith("board_"):
continue
option = option.lower()[6:]
try:
if isinstance(board_config.get(option), bool):
value = str(value).lower() in ("1", "yes", "true")
elif isinstance(board_config.get(option), int):
value = int(value)
except KeyError:
pass
board_config.update(option, value)
# load default variables from board config
for option_meta in ProjectOptions.values():
if not option_meta.buildenvvar or option_meta.buildenvvar in env:
continue
data_path = (option_meta.name[6:]
if option_meta.name.startswith("board_") else
option_meta.name.replace("_", "."))
data_path = (
option_meta.name[6:]
if option_meta.name.startswith("board_")
else option_meta.name.replace("_", ".")
)
try:
env[option_meta.buildenvvar] = board_config.get(data_path)
except KeyError:
@@ -115,25 +135,34 @@ def LoadPioPlatform(env):
def PrintConfiguration(env): # pylint: disable=too-many-statements
platform = env.PioPlatform()
pkg_metadata = PackageItem(platform.get_dir()).metadata
board_config = env.BoardConfig() if "BOARD" in env else None
def _get_configuration_data():
return None if not board_config else [
"CONFIGURATION:",
"https://docs.platformio.org/page/boards/%s/%s.html" %
(platform.name, board_config.id)
]
return (
None
if not board_config
else [
"CONFIGURATION:",
"https://docs.platformio.org/page/boards/%s/%s.html"
% (platform.name, board_config.id),
]
)
def _get_plaform_data():
data = ["PLATFORM: %s %s" % (platform.title, platform.version)]
src_manifest_path = platform.pm.get_src_manifest_path(
platform.get_dir())
if src_manifest_path:
src_manifest = fs.load_json(src_manifest_path)
if "version" in src_manifest:
data.append("#" + src_manifest['version'])
if int(ARGUMENTS.get("PIOVERBOSE", 0)):
data.append("(%s)" % src_manifest['url'])
data = [
"PLATFORM: %s (%s)"
% (
platform.title,
pkg_metadata.version if pkg_metadata else platform.version,
)
]
if (
int(ARGUMENTS.get("PIOVERBOSE", 0))
and pkg_metadata
and pkg_metadata.spec.external
):
data.append("(%s)" % pkg_metadata.spec.uri)
if board_config:
data.extend([">", board_config.get("name")])
return data
@@ -151,19 +180,23 @@ def PrintConfiguration(env): # pylint: disable=too-many-statements
return data
ram = board_config.get("upload", {}).get("maximum_ram_size")
flash = board_config.get("upload", {}).get("maximum_size")
data.append("%s RAM, %s Flash" %
(fs.format_filesize(ram), fs.format_filesize(flash)))
data.append(
"%s RAM, %s Flash"
% (fs.humanize_file_size(ram), fs.humanize_file_size(flash))
)
return data
def _get_debug_data():
debug_tools = board_config.get(
"debug", {}).get("tools") if board_config else None
debug_tools = (
board_config.get("debug", {}).get("tools") if board_config else None
)
if not debug_tools:
return None
data = [
"DEBUG:", "Current",
"(%s)" % board_config.get_debug_tool_name(
env.GetProjectOption("debug_tool"))
"DEBUG:",
"Current",
"(%s)"
% board_config.get_debug_tool_name(env.GetProjectOption("debug_tool")),
]
onboard = []
external = []
@@ -180,28 +213,28 @@ def PrintConfiguration(env): # pylint: disable=too-many-statements
def _get_packages_data():
data = []
for name, options in platform.packages.items():
if options.get("optional"):
continue
pkg_dir = platform.get_package_dir(name)
if not pkg_dir:
continue
manifest = platform.pm.load_manifest(pkg_dir)
original_version = util.get_original_version(manifest['version'])
info = "%s %s" % (manifest['name'], manifest['version'])
for item in platform.dump_used_packages():
original_version = get_original_version(item["version"])
info = "%s @ %s" % (item["name"], item["version"])
extra = []
if original_version:
extra.append(original_version)
if "__src_url" in manifest and int(ARGUMENTS.get("PIOVERBOSE", 0)):
extra.append(manifest['__src_url'])
if "src_url" in item and int(ARGUMENTS.get("PIOVERBOSE", 0)):
extra.append(item["src_url"])
if extra:
info += " (%s)" % ", ".join(extra)
data.append(info)
return ["PACKAGES:", ", ".join(data)]
if not data:
return None
return ["PACKAGES:"] + ["\n - %s" % d for d in sorted(data)]
for data in (_get_configuration_data(), _get_plaform_data(),
_get_hardware_data(), _get_debug_data(),
_get_packages_data()):
for data in (
_get_configuration_data(),
_get_plaform_data(),
_get_hardware_data(),
_get_debug_data(),
_get_packages_data(),
):
if data and len(data) > 1:
print(" ".join(data))

View File

@@ -14,28 +14,34 @@
from __future__ import absolute_import
from platformio.project.config import ProjectConfig, ProjectOptions
from platformio.compat import MISSING
from platformio.project.config import ProjectConfig
def GetProjectConfig(env):
return ProjectConfig.get_instance(env['PROJECT_CONFIG'])
return ProjectConfig.get_instance(env["PROJECT_CONFIG"])
def GetProjectOptions(env, as_dict=False):
return env.GetProjectConfig().items(env=env['PIOENV'], as_dict=as_dict)
return env.GetProjectConfig().items(env=env["PIOENV"], as_dict=as_dict)
def GetProjectOption(env, option, default=None):
return env.GetProjectConfig().get("env:" + env['PIOENV'], option, default)
def GetProjectOption(env, option, default=MISSING):
return env.GetProjectConfig().get("env:" + env["PIOENV"], option, default)
def LoadProjectOptions(env):
for option, value in env.GetProjectOptions():
option_meta = ProjectOptions.get("env." + option)
if (not option_meta or not option_meta.buildenvvar
or option_meta.buildenvvar in env):
config = env.GetProjectConfig()
section = "env:" + env["PIOENV"]
for option in config.options(section):
option_meta = config.find_option_meta(section, option)
if (
not option_meta
or not option_meta.buildenvvar
or option_meta.buildenvvar in env
):
continue
env[option_meta.buildenvvar] = value
env[option_meta.buildenvvar] = config.get(section, option)
def exists(_):

View File

@@ -0,0 +1,256 @@
# 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.
# pylint: disable=too-many-locals
from __future__ import absolute_import
import json
import sys
from os import environ, makedirs, remove
from os.path import isdir, join, splitdrive
from elftools.elf.descriptions import describe_sh_flags
from elftools.elf.elffile import ELFFile
from platformio.compat import IS_WINDOWS
from platformio.proc import exec_command
def _run_tool(cmd, env, tool_args):
sysenv = environ.copy()
sysenv["PATH"] = str(env["ENV"]["PATH"])
build_dir = env.subst("$BUILD_DIR")
if not isdir(build_dir):
makedirs(build_dir)
tmp_file = join(build_dir, "size-data-longcmd.txt")
with open(tmp_file, mode="w", encoding="utf8") as fp:
fp.write("\n".join(tool_args))
cmd.append("@" + tmp_file)
result = exec_command(cmd, env=sysenv)
remove(tmp_file)
return result
def _get_symbol_locations(env, elf_path, addrs):
if not addrs:
return {}
cmd = [env.subst("$CC").replace("-gcc", "-addr2line"), "-e", elf_path]
result = _run_tool(cmd, env, addrs)
locations = [line for line in result["out"].split("\n") if line]
assert len(addrs) == len(locations)
return dict(zip(addrs, [l.strip() for l in locations]))
def _get_demangled_names(env, mangled_names):
if not mangled_names:
return {}
result = _run_tool(
[env.subst("$CC").replace("-gcc", "-c++filt")], env, mangled_names
)
demangled_names = [line for line in result["out"].split("\n") if line]
assert len(mangled_names) == len(demangled_names)
return dict(
zip(
mangled_names,
[dn.strip().replace("::__FUNCTION__", "") for dn in demangled_names],
)
)
def _determine_section(sections, symbol_addr):
for section, info in sections.items():
if not _is_flash_section(info) and not _is_ram_section(info):
continue
if symbol_addr in range(info["start_addr"], info["start_addr"] + info["size"]):
return section
return "unknown"
def _is_ram_section(section):
return (
section.get("type", "") in ("SHT_NOBITS", "SHT_PROGBITS")
and section.get("flags", "") == "WA"
)
def _is_flash_section(section):
return section.get("type", "") == "SHT_PROGBITS" and "A" in section.get("flags", "")
def _is_valid_symbol(symbol_name, symbol_type, symbol_address):
return symbol_name and symbol_address != 0 and symbol_type != "STT_NOTYPE"
def _collect_sections_info(elffile):
sections = {}
for section in elffile.iter_sections():
if section.is_null() or section.name.startswith(".debug"):
continue
section_type = section["sh_type"]
section_flags = describe_sh_flags(section["sh_flags"])
section_size = section.data_size
sections[section.name] = {
"size": section_size,
"start_addr": section["sh_addr"],
"type": section_type,
"flags": section_flags,
}
return sections
def _collect_symbols_info(env, elffile, elf_path, sections):
symbols = []
symbol_section = elffile.get_section_by_name(".symtab")
if symbol_section.is_null():
sys.stderr.write("Couldn't find symbol table. Is ELF file stripped?")
env.Exit(1)
sysenv = environ.copy()
sysenv["PATH"] = str(env["ENV"]["PATH"])
symbol_addrs = []
mangled_names = []
for s in symbol_section.iter_symbols():
symbol_info = s.entry["st_info"]
symbol_addr = s["st_value"]
symbol_size = s["st_size"]
symbol_type = symbol_info["type"]
if not _is_valid_symbol(s.name, symbol_type, symbol_addr):
continue
symbol = {
"addr": symbol_addr,
"bind": symbol_info["bind"],
"name": s.name,
"type": symbol_type,
"size": symbol_size,
"section": _determine_section(sections, symbol_addr),
}
if s.name.startswith("_Z"):
mangled_names.append(s.name)
symbol_addrs.append(hex(symbol_addr))
symbols.append(symbol)
symbol_locations = _get_symbol_locations(env, elf_path, symbol_addrs)
demangled_names = _get_demangled_names(env, mangled_names)
for symbol in symbols:
if symbol["name"].startswith("_Z"):
symbol["demangled_name"] = demangled_names.get(symbol["name"])
location = symbol_locations.get(hex(symbol["addr"]))
if not location or "?" in location:
continue
if IS_WINDOWS:
drive, tail = splitdrive(location)
location = join(drive.upper(), tail)
symbol["file"] = location
symbol["line"] = 0
if ":" in location:
file_, line = location.rsplit(":", 1)
if line.isdigit():
symbol["file"] = file_
symbol["line"] = int(line)
return symbols
def _calculate_firmware_size(sections):
flash_size = ram_size = 0
for section_info in sections.values():
if _is_flash_section(section_info):
flash_size += section_info.get("size", 0)
if _is_ram_section(section_info):
ram_size += section_info.get("size", 0)
return ram_size, flash_size
def DumpSizeData(_, target, source, env): # pylint: disable=unused-argument
data = {"device": {}, "memory": {}, "version": 1}
board = env.BoardConfig()
if board:
data["device"] = {
"mcu": board.get("build.mcu", ""),
"cpu": board.get("build.cpu", ""),
"frequency": board.get("build.f_cpu"),
"flash": int(board.get("upload.maximum_size", 0)),
"ram": int(board.get("upload.maximum_ram_size", 0)),
}
if data["device"]["frequency"] and data["device"]["frequency"].endswith("L"):
data["device"]["frequency"] = int(data["device"]["frequency"][0:-1])
elf_path = env.subst("$PIOMAINPROG")
with open(elf_path, "rb") as fp:
elffile = ELFFile(fp)
if not elffile.has_dwarf_info():
sys.stderr.write("Elf file doesn't contain DWARF information")
env.Exit(1)
sections = _collect_sections_info(elffile)
firmware_ram, firmware_flash = _calculate_firmware_size(sections)
data["memory"]["total"] = {
"ram_size": firmware_ram,
"flash_size": firmware_flash,
"sections": sections,
}
files = {}
for symbol in _collect_symbols_info(env, elffile, elf_path, sections):
file_path = symbol.get("file") or "unknown"
if not files.get(file_path, {}):
files[file_path] = {"symbols": [], "ram_size": 0, "flash_size": 0}
symbol_size = symbol.get("size", 0)
section = sections.get(symbol.get("section", ""), {})
if _is_ram_section(section):
files[file_path]["ram_size"] += symbol_size
if _is_flash_section(section):
files[file_path]["flash_size"] += symbol_size
files[file_path]["symbols"].append(symbol)
data["memory"]["files"] = []
for k, v in files.items():
file_data = {"path": k}
file_data.update(v)
data["memory"]["files"].append(file_data)
with open(
join(env.subst("$BUILD_DIR"), "sizedata.json"), mode="w", encoding="utf8"
) as fp:
fp.write(json.dumps(data))
def exists(_):
return True
def generate(env):
env.AddMethod(DumpSizeData)
return env

View File

@@ -0,0 +1,113 @@
# 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.
from __future__ import absolute_import
import os
from SCons.Action import Action # pylint: disable=import-error
from SCons.Script import ARGUMENTS # pylint: disable=import-error
from SCons.Script import AlwaysBuild # pylint: disable=import-error
from platformio import compat, fs
def VerboseAction(_, act, actstr):
if int(ARGUMENTS.get("PIOVERBOSE", 0)):
return act
return Action(act, actstr)
def PioClean(env, clean_all=False):
def _relpath(path):
if compat.IS_WINDOWS:
prefix = os.getcwd()[:2].lower()
if (
":" not in prefix
or not path.lower().startswith(prefix)
or os.path.relpath(path).startswith("..")
):
return path
return os.path.relpath(path)
def _clean_dir(path):
clean_rel_path = _relpath(path)
print(f"Removing {clean_rel_path}")
fs.rmtree(path)
build_dir = env.subst("$BUILD_DIR")
libdeps_dir = env.subst("$PROJECT_LIBDEPS_DIR")
if os.path.isdir(build_dir):
_clean_dir(build_dir)
else:
print("Build environment is clean")
if clean_all and os.path.isdir(libdeps_dir):
_clean_dir(libdeps_dir)
print("Done cleaning")
def AddTarget( # pylint: disable=too-many-arguments
env,
name,
dependencies,
actions,
title=None,
description=None,
group="General",
always_build=True,
):
if "__PIO_TARGETS" not in env:
env["__PIO_TARGETS"] = {}
assert name not in env["__PIO_TARGETS"]
env["__PIO_TARGETS"][name] = dict(
name=name, title=title, description=description, group=group
)
target = env.Alias(name, dependencies, actions)
if always_build:
AlwaysBuild(target)
return target
def AddPlatformTarget(env, *args, **kwargs):
return env.AddTarget(group="Platform", *args, **kwargs)
def AddCustomTarget(env, *args, **kwargs):
return env.AddTarget(group="Custom", *args, **kwargs)
def DumpTargets(env):
targets = env.get("__PIO_TARGETS") or {}
# pre-fill default targets if embedded dev-platform
if env.PioPlatform().is_embedded() and not any(
t["group"] == "Platform" for t in targets.values()
):
targets["upload"] = dict(name="upload", group="Platform", title="Upload")
return list(targets.values())
def exists(_):
return True
def generate(env):
env.AddMethod(VerboseAction)
env.AddMethod(PioClean)
env.AddMethod(AddTarget)
env.AddMethod(AddPlatformTarget)
env.AddMethod(AddCustomTarget)
env.AddMethod(DumpTargets)
return env

View File

@@ -0,0 +1,63 @@
# 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.
from __future__ import absolute_import
import os
from platformio.builder.tools import platformio as piotool
from platformio.test.result import TestSuite
from platformio.test.runners.factory import TestRunnerFactory
def ConfigureTestTarget(env):
env.Append(
CPPDEFINES=["UNIT_TEST"], # deprecated, use PIO_UNIT_TESTING
PIOTEST_SRC_FILTER=[f"+<*.{ext}>" for ext in piotool.SRC_BUILD_EXT],
)
env.Prepend(CPPPATH=["$PROJECT_TEST_DIR"])
if "PIOTEST_RUNNING_NAME" in env:
test_name = env["PIOTEST_RUNNING_NAME"]
while True:
test_name = os.path.dirname(test_name) # parent dir
# skip nested tests (user's side issue?)
if not test_name or os.path.basename(test_name).startswith("test_"):
break
env.Prepend(
PIOTEST_SRC_FILTER=[
f"+<{test_name}{os.path.sep}*.{ext}>"
for ext in piotool.SRC_BUILD_EXT
],
CPPPATH=[os.path.join("$PROJECT_TEST_DIR", test_name)],
)
env.Prepend(
PIOTEST_SRC_FILTER=[f"+<$PIOTEST_RUNNING_NAME{os.path.sep}>"],
CPPPATH=[os.path.join("$PROJECT_TEST_DIR", "$PIOTEST_RUNNING_NAME")],
)
test_runner = TestRunnerFactory.new(
TestSuite(env["PIOENV"], env.get("PIOTEST_RUNNING_NAME", "*")),
env.GetProjectConfig(),
)
test_runner.configure_build_env(env)
def generate(env):
env.AddMethod(ConfigureTestTarget)
def exists(_):
return True

View File

@@ -12,25 +12,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# pylint: disable=unused-argument
from __future__ import absolute_import
import os
import re
import sys
from fnmatch import fnmatch
from os import environ
from os.path import isfile, join
from shutil import copyfile
from time import sleep
from SCons.Script import ARGUMENTS # pylint: disable=import-error
from serial import Serial, SerialException
from platformio import exception, fs, util
from platformio.compat import WINDOWS
from platformio import exception, fs
from platformio.device.finder import find_mbed_disk, find_serial_port, is_pattern_port
from platformio.device.list.util import list_serial_ports
from platformio.proc import exec_command
# pylint: disable=unused-argument
def FlushSerialBuffer(env, port):
s = Serial(env.subst(port))
@@ -60,9 +59,9 @@ def WaitForNewSerialPort(env, before):
prev_port = env.subst("$UPLOAD_PORT")
new_port = None
elapsed = 0
before = [p['port'] for p in before]
before = [p["port"] for p in before]
while elapsed < 5 and new_port is None:
now = [p['port'] for p in util.get_serial_ports()]
now = [p["port"] for p in list_serial_ports()]
for p in now:
if p not in before:
new_port = p
@@ -84,10 +83,12 @@ def WaitForNewSerialPort(env, before):
sleep(1)
if not new_port:
sys.stderr.write("Error: Couldn't find a board on the selected port. "
"Check that you have the correct port selected. "
"If it is correct, try pressing the board's reset "
"button after initiating the upload.\n")
sys.stderr.write(
"Error: Couldn't find a board on the selected port. "
"Check that you have the correct port selected. "
"If it is correct, try pressing the board's reset "
"button after initiating the upload.\n"
)
env.Exit(1)
return new_port
@@ -95,71 +96,30 @@ def WaitForNewSerialPort(env, before):
def AutodetectUploadPort(*args, **kwargs):
env = args[0]
def _get_pattern():
if "UPLOAD_PORT" not in env:
return None
if set(["*", "?", "[", "]"]) & set(env['UPLOAD_PORT']):
return env['UPLOAD_PORT']
return None
def _is_match_pattern(port):
pattern = _get_pattern()
if not pattern:
return True
return fnmatch(port, pattern)
def _look_for_mbed_disk():
msdlabels = ("mbed", "nucleo", "frdm", "microbit")
for item in util.get_logical_devices():
if item['path'].startswith("/net") or not _is_match_pattern(
item['path']):
continue
mbed_pages = [
join(item['path'], n) for n in ("mbed.htm", "mbed.html")
]
if any(isfile(p) for p in mbed_pages):
return item['path']
if item['name'] \
and any(l in item['name'].lower() for l in msdlabels):
return item['path']
return None
def _look_for_serial_port():
port = None
board_hwids = []
upload_protocol = env.subst("$UPLOAD_PROTOCOL")
if "BOARD" in env and "build.hwids" in env.BoardConfig():
board_hwids = env.BoardConfig().get("build.hwids")
for item in util.get_serial_ports(filter_hwid=True):
if not _is_match_pattern(item['port']):
continue
port = item['port']
if upload_protocol.startswith("blackmagic"):
if WINDOWS and port.startswith("COM") and len(port) > 4:
port = "\\\\.\\%s" % port
if "GDB" in item['description']:
return port
for hwid in board_hwids:
hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "")
if hwid_str in item['hwid']:
return port
return port
if "UPLOAD_PORT" in env and not _get_pattern():
print(env.subst("Use manually specified: $UPLOAD_PORT"))
initial_port = env.subst("$UPLOAD_PORT")
upload_protocol = env.subst("$UPLOAD_PROTOCOL")
if initial_port and not is_pattern_port(initial_port):
print(env.subst("Using manually specified: $UPLOAD_PORT"))
return
if (env.subst("$UPLOAD_PROTOCOL") == "mbed"
or ("mbed" in env.subst("$PIOFRAMEWORK")
and not env.subst("$UPLOAD_PROTOCOL"))):
env.Replace(UPLOAD_PORT=_look_for_mbed_disk())
if upload_protocol == "mbed" or (
"mbed" in env.subst("$PIOFRAMEWORK") and not upload_protocol
):
env.Replace(UPLOAD_PORT=find_mbed_disk(initial_port))
else:
try:
fs.ensure_udev_rules()
except exception.InvalidUdevRules as e:
sys.stderr.write("\n%s\n\n" % e)
env.Replace(UPLOAD_PORT=_look_for_serial_port())
except exception.InvalidUdevRules as exc:
sys.stderr.write("\n%s\n\n" % exc)
env.Replace(
UPLOAD_PORT=find_serial_port(
initial_port=initial_port,
board_config=env.BoardConfig() if "BOARD" in env else None,
upload_protocol=upload_protocol,
prefer_gdb_port="blackmagic" in upload_protocol,
verbose=int(ARGUMENTS.get("PIOVERBOSE", 0)),
)
)
if env.subst("$UPLOAD_PORT"):
print(env.subst("Auto-detected: $UPLOAD_PORT"))
@@ -168,7 +128,8 @@ def AutodetectUploadPort(*args, **kwargs):
"Error: Please specify `upload_port` for environment or use "
"global `--upload-port` option.\n"
"For some development platforms it can be a USB flash "
"drive (i.e. /media/<user>/<device name>)\n")
"drive (i.e. /media/<user>/<device name>)\n"
)
env.Exit(1)
@@ -176,19 +137,22 @@ def UploadToDisk(_, target, source, env):
assert "UPLOAD_PORT" in env
progname = env.subst("$PROGNAME")
for ext in ("bin", "hex"):
fpath = join(env.subst("$BUILD_DIR"), "%s.%s" % (progname, ext))
if not isfile(fpath):
fpath = os.path.join(env.subst("$BUILD_DIR"), "%s.%s" % (progname, ext))
if not os.path.isfile(fpath):
continue
copyfile(fpath,
join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)))
print("Firmware has been successfully uploaded.\n"
"(Some boards may require manual hard reset)")
copyfile(
fpath, os.path.join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext))
)
print(
"Firmware has been successfully uploaded.\n"
"(Some boards may require manual hard reset)"
)
def CheckUploadSize(_, target, source, env):
check_conditions = [
env.get("BOARD"),
env.get("SIZETOOL") or env.get("SIZECHECKCMD")
env.get("SIZETOOL") or env.get("SIZECHECKCMD"),
]
if not all(check_conditions):
return
@@ -198,9 +162,11 @@ def CheckUploadSize(_, target, source, env):
return
def _configure_defaults():
env.Replace(SIZECHECKCMD="$SIZETOOL -B -d $SOURCES",
SIZEPROGREGEXP=r"^(\d+)\s+(\d+)\s+\d+\s",
SIZEDATAREGEXP=r"^\d+\s+(\d+)\s+(\d+)\s+\d+")
env.Replace(
SIZECHECKCMD="$SIZETOOL -B -d $SOURCES",
SIZEPROGREGEXP=r"^(\d+)\s+(\d+)\s+\d+\s",
SIZEDATAREGEXP=r"^\d+\s+(\d+)\s+(\d+)\s+\d+",
)
def _get_size_output():
cmd = env.get("SIZECHECKCMD")
@@ -209,12 +175,12 @@ def CheckUploadSize(_, target, source, env):
if not isinstance(cmd, list):
cmd = cmd.split()
cmd = [arg.replace("$SOURCES", str(source[0])) for arg in cmd if arg]
sysenv = environ.copy()
sysenv['PATH'] = str(env['ENV']['PATH'])
sysenv = os.environ.copy()
sysenv["PATH"] = str(env["ENV"]["PATH"])
result = exec_command(env.subst(cmd), env=sysenv)
if result['returncode'] != 0:
if result["returncode"] != 0:
return None
return result['out'].strip()
return result["out"].strip()
def _calculate_size(output, pattern):
if not output or not pattern:
@@ -234,11 +200,12 @@ def CheckUploadSize(_, target, source, env):
def _format_availale_bytes(value, total):
percent_raw = float(value) / float(total)
blocks_per_progress = 10
used_blocks = int(round(blocks_per_progress * percent_raw))
if used_blocks > blocks_per_progress:
used_blocks = blocks_per_progress
used_blocks = min(
int(round(blocks_per_progress * percent_raw)), blocks_per_progress
)
return "[{:{}}] {: 6.1%} (used {:d} bytes from {:d} bytes)".format(
"=" * used_blocks, blocks_per_progress, percent_raw, value, total)
"=" * used_blocks, blocks_per_progress, percent_raw, value, total
)
if not env.get("SIZECHECKCMD") and not env.get("SIZEPROGREGEXP"):
_configure_defaults()
@@ -246,12 +213,11 @@ def CheckUploadSize(_, target, source, env):
program_size = _calculate_size(output, env.get("SIZEPROGREGEXP"))
data_size = _calculate_size(output, env.get("SIZEDATAREGEXP"))
print("Memory Usage -> http://bit.ly/pio-memory-usage")
print('Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"')
if data_max_size and data_size > -1:
print("DATA: %s" % _format_availale_bytes(data_size, data_max_size))
print("RAM: %s" % _format_availale_bytes(data_size, data_max_size))
if program_size > -1:
print("PROGRAM: %s" %
_format_availale_bytes(program_size, program_max_size))
print("Flash: %s" % _format_availale_bytes(program_size, program_max_size))
if int(ARGUMENTS.get("PIOVERBOSE", 0)):
print(output)
@@ -262,9 +228,10 @@ def CheckUploadSize(_, target, source, env):
# "than maximum allowed (%s bytes)\n" % (data_size, data_max_size))
# env.Exit(1)
if program_size > program_max_size:
sys.stderr.write("Error: The program size (%d bytes) is greater "
"than maximum allowed (%s bytes)\n" %
(program_size, program_max_size))
sys.stderr.write(
"Error: The program size (%d bytes) is greater "
"than maximum allowed (%s bytes)\n" % (program_size, program_max_size)
)
env.Exit(1)
@@ -272,8 +239,7 @@ def PrintUploadInfo(env):
configured = env.subst("$UPLOAD_PROTOCOL")
available = [configured] if configured else []
if "BOARD" in env:
available.extend(env.BoardConfig().get("upload",
{}).get("protocols", []))
available.extend(env.BoardConfig().get("upload", {}).get("protocols", []))
if available:
print("AVAILABLE: %s" % ", ".join(sorted(set(available))))
if configured:

View File

@@ -1,92 +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.
from __future__ import absolute_import
from hashlib import md5
from os import makedirs
from os.path import isdir, isfile, join
from platformio.compat import WINDOWS, hashlib_encode_data
# Windows CLI has limit with command length to 8192
# Leave 2000 chars for flags and other options
MAX_SOURCES_LENGTH = 6000
def long_sources_hook(env, sources):
_sources = str(sources).replace("\\", "/")
if len(str(_sources)) < MAX_SOURCES_LENGTH:
return sources
# fix space in paths
data = []
for line in _sources.split(".o "):
line = line.strip()
if not line.endswith(".o"):
line += ".o"
data.append('"%s"' % line)
return '@"%s"' % _file_long_data(env, " ".join(data))
def long_incflags_hook(env, incflags):
_incflags = env.subst(incflags).replace("\\", "/")
if len(_incflags) < MAX_SOURCES_LENGTH:
return incflags
# fix space in paths
data = []
for line in _incflags.split(" -I"):
line = line.strip()
if not line.startswith("-I"):
line = "-I" + line
data.append('-I"%s"' % line[2:])
return '@"%s"' % _file_long_data(env, " ".join(data))
def _file_long_data(env, data):
build_dir = env.subst("$BUILD_DIR")
if not isdir(build_dir):
makedirs(build_dir)
tmp_file = join(build_dir,
"longcmd-%s" % md5(hashlib_encode_data(data)).hexdigest())
if isfile(tmp_file):
return tmp_file
with open(tmp_file, "w") as fp:
fp.write(data)
return tmp_file
def exists(_):
return True
def generate(env):
if not WINDOWS:
return None
env.Replace(_long_sources_hook=long_sources_hook)
env.Replace(_long_incflags_hook=long_incflags_hook)
coms = {}
for key in ("ARCOM", "LINKCOM"):
coms[key] = env.get(key, "").replace(
"$SOURCES", "${_long_sources_hook(__env__, SOURCES)}")
for key in ("_CCCOMCOM", "ASPPCOM"):
coms[key] = env.get(key, "").replace(
"$_CPPINCFLAGS", "${_long_incflags_hook(__env__, _CPPINCFLAGS)}")
env.Replace(**coms)
return env

View File

@@ -14,24 +14,26 @@
from __future__ import absolute_import
import fnmatch
import os
import sys
from os.path import basename, dirname, isdir, join, realpath
from SCons import Builder, Util # pylint: disable=import-error
from SCons.Node import FS # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from SCons.Script import AlwaysBuild # pylint: disable=import-error
from SCons.Script import DefaultEnvironment # pylint: disable=import-error
from SCons.Script import Export # pylint: disable=import-error
from SCons.Script import SConscript # pylint: disable=import-error
from platformio import fs
from platformio.compat import string_types
from platformio.util import pioversion_to_intstr
from platformio import __version__, fs
from platformio.compat import IS_MACOS, string_types
from platformio.package.version import pepver_to_semver
SRC_HEADER_EXT = ["h", "hpp"]
SRC_C_EXT = ["c", "cc", "cpp"]
SRC_BUILD_EXT = SRC_C_EXT + ["S", "spp", "SPP", "sx", "s", "asm", "ASM"]
SRC_ASM_EXT = ["S", "spp", "SPP", "sx", "s", "asm", "ASM"]
SRC_C_EXT = ["c"]
SRC_CXX_EXT = ["cc", "cpp", "cxx", "c++"]
SRC_BUILD_EXT = SRC_C_EXT + SRC_CXX_EXT + SRC_ASM_EXT
SRC_FILTER_DEFAULT = ["+<*>", "-<.git%s>" % os.sep, "-<.svn%s>" % os.sep]
@@ -43,62 +45,72 @@ def scons_patched_match_splitext(path, suffixes=None):
return tokens
def _build_project_deps(env):
project_lib_builder = env.ConfigureProjectLibBuilder()
# prepend project libs to the beginning of list
env.Prepend(LIBS=project_lib_builder.build())
# prepend extra linker related options from libs
env.PrependUnique(
**{
key: project_lib_builder.env.get(key)
for key in ("LIBS", "LIBPATH", "LINKFLAGS")
if project_lib_builder.env.get(key)
})
projenv = env.Clone()
# CPPPATH from dependencies
projenv.PrependUnique(CPPPATH=project_lib_builder.env.get("CPPPATH"))
# extra build flags from `platformio.ini`
projenv.ProcessFlags(env.get("SRC_BUILD_FLAGS"))
is_test = "__test" in COMMAND_LINE_TARGETS
if is_test:
projenv.BuildSources("$BUILDTEST_DIR", "$PROJECTTEST_DIR",
"$PIOTEST_SRC_FILTER")
if not is_test or env.GetProjectOption("test_build_project_src", False):
projenv.BuildSources("$BUILDSRC_DIR", "$PROJECTSRC_DIR",
env.get("SRC_FILTER"))
if not env.get("PIOBUILDFILES") and not COMMAND_LINE_TARGETS:
sys.stderr.write(
"Error: Nothing to build. Please put your source code files "
"to '%s' folder\n" % env.subst("$PROJECTSRC_DIR"))
env.Exit(1)
Export("projenv")
def GetBuildType(env):
modes = []
if (
set(["__debug", "sizedata"]) # sizedata = for memory inspection
& set(COMMAND_LINE_TARGETS)
or env.GetProjectOption("build_type") == "debug"
):
modes.append("debug")
if "__test" in COMMAND_LINE_TARGETS or env.GetProjectOption("build_type") == "test":
modes.append("test")
return "+".join(modes or ["release"])
def BuildProgram(env):
env.ProcessProgramDeps()
env.ProcessProjectDeps()
# append into the beginning a main LD script
if env.get("LDSCRIPT_PATH") and not any("-Wl,-T" in f for f in env["LINKFLAGS"]):
env.Prepend(LINKFLAGS=["-T", env.subst("$LDSCRIPT_PATH")])
# enable "cyclic reference" for linker
if (
env.get("LIBS")
and env.GetCompilerType() == "gcc"
and (env.PioPlatform().is_embedded() or not IS_MACOS)
):
env.Prepend(_LIBFLAGS="-Wl,--start-group ")
env.Append(_LIBFLAGS=" -Wl,--end-group")
program = env.Program(env.subst("$PROGPATH"), env["PIOBUILDFILES"])
env.Replace(PIOMAINPROG=program)
AlwaysBuild(
env.Alias(
"checkprogsize",
program,
env.VerboseAction(env.CheckUploadSize, "Checking size $PIOMAINPROG"),
)
)
print("Building in %s mode" % env.GetBuildType())
return program
def ProcessProgramDeps(env):
def _append_pio_macros():
env.AppendUnique(CPPDEFINES=[(
"PLATFORMIO",
int("{0:02d}{1:02d}{2:02d}".format(*pioversion_to_intstr())))])
core_version = pepver_to_semver(__version__)
env.AppendUnique(
CPPDEFINES=[
(
"PLATFORMIO",
int(
"{0:02d}{1:02d}{2:02d}".format(
core_version.major, core_version.minor, core_version.patch
)
),
)
]
)
_append_pio_macros()
env.PrintConfiguration()
# fix ASM handling under non case-sensitive OS
if not Util.case_sensitive_suffixes(".s", ".S"):
env.Replace(AS="$CC", ASCOM="$ASPPCOM")
if ("debug" in COMMAND_LINE_TARGETS
or env.GetProjectOption("build_type") == "debug"):
env.ProcessDebug()
# process extra flags from board
if "BOARD" in env and "build.extra_flags" in env.BoardConfig():
env.ProcessFlags(env.BoardConfig().get("build.extra_flags"))
@@ -109,39 +121,57 @@ def BuildProgram(env):
# process framework scripts
env.BuildFrameworks(env.get("PIOFRAMEWORK"))
# restore PIO macros if it was deleted by framework
_append_pio_macros()
if "debug" in env.GetBuildType():
env.ConfigureDebugTarget()
# remove specified flags
env.ProcessUnFlags(env.get("BUILD_UNFLAGS"))
if "__test" in COMMAND_LINE_TARGETS:
env.ProcessTest()
if "compiledb" in COMMAND_LINE_TARGETS and env.get(
"COMPILATIONDB_INCLUDE_TOOLCHAIN"
):
for scope, includes in env.DumpIntegrationIncludes().items():
if scope in ("toolchain",):
env.Append(CPPPATH=includes)
# build project with dependencies
_build_project_deps(env)
# append into the beginning a main LD script
if (env.get("LDSCRIPT_PATH")
and not any("-Wl,-T" in f for f in env['LINKFLAGS'])):
env.Prepend(LINKFLAGS=["-T", "$LDSCRIPT_PATH"])
def ProcessProjectDeps(env):
plb = env.ConfigureProjectLibBuilder()
# enable "cyclic reference" for linker
if env.get("LIBS") and env.GetCompilerType() == "gcc":
env.Prepend(_LIBFLAGS="-Wl,--start-group ")
env.Append(_LIBFLAGS=" -Wl,--end-group")
# prepend project libs to the beginning of list
env.Prepend(LIBS=plb.build())
# prepend extra linker related options from libs
env.PrependUnique(
**{
key: plb.env.get(key)
for key in ("LIBS", "LIBPATH", "LINKFLAGS")
if plb.env.get(key)
}
)
program = env.Program(join("$BUILD_DIR", env.subst("$PROGNAME")),
env['PIOBUILDFILES'])
env.Replace(PIOMAINPROG=program)
if "test" in env.GetBuildType():
build_files_before_nums = len(env.get("PIOBUILDFILES", []))
plb.env.BuildSources(
"$BUILD_TEST_DIR", "$PROJECT_TEST_DIR", "$PIOTEST_SRC_FILTER"
)
if len(env.get("PIOBUILDFILES", [])) - build_files_before_nums < 1:
sys.stderr.write(
"Error: Nothing to build. Please put your test suites "
"to the '%s' folder\n" % env.subst("$PROJECT_TEST_DIR")
)
env.Exit(1)
AlwaysBuild(
env.Alias(
"checkprogsize", program,
env.VerboseAction(env.CheckUploadSize,
"Checking size $PIOMAINPROG")))
if "test" not in env.GetBuildType() or env.GetProjectOption("test_build_src"):
plb.env.BuildSources(
"$BUILD_SRC_DIR", "$PROJECT_SRC_DIR", env.get("SRC_FILTER")
)
return program
if not env.get("PIOBUILDFILES") and not COMMAND_LINE_TARGETS:
sys.stderr.write(
"Error: Nothing to build. Please put your source code files "
"to the '%s' folder\n" % env.subst("$PROJECT_SRC_DIR")
)
env.Exit(1)
def ParseFlagsExtended(env, flags): # pylint: disable=too-many-branches
@@ -155,30 +185,30 @@ def ParseFlagsExtended(env, flags): # pylint: disable=too-many-branches
result[key].extend(value)
cppdefines = []
for item in result['CPPDEFINES']:
for item in result["CPPDEFINES"]:
if not Util.is_Sequence(item):
cppdefines.append(item)
continue
name, value = item[:2]
if '\"' in value:
value = value.replace('\"', '\\\"')
if '"' in value:
value = value.replace('"', '\\"')
elif value.isdigit():
value = int(value)
elif value.replace(".", "", 1).isdigit():
value = float(value)
cppdefines.append((name, value))
result['CPPDEFINES'] = cppdefines
result["CPPDEFINES"] = cppdefines
# fix relative CPPPATH & LIBPATH
for k in ("CPPPATH", "LIBPATH"):
for i, p in enumerate(result.get(k, [])):
if isdir(p):
result[k][i] = realpath(p)
if os.path.isdir(p):
result[k][i] = os.path.abspath(p)
# fix relative path for "-include"
for i, f in enumerate(result.get("CCFLAGS", [])):
if isinstance(f, tuple) and f[0] == "-include":
result['CCFLAGS'][i] = (f[0], env.File(realpath(f[1].get_path())))
result["CCFLAGS"][i] = (f[0], env.File(os.path.abspath(f[1].get_path())))
return result
@@ -191,14 +221,15 @@ def ProcessFlags(env, flags): # pylint: disable=too-many-branches
# Cancel any previous definition of name, either built in or
# provided with a -U option // Issue #191
undefines = [
u for u in env.get("CCFLAGS", [])
u
for u in env.get("CCFLAGS", [])
if isinstance(u, string_types) and u.startswith("-U")
]
if undefines:
for undef in undefines:
env['CCFLAGS'].remove(undef)
if undef[2:] in env['CPPDEFINES']:
env['CPPDEFINES'].remove(undef[2:])
env["CCFLAGS"].remove(undef)
if undef[2:] in env["CPPDEFINES"]:
env["CPPDEFINES"].remove(undef[2:])
env.Append(_CPPDEFFLAGS=" %s" % " ".join(undefines))
@@ -206,40 +237,35 @@ def ProcessUnFlags(env, flags):
if not flags:
return
parsed = env.ParseFlagsExtended(flags)
# get all flags and copy them to each "*FLAGS" variable
all_flags = []
for key, unflags in parsed.items():
if key.endswith("FLAGS"):
all_flags.extend(unflags)
for key, unflags in parsed.items():
if key.endswith("FLAGS"):
parsed[key].extend(all_flags)
for key, unflags in parsed.items():
for unflag in unflags:
for current in env.get(key, []):
conditions = [
unflag == current,
isinstance(current, (tuple, list))
and unflag[0] == current[0]
]
if any(conditions):
env[key].remove(current)
unflag_scopes = tuple(set(["ASPPFLAGS"] + list(parsed.keys())))
for scope in unflag_scopes:
for unflags in parsed.values():
for unflag in unflags:
for current in env.get(scope, []):
conditions = [
unflag == current,
not isinstance(unflag, (tuple, list))
and isinstance(current, (tuple, list))
and unflag == current[0],
]
if any(conditions):
env[scope].remove(current)
def MatchSourceFiles(env, src_dir, src_filter=None):
def StringifyMacro(env, value): # pylint: disable=unused-argument
return '\\"%s\\"' % value.replace('"', '\\\\\\"')
def MatchSourceFiles(env, src_dir, src_filter=None, src_exts=None):
src_filter = env.subst(src_filter) if src_filter else None
src_filter = src_filter or SRC_FILTER_DEFAULT
return fs.match_src_files(env.subst(src_dir), src_filter,
SRC_BUILD_EXT + SRC_HEADER_EXT)
src_exts = src_exts or (SRC_BUILD_EXT + SRC_HEADER_EXT)
return fs.match_src_files(env.subst(src_dir), src_filter, src_exts)
def CollectBuildFiles(env,
variant_dir,
src_dir,
src_filter=None,
duplicate=False):
def CollectBuildFiles(
env, variant_dir, src_dir, src_filter=None, duplicate=False
): # pylint: disable=too-many-locals
sources = []
variants = []
@@ -247,19 +273,36 @@ def CollectBuildFiles(env,
if src_dir.endswith(os.sep):
src_dir = src_dir[:-1]
for item in env.MatchSourceFiles(src_dir, src_filter):
_reldir = dirname(item)
_src_dir = join(src_dir, _reldir) if _reldir else src_dir
_var_dir = join(variant_dir, _reldir) if _reldir else variant_dir
for item in env.MatchSourceFiles(src_dir, src_filter, SRC_BUILD_EXT):
_reldir = os.path.dirname(item)
_src_dir = os.path.join(src_dir, _reldir) if _reldir else src_dir
_var_dir = os.path.join(variant_dir, _reldir) if _reldir else variant_dir
if _var_dir not in variants:
variants.append(_var_dir)
env.VariantDir(_var_dir, _src_dir, duplicate)
if fs.path_endswith_ext(item, SRC_BUILD_EXT):
sources.append(env.File(join(_var_dir, basename(item))))
sources.append(env.File(os.path.join(_var_dir, os.path.basename(item))))
return sources
middlewares = env.get("__PIO_BUILD_MIDDLEWARES")
if not middlewares:
return sources
new_sources = []
for node in sources:
new_node = node
for callback, pattern in middlewares:
if pattern and not fnmatch.fnmatch(node.srcnode().get_path(), pattern):
continue
new_node = callback(new_node)
if new_node:
new_sources.append(new_node)
return new_sources
def AddBuildMiddleware(env, callback, pattern=None):
env.Append(__PIO_BUILD_MIDDLEWARES=[(callback, pattern)])
def BuildFrameworks(env, frameworks):
@@ -267,45 +310,40 @@ def BuildFrameworks(env, frameworks):
return
if "BOARD" not in env:
sys.stderr.write("Please specify `board` in `platformio.ini` to use "
"with '%s' framework\n" % ", ".join(frameworks))
sys.stderr.write(
"Please specify `board` in `platformio.ini` to use "
"with '%s' framework\n" % ", ".join(frameworks)
)
env.Exit(1)
board_frameworks = env.BoardConfig().get("frameworks", [])
if frameworks == ["platformio"]:
if board_frameworks:
frameworks.insert(0, board_frameworks[0])
else:
sys.stderr.write(
"Error: Please specify `board` in `platformio.ini`\n")
env.Exit(1)
for f in frameworks:
if f == "arduino":
# Arduino IDE appends .o the end of filename
supported_frameworks = env.BoardConfig().get("frameworks", [])
for name in frameworks:
if name == "arduino":
# Arduino IDE appends .o to the end of filename
Builder.match_splitext = scons_patched_match_splitext
if "nobuild" not in COMMAND_LINE_TARGETS:
env.ConvertInoToCpp()
if f in board_frameworks:
SConscript(env.GetFrameworkScript(f), exports="env")
if name in supported_frameworks:
SConscript(env.GetFrameworkScript(name), exports="env")
else:
sys.stderr.write(
"Error: This board doesn't support %s framework!\n" % f)
sys.stderr.write("Error: This board doesn't support %s framework!\n" % name)
env.Exit(1)
def BuildLibrary(env, variant_dir, src_dir, src_filter=None):
def BuildLibrary(env, variant_dir, src_dir, src_filter=None, nodes=None):
env.ProcessUnFlags(env.get("BUILD_UNFLAGS"))
return env.StaticLibrary(
env.subst(variant_dir),
env.CollectBuildFiles(variant_dir, src_dir, src_filter))
nodes = nodes or env.CollectBuildFiles(variant_dir, src_dir, src_filter)
return env.StaticLibrary(env.subst(variant_dir), nodes)
def BuildSources(env, variant_dir, src_dir, src_filter=None):
nodes = env.CollectBuildFiles(variant_dir, src_dir, src_filter)
DefaultEnvironment().Append(
PIOBUILDFILES=[env.Object(node) for node in nodes])
PIOBUILDFILES=[
env.Object(node) if isinstance(node, FS.File) else node for node in nodes
]
)
def exists(_):
@@ -313,12 +351,17 @@ def exists(_):
def generate(env):
env.AddMethod(GetBuildType)
env.AddMethod(BuildProgram)
env.AddMethod(ProcessProgramDeps)
env.AddMethod(ProcessProjectDeps)
env.AddMethod(ParseFlagsExtended)
env.AddMethod(ProcessFlags)
env.AddMethod(ProcessUnFlags)
env.AddMethod(StringifyMacro)
env.AddMethod(MatchSourceFiles)
env.AddMethod(CollectBuildFiles)
env.AddMethod(AddBuildMiddleware)
env.AddMethod(BuildFrameworks)
env.AddMethod(BuildLibrary)
env.AddMethod(BuildSources)

165
platformio/cache.py Normal file
View File

@@ -0,0 +1,165 @@
# 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.
import codecs
import hashlib
import os
from time import time
from platformio import app, fs
from platformio.compat import hashlib_encode_data
from platformio.package.lockfile import LockFile
from platformio.project.helpers import get_project_cache_dir
class ContentCache:
def __init__(self, namespace=None):
self.cache_dir = os.path.join(get_project_cache_dir(), namespace or "content")
self._db_path = os.path.join(self.cache_dir, "db.data")
self._lockfile = None
if not os.path.isdir(self.cache_dir):
os.makedirs(self.cache_dir)
def __enter__(self):
# cleanup obsolete items
self.delete()
return self
def __exit__(self, type_, value, traceback):
pass
@staticmethod
def key_from_args(*args):
h = hashlib.sha1()
for arg in args:
if arg:
h.update(hashlib_encode_data(arg))
return h.hexdigest()
def get_cache_path(self, key):
assert "/" not in key and "\\" not in key
key = str(key)
assert len(key) > 3
return os.path.join(self.cache_dir, key)
def get(self, key):
cache_path = self.get_cache_path(key)
if not os.path.isfile(cache_path):
return None
with codecs.open(cache_path, "rb", encoding="utf8") as fp:
return fp.read()
def set(self, key, data, valid):
if not app.get_setting("enable_cache"):
return False
cache_path = self.get_cache_path(key)
if os.path.isfile(cache_path):
self.delete(key)
if not data:
return False
tdmap = {"s": 1, "m": 60, "h": 3600, "d": 86400}
assert valid.endswith(tuple(tdmap))
expire_time = int(time() + tdmap[valid[-1]] * int(valid[:-1]))
if not self._lock_dbindex():
return False
if not os.path.isdir(os.path.dirname(cache_path)):
os.makedirs(os.path.dirname(cache_path))
try:
with codecs.open(cache_path, mode="wb", encoding="utf8") as fp:
fp.write(data)
with open(self._db_path, mode="a", encoding="utf8") as fp:
fp.write("%s=%s\n" % (str(expire_time), os.path.basename(cache_path)))
except UnicodeError:
if os.path.isfile(cache_path):
try:
os.remove(cache_path)
except OSError:
pass
return self._unlock_dbindex()
def delete(self, keys=None):
"""Keys=None, delete expired items"""
if not os.path.isfile(self._db_path):
return None
if not keys:
keys = []
if not isinstance(keys, list):
keys = [keys]
paths_for_delete = [self.get_cache_path(k) for k in keys]
found = False
newlines = []
with open(self._db_path, encoding="utf8") as fp:
for line in fp.readlines():
line = line.strip()
if "=" not in line:
continue
expire, fname = line.split("=")
path = os.path.join(self.cache_dir, fname)
try:
if (
time() < int(expire)
and os.path.isfile(path)
and path not in paths_for_delete
):
newlines.append(line)
continue
except ValueError:
pass
found = True
if os.path.isfile(path):
try:
os.remove(path)
if not os.listdir(os.path.dirname(path)):
fs.rmtree(os.path.dirname(path))
except OSError:
pass
if found and self._lock_dbindex():
with open(self._db_path, mode="w", encoding="utf8") as fp:
fp.write("\n".join(newlines) + "\n")
self._unlock_dbindex()
return True
def clean(self):
if not os.path.isdir(self.cache_dir):
return
fs.rmtree(self.cache_dir)
def _lock_dbindex(self):
self._lockfile = LockFile(self.cache_dir)
try:
self._lockfile.acquire()
except: # pylint: disable=bare-except
return False
return True
def _unlock_dbindex(self):
if self._lockfile:
self._lockfile.release()
return True
#
# Helpers
#
def cleanup_content_cache(namespace=None):
with ContentCache(namespace) as cc:
cc.clean()

View File

@@ -11,5 +11,3 @@
# 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.
from platformio.commands.home.command import cli

326
platformio/check/cli.py Normal file
View File

@@ -0,0 +1,326 @@
# 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.
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
# pylint: disable=redefined-builtin,too-many-statements
import json
import os
import shutil
from collections import Counter
from os.path import dirname, isfile
from time import time
import click
from tabulate import tabulate
from platformio import app, exception, fs, util
from platformio.check.defect import DefectItem
from platformio.check.tools import CheckToolFactory
from platformio.project.config import ProjectConfig
from platformio.project.helpers import find_project_dir_above, get_project_dir
@click.command("check", short_help="Static Code Analysis")
@click.option("-e", "--environment", multiple=True)
@click.option(
"-d",
"--project-dir",
default=os.getcwd,
type=click.Path(
exists=True, file_okay=True, dir_okay=True, writable=True, resolve_path=True
),
)
@click.option(
"-c",
"--project-conf",
type=click.Path(
exists=True, file_okay=True, dir_okay=False, readable=True, resolve_path=True
),
)
@click.option("--pattern", multiple=True)
@click.option("--flags", multiple=True)
@click.option(
"--severity", multiple=True, type=click.Choice(DefectItem.SEVERITY_LABELS.values())
)
@click.option("-s", "--silent", is_flag=True)
@click.option("-v", "--verbose", is_flag=True)
@click.option("--json-output", is_flag=True)
@click.option(
"--fail-on-defect",
multiple=True,
type=click.Choice(DefectItem.SEVERITY_LABELS.values()),
)
@click.option("--skip-packages", is_flag=True)
def cli(
environment,
project_dir,
project_conf,
pattern,
flags,
severity,
silent,
verbose,
json_output,
fail_on_defect,
skip_packages,
):
app.set_session_var("custom_project_conf", project_conf)
# find project directory on upper level
if isfile(project_dir):
project_dir = find_project_dir_above(project_dir)
results = []
with fs.cd(project_dir):
config = ProjectConfig.get_instance(project_conf)
config.validate(environment)
default_envs = config.default_envs()
for envname in config.envs():
skipenv = any(
[
environment and envname not in environment,
not environment and default_envs and envname not in default_envs,
]
)
env_options = config.items(env=envname, as_dict=True)
env_dump = []
for k, v in env_options.items():
if k not in ("platform", "framework", "board"):
continue
env_dump.append(
"%s: %s" % (k, ", ".join(v) if isinstance(v, list) else v)
)
default_patterns = [
config.get("platformio", "src_dir"),
config.get("platformio", "include_dir"),
]
tool_options = dict(
verbose=verbose,
silent=silent,
patterns=pattern or env_options.get("check_patterns", default_patterns),
flags=flags or env_options.get("check_flags"),
severity=[DefectItem.SEVERITY_LABELS[DefectItem.SEVERITY_HIGH]]
if silent
else severity or config.get("env:" + envname, "check_severity"),
skip_packages=skip_packages or env_options.get("check_skip_packages"),
platform_packages=env_options.get("platform_packages"),
)
for tool in config.get("env:" + envname, "check_tool"):
if skipenv:
results.append({"env": envname, "tool": tool})
continue
if not silent and not json_output:
print_processing_header(tool, envname, env_dump)
ct = CheckToolFactory.new(
tool, project_dir, config, envname, tool_options
)
result = {"env": envname, "tool": tool, "duration": time()}
rc = ct.check(
on_defect_callback=None
if (json_output or verbose)
else lambda defect: click.echo(repr(defect))
)
result["defects"] = ct.get_defects()
result["duration"] = time() - result["duration"]
result["succeeded"] = rc == 0
if fail_on_defect:
result["succeeded"] = rc == 0 and not any(
DefectItem.SEVERITY_LABELS[d.severity] in fail_on_defect
for d in result["defects"]
)
result["stats"] = collect_component_stats(result)
results.append(result)
if verbose:
click.echo("\n".join(repr(d) for d in result["defects"]))
if not json_output and not silent:
if rc != 0:
click.echo(
"Error: %s failed to perform check! Please "
"examine tool output in verbose mode." % tool
)
elif not result["defects"]:
click.echo("No defects found")
print_processing_footer(result)
if json_output:
click.echo(json.dumps(results_to_json(results)))
elif not silent:
print_check_summary(results, verbose=verbose)
# Reset custom project config
app.set_session_var("custom_project_conf", None)
command_failed = any(r.get("succeeded") is False for r in results)
if command_failed:
raise exception.ReturnErrorCode(1)
def results_to_json(raw):
results = []
for item in raw:
if item.get("succeeded") is None:
continue
item.update(
{
"succeeded": bool(item.get("succeeded")),
"defects": [d.as_dict() for d in item.get("defects", [])],
}
)
results.append(item)
return results
def print_processing_header(tool, envname, envdump):
click.echo(
"Checking %s > %s (%s)"
% (click.style(envname, fg="cyan", bold=True), tool, "; ".join(envdump))
)
terminal_width, _ = shutil.get_terminal_size()
click.secho("-" * terminal_width, bold=True)
def print_processing_footer(result):
is_failed = not result.get("succeeded")
util.print_labeled_bar(
"[%s] Took %.2f seconds"
% (
(
click.style("FAILED", fg="red", bold=True)
if is_failed
else click.style("PASSED", fg="green", bold=True)
),
result["duration"],
),
is_error=is_failed,
)
def collect_component_stats(result):
components = {}
def _append_defect(component, defect):
if not components.get(component):
components[component] = Counter()
components[component].update({DefectItem.SEVERITY_LABELS[defect.severity]: 1})
for defect in result.get("defects", []):
component = dirname(defect.file) or defect.file
_append_defect(component, defect)
if component.lower().startswith(get_project_dir().lower()):
while os.sep in component:
component = dirname(component)
_append_defect(component, defect)
return components
def print_defects_stats(results):
if not results:
return
component_stats = {}
for r in results:
for k, v in r.get("stats", {}).items():
if not component_stats.get(k):
component_stats[k] = Counter()
component_stats[k].update(r["stats"][k])
if not component_stats:
return
severity_labels = list(DefectItem.SEVERITY_LABELS.values())
severity_labels.reverse()
tabular_data = []
for k, v in component_stats.items():
tool_defect = [v.get(s, 0) for s in severity_labels]
tabular_data.append([k] + tool_defect)
total = ["Total"] + [sum(d) for d in list(zip(*tabular_data))[1:]]
tabular_data.sort()
tabular_data.append([]) # Empty line as delimiter
tabular_data.append(total)
headers = ["Component"]
headers.extend([l.upper() for l in severity_labels])
headers = [click.style(h, bold=True) for h in headers]
click.echo(tabulate(tabular_data, headers=headers, numalign="center"))
click.echo()
def print_check_summary(results, verbose=False):
click.echo()
tabular_data = []
succeeded_nums = 0
failed_nums = 0
duration = 0
print_defects_stats(results)
for result in results:
duration += result.get("duration", 0)
if result.get("succeeded") is False:
failed_nums += 1
status_str = click.style("FAILED", fg="red")
elif result.get("succeeded") is None:
status_str = "IGNORED"
if not verbose:
continue
else:
succeeded_nums += 1
status_str = click.style("PASSED", fg="green")
tabular_data.append(
(
click.style(result["env"], fg="cyan"),
result["tool"],
status_str,
util.humanize_duration_time(result.get("duration")),
)
)
click.echo(
tabulate(
tabular_data,
headers=[
click.style(s, bold=True)
for s in ("Environment", "Tool", "Status", "Duration")
],
),
err=failed_nums,
)
util.print_labeled_bar(
"%s%d succeeded in %s"
% (
"%d failed, " % failed_nums if failed_nums else "",
succeeded_nums,
util.humanize_duration_time(duration),
),
is_error=failed_nums,
fg="red" if failed_nums else "green",
)

View File

@@ -0,0 +1,95 @@
# 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.
import os
import click
from platformio.project.helpers import get_project_dir
# pylint: disable=too-many-instance-attributes, redefined-builtin
# pylint: disable=too-many-arguments
class DefectItem:
SEVERITY_HIGH = 1
SEVERITY_MEDIUM = 2
SEVERITY_LOW = 4
SEVERITY_LABELS = {4: "low", 2: "medium", 1: "high"}
def __init__(
self,
severity,
category,
message,
file=None,
line=0,
column=0,
id=None,
callstack=None,
cwe=None,
):
assert severity in (self.SEVERITY_HIGH, self.SEVERITY_MEDIUM, self.SEVERITY_LOW)
self.severity = severity
self.category = category
self.message = message
self.line = int(line)
self.column = int(column)
self.callstack = callstack
self.cwe = cwe
self.id = id
self.file = file or "unknown"
if file.lower().startswith(get_project_dir().lower()):
self.file = os.path.relpath(file, get_project_dir())
def __repr__(self):
defect_color = None
if self.severity == self.SEVERITY_HIGH:
defect_color = "red"
elif self.severity == self.SEVERITY_MEDIUM:
defect_color = "yellow"
format_str = "{file}:{line}: [{severity}:{category}] {message} {id}"
return format_str.format(
severity=click.style(self.SEVERITY_LABELS[self.severity], fg=defect_color),
category=click.style(self.category.lower(), fg=defect_color),
file=click.style(self.file, bold=True),
message=self.message,
line=self.line,
id="%s" % "[%s]" % self.id if self.id else "",
)
def __or__(self, defect):
return self.severity | defect.severity
@staticmethod
def severity_to_int(label):
for key, value in DefectItem.SEVERITY_LABELS.items():
if label == value:
return key
raise Exception("Unknown severity label -> %s" % label)
def as_dict(self):
return {
"severity": self.SEVERITY_LABELS[self.severity],
"category": self.category,
"message": self.message,
"file": os.path.abspath(self.file),
"line": self.line,
"column": self.column,
"callstack": self.callstack,
"id": self.id,
"cwe": self.cwe,
}

View File

@@ -0,0 +1,33 @@
# 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.
from platformio import exception
from platformio.check.tools.clangtidy import ClangtidyCheckTool
from platformio.check.tools.cppcheck import CppcheckCheckTool
from platformio.check.tools.pvsstudio import PvsStudioCheckTool
class CheckToolFactory:
@staticmethod
def new(tool, project_dir, config, envname, options):
cls = None
if tool == "cppcheck":
cls = CppcheckCheckTool
elif tool == "clangtidy":
cls = ClangtidyCheckTool
elif tool == "pvs-studio":
cls = PvsStudioCheckTool
else:
raise exception.PlatformioException("Unknown check tool `%s`" % tool)
return cls(project_dir, config, envname, options)

View File

@@ -0,0 +1,245 @@
# 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.
import glob
import os
import tempfile
import click
from platformio import fs, proc
from platformio.check.defect import DefectItem
from platformio.package.manager.core import get_core_package_dir
from platformio.package.meta import PackageSpec
from platformio.project.helpers import load_build_metadata
class CheckToolBase: # pylint: disable=too-many-instance-attributes
def __init__(self, project_dir, config, envname, options):
self.config = config
self.envname = envname
self.options = options
self.cc_flags = []
self.cxx_flags = []
self.cpp_includes = []
self.cpp_defines = []
self.toolchain_defines = []
self._tmp_files = []
self.cc_path = None
self.cxx_path = None
self._defects = []
self._on_defect_callback = None
self._bad_input = False
self._load_cpp_data(project_dir)
# detect all defects by default
if not self.options.get("severity"):
self.options["severity"] = [
DefectItem.SEVERITY_LOW,
DefectItem.SEVERITY_MEDIUM,
DefectItem.SEVERITY_HIGH,
]
# cast to severity by ids
self.options["severity"] = [
s if isinstance(s, int) else DefectItem.severity_to_int(s)
for s in self.options["severity"]
]
def _load_cpp_data(self, project_dir):
data = load_build_metadata(project_dir, self.envname)
if not data:
return
self.cc_flags = click.parser.split_arg_string(data.get("cc_flags", ""))
self.cxx_flags = click.parser.split_arg_string(data.get("cxx_flags", ""))
self.cpp_includes = self._dump_includes(data.get("includes", {}))
self.cpp_defines = data.get("defines", [])
self.cc_path = data.get("cc_path")
self.cxx_path = data.get("cxx_path")
self.toolchain_defines = self._get_toolchain_defines()
def get_tool_dir(self, pkg_name):
for spec in self.options["platform_packages"] or []:
spec = PackageSpec(spec)
if spec.name == pkg_name:
return get_core_package_dir(pkg_name, spec=spec)
return get_core_package_dir(pkg_name)
def get_flags(self, tool):
result = []
flags = self.options.get("flags") or []
for flag in flags:
if ":" not in flag or flag.startswith("-"):
result.extend([f for f in flag.split(" ") if f])
elif flag.startswith("%s:" % tool):
result.extend([f for f in flag.split(":", 1)[1].split(" ") if f])
return result
def _get_toolchain_defines(self):
def _extract_defines(language, includes_file):
build_flags = self.cxx_flags if language == "c++" else self.cc_flags
defines = []
cmd = "echo | %s -x %s %s %s -dM -E -" % (
self.cc_path,
language,
" ".join(
[f for f in build_flags if f.startswith(("-m", "-f", "-std"))]
),
includes_file,
)
result = proc.exec_command(cmd, shell=True)
for line in result["out"].split("\n"):
tokens = line.strip().split(" ", 2)
if not tokens or tokens[0] != "#define":
continue
if len(tokens) > 2:
defines.append("%s=%s" % (tokens[1], tokens[2]))
else:
defines.append(tokens[1])
return defines
incflags_file = self._long_includes_hook(self.cpp_includes)
return {lang: _extract_defines(lang, incflags_file) for lang in ("c", "c++")}
def _create_tmp_file(self, data):
with tempfile.NamedTemporaryFile("w", delete=False) as fp:
fp.write(data)
self._tmp_files.append(fp.name)
return fp.name
def _long_includes_hook(self, includes):
data = []
for inc in includes:
data.append('-I"%s"' % fs.to_unix_path(inc))
return '@"%s"' % self._create_tmp_file(" ".join(data))
@staticmethod
def _dump_includes(includes_map):
result = []
for includes in includes_map.values():
for include in includes:
if include not in result:
result.append(include)
return result
@staticmethod
def is_flag_set(flag, flags):
return any(flag in f for f in flags)
def get_defects(self):
return self._defects
def configure_command(self):
raise NotImplementedError
def on_tool_output(self, line):
line = self.tool_output_filter(line)
if not line:
return
defect = self.parse_defect(line)
if not isinstance(defect, DefectItem):
if self.options.get("verbose"):
click.echo(line)
return
if defect.severity not in self.options["severity"]:
return
self._defects.append(defect)
if self._on_defect_callback:
self._on_defect_callback(defect)
@staticmethod
def tool_output_filter(line):
return line
@staticmethod
def parse_defect(raw_line):
return raw_line
def clean_up(self):
for f in self._tmp_files:
if os.path.isfile(f):
os.remove(f)
@staticmethod
def is_check_successful(cmd_result):
return cmd_result["returncode"] == 0
def execute_check_cmd(self, cmd):
result = proc.exec_command(
cmd,
stdout=proc.LineBufferedAsyncPipe(self.on_tool_output),
stderr=proc.LineBufferedAsyncPipe(self.on_tool_output),
)
if not self.is_check_successful(result):
click.echo(
"\nError: Failed to execute check command! Exited with code %d."
% result["returncode"]
)
if self.options.get("verbose"):
click.echo(result["out"])
click.echo(result["err"])
self._bad_input = True
return result
@staticmethod
def get_project_target_files(patterns):
c_extension = (".c",)
cpp_extensions = (".cc", ".cpp", ".cxx", ".ino")
header_extensions = (".h", ".hh", ".hpp", ".hxx")
result = {"c": [], "c++": [], "headers": []}
def _add_file(path):
if path.endswith(header_extensions):
result["headers"].append(os.path.abspath(path))
elif path.endswith(c_extension):
result["c"].append(os.path.abspath(path))
elif path.endswith(cpp_extensions):
result["c++"].append(os.path.abspath(path))
for pattern in patterns:
for item in glob.glob(pattern, recursive=True):
if not os.path.isdir(item):
_add_file(item)
for root, _, files in os.walk(item, followlinks=True):
for f in files:
_add_file(os.path.join(root, f))
return result
def check(self, on_defect_callback=None):
self._on_defect_callback = on_defect_callback
cmd = self.configure_command()
if cmd:
if self.options.get("verbose"):
click.echo(" ".join(cmd))
self.execute_check_cmd(cmd)
else:
if self.options.get("verbose"):
click.echo("Error: Couldn't configure command")
self._bad_input = True
self.clean_up()
return self._bad_input

View File

@@ -0,0 +1,88 @@
# 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.
import re
from os.path import join
from platformio.check.defect import DefectItem
from platformio.check.tools.base import CheckToolBase
class ClangtidyCheckTool(CheckToolBase):
def tool_output_filter(self, line): # pylint: disable=arguments-differ
if not self.options.get("verbose") and "[clang-diagnostic-error]" in line:
return ""
if "[CommonOptionsParser]" in line:
self._bad_input = True
return line
if any(d in line for d in ("note: ", "error: ", "warning: ")):
return line
return ""
def parse_defect(self, raw_line): # pylint: disable=arguments-differ
match = re.match(r"^(.*):(\d+):(\d+):\s+([^:]+):\s(.+)\[([^]]+)\]$", raw_line)
if not match:
return raw_line
file_, line, column, category, message, defect_id = match.groups()
severity = DefectItem.SEVERITY_LOW
if category == "error":
severity = DefectItem.SEVERITY_HIGH
elif category == "warning":
severity = DefectItem.SEVERITY_MEDIUM
return DefectItem(severity, category, message, file_, line, column, defect_id)
@staticmethod
def is_check_successful(cmd_result):
# Note: Clang-Tidy returns 1 for not critical compilation errors,
# so 0 and 1 are only acceptable values
return cmd_result["returncode"] < 2
def configure_command(self):
tool_path = join(self.get_tool_dir("tool-clangtidy"), "clang-tidy")
cmd = [tool_path, "--quiet"]
flags = self.get_flags("clangtidy")
if not (
self.is_flag_set("--checks", flags) or self.is_flag_set("--config", flags)
):
cmd.append("--checks=*")
project_files = self.get_project_target_files(self.options["patterns"])
src_files = []
for items in project_files.values():
src_files.extend(items)
cmd.extend(flags + src_files + ["--"])
cmd.extend(
["-D%s" % d for d in self.cpp_defines + self.toolchain_defines["c++"]]
)
includes = []
for inc in self.cpp_includes:
if self.options.get("skip_packages") and inc.lower().startswith(
self.config.get("platformio", "packages_dir").lower()
):
continue
includes.append(inc)
cmd.extend(["-I%s" % inc for inc in includes])
return cmd

View File

@@ -0,0 +1,267 @@
# 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.
import os
import click
from platformio import proc
from platformio.check.defect import DefectItem
from platformio.check.tools.base import CheckToolBase
class CppcheckCheckTool(CheckToolBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._field_delimiter = "<&PIO&>"
self._buffer = ""
self.defect_fields = [
"severity",
"message",
"file",
"line",
"column",
"callstack",
"cwe",
"id",
]
def tool_output_filter(self, line): # pylint: disable=arguments-differ
if (
not self.options.get("verbose")
and "--suppress=unmatchedSuppression:" in line
):
return ""
if any(
msg in line
for msg in (
"No C or C++ source files found",
"unrecognized command line option",
"there was an internal error",
)
):
self._bad_input = True
return line
def parse_defect(self, raw_line): # pylint: disable=arguments-differ
if self._field_delimiter not in raw_line:
return None
self._buffer += raw_line
if any(f not in self._buffer for f in self.defect_fields):
return None
args = {}
for field in self._buffer.split(self._field_delimiter):
field = field.strip().replace('"', "")
name, value = field.split("=", 1)
args[name] = value
args["category"] = args["severity"]
if args["severity"] == "error":
args["severity"] = DefectItem.SEVERITY_HIGH
elif args["severity"] == "warning":
args["severity"] = DefectItem.SEVERITY_MEDIUM
else:
args["severity"] = DefectItem.SEVERITY_LOW
# Skip defects found in third-party software, but keep in mind that such defects
# might break checking process so defects from project files are not reported
breaking_defect_ids = ("preprocessorErrorDirective", "syntaxError")
if (
args.get("file", "")
.lower()
.startswith(self.config.get("platformio", "packages_dir").lower())
):
if args["id"] in breaking_defect_ids:
if self.options.get("verbose"):
click.echo(
"Error: Found a breaking defect '%s' in %s:%s\n"
"Please note: check results might not be valid!\n"
"Try adding --skip-packages"
% (args.get("message"), args.get("file"), args.get("line"))
)
click.echo()
self._bad_input = True
self._buffer = ""
return None
self._buffer = ""
return DefectItem(**args)
def configure_command(self, language, src_file): # pylint: disable=arguments-differ
tool_path = os.path.join(self.get_tool_dir("tool-cppcheck"), "cppcheck")
cmd = [
tool_path,
"--addon-python=%s" % proc.get_pythonexe_path(),
"--error-exitcode=3",
"--verbose" if self.options.get("verbose") else "--quiet",
]
cmd.append(
'--template="%s"'
% self._field_delimiter.join(
["{0}={{{0}}}".format(f) for f in self.defect_fields]
)
)
flags = self.get_flags("cppcheck")
if not flags:
# by default user can suppress reporting individual defects
# directly in code // cppcheck-suppress warningID
cmd.append("--inline-suppr")
if not self.is_flag_set("--platform", flags):
cmd.append("--platform=unspecified")
if not self.is_flag_set("--enable", flags):
enabled_checks = [
"warning",
"style",
"performance",
"portability",
"unusedFunction",
]
cmd.append("--enable=%s" % ",".join(enabled_checks))
if not self.is_flag_set("--language", flags):
cmd.append("--language=" + language)
build_flags = self.cxx_flags if language == "c++" else self.cc_flags
if not self.is_flag_set("--std", flags):
# Try to guess the standard version from the build flags
for flag in build_flags:
if "-std" in flag:
cmd.append("-" + self.convert_language_standard(flag))
cmd.extend(
["-D%s" % d for d in self.cpp_defines + self.toolchain_defines[language]]
)
cmd.extend(flags)
cmd.extend(
"--include=" + inc
for inc in self.get_forced_includes(build_flags, self.cpp_includes)
)
cmd.append("--includes-file=%s" % self._generate_inc_file())
cmd.append('"%s"' % src_file)
return cmd
@staticmethod
def get_forced_includes(build_flags, includes):
def _extract_filepath(flag, include_options, build_flags):
path = ""
for option in include_options:
if not flag.startswith(option):
continue
if flag.split(option)[1].strip():
path = flag.split(option)[1].strip()
elif build_flags.index(flag) + 1 < len(build_flags):
path = build_flags[build_flags.index(flag) + 1]
return path
def _search_include_dir(filepath, include_paths):
for inc_path in include_paths:
path = os.path.join(inc_path, filepath)
if os.path.isfile(path):
return path
return ""
result = []
include_options = ("-include", "-imacros")
for f in build_flags:
if f.startswith(include_options):
filepath = _extract_filepath(f, include_options, build_flags)
if not os.path.isabs(filepath):
filepath = _search_include_dir(filepath, includes)
if os.path.isfile(filepath):
result.append(filepath)
return result
def _generate_src_file(self, src_files):
return self._create_tmp_file("\n".join(src_files))
def _generate_inc_file(self):
result = []
for inc in self.cpp_includes:
if self.options.get("skip_packages") and inc.lower().startswith(
self.config.get("platformio", "packages_dir").lower()
):
continue
result.append(inc)
return self._create_tmp_file("\n".join(result))
def clean_up(self):
super().clean_up()
# delete temporary dump files generated by addons
if not self.is_flag_set("--addon", self.get_flags("cppcheck")):
return
for files in self.get_project_target_files(self.options["patterns"]).values():
for f in files:
dump_file = f + ".dump"
if os.path.isfile(dump_file):
os.remove(dump_file)
@staticmethod
def is_check_successful(cmd_result):
# Cppcheck is configured to return '3' if a defect is found
return cmd_result["returncode"] in (0, 3)
@staticmethod
def convert_language_standard(flag):
cpp_standards_map = {
"0x": "11",
"1y": "14",
"1z": "17",
"2a": "20",
}
standard = flag[-2:]
# Note: GNU extensions are not supported and converted to regular standards
return flag.replace("gnu", "c").replace(
standard, cpp_standards_map.get(standard, standard)
)
def check(self, on_defect_callback=None):
self._on_defect_callback = on_defect_callback
project_files = self.get_project_target_files(self.options["patterns"])
src_files_scope = ("c", "c++")
if not any(project_files[t] for t in src_files_scope):
click.echo("Error: Nothing to check.")
return True
for scope, files in project_files.items():
if scope not in src_files_scope:
continue
for src_file in files:
cmd = self.configure_command(scope, src_file)
if not cmd:
self._bad_input = True
continue
if self.options.get("verbose"):
click.echo(" ".join(cmd))
self.execute_check_cmd(cmd)
self.clean_up()
return self._bad_input

View File

@@ -0,0 +1,251 @@
# Copyright (c) 2020-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.
import os
import shutil
import tempfile
from xml.etree.ElementTree import fromstring
import click
from platformio import proc
from platformio.check.defect import DefectItem
from platformio.check.tools.base import CheckToolBase
from platformio.compat import IS_WINDOWS
class PvsStudioCheckTool(CheckToolBase): # pylint: disable=too-many-instance-attributes
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._tmp_dir = tempfile.mkdtemp(prefix="piocheck")
self._tmp_preprocessed_file = self._generate_tmp_file_path() + ".i"
self._tmp_output_file = self._generate_tmp_file_path() + ".pvs"
self._tmp_cfg_file = self._generate_tmp_file_path() + ".cfg"
self._tmp_cmd_file = self._generate_tmp_file_path() + ".cmd"
self.tool_path = os.path.join(
self.get_tool_dir("tool-pvs-studio"),
"x64" if IS_WINDOWS else "bin",
"pvs-studio",
)
with open(self._tmp_cfg_file, mode="w", encoding="utf8") as fp:
fp.write(
"exclude-path = "
+ self.config.get("platformio", "packages_dir").replace("\\", "/")
)
with open(self._tmp_cmd_file, mode="w", encoding="utf8") as fp:
fp.write(
" ".join(
['-I"%s"' % inc.replace("\\", "/") for inc in self.cpp_includes]
)
)
def tool_output_filter(self, line): # pylint: disable=arguments-differ
if any(
err_msg in line.lower()
for err_msg in (
"license was not entered",
"license information is incorrect",
)
):
self._bad_input = True
return line
def _process_defects(self, defects):
for defect in defects:
if not isinstance(defect, DefectItem):
return
if defect.severity not in self.options["severity"]:
return
self._defects.append(defect)
if self._on_defect_callback:
self._on_defect_callback(defect)
def _demangle_report(self, output_file):
converter_tool = os.path.join(
self.get_tool_dir("tool-pvs-studio"),
"HtmlGenerator" if IS_WINDOWS else os.path.join("bin", "plog-converter"),
)
cmd = (
converter_tool,
"-t",
"xml",
output_file,
"-m",
"cwe",
"-m",
"misra",
"-a",
# Enable all possible analyzers and defect levels
"GA:1,2,3;64:1,2,3;OP:1,2,3;CS:1,2,3;MISRA:1,2,3",
"--cerr",
)
result = proc.exec_command(cmd)
if result["returncode"] != 0:
click.echo(result["err"])
self._bad_input = True
return result["err"]
def parse_defects(self, output_file):
defects = []
report = self._demangle_report(output_file)
if not report:
self._bad_input = True
return []
try:
defects_data = fromstring(report)
except: # pylint: disable=bare-except
click.echo("Error: Couldn't decode generated report!")
self._bad_input = True
return []
for table in defects_data.iter("PVS-Studio_Analysis_Log"):
message = table.find("Message").text
category = table.find("ErrorType").text
line = table.find("Line").text
file_ = table.find("File").text
defect_id = table.find("ErrorCode").text
cwe = table.find("CWECode")
cwe_id = None
if cwe is not None:
cwe_id = cwe.text.lower().replace("cwe-", "")
misra = table.find("MISRA")
if misra is not None:
message += " [%s]" % misra.text
severity = DefectItem.SEVERITY_LOW
if category == "error":
severity = DefectItem.SEVERITY_HIGH
elif category == "warning":
severity = DefectItem.SEVERITY_MEDIUM
defects.append(
DefectItem(
severity, category, message, file_, line, id=defect_id, cwe=cwe_id
)
)
return defects
def configure_command(self, src_file): # pylint: disable=arguments-differ
if os.path.isfile(self._tmp_output_file):
os.remove(self._tmp_output_file)
if not os.path.isfile(self._tmp_preprocessed_file):
click.echo("Error: Missing preprocessed file for '%s'" % src_file)
return ""
cmd = [
self.tool_path,
"--skip-cl-exe",
"yes",
"--language",
"C" if src_file.endswith(".c") else "C++",
"--preprocessor",
"gcc",
"--cfg",
self._tmp_cfg_file,
"--source-file",
src_file,
"--i-file",
self._tmp_preprocessed_file,
"--output-file",
self._tmp_output_file,
]
flags = self.get_flags("pvs-studio")
if not self.is_flag_set("--platform", flags):
cmd.append("--platform=arm")
cmd.extend(flags)
return cmd
def _generate_tmp_file_path(self):
# pylint: disable=protected-access
return os.path.join(self._tmp_dir, next(tempfile._get_candidate_names()))
def _prepare_preprocessed_file(self, src_file):
if os.path.isfile(self._tmp_preprocessed_file):
os.remove(self._tmp_preprocessed_file)
flags = self.cxx_flags
compiler = self.cxx_path
if src_file.endswith(".c"):
flags = self.cc_flags
compiler = self.cc_path
cmd = [
compiler,
'"%s"' % src_file,
"-E",
"-o",
'"%s"' % self._tmp_preprocessed_file,
]
cmd.extend([f for f in flags if f])
cmd.extend(['"-D%s"' % d.replace('"', '\\"') for d in self.cpp_defines])
cmd.append('@"%s"' % self._tmp_cmd_file)
# Explicitly specify C++ as the language used in .ino files
if src_file.endswith(".ino"):
cmd.insert(1, "-xc++")
result = proc.exec_command(" ".join(cmd), shell=True)
if result["returncode"] != 0 or result["err"]:
if self.options.get("verbose"):
click.echo(" ".join(cmd))
click.echo(result["err"])
self._bad_input = True
def clean_up(self):
super().clean_up()
if os.path.isdir(self._tmp_dir):
shutil.rmtree(self._tmp_dir)
@staticmethod
def is_check_successful(cmd_result):
return (
"license" not in cmd_result["err"].lower() and cmd_result["returncode"] == 0
)
def check(self, on_defect_callback=None):
self._on_defect_callback = on_defect_callback
for scope, files in self.get_project_target_files(
self.options["patterns"]
).items():
if scope not in ("c", "c++"):
continue
for src_file in files:
self._prepare_preprocessed_file(src_file)
cmd = self.configure_command(src_file)
if self.options.get("verbose"):
click.echo(" ".join(cmd))
if not cmd:
self._bad_input = True
continue
result = self.execute_check_cmd(cmd)
if result["returncode"] != 0:
continue
self._process_defects(self.parse_defects(self._tmp_output_file))
self.clean_up()
return self._bad_input

96
platformio/cli.py Normal file
View File

@@ -0,0 +1,96 @@
# 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.
import importlib
from pathlib import Path
import click
class PlatformioCLI(click.MultiCommand):
leftover_args = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._pio_root_path = Path(__file__).parent
self._pio_cmd_aliases = dict(package="pkg")
def _find_pio_commands(self):
def _to_module_path(p):
return (
"platformio." + ".".join(p.relative_to(self._pio_root_path).parts)[:-3]
)
result = {}
for p in self._pio_root_path.rglob("cli.py"):
# skip this module
if p.parent == self._pio_root_path:
continue
cmd_name = p.parent.name
result[self._pio_cmd_aliases.get(cmd_name, cmd_name)] = _to_module_path(p)
# find legacy commands
for p in (self._pio_root_path / "commands").iterdir():
if p.name.startswith("_"):
continue
if (p / "command.py").is_file():
result[p.name] = _to_module_path(p / "command.py")
elif p.name.endswith(".py"):
result[p.name[:-3]] = _to_module_path(p)
return result
@staticmethod
def in_silence():
args = PlatformioCLI.leftover_args
return args and any(
[
args[0] == "debug" and "--interpreter" in " ".join(args),
args[0] == "upgrade",
"--json-output" in args,
"--version" in args,
]
)
def invoke(self, ctx):
PlatformioCLI.leftover_args = ctx.args
if hasattr(ctx, "protected_args"):
PlatformioCLI.leftover_args = ctx.protected_args + ctx.args
return super().invoke(ctx)
def list_commands(self, ctx):
return sorted(list(self._find_pio_commands()))
def get_command(self, ctx, cmd_name):
commands = self._find_pio_commands()
if cmd_name not in commands:
return self._handle_obsolate_command(ctx, cmd_name)
module = importlib.import_module(commands[cmd_name])
return getattr(module, "cli")
@staticmethod
def _handle_obsolate_command(ctx, cmd_name):
# pylint: disable=import-outside-toplevel
if cmd_name == "init":
from platformio.project.commands.init import project_init_cmd
return project_init_cmd
if cmd_name == "package":
from platformio.package.cli import cli
return cli
raise click.UsageError('No such command "%s"' % cmd_name, ctx)

View File

@@ -11,62 +11,3 @@
# 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.
import os
from os.path import dirname, isfile, join
import click
class PlatformioCLI(click.MultiCommand):
leftover_args = []
@staticmethod
def in_silence():
args = PlatformioCLI.leftover_args
return args and any([
args[0] == "debug" and "--interpreter" in " ".join(args),
args[0] == "upgrade", "--json-output" in args, "--version" in args
])
def invoke(self, ctx):
PlatformioCLI.leftover_args = ctx.args
if hasattr(ctx, "protected_args"):
PlatformioCLI.leftover_args = ctx.protected_args + ctx.args
return super(PlatformioCLI, self).invoke(ctx)
def list_commands(self, ctx):
cmds = []
cmds_dir = dirname(__file__)
for name in os.listdir(cmds_dir):
if name.startswith("__init__"):
continue
if isfile(join(cmds_dir, name, "command.py")):
cmds.append(name)
elif name.endswith(".py"):
cmds.append(name[:-3])
cmds.sort()
return cmds
def get_command(self, ctx, cmd_name):
mod = None
try:
mod = __import__("platformio.commands." + cmd_name, None, None,
["cli"])
except ImportError:
try:
return self._handle_obsolate_command(cmd_name)
except AttributeError:
raise click.UsageError('No such command "%s"' % cmd_name, ctx)
return mod.cli
@staticmethod
def _handle_obsolate_command(name):
if name == "platforms":
from platformio.commands import platform
return platform.cli
if name == "serialports":
from platformio.commands import device
return device.cli
raise AttributeError()

View File

@@ -1,72 +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.
# pylint: disable=unused-argument
import sys
import click
from platformio.managers.core import pioplus_call
@click.group("account", short_help="Manage PIO Account")
def cli():
pass
@cli.command("register", short_help="Create new PIO Account")
@click.option("-u", "--username")
def account_register(**kwargs):
pioplus_call(sys.argv[1:])
@cli.command("login", short_help="Log in to PIO Account")
@click.option("-u", "--username")
@click.option("-p", "--password")
def account_login(**kwargs):
pioplus_call(sys.argv[1:])
@cli.command("logout", short_help="Log out of PIO Account")
def account_logout():
pioplus_call(sys.argv[1:])
@cli.command("password", short_help="Change password")
@click.option("--old-password")
@click.option("--new-password")
def account_password(**kwargs):
pioplus_call(sys.argv[1:])
@cli.command("token", short_help="Get or regenerate Authentication Token")
@click.option("-p", "--password")
@click.option("--regenerate", is_flag=True)
@click.option("--json-output", is_flag=True)
def account_token(**kwargs):
pioplus_call(sys.argv[1:])
@cli.command("forgot", short_help="Forgot password")
@click.option("-u", "--username")
def account_forgot(**kwargs):
pioplus_call(sys.argv[1:])
@cli.command("show", short_help="PIO Account information")
@click.option("--offline", is_flag=True)
@click.option("--json-output", is_flag=True)
def account_show(**kwargs):
pioplus_call(sys.argv[1:])

View File

@@ -13,16 +13,16 @@
# limitations under the License.
import json
import shutil
import click
from tabulate import tabulate
from platformio import fs
from platformio.compat import dump_json_to_unicode
from platformio.managers.platform import PlatformManager
from platformio.package.manager.platform import PlatformPackageManager
@click.command("boards", short_help="Embedded Board Explorer")
@click.command("boards", short_help="Board Explorer")
@click.argument("query", required=False)
@click.option("--installed", is_flag=True)
@click.option("--json-output", is_flag=True)
@@ -32,13 +32,16 @@ def cli(query, installed, json_output): # pylint: disable=R0912
grpboards = {}
for board in _get_boards(installed):
if query and query.lower() not in json.dumps(board).lower():
if query and not any(
query.lower() in str(board.get(k, "")).lower()
for k in ("id", "name", "mcu", "vendor", "platform", "frameworks")
):
continue
if board['platform'] not in grpboards:
grpboards[board['platform']] = []
grpboards[board['platform']].append(board)
if board["platform"] not in grpboards:
grpboards[board["platform"]] = []
grpboards[board["platform"]].append(board)
terminal_width, _ = click.get_terminal_size()
terminal_width, _ = shutil.get_terminal_size()
for (platform, boards) in sorted(grpboards.items()):
click.echo("")
click.echo("Platform: ", nl=False)
@@ -50,15 +53,25 @@ def cli(query, installed, json_output): # pylint: disable=R0912
def print_boards(boards):
click.echo(
tabulate([(click.style(b['id'], fg="cyan"), b['mcu'], "%dMHz" %
(b['fcpu'] / 1000000), fs.format_filesize(
b['rom']), fs.format_filesize(b['ram']), b['name'])
for b in boards],
headers=["ID", "MCU", "Frequency", "Flash", "RAM", "Name"]))
tabulate(
[
(
click.style(b["id"], fg="cyan"),
b["mcu"],
"%dMHz" % (b["fcpu"] / 1000000),
fs.humanize_file_size(b["rom"]),
fs.humanize_file_size(b["ram"]),
b["name"],
)
for b in boards
],
headers=["ID", "MCU", "Frequency", "Flash", "RAM", "Name"],
)
)
def _get_boards(installed=False):
pm = PlatformManager()
pm = PlatformPackageManager()
return pm.get_installed_boards() if installed else pm.get_all_boards()
@@ -66,8 +79,8 @@ def _print_boards_json(query, installed=False):
result = []
for board in _get_boards(installed):
if query:
search_data = "%s %s" % (board['id'], json.dumps(board).lower())
search_data = "%s %s" % (board["id"], json.dumps(board).lower())
if query.lower() not in search_data.lower():
continue
result.append(board)
click.echo(dump_json_to_unicode(result))
click.echo(json.dumps(result))

View File

@@ -12,21 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from glob import glob
from os import getenv, makedirs, remove
from os.path import abspath, basename, expanduser, isdir, isfile, join
from shutil import copyfile, copytree
from tempfile import mkdtemp
import glob
import os
import shutil
import tempfile
import click
from platformio import app, fs
from platformio.commands.init import cli as cmd_init
from platformio.commands.init import validate_boards
from platformio.commands.run import cli as cmd_run
from platformio.compat import glob_escape
from platformio.exception import CIBuildEnvsEmpty
from platformio.project.commands.init import project_init_cmd, validate_boards
from platformio.project.config import ProjectConfig
from platformio.run.cli import cli as cmd_run
def validate_path(ctx, param, value): # pylint: disable=unused-argument
@@ -34,74 +31,75 @@ def validate_path(ctx, param, value): # pylint: disable=unused-argument
value = list(value)
for i, p in enumerate(value):
if p.startswith("~"):
value[i] = expanduser(p)
value[i] = abspath(value[i])
if not glob(value[i]):
value[i] = fs.expanduser(p)
value[i] = os.path.abspath(value[i])
if not glob.glob(value[i], recursive=True):
invalid_path = p
break
try:
assert invalid_path is None
return value
except AssertionError:
raise click.BadParameter("Found invalid path: %s" % invalid_path)
except AssertionError as exc:
raise click.BadParameter("Found invalid path: %s" % invalid_path) from exc
@click.command("ci", short_help="Continuous Integration")
@click.argument("src", nargs=-1, callback=validate_path)
@click.option("-l",
"--lib",
multiple=True,
callback=validate_path,
metavar="DIRECTORY")
@click.option("-l", "--lib", multiple=True, callback=validate_path, metavar="DIRECTORY")
@click.option("--exclude", multiple=True)
@click.option("-b",
"--board",
multiple=True,
metavar="ID",
callback=validate_boards)
@click.option("--build-dir",
default=mkdtemp,
type=click.Path(file_okay=False,
dir_okay=True,
writable=True,
resolve_path=True))
@click.option("-b", "--board", multiple=True, metavar="ID", callback=validate_boards)
@click.option(
"--build-dir",
default=tempfile.mkdtemp,
type=click.Path(file_okay=False, dir_okay=True, writable=True, resolve_path=True),
)
@click.option("--keep-build-dir", is_flag=True)
@click.option("-c",
"--project-conf",
type=click.Path(exists=True,
file_okay=True,
dir_okay=False,
readable=True,
resolve_path=True))
@click.option(
"-c",
"--project-conf",
type=click.Path(
exists=True, file_okay=True, dir_okay=False, readable=True, resolve_path=True
),
)
@click.option("-O", "--project-option", multiple=True)
@click.option("-e", "--environment", "environments", multiple=True)
@click.option("-v", "--verbose", is_flag=True)
@click.pass_context
def cli( # pylint: disable=too-many-arguments, too-many-branches
ctx, src, lib, exclude, board, build_dir, keep_build_dir, project_conf,
project_option, verbose):
if not src and getenv("PLATFORMIO_CI_SRC"):
src = validate_path(ctx, None, getenv("PLATFORMIO_CI_SRC").split(":"))
ctx,
src,
lib,
exclude,
board,
build_dir,
keep_build_dir,
project_conf,
project_option,
environments,
verbose,
):
if not src and os.getenv("PLATFORMIO_CI_SRC"):
src = validate_path(ctx, None, os.getenv("PLATFORMIO_CI_SRC").split(":"))
if not src:
raise click.BadParameter("Missing argument 'src'")
try:
app.set_session_var("force_option", True)
if not keep_build_dir and isdir(build_dir):
if not keep_build_dir and os.path.isdir(build_dir):
fs.rmtree(build_dir)
if not isdir(build_dir):
makedirs(build_dir)
if not os.path.isdir(build_dir):
os.makedirs(build_dir)
for dir_name, patterns in dict(lib=lib, src=src).items():
if not patterns:
continue
contents = []
for p in patterns:
contents += glob(p)
_copy_contents(join(build_dir, dir_name), contents)
contents += glob.glob(p, recursive=True)
_copy_contents(os.path.join(build_dir, dir_name), contents)
if project_conf and isfile(project_conf):
if project_conf and os.path.isfile(project_conf):
_copy_project_conf(build_dir, project_conf)
elif not board:
raise CIBuildEnvsEmpty()
@@ -110,64 +108,71 @@ def cli( # pylint: disable=too-many-arguments, too-many-branches
_exclude_contents(build_dir, exclude)
# initialise project
ctx.invoke(cmd_init,
project_dir=build_dir,
board=board,
project_option=project_option)
ctx.invoke(
project_init_cmd,
project_dir=build_dir,
board=board,
project_option=project_option,
)
# process project
ctx.invoke(cmd_run, project_dir=build_dir, verbose=verbose)
ctx.invoke(
cmd_run, project_dir=build_dir, environment=environments, verbose=verbose
)
finally:
if not keep_build_dir:
fs.rmtree(build_dir)
def _copy_contents(dst_dir, contents):
def _copy_contents(dst_dir, contents): # pylint: disable=too-many-branches
items = {"dirs": set(), "files": set()}
for path in contents:
if isdir(path):
items['dirs'].add(path)
elif isfile(path):
items['files'].add(path)
if os.path.isdir(path):
items["dirs"].add(path)
elif os.path.isfile(path):
items["files"].add(path)
dst_dir_name = basename(dst_dir)
dst_dir_name = os.path.basename(dst_dir)
if dst_dir_name == "src" and len(items['dirs']) == 1:
copytree(list(items['dirs']).pop(), dst_dir, symlinks=True)
if dst_dir_name == "src" and len(items["dirs"]) == 1:
if not os.path.isdir(dst_dir):
shutil.copytree(list(items["dirs"]).pop(), dst_dir, symlinks=True)
else:
if not isdir(dst_dir):
makedirs(dst_dir)
for d in items['dirs']:
copytree(d, join(dst_dir, basename(d)), symlinks=True)
if not os.path.isdir(dst_dir):
os.makedirs(dst_dir)
for d in items["dirs"]:
src_dst_dir = os.path.join(dst_dir, os.path.basename(d))
if not os.path.isdir(src_dst_dir):
shutil.copytree(d, src_dst_dir, symlinks=True)
if not items['files']:
if not items["files"]:
return
if dst_dir_name == "lib":
dst_dir = join(dst_dir, mkdtemp(dir=dst_dir))
dst_dir = os.path.join(dst_dir, tempfile.mkdtemp(dir=dst_dir))
for f in items['files']:
dst_file = join(dst_dir, basename(f))
for f in items["files"]:
dst_file = os.path.join(dst_dir, os.path.basename(f))
if f == dst_file:
continue
copyfile(f, dst_file)
shutil.copyfile(f, dst_file)
def _exclude_contents(dst_dir, patterns):
contents = []
for p in patterns:
contents += glob(join(glob_escape(dst_dir), p))
contents += glob.glob(os.path.join(glob.escape(dst_dir), p), recursive=True)
for path in contents:
path = abspath(path)
if isdir(path):
path = os.path.abspath(path)
if os.path.isdir(path):
fs.rmtree(path)
elif isfile(path):
remove(path)
elif os.path.isfile(path):
os.remove(path)
def _copy_project_conf(build_dir, project_conf):
config = ProjectConfig(project_conf, parse_extra=False)
if config.has_section("platformio"):
config.remove_section("platformio")
config.save(join(build_dir, "platformio.ini"))
config.save(os.path.join(build_dir, "platformio.ini"))

View File

@@ -1,292 +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.
import json
import os
import re
import signal
import time
from hashlib import sha1
from os.path import abspath, basename, dirname, isdir, join, splitext
from tempfile import mkdtemp
from twisted.internet import protocol # pylint: disable=import-error
from twisted.internet import reactor # pylint: disable=import-error
from twisted.internet import stdio # pylint: disable=import-error
from twisted.internet import task # pylint: disable=import-error
from platformio import app, exception, fs, proc, util
from platformio.commands.debug import helpers, initcfgs
from platformio.commands.debug.process import BaseProcess
from platformio.commands.debug.server import DebugServer
from platformio.compat import hashlib_encode_data
from platformio.project.helpers import get_project_cache_dir
from platformio.telemetry import MeasurementProtocol
LOG_FILE = None
class GDBClient(BaseProcess): # pylint: disable=too-many-instance-attributes
PIO_SRC_NAME = ".pioinit"
INIT_COMPLETED_BANNER = "PlatformIO: Initialization completed"
def __init__(self, project_dir, args, debug_options, env_options):
self.project_dir = project_dir
self.args = list(args)
self.debug_options = debug_options
self.env_options = env_options
self._debug_server = DebugServer(debug_options, env_options)
self._session_id = None
if not isdir(get_project_cache_dir()):
os.makedirs(get_project_cache_dir())
self._gdbsrc_dir = mkdtemp(dir=get_project_cache_dir(),
prefix=".piodebug-")
self._target_is_run = False
self._last_server_activity = 0
self._auto_continue_timer = None
def spawn(self, gdb_path, prog_path):
session_hash = gdb_path + prog_path
self._session_id = sha1(hashlib_encode_data(session_hash)).hexdigest()
self._kill_previous_session()
patterns = {
"PROJECT_DIR": self.project_dir,
"PROG_PATH": prog_path,
"PROG_DIR": dirname(prog_path),
"PROG_NAME": basename(splitext(prog_path)[0]),
"DEBUG_PORT": self.debug_options['port'],
"UPLOAD_PROTOCOL": self.debug_options['upload_protocol'],
"INIT_BREAK": self.debug_options['init_break'] or "",
"LOAD_CMDS": "\n".join(self.debug_options['load_cmds'] or []),
}
self._debug_server.spawn(patterns)
if not patterns['DEBUG_PORT']:
patterns['DEBUG_PORT'] = self._debug_server.get_debug_port()
self.generate_pioinit(self._gdbsrc_dir, patterns)
# start GDB client
args = [
"piogdb",
"-q",
"--directory", self._gdbsrc_dir,
"--directory", self.project_dir,
"-l", "10"
] # yapf: disable
args.extend(self.args)
if not gdb_path:
raise exception.DebugInvalidOptions("GDB client is not configured")
gdb_data_dir = self._get_data_dir(gdb_path)
if gdb_data_dir:
args.extend(["--data-directory", gdb_data_dir])
args.append(patterns['PROG_PATH'])
return reactor.spawnProcess(self,
gdb_path,
args,
path=self.project_dir,
env=os.environ)
@staticmethod
def _get_data_dir(gdb_path):
if "msp430" in gdb_path:
return None
gdb_data_dir = abspath(join(dirname(gdb_path), "..", "share", "gdb"))
return gdb_data_dir if isdir(gdb_data_dir) else None
def generate_pioinit(self, dst_dir, patterns):
server_exe = (self.debug_options.get("server")
or {}).get("executable", "").lower()
if "jlink" in server_exe:
cfg = initcfgs.GDB_JLINK_INIT_CONFIG
elif "st-util" in server_exe:
cfg = initcfgs.GDB_STUTIL_INIT_CONFIG
elif "mspdebug" in server_exe:
cfg = initcfgs.GDB_MSPDEBUG_INIT_CONFIG
elif "qemu" in server_exe:
cfg = initcfgs.GDB_QEMU_INIT_CONFIG
elif self.debug_options['require_debug_port']:
cfg = initcfgs.GDB_BLACKMAGIC_INIT_CONFIG
else:
cfg = initcfgs.GDB_DEFAULT_INIT_CONFIG
commands = cfg.split("\n")
if self.debug_options['init_cmds']:
commands = self.debug_options['init_cmds']
commands.extend(self.debug_options['extra_cmds'])
if not any("define pio_reset_target" in cmd for cmd in commands):
commands = [
"define pio_reset_target",
" echo Warning! Undefined pio_reset_target command\\n",
" mon reset",
"end"
] + commands # yapf: disable
if not any("define pio_reset_halt_target" in cmd for cmd in commands):
commands = [
"define pio_reset_halt_target",
" echo Warning! Undefined pio_reset_halt_target command\\n",
" mon reset halt",
"end"
] + commands # yapf: disable
if not any("define pio_restart_target" in cmd for cmd in commands):
commands += [
"define pio_restart_target",
" pio_reset_halt_target",
" $INIT_BREAK",
" %s" % ("continue" if patterns['INIT_BREAK'] else "next"),
"end"
] # yapf: disable
banner = [
"echo PlatformIO Unified Debugger -> http://bit.ly/pio-debug\\n",
"echo PlatformIO: debug_tool = %s\\n" % self.debug_options['tool'],
"echo PlatformIO: Initializing remote target...\\n"
]
footer = ["echo %s\\n" % self.INIT_COMPLETED_BANNER]
commands = banner + commands + footer
with open(join(dst_dir, self.PIO_SRC_NAME), "w") as fp:
fp.write("\n".join(self.apply_patterns(commands, patterns)))
def connectionMade(self):
self._lock_session(self.transport.pid)
p = protocol.Protocol()
p.dataReceived = self.onStdInData
stdio.StandardIO(p)
def onStdInData(self, data):
if LOG_FILE:
with open(LOG_FILE, "ab") as fp:
fp.write(data)
self._last_server_activity = time.time()
if b"-exec-run" in data:
if self._target_is_run:
token, _ = data.split(b"-", 1)
self.outReceived(token + b"^running\n")
return
data = data.replace(b"-exec-run", b"-exec-continue")
if b"-exec-continue" in data:
self._target_is_run = True
if b"-gdb-exit" in data or data.strip() in (b"q", b"quit"):
# Allow terminating via SIGINT/CTRL+C
signal.signal(signal.SIGINT, signal.default_int_handler)
self.transport.write(b"pio_reset_target\n")
self.transport.write(data)
def processEnded(self, reason): # pylint: disable=unused-argument
self._unlock_session()
if self._gdbsrc_dir and isdir(self._gdbsrc_dir):
fs.rmtree(self._gdbsrc_dir)
if self._debug_server:
self._debug_server.terminate()
reactor.stop()
def outReceived(self, data):
if LOG_FILE:
with open(LOG_FILE, "ab") as fp:
fp.write(data)
self._last_server_activity = time.time()
super(GDBClient, self).outReceived(data)
self._handle_error(data)
# go to init break automatically
if self.INIT_COMPLETED_BANNER.encode() in data:
self._auto_continue_timer = task.LoopingCall(
self._auto_exec_continue)
self._auto_continue_timer.start(0.1)
def errReceived(self, data):
super(GDBClient, self).errReceived(data)
self._handle_error(data)
def console_log(self, msg):
if helpers.is_mi_mode(self.args):
self.outReceived(('~"%s\\n"\n' % msg).encode())
else:
self.outReceived(("%s\n" % msg).encode())
def _auto_exec_continue(self):
auto_exec_delay = 0.5 # in seconds
if self._last_server_activity > (time.time() - auto_exec_delay):
return
if self._auto_continue_timer:
self._auto_continue_timer.stop()
self._auto_continue_timer = None
if not self.debug_options['init_break'] or self._target_is_run:
return
self.console_log(
"PlatformIO: Resume the execution to `debug_init_break = %s`" %
self.debug_options['init_break'])
self.console_log("PlatformIO: More configuration options -> "
"http://bit.ly/pio-debug")
self.transport.write(b"0-exec-continue\n" if helpers.
is_mi_mode(self.args) else b"continue\n")
self._target_is_run = True
def _handle_error(self, data):
if (self.PIO_SRC_NAME.encode() not in data
or b"Error in sourced" not in data):
return
configuration = {"debug": self.debug_options, "env": self.env_options}
exd = re.sub(r'\\(?!")', "/", json.dumps(configuration))
exd = re.sub(r'"(?:[a-z]\:)?((/[^"/]+)+)"',
lambda m: '"%s"' % join(*m.group(1).split("/")[-2:]), exd,
re.I | re.M)
mp = MeasurementProtocol()
mp['exd'] = "DebugGDBPioInitError: %s" % exd
mp['exf'] = 1
mp.send("exception")
self.transport.loseConnection()
def _kill_previous_session(self):
assert self._session_id
pid = None
with app.ContentCache() as cc:
pid = cc.get(self._session_id)
cc.delete(self._session_id)
if not pid:
return
if "windows" in util.get_systype():
kill = ["Taskkill", "/PID", pid, "/F"]
else:
kill = ["kill", pid]
try:
proc.exec_command(kill)
except: # pylint: disable=bare-except
pass
def _lock_session(self, pid):
if not self._session_id:
return
with app.ContentCache() as cc:
cc.set(self._session_id, str(pid), "1h")
def _unlock_session(self):
if not self._session_id:
return
with app.ContentCache() as cc:
cc.delete(self._session_id)

View File

@@ -1,151 +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.
# pylint: disable=too-many-arguments, too-many-statements
# pylint: disable=too-many-locals, too-many-branches
import os
import signal
from os.path import isfile, join
import click
from platformio import exception, fs, proc, util
from platformio.commands.debug import helpers
from platformio.managers.core import inject_contrib_pysite
from platformio.project.config import ProjectConfig
from platformio.project.helpers import (is_platformio_project,
load_project_ide_data)
@click.command("debug",
context_settings=dict(ignore_unknown_options=True),
short_help="PIO Unified Debugger")
@click.option("-d",
"--project-dir",
default=os.getcwd,
type=click.Path(exists=True,
file_okay=False,
dir_okay=True,
writable=True,
resolve_path=True))
@click.option("-c",
"--project-conf",
type=click.Path(exists=True,
file_okay=True,
dir_okay=False,
readable=True,
resolve_path=True))
@click.option("--environment", "-e", metavar="<environment>")
@click.option("--verbose", "-v", is_flag=True)
@click.option("--interface", type=click.Choice(["gdb"]))
@click.argument("__unprocessed", nargs=-1, type=click.UNPROCESSED)
@click.pass_context
def cli(ctx, project_dir, project_conf, environment, verbose, interface,
__unprocessed):
# use env variables from Eclipse or CLion
for sysenv in ("CWD", "PWD", "PLATFORMIO_PROJECT_DIR"):
if is_platformio_project(project_dir):
break
if os.getenv(sysenv):
project_dir = os.getenv(sysenv)
with fs.cd(project_dir):
config = ProjectConfig.get_instance(
project_conf or join(project_dir, "platformio.ini"))
config.validate(envs=[environment] if environment else None)
env_name = environment or helpers.get_default_debug_env(config)
env_options = config.items(env=env_name, as_dict=True)
if not set(env_options.keys()) >= set(["platform", "board"]):
raise exception.ProjectEnvsNotAvailable()
debug_options = helpers.validate_debug_options(ctx, env_options)
assert debug_options
if not interface:
return helpers.predebug_project(ctx, project_dir, env_name, False,
verbose)
configuration = load_project_ide_data(project_dir, env_name)
if not configuration:
raise exception.DebugInvalidOptions(
"Could not load debug configuration")
if "--version" in __unprocessed:
result = proc.exec_command([configuration['gdb_path'], "--version"])
if result['returncode'] == 0:
return click.echo(result['out'])
raise exception.PlatformioException("\n".join(
[result['out'], result['err']]))
try:
fs.ensure_udev_rules()
except exception.InvalidUdevRules as e:
for line in str(e).split("\n") + [""]:
click.echo(
('~"%s\\n"' if helpers.is_mi_mode(__unprocessed) else "%s") %
line)
debug_options['load_cmds'] = helpers.configure_esp32_load_cmds(
debug_options, configuration)
rebuild_prog = False
preload = debug_options['load_cmds'] == ["preload"]
load_mode = debug_options['load_mode']
if load_mode == "always":
rebuild_prog = (
preload
or not helpers.has_debug_symbols(configuration['prog_path']))
elif load_mode == "modified":
rebuild_prog = (
helpers.is_prog_obsolete(configuration['prog_path'])
or not helpers.has_debug_symbols(configuration['prog_path']))
else:
rebuild_prog = not isfile(configuration['prog_path'])
if preload or (not rebuild_prog and load_mode != "always"):
# don't load firmware through debug server
debug_options['load_cmds'] = []
if rebuild_prog:
if helpers.is_mi_mode(__unprocessed):
click.echo('~"Preparing firmware for debugging...\\n"')
output = helpers.GDBBytesIO()
with util.capture_std_streams(output):
helpers.predebug_project(ctx, project_dir, env_name, preload,
verbose)
output.close()
else:
click.echo("Preparing firmware for debugging...")
helpers.predebug_project(ctx, project_dir, env_name, preload,
verbose)
# save SHA sum of newly created prog
if load_mode == "modified":
helpers.is_prog_obsolete(configuration['prog_path'])
if not isfile(configuration['prog_path']):
raise exception.DebugInvalidOptions("Program/firmware is missed")
# run debugging client
inject_contrib_pysite()
from platformio.commands.debug.client import GDBClient, reactor
client = GDBClient(project_dir, __unprocessed, debug_options, env_options)
client.spawn(configuration['gdb_path'], configuration['prog_path'])
signal.signal(signal.SIGINT, lambda *args, **kwargs: None)
reactor.run()
return True

View File

@@ -1,265 +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.
import sys
import time
from fnmatch import fnmatch
from hashlib import sha1
from io import BytesIO
from os.path import isfile
from platformio import exception, fs, util
from platformio.commands.platform import \
platform_install as cmd_platform_install
from platformio.commands.run import cli as cmd_run
from platformio.managers.platform import PlatformFactory
from platformio.project.config import ProjectConfig
class GDBBytesIO(BytesIO): # pylint: disable=too-few-public-methods
STDOUT = sys.stdout
def write(self, text):
if "\n" in text:
for line in text.strip().split("\n"):
self.STDOUT.write('~"%s\\n"\n' % line)
else:
self.STDOUT.write('~"%s"' % text)
self.STDOUT.flush()
def is_mi_mode(args):
return "--interpreter" in " ".join(args)
def get_default_debug_env(config):
default_envs = config.default_envs()
all_envs = config.envs()
for env in default_envs:
if config.get("env:" + env, "build_type") == "debug":
return env
for env in all_envs:
if config.get("env:" + env, "build_type") == "debug":
return env
return default_envs[0] if default_envs else all_envs[0]
def predebug_project(ctx, project_dir, env_name, preload, verbose):
ctx.invoke(cmd_run,
project_dir=project_dir,
environment=[env_name],
target=["debug"] + (["upload"] if preload else []),
verbose=verbose)
if preload:
time.sleep(5)
def validate_debug_options(cmd_ctx, env_options):
def _cleanup_cmds(items):
items = ProjectConfig.parse_multi_values(items)
return [
"$LOAD_CMDS" if item == "$LOAD_CMD" else item for item in items
]
try:
platform = PlatformFactory.newPlatform(env_options['platform'])
except exception.UnknownPlatform:
cmd_ctx.invoke(cmd_platform_install,
platforms=[env_options['platform']],
skip_default_package=True)
platform = PlatformFactory.newPlatform(env_options['platform'])
board_config = platform.board_config(env_options['board'])
tool_name = board_config.get_debug_tool_name(env_options.get("debug_tool"))
tool_settings = board_config.get("debug", {}).get("tools",
{}).get(tool_name, {})
server_options = None
# specific server per a system
if isinstance(tool_settings.get("server", {}), list):
for item in tool_settings['server'][:]:
tool_settings['server'] = item
if util.get_systype() in item.get("system", []):
break
# user overwrites debug server
if env_options.get("debug_server"):
server_options = {
"cwd": None,
"executable": None,
"arguments": env_options.get("debug_server")
}
server_options['executable'] = server_options['arguments'][0]
server_options['arguments'] = server_options['arguments'][1:]
elif "server" in tool_settings:
server_package = tool_settings['server'].get("package")
server_package_dir = platform.get_package_dir(
server_package) if server_package else None
if server_package and not server_package_dir:
platform.install_packages(with_packages=[server_package],
skip_default_package=True,
silent=True)
server_package_dir = platform.get_package_dir(server_package)
server_options = dict(
cwd=server_package_dir if server_package else None,
executable=tool_settings['server'].get("executable"),
arguments=[
a.replace("$PACKAGE_DIR", server_package_dir)
if server_package_dir else a
for a in tool_settings['server'].get("arguments", [])
])
extra_cmds = _cleanup_cmds(env_options.get("debug_extra_cmds"))
extra_cmds.extend(_cleanup_cmds(tool_settings.get("extra_cmds")))
result = dict(
tool=tool_name,
upload_protocol=env_options.get(
"upload_protocol",
board_config.get("upload", {}).get("protocol")),
load_cmds=_cleanup_cmds(
env_options.get(
"debug_load_cmds",
tool_settings.get("load_cmds",
tool_settings.get("load_cmd", "load")))),
load_mode=env_options.get("debug_load_mode",
tool_settings.get("load_mode", "always")),
init_break=env_options.get(
"debug_init_break", tool_settings.get("init_break",
"tbreak main")),
init_cmds=_cleanup_cmds(
env_options.get("debug_init_cmds",
tool_settings.get("init_cmds"))),
extra_cmds=extra_cmds,
require_debug_port=tool_settings.get("require_debug_port", False),
port=reveal_debug_port(
env_options.get("debug_port", tool_settings.get("port")),
tool_name, tool_settings),
server=server_options)
return result
def configure_esp32_load_cmds(debug_options, configuration):
ignore_conds = [
debug_options['load_cmds'] != ["load"],
"xtensa-esp32" not in configuration.get("cc_path", ""),
not configuration.get("flash_extra_images"), not all([
isfile(item['path'])
for item in configuration.get("flash_extra_images")
])
]
if any(ignore_conds):
return debug_options['load_cmds']
mon_cmds = [
'monitor program_esp32 "{{{path}}}" {offset} verify'.format(
path=fs.to_unix_path(item['path']), offset=item['offset'])
for item in configuration.get("flash_extra_images")
]
mon_cmds.append('monitor program_esp32 "{%s.bin}" 0x10000 verify' %
fs.to_unix_path(configuration['prog_path'][:-4]))
return mon_cmds
def has_debug_symbols(prog_path):
if not isfile(prog_path):
return False
matched = {
b".debug_info": False,
b".debug_abbrev": False,
b" -Og": False,
b" -g": False,
b"__PLATFORMIO_BUILD_DEBUG__": False
}
with open(prog_path, "rb") as fp:
last_data = b""
while True:
data = fp.read(1024)
if not data:
break
for pattern, found in matched.items():
if found:
continue
if pattern in last_data + data:
matched[pattern] = True
last_data = data
return all(matched.values())
def is_prog_obsolete(prog_path):
prog_hash_path = prog_path + ".sha1"
if not isfile(prog_path):
return True
shasum = sha1()
with open(prog_path, "rb") as fp:
while True:
data = fp.read(1024)
if not data:
break
shasum.update(data)
new_digest = shasum.hexdigest()
old_digest = None
if isfile(prog_hash_path):
with open(prog_hash_path, "r") as fp:
old_digest = fp.read()
if new_digest == old_digest:
return False
with open(prog_hash_path, "w") as fp:
fp.write(new_digest)
return True
def reveal_debug_port(env_debug_port, tool_name, tool_settings):
def _get_pattern():
if not env_debug_port:
return None
if set(["*", "?", "[", "]"]) & set(env_debug_port):
return env_debug_port
return None
def _is_match_pattern(port):
pattern = _get_pattern()
if not pattern:
return True
return fnmatch(port, pattern)
def _look_for_serial_port(hwids):
for item in util.get_serialports(filter_hwid=True):
if not _is_match_pattern(item['port']):
continue
port = item['port']
if tool_name.startswith("blackmagic"):
if "windows" in util.get_systype() and \
port.startswith("COM") and len(port) > 4:
port = "\\\\.\\%s" % port
if "GDB" in item['description']:
return port
for hwid in hwids:
hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "")
if hwid_str in item['hwid']:
return port
return None
if env_debug_port and not _get_pattern():
return env_debug_port
if not tool_settings.get("require_debug_port"):
return None
debug_port = _look_for_serial_port(tool_settings.get("hwids", []))
if not debug_port:
raise exception.DebugInvalidOptions(
"Please specify `debug_port` for environment")
return debug_port

View File

@@ -1,124 +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.
GDB_DEFAULT_INIT_CONFIG = """
define pio_reset_halt_target
monitor reset halt
end
define pio_reset_target
monitor reset
end
target extended-remote $DEBUG_PORT
$INIT_BREAK
pio_reset_halt_target
$LOAD_CMDS
monitor init
pio_reset_halt_target
"""
GDB_STUTIL_INIT_CONFIG = """
define pio_reset_halt_target
monitor halt
monitor reset
end
define pio_reset_target
monitor reset
end
target extended-remote $DEBUG_PORT
$INIT_BREAK
pio_reset_halt_target
$LOAD_CMDS
pio_reset_halt_target
"""
GDB_JLINK_INIT_CONFIG = """
define pio_reset_halt_target
monitor halt
monitor reset
end
define pio_reset_target
monitor reset
end
target extended-remote $DEBUG_PORT
$INIT_BREAK
pio_reset_halt_target
$LOAD_CMDS
pio_reset_halt_target
"""
GDB_BLACKMAGIC_INIT_CONFIG = """
define pio_reset_halt_target
set language c
set *0xE000ED0C = 0x05FA0004
set $busy = (*0xE000ED0C & 0x4)
while ($busy)
set $busy = (*0xE000ED0C & 0x4)
end
set language auto
end
define pio_reset_target
pio_reset_halt_target
end
target extended-remote $DEBUG_PORT
monitor swdp_scan
attach 1
set mem inaccessible-by-default off
$INIT_BREAK
$LOAD_CMDS
set language c
set *0xE000ED0C = 0x05FA0004
set $busy = (*0xE000ED0C & 0x4)
while ($busy)
set $busy = (*0xE000ED0C & 0x4)
end
set language auto
"""
GDB_MSPDEBUG_INIT_CONFIG = """
define pio_reset_halt_target
end
define pio_reset_target
end
target extended-remote $DEBUG_PORT
$INIT_BREAK
monitor erase
$LOAD_CMDS
pio_reset_halt_target
"""
GDB_QEMU_INIT_CONFIG = """
define pio_reset_halt_target
monitor system_reset
end
define pio_reset_target
pio_reset_halt_target
end
target extended-remote $DEBUG_PORT
$INIT_BREAK
$LOAD_CMDS
pio_reset_halt_target
"""

View File

@@ -1,84 +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.
import signal
import click
from twisted.internet import protocol # pylint: disable=import-error
from platformio import fs
from platformio.compat import string_types
from platformio.proc import get_pythonexe_path
from platformio.project.helpers import get_project_core_dir
LOG_FILE = None
class BaseProcess(protocol.ProcessProtocol, object):
STDOUT_CHUNK_SIZE = 2048
COMMON_PATTERNS = {
"PLATFORMIO_HOME_DIR": get_project_core_dir(),
"PLATFORMIO_CORE_DIR": get_project_core_dir(),
"PYTHONEXE": get_pythonexe_path()
}
def apply_patterns(self, source, patterns=None):
_patterns = self.COMMON_PATTERNS.copy()
_patterns.update(patterns or {})
for key, value in _patterns.items():
if key.endswith(("_DIR", "_PATH")):
_patterns[key] = fs.to_unix_path(value)
def _replace(text):
for key, value in _patterns.items():
pattern = "$%s" % key
text = text.replace(pattern, value or "")
return text
if isinstance(source, string_types):
source = _replace(source)
elif isinstance(source, (list, dict)):
items = enumerate(source) if isinstance(source,
list) else source.items()
for key, value in items:
if isinstance(value, string_types):
source[key] = _replace(value)
elif isinstance(value, (list, dict)):
source[key] = self.apply_patterns(value, patterns)
return source
def outReceived(self, data):
if LOG_FILE:
with open(LOG_FILE, "ab") as fp:
fp.write(data)
while data:
chunk = data[:self.STDOUT_CHUNK_SIZE]
click.echo(chunk, nl=False)
data = data[self.STDOUT_CHUNK_SIZE:]
@staticmethod
def errReceived(data):
if LOG_FILE:
with open(LOG_FILE, "ab") as fp:
fp.write(data)
click.echo(data, nl=False, err=True)
@staticmethod
def processEnded(_):
# Allow terminating via SIGINT/CTRL+C
signal.signal(signal.SIGINT, signal.default_int_handler)

View File

@@ -1,122 +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.
import os
from os.path import isdir, isfile, join
from twisted.internet import error # pylint: disable=import-error
from twisted.internet import reactor # pylint: disable=import-error
from platformio import exception, fs, util
from platformio.commands.debug.process import BaseProcess
from platformio.proc import where_is_program
class DebugServer(BaseProcess):
def __init__(self, debug_options, env_options):
self.debug_options = debug_options
self.env_options = env_options
self._debug_port = None
self._transport = None
self._process_ended = False
def spawn(self, patterns): # pylint: disable=too-many-branches
systype = util.get_systype()
server = self.debug_options.get("server")
if not server:
return None
server = self.apply_patterns(server, patterns)
server_executable = server['executable']
if not server_executable:
return None
if server['cwd']:
server_executable = join(server['cwd'], server_executable)
if ("windows" in systype and not server_executable.endswith(".exe")
and isfile(server_executable + ".exe")):
server_executable = server_executable + ".exe"
if not isfile(server_executable):
server_executable = where_is_program(server_executable)
if not isfile(server_executable):
raise exception.DebugInvalidOptions(
"\nCould not launch Debug Server '%s'. Please check that it "
"is installed and is included in a system PATH\n\n"
"See documentation or contact contact@platformio.org:\n"
"http://docs.platformio.org/page/plus/debugging.html\n" %
server_executable)
self._debug_port = ":3333"
openocd_pipe_allowed = all([
not self.debug_options['port'],
"openocd" in server_executable
]) # yapf: disable
if openocd_pipe_allowed:
args = []
if server['cwd']:
args.extend(["-s", server['cwd']])
args.extend([
"-c", "gdb_port pipe; tcl_port disabled; telnet_port disabled"
])
args.extend(server['arguments'])
str_args = " ".join(
[arg if arg.startswith("-") else '"%s"' % arg for arg in args])
self._debug_port = '| "%s" %s' % (server_executable, str_args)
self._debug_port = fs.to_unix_path(self._debug_port)
else:
env = os.environ.copy()
# prepend server "lib" folder to LD path
if ("windows" not in systype and server['cwd']
and isdir(join(server['cwd'], "lib"))):
ld_key = ("DYLD_LIBRARY_PATH"
if "darwin" in systype else "LD_LIBRARY_PATH")
env[ld_key] = join(server['cwd'], "lib")
if os.environ.get(ld_key):
env[ld_key] = "%s:%s" % (env[ld_key],
os.environ.get(ld_key))
# prepend BIN to PATH
if server['cwd'] and isdir(join(server['cwd'], "bin")):
env['PATH'] = "%s%s%s" % (
join(server['cwd'], "bin"), os.pathsep,
os.environ.get("PATH", os.environ.get("Path", "")))
self._transport = reactor.spawnProcess(
self,
server_executable, [server_executable] + server['arguments'],
path=server['cwd'],
env=env)
if "mspdebug" in server_executable.lower():
self._debug_port = ":2000"
elif "jlink" in server_executable.lower():
self._debug_port = ":2331"
elif "qemu" in server_executable.lower():
self._debug_port = ":1234"
return self._transport
def get_debug_port(self):
return self._debug_port
def processEnded(self, reason):
self._process_ended = True
super(DebugServer, self).processEnded(reason)
def terminate(self):
if self._process_ended or not self._transport:
return
try:
self._transport.signalProcess("KILL")
except (OSError, error.ProcessExitedAlready):
pass

View File

@@ -1,221 +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.
import sys
from fnmatch import fnmatch
from os import getcwd
from os.path import join
import click
from serial.tools import miniterm
from platformio import exception, util
from platformio.compat import dump_json_to_unicode
from platformio.project.config import ProjectConfig
@click.group(short_help="Monitor device or list existing")
def cli():
pass
@cli.command("list", short_help="List devices")
@click.option("--serial", is_flag=True, help="List serial ports, default")
@click.option("--logical", is_flag=True, help="List logical devices")
@click.option("--mdns", is_flag=True, help="List multicast DNS services")
@click.option("--json-output", is_flag=True)
def device_list( # pylint: disable=too-many-branches
serial, logical, mdns, json_output):
if not logical and not mdns:
serial = True
data = {}
if serial:
data['serial'] = util.get_serial_ports()
if logical:
data['logical'] = util.get_logical_devices()
if mdns:
data['mdns'] = util.get_mdns_services()
single_key = list(data)[0] if len(list(data)) == 1 else None
if json_output:
return click.echo(
dump_json_to_unicode(data[single_key] if single_key else data))
titles = {
"serial": "Serial Ports",
"logical": "Logical Devices",
"mdns": "Multicast DNS Services"
}
for key, value in data.items():
if not single_key:
click.secho(titles[key], bold=True)
click.echo("=" * len(titles[key]))
if key == "serial":
for item in value:
click.secho(item['port'], fg="cyan")
click.echo("-" * len(item['port']))
click.echo("Hardware ID: %s" % item['hwid'])
click.echo("Description: %s" % item['description'])
click.echo("")
if key == "logical":
for item in value:
click.secho(item['path'], fg="cyan")
click.echo("-" * len(item['path']))
click.echo("Name: %s" % item['name'])
click.echo("")
if key == "mdns":
for item in value:
click.secho(item['name'], fg="cyan")
click.echo("-" * len(item['name']))
click.echo("Type: %s" % item['type'])
click.echo("IP: %s" % item['ip'])
click.echo("Port: %s" % item['port'])
if item['properties']:
click.echo("Properties: %s" % ("; ".join([
"%s=%s" % (k, v)
for k, v in item['properties'].items()
])))
click.echo("")
if single_key:
click.echo("")
return True
@cli.command("monitor", short_help="Monitor device (Serial)")
@click.option("--port", "-p", help="Port, a number or a device name")
@click.option("--baud", "-b", type=int, help="Set baud rate, default=9600")
@click.option("--parity",
default="N",
type=click.Choice(["N", "E", "O", "S", "M"]),
help="Set parity, default=N")
@click.option("--rtscts",
is_flag=True,
help="Enable RTS/CTS flow control, default=Off")
@click.option("--xonxoff",
is_flag=True,
help="Enable software flow control, default=Off")
@click.option("--rts",
default=None,
type=click.IntRange(0, 1),
help="Set initial RTS line state")
@click.option("--dtr",
default=None,
type=click.IntRange(0, 1),
help="Set initial DTR line state")
@click.option("--echo", is_flag=True, help="Enable local echo, default=Off")
@click.option("--encoding",
default="UTF-8",
help="Set the encoding for the serial port (e.g. hexlify, "
"Latin1, UTF-8), default: UTF-8")
@click.option("--filter", "-f", multiple=True, help="Add text transformation")
@click.option("--eol",
default="CRLF",
type=click.Choice(["CR", "LF", "CRLF"]),
help="End of line mode, default=CRLF")
@click.option("--raw",
is_flag=True,
help="Do not apply any encodings/transformations")
@click.option("--exit-char",
type=int,
default=3,
help="ASCII code of special character that is used to exit "
"the application, default=3 (Ctrl+C)")
@click.option("--menu-char",
type=int,
default=20,
help="ASCII code of special character that is used to "
"control miniterm (menu), default=20 (DEC)")
@click.option("--quiet",
is_flag=True,
help="Diagnostics: suppress non-error messages, default=Off")
@click.option("-d",
"--project-dir",
default=getcwd,
type=click.Path(exists=True,
file_okay=False,
dir_okay=True,
resolve_path=True))
@click.option(
"-e",
"--environment",
help="Load configuration from `platformio.ini` and specified environment")
def device_monitor(**kwargs): # pylint: disable=too-many-branches
env_options = {}
try:
env_options = get_project_options(kwargs['project_dir'],
kwargs['environment'])
for k in ("port", "speed", "rts", "dtr"):
k2 = "monitor_%s" % k
if k == "speed":
k = "baud"
if kwargs[k] is None and k2 in env_options:
kwargs[k] = env_options[k2]
if k != "port":
kwargs[k] = int(kwargs[k])
except exception.NotPlatformIOProject:
pass
if not kwargs['port']:
ports = util.get_serial_ports(filter_hwid=True)
if len(ports) == 1:
kwargs['port'] = ports[0]['port']
sys.argv = ["monitor"] + env_options.get("monitor_flags", [])
for k, v in kwargs.items():
if k in ("port", "baud", "rts", "dtr", "environment", "project_dir"):
continue
k = "--" + k.replace("_", "-")
if k in env_options.get("monitor_flags", []):
continue
if isinstance(v, bool):
if v:
sys.argv.append(k)
elif isinstance(v, tuple):
for i in v:
sys.argv.extend([k, i])
else:
sys.argv.extend([k, str(v)])
if kwargs['port'] and (set(["*", "?", "[", "]"]) & set(kwargs['port'])):
for item in util.get_serial_ports():
if fnmatch(item['port'], kwargs['port']):
kwargs['port'] = item['port']
break
try:
miniterm.main(default_port=kwargs['port'],
default_baudrate=kwargs['baud'] or 9600,
default_rts=kwargs['rts'],
default_dtr=kwargs['dtr'])
except Exception as e:
raise exception.MinitermException(e)
def get_project_options(project_dir, environment=None):
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
config.validate(envs=[environment] if environment else None)
if not environment:
default_envs = config.default_envs()
if default_envs:
environment = default_envs[0]
else:
environment = config.envs()[0]
return config.items(env=environment, as_dict=True)

View File

@@ -0,0 +1,18 @@
# 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.
# pylint: disable=unused-import
from platformio.device.monitor.filters.base import (
DeviceMonitorFilterBase as DeviceMonitorFilter,
)

View File

@@ -1,109 +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.
import mimetypes
import socket
from os.path import isdir
import click
from platformio import exception
from platformio.managers.core import (get_core_package_dir,
inject_contrib_pysite)
@click.command("home", short_help="PIO Home")
@click.option("--port", type=int, default=8008, help="HTTP port, default=8008")
@click.option(
"--host",
default="127.0.0.1",
help="HTTP host, default=127.0.0.1. "
"You can open PIO Home for inbound connections with --host=0.0.0.0")
@click.option("--no-open", is_flag=True) # pylint: disable=too-many-locals
def cli(port, host, no_open):
# import contrib modules
inject_contrib_pysite()
# pylint: disable=import-error
from autobahn.twisted.resource import WebSocketResource
from twisted.internet import reactor
from twisted.web import server
# pylint: enable=import-error
from platformio.commands.home.rpc.handlers.app import AppRPC
from platformio.commands.home.rpc.handlers.ide import IDERPC
from platformio.commands.home.rpc.handlers.misc import MiscRPC
from platformio.commands.home.rpc.handlers.os import OSRPC
from platformio.commands.home.rpc.handlers.piocore import PIOCoreRPC
from platformio.commands.home.rpc.handlers.project import ProjectRPC
from platformio.commands.home.rpc.server import JSONRPCServerFactory
from platformio.commands.home.web import WebRoot
factory = JSONRPCServerFactory()
factory.addHandler(AppRPC(), namespace="app")
factory.addHandler(IDERPC(), namespace="ide")
factory.addHandler(MiscRPC(), namespace="misc")
factory.addHandler(OSRPC(), namespace="os")
factory.addHandler(PIOCoreRPC(), namespace="core")
factory.addHandler(ProjectRPC(), namespace="project")
contrib_dir = get_core_package_dir("contrib-piohome")
if not isdir(contrib_dir):
raise exception.PlatformioException("Invalid path to PIO Home Contrib")
# Ensure PIO Home mimetypes are known
mimetypes.add_type("text/html", ".html")
mimetypes.add_type("text/css", ".css")
mimetypes.add_type("application/javascript", ".js")
root = WebRoot(contrib_dir)
root.putChild(b"wsrpc", WebSocketResource(factory))
site = server.Site(root)
# hook for `platformio-node-helpers`
if host == "__do_not_start__":
return
# if already started
already_started = False
socket.setdefaulttimeout(1)
try:
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
already_started = True
except: # pylint: disable=bare-except
pass
home_url = "http://%s:%d" % (host, port)
if not no_open:
if already_started:
click.launch(home_url)
else:
reactor.callLater(1, lambda: click.launch(home_url))
click.echo("\n".join([
"",
" ___I_",
" /\\-_--\\ PlatformIO Home",
"/ \\_-__\\",
"|[]| [] | %s" % home_url,
"|__|____|______________%s" % ("_" * len(host)),
]))
click.echo("")
click.echo("Open PIO Home in your browser by this URL => %s" % home_url)
if already_started:
return
click.echo("PIO Home has been started. Press Ctrl+C to shutdown.")
reactor.listenTCP(port, site, interface=host)
reactor.run()

View File

@@ -1,71 +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.
# pylint: disable=keyword-arg-before-vararg, arguments-differ
import os
import socket
import requests
from twisted.internet import defer # pylint: disable=import-error
from twisted.internet import reactor # pylint: disable=import-error
from twisted.internet import threads # pylint: disable=import-error
from platformio import util
from platformio.proc import where_is_program
class AsyncSession(requests.Session):
def __init__(self, n=None, *args, **kwargs):
if n:
pool = reactor.getThreadPool()
pool.adjustPoolsize(0, n)
super(AsyncSession, self).__init__(*args, **kwargs)
def request(self, *args, **kwargs):
func = super(AsyncSession, self).request
return threads.deferToThread(func, *args, **kwargs)
def wrap(self, *args, **kwargs): # pylint: disable=no-self-use
return defer.ensureDeferred(*args, **kwargs)
@util.memoized(expire="60s")
def requests_session():
return AsyncSession(n=5)
@util.memoized(expire="60s")
def get_core_fullpath():
return where_is_program(
"platformio" + (".exe" if "windows" in util.get_systype() else ""))
@util.memoized(expire="10s")
def is_twitter_blocked():
ip = "104.244.42.1"
timeout = 2
try:
if os.getenv("HTTP_PROXY", os.getenv("HTTPS_PROXY")):
requests.get("http://%s" % ip,
allow_redirects=False,
timeout=timeout)
else:
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((ip, 80))
return False
except: # pylint: disable=bare-except
pass
return True

View File

@@ -1,81 +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.
from __future__ import absolute_import
from os.path import expanduser, join
from platformio import __version__, app, util
from platformio.project.helpers import (get_project_core_dir,
is_platformio_project)
class AppRPC(object):
APPSTATE_PATH = join(get_project_core_dir(), "homestate.json")
IGNORE_STORAGE_KEYS = [
"cid", "coreVersion", "coreSystype", "coreCaller", "coreSettings",
"homeDir", "projectsDir"
]
@staticmethod
def load_state():
with app.State(AppRPC.APPSTATE_PATH, lock=True) as state:
storage = state.get("storage", {})
# base data
caller_id = app.get_session_var("caller_id")
storage['cid'] = app.get_cid()
storage['coreVersion'] = __version__
storage['coreSystype'] = util.get_systype()
storage['coreCaller'] = (str(caller_id).lower()
if caller_id else None)
storage['coreSettings'] = {
name: {
"description": data['description'],
"default_value": data['value'],
"value": app.get_setting(name)
}
for name, data in app.DEFAULT_SETTINGS.items()
}
storage['homeDir'] = expanduser("~")
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)
]
state['storage'] = storage
state.modified = False # skip saving extra fields
return state.as_dict()
@staticmethod
def get_state():
return AppRPC.load_state()
@staticmethod
def save_state(state):
with app.State(AppRPC.APPSTATE_PATH, lock=True) as s:
s.clear()
s.update(state)
storage = s.get("storage", {})
for k in AppRPC.IGNORE_STORAGE_KEYS:
if k in storage:
del storage[k]
return True

View File

@@ -1,44 +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.
import time
import jsonrpc # pylint: disable=import-error
from twisted.internet import defer # pylint: disable=import-error
class IDERPC(object):
def __init__(self):
self._queue = {}
def send_command(self, command, params, sid=0):
if not self._queue.get(sid):
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4005, message="PIO Home IDE agent is not started")
while self._queue[sid]:
self._queue[sid].pop().callback({
"id": time.time(),
"method": command,
"params": params
})
def listen_commands(self, sid=0):
if sid not in self._queue:
self._queue[sid] = []
self._queue[sid].append(defer.Deferred())
return self._queue[sid][-1]
def open_project(self, project_dir, sid=0):
return self.send_command("open_project", project_dir, sid)

View File

@@ -1,54 +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.
import json
import time
from twisted.internet import defer, reactor # pylint: disable=import-error
from platformio import app
from platformio.commands.home.rpc.handlers.os import OSRPC
class MiscRPC(object):
def load_latest_tweets(self, username):
cache_key = "piohome_latest_tweets_" + str(username)
cache_valid = "7d"
with app.ContentCache() as cc:
cache_data = cc.get(cache_key)
if cache_data:
cache_data = json.loads(cache_data)
# automatically update cache in background every 12 hours
if cache_data['time'] < (time.time() - (3600 * 12)):
reactor.callLater(5, self._preload_latest_tweets, username,
cache_key, cache_valid)
return cache_data['result']
result = self._preload_latest_tweets(username, cache_key, cache_valid)
return result
@staticmethod
@defer.inlineCallbacks
def _preload_latest_tweets(username, cache_key, cache_valid):
result = yield OSRPC.fetch_content(
"https://api.platformio.org/tweets/" + username)
result = json.loads(result)
with app.ContentCache() as cc:
cc.set(cache_key,
json.dumps({
"time": int(time.time()),
"result": result
}), cache_valid)
defer.returnValue(result)

View File

@@ -1,162 +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.
from __future__ import absolute_import
import json
import os
import sys
from io import BytesIO, StringIO
import click
import jsonrpc # pylint: disable=import-error
from twisted.internet import defer # pylint: disable=import-error
from twisted.internet import threads # pylint: disable=import-error
from twisted.internet import utils # pylint: disable=import-error
from platformio import __main__, __version__, fs
from platformio.commands.home import helpers
from platformio.compat import (PY2, get_filesystem_encoding, is_bytes,
string_types)
try:
from thread import get_ident as thread_get_ident
except ImportError:
from threading import get_ident as thread_get_ident
class MultiThreadingStdStream(object):
def __init__(self, parent_stream):
self._buffers = {thread_get_ident(): parent_stream}
def __getattr__(self, name):
thread_id = thread_get_ident()
self._ensure_thread_buffer(thread_id)
return getattr(self._buffers[thread_id], name)
def _ensure_thread_buffer(self, thread_id):
if thread_id not in self._buffers:
self._buffers[thread_id] = BytesIO() if PY2 else StringIO()
def write(self, value):
thread_id = thread_get_ident()
self._ensure_thread_buffer(thread_id)
return self._buffers[thread_id].write(
value.decode() if is_bytes(value) else value)
def get_value_and_reset(self):
result = ""
try:
result = self.getvalue()
self.truncate(0)
self.seek(0)
except AttributeError:
pass
return result
class PIOCoreRPC(object):
@staticmethod
def version():
return __version__
@staticmethod
def setup_multithreading_std_streams():
if isinstance(sys.stdout, MultiThreadingStdStream):
return
PIOCoreRPC.thread_stdout = MultiThreadingStdStream(sys.stdout)
PIOCoreRPC.thread_stderr = MultiThreadingStdStream(sys.stderr)
sys.stdout = PIOCoreRPC.thread_stdout
sys.stderr = PIOCoreRPC.thread_stderr
@staticmethod
def call(args, options=None):
return defer.maybeDeferred(PIOCoreRPC._call_generator, args, options)
@staticmethod
@defer.inlineCallbacks
def _call_generator(args, options=None):
for i, arg in enumerate(args):
if isinstance(arg, string_types):
args[i] = arg.encode(get_filesystem_encoding()) if PY2 else arg
else:
args[i] = str(arg)
to_json = "--json-output" in args
try:
if args and args[0] in ("account", "remote"):
result = yield PIOCoreRPC._call_subprocess(args, options)
defer.returnValue(PIOCoreRPC._process_result(result, to_json))
else:
result = yield PIOCoreRPC._call_inline(args, options)
try:
defer.returnValue(
PIOCoreRPC._process_result(result, to_json))
except ValueError:
# fall-back to subprocess method
result = yield PIOCoreRPC._call_subprocess(args, options)
defer.returnValue(
PIOCoreRPC._process_result(result, to_json))
except Exception as e: # pylint: disable=bare-except
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4003, message="PIO Core Call Error", data=str(e))
@staticmethod
def _call_inline(args, options):
PIOCoreRPC.setup_multithreading_std_streams()
cwd = (options or {}).get("cwd") or os.getcwd()
def _thread_task():
with fs.cd(cwd):
exit_code = __main__.main(["-c"] + args)
return (PIOCoreRPC.thread_stdout.get_value_and_reset(),
PIOCoreRPC.thread_stderr.get_value_and_reset(), exit_code)
return threads.deferToThread(_thread_task)
@staticmethod
def _call_subprocess(args, options):
cwd = (options or {}).get("cwd") or os.getcwd()
return utils.getProcessOutputAndValue(
helpers.get_core_fullpath(),
args,
path=cwd,
env={k: v
for k, v in os.environ.items() if "%" not in k})
@staticmethod
def _process_result(result, to_json=False):
out, err, code = result
text = ("%s\n\n%s" % (out, err)).strip()
if code != 0:
raise Exception(text)
if not to_json:
return text
try:
return json.loads(out)
except ValueError as e:
click.secho("%s => `%s`" % (e, out), fg="red", err=True)
# if PIO Core prints unhandled warnings
for line in out.split("\n"):
line = line.strip()
if not line:
continue
try:
return json.loads(line)
except ValueError:
pass
raise e

View File

@@ -1,277 +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.
from __future__ import absolute_import
import os
import shutil
import time
from os.path import (basename, expanduser, getmtime, isdir, isfile, join,
realpath, sep)
import jsonrpc # pylint: disable=import-error
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.compat import PY2, get_filesystem_encoding
from platformio.ide.projectgenerator import ProjectGenerator
from platformio.managers.platform import PlatformManager
from platformio.project.config import ProjectConfig
from platformio.project.helpers import (get_project_libdeps_dir,
get_project_src_dir,
is_platformio_project)
class ProjectRPC(object):
@staticmethod
def _get_projects(project_dirs=None):
def _get_project_data(project_dir):
data = {"boards": [], "envLibdepsDirs": [], "libExtraDirs": []}
config = ProjectConfig(join(project_dir, "platformio.ini"))
libdeps_dir = get_project_libdeps_dir()
data['libExtraDirs'].extend(
config.get("platformio", "lib_extra_dirs", []))
for section in config.sections():
if not section.startswith("env:"):
continue
data['envLibdepsDirs'].append(join(libdeps_dir, section[4:]))
if config.has_option(section, "board"):
data['boards'].append(config.get(section, "board"))
data['libExtraDirs'].extend(
config.get(section, "lib_extra_dirs", []))
# skip non existing folders and resolve full path
for key in ("envLibdepsDirs", "libExtraDirs"):
data[key] = [
expanduser(d) if d.startswith("~") else realpath(d)
for d in data[key] if isdir(d)
]
return data
def _path_to_name(path):
return (sep).join(path.split(sep)[-2:])
if not project_dirs:
project_dirs = AppRPC.load_state()['storage']['recentProjects']
result = []
pm = PlatformManager()
for project_dir in project_dirs:
data = {}
boards = []
try:
with fs.cd(project_dir):
data = _get_project_data(project_dir)
except exception.PlatformIOProjectException:
continue
for board_id in data.get("boards", []):
name = board_id
try:
name = pm.board_config(board_id)['name']
except exception.PlatformioException:
pass
boards.append({"id": board_id, "name": name})
result.append({
"path":
project_dir,
"name":
_path_to_name(project_dir),
"modified":
int(getmtime(project_dir)),
"boards":
boards,
"envLibStorages": [{
"name": basename(d),
"path": d
} for d in data.get("envLibdepsDirs", [])],
"extraLibStorages": [{
"name": _path_to_name(d),
"path": d
} for d in data.get("libExtraDirs", [])]
})
return result
def get_projects(self, project_dirs=None):
return self._get_projects(project_dirs)
@staticmethod
def get_project_examples():
result = []
for manifest in PlatformManager().get_installed():
examples_dir = join(manifest['__pkg_dir'], "examples")
if not isdir(examples_dir):
continue
items = []
for project_dir, _, __ in os.walk(examples_dir):
project_description = None
try:
config = ProjectConfig(join(project_dir, "platformio.ini"))
config.validate(silent=True)
project_description = config.get("platformio",
"description")
except exception.PlatformIOProjectException:
continue
path_tokens = project_dir.split(sep)
items.append({
"name":
"/".join(path_tokens[path_tokens.index("examples") + 1:]),
"path":
project_dir,
"description":
project_description
})
result.append({
"platform": {
"title": manifest['title'],
"version": manifest['version']
},
"items": sorted(items, key=lambda item: item['name'])
})
return sorted(result, key=lambda data: data['platform']['title'])
def init(self, board, framework, project_dir):
assert project_dir
state = AppRPC.load_state()
if not isdir(project_dir):
os.makedirs(project_dir)
args = ["init", "--board", board]
if framework:
args.extend(["--project-option", "framework = %s" % framework])
if (state['storage']['coreCaller'] and state['storage']['coreCaller']
in ProjectGenerator.get_supported_ides()):
args.extend(["--ide", state['storage']['coreCaller']])
d = PIOCoreRPC.call(args, options={"cwd": project_dir})
d.addCallback(self._generate_project_main, project_dir, framework)
return d
@staticmethod
def _generate_project_main(_, project_dir, framework):
main_content = None
if framework == "arduino":
main_content = "\n".join([
"#include <Arduino.h>",
"",
"void setup() {",
" // put your setup code here, to run once:",
"}",
"",
"void loop() {",
" // put your main code here, to run repeatedly:",
"}"
""
]) # yapf: disable
elif framework == "mbed":
main_content = "\n".join([
"#include <mbed.h>",
"",
"int main() {",
"",
" // put your setup code here, to run once:",
"",
" while(1) {",
" // put your main code here, to run repeatedly:",
" }",
"}",
""
]) # yapf: disable
if not main_content:
return project_dir
with fs.cd(project_dir):
src_dir = get_project_src_dir()
main_path = join(src_dir, "main.cpp")
if isfile(main_path):
return project_dir
if not isdir(src_dir):
os.makedirs(src_dir)
with open(main_path, "w") as f:
f.write(main_content.strip())
return project_dir
def import_arduino(self, board, use_arduino_libs, arduino_project_dir):
board = str(board)
if arduino_project_dir and PY2:
arduino_project_dir = arduino_project_dir.encode(
get_filesystem_encoding())
# don't import PIO Project
if is_platformio_project(arduino_project_dir):
return arduino_project_dir
is_arduino_project = any([
isfile(
join(arduino_project_dir,
"%s.%s" % (basename(arduino_project_dir), ext)))
for ext in ("ino", "pde")
])
if not is_arduino_project:
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4000,
message="Not an Arduino project: %s" % arduino_project_dir)
state = AppRPC.load_state()
project_dir = join(state['storage']['projectsDir'],
time.strftime("%y%m%d-%H%M%S-") + board)
if not isdir(project_dir):
os.makedirs(project_dir)
args = ["init", "--board", board]
args.extend(["--project-option", "framework = arduino"])
if use_arduino_libs:
args.extend([
"--project-option",
"lib_extra_dirs = ~/Documents/Arduino/libraries"
])
if (state['storage']['coreCaller'] and state['storage']['coreCaller']
in ProjectGenerator.get_supported_ides()):
args.extend(["--ide", state['storage']['coreCaller']])
d = PIOCoreRPC.call(args, options={"cwd": project_dir})
d.addCallback(self._finalize_arduino_import, project_dir,
arduino_project_dir)
return d
@staticmethod
def _finalize_arduino_import(_, project_dir, arduino_project_dir):
with fs.cd(project_dir):
src_dir = get_project_src_dir()
if isdir(src_dir):
fs.rmtree(src_dir)
shutil.copytree(arduino_project_dir, src_dir)
return project_dir
@staticmethod
def import_pio(project_dir):
if not project_dir or not is_platformio_project(project_dir):
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4001,
message="Not an PlatformIO project: %s" % project_dir)
new_project_dir = join(
AppRPC.load_state()['storage']['projectsDir'],
time.strftime("%y%m%d-%H%M%S-") + basename(project_dir))
shutil.copytree(project_dir, new_project_dir)
state = AppRPC.load_state()
args = ["init"]
if (state['storage']['coreCaller'] and state['storage']['coreCaller']
in ProjectGenerator.get_supported_ides()):
args.extend(["--ide", state['storage']['coreCaller']])
d = PIOCoreRPC.call(args, options={"cwd": new_project_dir})
d.addCallback(lambda _: new_project_dir)
return d

Some files were not shown because too many files have changed in this diff Show More