From aadb1071fc9bca1a83bf8bbeb92bcd1924aeda97 Mon Sep 17 00:00:00 2001
From: unknown <2569982966@qq.com>
Date: Sat, 7 Oct 2023 14:54:02 +0800
Subject: [PATCH] test
---
.github/FUNDING.yml | 1 +
.github/ISSUE_TEMPLATE.md | 63 +
.github/workflows/core.yml | 52 +
.github/workflows/deployment.yml | 45 +
.github/workflows/docs.yml | 109 ++
.github/workflows/examples.yml | 63 +
.github/workflows/projects.yml | 69 +
.gitignore | 12 +
.gitmodules | 7 +
.pylintrc | 12 +
CODE_OF_CONDUCT.md | 3 +
CONTRIBUTING.md | 22 +
HISTORY.rst | 324 +++++
LICENSE | 174 +++
Makefile | 38 +
README.rst | 103 ++
SECURITY.md | 34 +
platformio/__init__.py | 73 +
platformio/__main__.py | 144 ++
platformio/account/__init__.py | 13 +
platformio/account/cli.py | 44 +
platformio/account/client.py | 352 +++++
platformio/account/commands/__init__.py | 13 +
platformio/account/commands/destroy.py | 37 +
platformio/account/commands/forgot.py | 29 +
platformio/account/commands/login.py | 26 +
platformio/account/commands/logout.py | 24 +
platformio/account/commands/password.py | 26 +
platformio/account/commands/register.py | 52 +
platformio/account/commands/show.py | 116 ++
platformio/account/commands/token.py | 32 +
platformio/account/commands/update.py | 59 +
platformio/account/org/__init__.py | 13 +
platformio/account/org/cli.py | 38 +
platformio/account/org/commands/__init__.py | 13 +
platformio/account/org/commands/add.py | 34 +
platformio/account/org/commands/create.py | 38 +
platformio/account/org/commands/destroy.py | 34 +
platformio/account/org/commands/list.py | 48 +
platformio/account/org/commands/remove.py | 34 +
platformio/account/org/commands/update.py | 50 +
platformio/account/team/__init__.py | 13 +
platformio/account/team/cli.py | 38 +
platformio/account/team/commands/__init__.py | 13 +
platformio/account/team/commands/add.py | 38 +
platformio/account/team/commands/create.py | 37 +
platformio/account/team/commands/destroy.py | 40 +
platformio/account/team/commands/list.py | 59 +
platformio/account/team/commands/remove.py | 36 +
platformio/account/team/commands/update.py | 51 +
platformio/account/validate.py | 84 ++
platformio/app.py | 293 ++++
platformio/assets/schema/library.json | 487 +++++++
.../assets/system/99-platformio-udev.rules | 173 +++
platformio/builder/__init__.py | 13 +
platformio/builder/main.py | 250 ++++
platformio/builder/tools/__init__.py | 13 +
platformio/builder/tools/pioasm.py | 29 +
platformio/builder/tools/piobuild.py | 390 ++++++
platformio/builder/tools/piohooks.py | 50 +
platformio/builder/tools/pioino.py | 256 ++++
platformio/builder/tools/piointegration.py | 193 +++
platformio/builder/tools/piolib.py | 1209 ++++++++++++++++
platformio/builder/tools/piomaxlen.py | 96 ++
platformio/builder/tools/piomisc.py | 149 ++
platformio/builder/tools/pioplatform.py | 248 ++++
platformio/builder/tools/pioproject.py | 54 +
platformio/builder/tools/piosize.py | 266 ++++
platformio/builder/tools/piotarget.py | 116 ++
platformio/builder/tools/piotest.py | 61 +
platformio/builder/tools/pioupload.py | 258 ++++
platformio/cache.py | 165 +++
platformio/check/__init__.py | 13 +
platformio/check/cli.py | 334 +++++
platformio/check/defect.py | 95 ++
platformio/check/tools/__init__.py | 33 +
platformio/check/tools/base.py | 267 ++++
platformio/check/tools/clangtidy.py | 90 ++
platformio/check/tools/cppcheck.py | 271 ++++
platformio/check/tools/pvsstudio.py | 251 ++++
platformio/cli.py | 110 ++
platformio/commands/__init__.py | 13 +
platformio/commands/boards.py | 86 ++
platformio/commands/ci.py | 174 +++
platformio/commands/device/__init__.py | 18 +
platformio/commands/lib.py | 459 +++++++
platformio/commands/platform.py | 391 ++++++
platformio/commands/settings.py | 80 ++
platformio/commands/update.py | 38 +
platformio/commands/upgrade.py | 153 +++
platformio/compat.py | 134 ++
platformio/debug/__init__.py | 13 +
platformio/debug/cli.py | 180 +++
platformio/debug/config/__init__.py | 13 +
platformio/debug/config/base.py | 247 ++++
platformio/debug/config/blackmagic.py | 71 +
platformio/debug/config/factory.py | 48 +
platformio/debug/config/generic.py | 38 +
platformio/debug/config/jlink.py | 46 +
platformio/debug/config/mspdebug.py | 36 +
platformio/debug/config/native.py | 33 +
platformio/debug/config/qemu.py | 37 +
platformio/debug/config/renode.py | 45 +
platformio/debug/exception.py | 36 +
platformio/debug/helpers.py | 160 +++
platformio/debug/process/__init__.py | 13 +
platformio/debug/process/base.py | 154 +++
platformio/debug/process/client.py | 104 ++
platformio/debug/process/gdb.py | 181 +++
platformio/debug/process/server.py | 147 ++
platformio/device/__init__.py | 13 +
platformio/device/cli.py | 30 +
platformio/device/finder.py | 257 ++++
platformio/device/list/__init__.py | 13 +
platformio/device/list/command.py | 99 ++
platformio/device/list/util.py | 165 +++
platformio/device/monitor/__init__.py | 13 +
platformio/device/monitor/command.py | 177 +++
platformio/device/monitor/filters/__init__.py | 13 +
platformio/device/monitor/filters/base.py | 100 ++
platformio/device/monitor/filters/hexlify.py | 38 +
platformio/device/monitor/filters/log2file.py | 47 +
.../device/monitor/filters/send_on_enter.py | 38 +
platformio/device/monitor/filters/time.py | 37 +
platformio/device/monitor/terminal.py | 188 +++
platformio/exception.py | 110 ++
platformio/fs.py | 226 +++
platformio/home/__init__.py | 13 +
platformio/home/cli.py | 118 ++
platformio/home/rpc/__init__.py | 13 +
platformio/home/rpc/handlers/__init__.py | 13 +
platformio/home/rpc/handlers/account.py | 30 +
platformio/home/rpc/handlers/app.py | 86 ++
platformio/home/rpc/handlers/base.py | 17 +
platformio/home/rpc/handlers/ide.py | 86 ++
platformio/home/rpc/handlers/misc.py | 50 +
platformio/home/rpc/handlers/os.py | 172 +++
platformio/home/rpc/handlers/piocore.py | 229 ++++
platformio/home/rpc/handlers/platform.py | 140 ++
platformio/home/rpc/handlers/project.py | 386 ++++++
platformio/home/rpc/handlers/registry.py | 31 +
platformio/home/rpc/server.py | 131 ++
platformio/home/run.py | 103 ++
platformio/http.py | 221 +++
platformio/maintenance.py | 282 ++++
platformio/package/__init__.py | 13 +
platformio/package/cli.py | 48 +
platformio/package/commands/__init__.py | 13 +
platformio/package/commands/exec.py | 109 ++
platformio/package/commands/install.py | 336 +++++
platformio/package/commands/list.py | 229 ++++
platformio/package/commands/outdated.py | 216 +++
platformio/package/commands/pack.py | 45 +
platformio/package/commands/publish.py | 206 +++
platformio/package/commands/search.py | 77 ++
platformio/package/commands/show.py | 154 +++
platformio/package/commands/uninstall.py | 237 ++++
platformio/package/commands/unpublish.py | 46 +
platformio/package/commands/update.py | 250 ++++
platformio/package/download.py | 165 +++
platformio/package/exception.py | 68 +
platformio/package/lockfile.py | 117 ++
platformio/package/manager/__init__.py | 13 +
platformio/package/manager/_download.py | 100 ++
platformio/package/manager/_install.py | 293 ++++
platformio/package/manager/_legacy.py | 61 +
platformio/package/manager/_registry.py | 197 +++
platformio/package/manager/_symlink.py | 71 +
platformio/package/manager/_uninstall.py | 97 ++
platformio/package/manager/_update.py | 137 ++
platformio/package/manager/base.py | 341 +++++
platformio/package/manager/core.py | 93 ++
platformio/package/manager/library.py | 124 ++
platformio/package/manager/platform.py | 180 +++
platformio/package/manager/tool.py | 30 +
platformio/package/manifest/__init__.py | 13 +
platformio/package/manifest/parser.py | 715 ++++++++++
platformio/package/manifest/schema.py | 284 ++++
platformio/package/meta.py | 528 +++++++
platformio/package/pack.py | 258 ++++
platformio/package/unpack.py | 209 +++
platformio/package/vcsclient.py | 273 ++++
platformio/package/version.py | 59 +
platformio/platform/__init__.py | 13 +
platformio/platform/_packages.py | 92 ++
platformio/platform/_run.py | 183 +++
platformio/platform/base.py | 239 ++++
platformio/platform/board.py | 145 ++
platformio/platform/exception.py | 46 +
platformio/platform/factory.py | 103 ++
platformio/proc.py | 219 +++
platformio/project/__init__.py | 13 +
platformio/project/cli.py | 32 +
platformio/project/commands/__init__.py | 13 +
platformio/project/commands/config.py | 104 ++
platformio/project/commands/init.py | 408 ++++++
platformio/project/commands/metadata.py | 81 ++
platformio/project/config.py | 524 +++++++
platformio/project/exception.py | 54 +
platformio/project/helpers.py | 196 +++
platformio/project/integration/__init__.py | 13 +
platformio/project/integration/generator.py | 176 +++
.../integration/tpls/clion/.gitignore.tpl | 1 +
.../tpls/codeblocks/platformio.cbp.tpl | 64 +
.../integration/tpls/eclipse/.cproject.tpl | 316 +++++
.../integration/tpls/eclipse/.project.tpl | 27 +
.../.settings/PlatformIO Debugger.launch.tpl | 38 +
.../.settings/language.settings.xml.tpl | 36 +
.../.settings/org.eclipse.cdt.core.prefs.tpl | 11 +
.../project/integration/tpls/emacs/.ccls.tpl | 14 +
.../integration/tpls/emacs/.gitignore.tpl | 3 +
.../netbeans/nbproject/configurations.xml.tpl | 73 +
.../nbproject/private/configurations.xml.tpl | 61 +
.../nbproject/private/launcher.properties.tpl | 40 +
.../nbproject/private/private.xml.tpl | 10 +
.../tpls/netbeans/nbproject/project.xml.tpl | 26 +
.../integration/tpls/qtcreator/.gitignore.tpl | 2 +
.../integration/tpls/qtcreator/Makefile.tpl | 12 +
.../tpls/qtcreator/platformio.cflags.tpl | 3 +
.../tpls/qtcreator/platformio.config.tpl | 8 +
.../tpls/qtcreator/platformio.creator.tpl | 2 +
.../tpls/qtcreator/platformio.cxxflags.tpl | 3 +
.../tpls/qtcreator/platformio.files.tpl | 6 +
.../tpls/qtcreator/platformio.includes.tpl | 4 +
.../integration/tpls/sublimetext/.ccls.tpl | 14 +
.../platformio.sublime-project.tpl | 108 ++
.../project/integration/tpls/vim/.ccls.tpl | 14 +
.../integration/tpls/vim/.gitignore.tpl | 4 +
.../platformio.vcxproj.filters.tpl | 29 +
.../tpls/visualstudio/platformio.vcxproj.tpl | 75 +
.../integration/tpls/vscode/.gitignore.tpl | 5 +
.../vscode/.vscode/c_cpp_properties.json.tpl | 138 ++
.../tpls/vscode/.vscode/extensions.json.tpl | 35 +
.../tpls/vscode/.vscode/launch.json.tpl | 99 ++
platformio/project/options.py | 852 ++++++++++++
platformio/project/savedeps.py | 87 ++
platformio/public.py | 29 +
platformio/registry/__init__.py | 13 +
platformio/registry/access/__init__.py | 13 +
platformio/registry/access/cli.py | 36 +
.../registry/access/commands/__init__.py | 13 +
platformio/registry/access/commands/grant.py | 39 +
platformio/registry/access/commands/list.py | 58 +
.../registry/access/commands/private.py | 33 +
platformio/registry/access/commands/public.py | 33 +
platformio/registry/access/commands/revoke.py | 38 +
platformio/registry/access/validate.py | 34 +
platformio/registry/client.py | 162 +++
platformio/registry/mirror.py | 98 ++
platformio/remote/__init__.py | 13 +
platformio/remote/ac/__init__.py | 13 +
platformio/remote/ac/base.py | 90 ++
platformio/remote/ac/process.py | 42 +
platformio/remote/ac/psync.py | 66 +
platformio/remote/ac/serial.py | 60 +
platformio/remote/cli.py | 412 ++++++
platformio/remote/client/__init__.py | 13 +
platformio/remote/client/agent_list.py | 38 +
platformio/remote/client/agent_service.py | 228 ++++
platformio/remote/client/async_base.py | 65 +
platformio/remote/client/base.py | 192 +++
platformio/remote/client/device_list.py | 54 +
platformio/remote/client/device_monitor.py | 239 ++++
platformio/remote/client/run_or_test.py | 271 ++++
platformio/remote/client/update_core.py | 22 +
platformio/remote/factory/__init__.py | 13 +
platformio/remote/factory/client.py | 86 ++
platformio/remote/factory/ssl.py | 41 +
platformio/remote/projectsync.py | 117 ++
platformio/run/__init__.py | 13 +
platformio/run/cli.py | 336 +++++
platformio/run/helpers.py | 45 +
platformio/run/processor.py | 91 ++
platformio/system/__init__.py | 13 +
platformio/system/cli.py | 32 +
platformio/system/commands/__init__.py | 13 +
platformio/system/commands/completion.py | 69 +
platformio/system/commands/info.py | 84 ++
platformio/system/commands/prune.py | 70 +
platformio/system/completion.py | 101 ++
platformio/system/prune.py | 98 ++
platformio/telemetry.py | 380 ++++++
platformio/test/__init__.py | 13 +
platformio/test/cli.py | 203 +++
platformio/test/exception.py | 33 +
platformio/test/helpers.py | 73 +
platformio/test/reports/__init__.py | 13 +
platformio/test/reports/base.py | 34 +
platformio/test/reports/json.py | 100 ++
platformio/test/reports/junit.py | 107 ++
platformio/test/reports/stdout.py | 99 ++
platformio/test/result.py | 166 +++
platformio/test/runners/__init__.py | 13 +
platformio/test/runners/base.py | 215 +++
platformio/test/runners/doctest.py | 121 ++
platformio/test/runners/factory.py | 67 +
platformio/test/runners/googletest.py | 109 ++
platformio/test/runners/readers/__init__.py | 13 +
platformio/test/runners/readers/native.py | 136 ++
platformio/test/runners/readers/serial.py | 81 ++
platformio/test/runners/unity.py | 303 ++++
platformio/util.py | 208 +++
scripts/docspregen.py | 1216 +++++++++++++++++
scripts/fixsymlink.py | 40 +
scripts/install_devplatforms.py | 62 +
setup.py | 96 ++
tests/__init__.py | 13 +
tests/commands/__init__.py | 13 +
tests/commands/pkg/__init__.py | 13 +
tests/commands/pkg/test_exec.py | 59 +
tests/commands/pkg/test_install.py | 592 ++++++++
tests/commands/pkg/test_list.py | 137 ++
tests/commands/pkg/test_outdated.py | 62 +
tests/commands/pkg/test_search.py | 58 +
tests/commands/pkg/test_show.py | 103 ++
tests/commands/pkg/test_uninstall.py | 408 ++++++
tests/commands/pkg/test_update.py | 374 +++++
tests/commands/test_account_org_team.py | 524 +++++++
tests/commands/test_boards.py | 52 +
tests/commands/test_check.py | 759 ++++++++++
tests/commands/test_ci.py | 193 +++
tests/commands/test_init.py | 217 +++
tests/commands/test_lib.py | 234 ++++
tests/commands/test_lib_complex.py | 344 +++++
tests/commands/test_platform.py | 141 ++
tests/commands/test_run.py | 446 ++++++
tests/commands/test_settings.py | 24 +
tests/commands/test_test.py | 660 +++++++++
tests/conftest.py | 150 ++
tests/misc/__init__.py | 13 +
tests/misc/ino2cpp/__init__.py | 13 +
tests/misc/ino2cpp/examples/basic/basic.ino | 60 +
.../misc/ino2cpp/examples/multifiles/bar.ino | 4 +
.../misc/ino2cpp/examples/multifiles/foo.pde | 13 +
.../ino2cpp/examples/strmultilines/main.ino | 79 ++
tests/misc/ino2cpp/test_ino2cpp.py | 48 +
tests/misc/test_maintenance.py | 50 +
tests/misc/test_misc.py | 48 +
tests/package/__init__.py | 13 +
tests/package/test_manager.py | 654 +++++++++
tests/package/test_manifest.py | 905 ++++++++++++
tests/package/test_meta.py | 337 +++++
tests/package/test_pack.py | 188 +++
tests/project/__init__.py | 13 +
tests/project/test_config.py | 717 ++++++++++
tests/project/test_savedeps.py | 224 +++
tests/test_examples.py | 102 ++
tox.ini | 71 +
348 files changed, 43895 insertions(+)
create mode 100644 .github/FUNDING.yml
create mode 100644 .github/ISSUE_TEMPLATE.md
create mode 100644 .github/workflows/core.yml
create mode 100644 .github/workflows/deployment.yml
create mode 100644 .github/workflows/docs.yml
create mode 100644 .github/workflows/examples.yml
create mode 100644 .github/workflows/projects.yml
create mode 100644 .gitignore
create mode 100644 .gitmodules
create mode 100644 .pylintrc
create mode 100644 CODE_OF_CONDUCT.md
create mode 100644 CONTRIBUTING.md
create mode 100644 HISTORY.rst
create mode 100644 LICENSE
create mode 100644 Makefile
create mode 100644 README.rst
create mode 100644 SECURITY.md
create mode 100644 platformio/__init__.py
create mode 100644 platformio/__main__.py
create mode 100644 platformio/account/__init__.py
create mode 100644 platformio/account/cli.py
create mode 100644 platformio/account/client.py
create mode 100644 platformio/account/commands/__init__.py
create mode 100644 platformio/account/commands/destroy.py
create mode 100644 platformio/account/commands/forgot.py
create mode 100644 platformio/account/commands/login.py
create mode 100644 platformio/account/commands/logout.py
create mode 100644 platformio/account/commands/password.py
create mode 100644 platformio/account/commands/register.py
create mode 100644 platformio/account/commands/show.py
create mode 100644 platformio/account/commands/token.py
create mode 100644 platformio/account/commands/update.py
create mode 100644 platformio/account/org/__init__.py
create mode 100644 platformio/account/org/cli.py
create mode 100644 platformio/account/org/commands/__init__.py
create mode 100644 platformio/account/org/commands/add.py
create mode 100644 platformio/account/org/commands/create.py
create mode 100644 platformio/account/org/commands/destroy.py
create mode 100644 platformio/account/org/commands/list.py
create mode 100644 platformio/account/org/commands/remove.py
create mode 100644 platformio/account/org/commands/update.py
create mode 100644 platformio/account/team/__init__.py
create mode 100644 platformio/account/team/cli.py
create mode 100644 platformio/account/team/commands/__init__.py
create mode 100644 platformio/account/team/commands/add.py
create mode 100644 platformio/account/team/commands/create.py
create mode 100644 platformio/account/team/commands/destroy.py
create mode 100644 platformio/account/team/commands/list.py
create mode 100644 platformio/account/team/commands/remove.py
create mode 100644 platformio/account/team/commands/update.py
create mode 100644 platformio/account/validate.py
create mode 100644 platformio/app.py
create mode 100644 platformio/assets/schema/library.json
create mode 100644 platformio/assets/system/99-platformio-udev.rules
create mode 100644 platformio/builder/__init__.py
create mode 100644 platformio/builder/main.py
create mode 100644 platformio/builder/tools/__init__.py
create mode 100644 platformio/builder/tools/pioasm.py
create mode 100644 platformio/builder/tools/piobuild.py
create mode 100644 platformio/builder/tools/piohooks.py
create mode 100644 platformio/builder/tools/pioino.py
create mode 100644 platformio/builder/tools/piointegration.py
create mode 100644 platformio/builder/tools/piolib.py
create mode 100644 platformio/builder/tools/piomaxlen.py
create mode 100644 platformio/builder/tools/piomisc.py
create mode 100644 platformio/builder/tools/pioplatform.py
create mode 100644 platformio/builder/tools/pioproject.py
create mode 100644 platformio/builder/tools/piosize.py
create mode 100644 platformio/builder/tools/piotarget.py
create mode 100644 platformio/builder/tools/piotest.py
create mode 100644 platformio/builder/tools/pioupload.py
create mode 100644 platformio/cache.py
create mode 100644 platformio/check/__init__.py
create mode 100644 platformio/check/cli.py
create mode 100644 platformio/check/defect.py
create mode 100644 platformio/check/tools/__init__.py
create mode 100644 platformio/check/tools/base.py
create mode 100644 platformio/check/tools/clangtidy.py
create mode 100644 platformio/check/tools/cppcheck.py
create mode 100644 platformio/check/tools/pvsstudio.py
create mode 100644 platformio/cli.py
create mode 100644 platformio/commands/__init__.py
create mode 100644 platformio/commands/boards.py
create mode 100644 platformio/commands/ci.py
create mode 100644 platformio/commands/device/__init__.py
create mode 100644 platformio/commands/lib.py
create mode 100644 platformio/commands/platform.py
create mode 100644 platformio/commands/settings.py
create mode 100644 platformio/commands/update.py
create mode 100644 platformio/commands/upgrade.py
create mode 100644 platformio/compat.py
create mode 100644 platformio/debug/__init__.py
create mode 100644 platformio/debug/cli.py
create mode 100644 platformio/debug/config/__init__.py
create mode 100644 platformio/debug/config/base.py
create mode 100644 platformio/debug/config/blackmagic.py
create mode 100644 platformio/debug/config/factory.py
create mode 100644 platformio/debug/config/generic.py
create mode 100644 platformio/debug/config/jlink.py
create mode 100644 platformio/debug/config/mspdebug.py
create mode 100644 platformio/debug/config/native.py
create mode 100644 platformio/debug/config/qemu.py
create mode 100644 platformio/debug/config/renode.py
create mode 100644 platformio/debug/exception.py
create mode 100644 platformio/debug/helpers.py
create mode 100644 platformio/debug/process/__init__.py
create mode 100644 platformio/debug/process/base.py
create mode 100644 platformio/debug/process/client.py
create mode 100644 platformio/debug/process/gdb.py
create mode 100644 platformio/debug/process/server.py
create mode 100644 platformio/device/__init__.py
create mode 100644 platformio/device/cli.py
create mode 100644 platformio/device/finder.py
create mode 100644 platformio/device/list/__init__.py
create mode 100644 platformio/device/list/command.py
create mode 100644 platformio/device/list/util.py
create mode 100644 platformio/device/monitor/__init__.py
create mode 100644 platformio/device/monitor/command.py
create mode 100644 platformio/device/monitor/filters/__init__.py
create mode 100644 platformio/device/monitor/filters/base.py
create mode 100644 platformio/device/monitor/filters/hexlify.py
create mode 100644 platformio/device/monitor/filters/log2file.py
create mode 100644 platformio/device/monitor/filters/send_on_enter.py
create mode 100644 platformio/device/monitor/filters/time.py
create mode 100644 platformio/device/monitor/terminal.py
create mode 100644 platformio/exception.py
create mode 100644 platformio/fs.py
create mode 100644 platformio/home/__init__.py
create mode 100644 platformio/home/cli.py
create mode 100644 platformio/home/rpc/__init__.py
create mode 100644 platformio/home/rpc/handlers/__init__.py
create mode 100644 platformio/home/rpc/handlers/account.py
create mode 100644 platformio/home/rpc/handlers/app.py
create mode 100644 platformio/home/rpc/handlers/base.py
create mode 100644 platformio/home/rpc/handlers/ide.py
create mode 100644 platformio/home/rpc/handlers/misc.py
create mode 100644 platformio/home/rpc/handlers/os.py
create mode 100644 platformio/home/rpc/handlers/piocore.py
create mode 100644 platformio/home/rpc/handlers/platform.py
create mode 100644 platformio/home/rpc/handlers/project.py
create mode 100644 platformio/home/rpc/handlers/registry.py
create mode 100644 platformio/home/rpc/server.py
create mode 100644 platformio/home/run.py
create mode 100644 platformio/http.py
create mode 100644 platformio/maintenance.py
create mode 100644 platformio/package/__init__.py
create mode 100644 platformio/package/cli.py
create mode 100644 platformio/package/commands/__init__.py
create mode 100644 platformio/package/commands/exec.py
create mode 100644 platformio/package/commands/install.py
create mode 100644 platformio/package/commands/list.py
create mode 100644 platformio/package/commands/outdated.py
create mode 100644 platformio/package/commands/pack.py
create mode 100644 platformio/package/commands/publish.py
create mode 100644 platformio/package/commands/search.py
create mode 100644 platformio/package/commands/show.py
create mode 100644 platformio/package/commands/uninstall.py
create mode 100644 platformio/package/commands/unpublish.py
create mode 100644 platformio/package/commands/update.py
create mode 100644 platformio/package/download.py
create mode 100644 platformio/package/exception.py
create mode 100644 platformio/package/lockfile.py
create mode 100644 platformio/package/manager/__init__.py
create mode 100644 platformio/package/manager/_download.py
create mode 100644 platformio/package/manager/_install.py
create mode 100644 platformio/package/manager/_legacy.py
create mode 100644 platformio/package/manager/_registry.py
create mode 100644 platformio/package/manager/_symlink.py
create mode 100644 platformio/package/manager/_uninstall.py
create mode 100644 platformio/package/manager/_update.py
create mode 100644 platformio/package/manager/base.py
create mode 100644 platformio/package/manager/core.py
create mode 100644 platformio/package/manager/library.py
create mode 100644 platformio/package/manager/platform.py
create mode 100644 platformio/package/manager/tool.py
create mode 100644 platformio/package/manifest/__init__.py
create mode 100644 platformio/package/manifest/parser.py
create mode 100644 platformio/package/manifest/schema.py
create mode 100644 platformio/package/meta.py
create mode 100644 platformio/package/pack.py
create mode 100644 platformio/package/unpack.py
create mode 100644 platformio/package/vcsclient.py
create mode 100644 platformio/package/version.py
create mode 100644 platformio/platform/__init__.py
create mode 100644 platformio/platform/_packages.py
create mode 100644 platformio/platform/_run.py
create mode 100644 platformio/platform/base.py
create mode 100644 platformio/platform/board.py
create mode 100644 platformio/platform/exception.py
create mode 100644 platformio/platform/factory.py
create mode 100644 platformio/proc.py
create mode 100644 platformio/project/__init__.py
create mode 100644 platformio/project/cli.py
create mode 100644 platformio/project/commands/__init__.py
create mode 100644 platformio/project/commands/config.py
create mode 100644 platformio/project/commands/init.py
create mode 100644 platformio/project/commands/metadata.py
create mode 100644 platformio/project/config.py
create mode 100644 platformio/project/exception.py
create mode 100644 platformio/project/helpers.py
create mode 100644 platformio/project/integration/__init__.py
create mode 100644 platformio/project/integration/generator.py
create mode 100644 platformio/project/integration/tpls/clion/.gitignore.tpl
create mode 100644 platformio/project/integration/tpls/codeblocks/platformio.cbp.tpl
create mode 100644 platformio/project/integration/tpls/eclipse/.cproject.tpl
create mode 100644 platformio/project/integration/tpls/eclipse/.project.tpl
create mode 100644 platformio/project/integration/tpls/eclipse/.settings/PlatformIO Debugger.launch.tpl
create mode 100644 platformio/project/integration/tpls/eclipse/.settings/language.settings.xml.tpl
create mode 100644 platformio/project/integration/tpls/eclipse/.settings/org.eclipse.cdt.core.prefs.tpl
create mode 100644 platformio/project/integration/tpls/emacs/.ccls.tpl
create mode 100644 platformio/project/integration/tpls/emacs/.gitignore.tpl
create mode 100644 platformio/project/integration/tpls/netbeans/nbproject/configurations.xml.tpl
create mode 100644 platformio/project/integration/tpls/netbeans/nbproject/private/configurations.xml.tpl
create mode 100644 platformio/project/integration/tpls/netbeans/nbproject/private/launcher.properties.tpl
create mode 100644 platformio/project/integration/tpls/netbeans/nbproject/private/private.xml.tpl
create mode 100644 platformio/project/integration/tpls/netbeans/nbproject/project.xml.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/.gitignore.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/Makefile.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.cflags.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.config.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.creator.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.cxxflags.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.files.tpl
create mode 100644 platformio/project/integration/tpls/qtcreator/platformio.includes.tpl
create mode 100644 platformio/project/integration/tpls/sublimetext/.ccls.tpl
create mode 100644 platformio/project/integration/tpls/sublimetext/platformio.sublime-project.tpl
create mode 100644 platformio/project/integration/tpls/vim/.ccls.tpl
create mode 100644 platformio/project/integration/tpls/vim/.gitignore.tpl
create mode 100644 platformio/project/integration/tpls/visualstudio/platformio.vcxproj.filters.tpl
create mode 100644 platformio/project/integration/tpls/visualstudio/platformio.vcxproj.tpl
create mode 100644 platformio/project/integration/tpls/vscode/.gitignore.tpl
create mode 100644 platformio/project/integration/tpls/vscode/.vscode/c_cpp_properties.json.tpl
create mode 100644 platformio/project/integration/tpls/vscode/.vscode/extensions.json.tpl
create mode 100644 platformio/project/integration/tpls/vscode/.vscode/launch.json.tpl
create mode 100644 platformio/project/options.py
create mode 100644 platformio/project/savedeps.py
create mode 100644 platformio/public.py
create mode 100644 platformio/registry/__init__.py
create mode 100644 platformio/registry/access/__init__.py
create mode 100644 platformio/registry/access/cli.py
create mode 100644 platformio/registry/access/commands/__init__.py
create mode 100644 platformio/registry/access/commands/grant.py
create mode 100644 platformio/registry/access/commands/list.py
create mode 100644 platformio/registry/access/commands/private.py
create mode 100644 platformio/registry/access/commands/public.py
create mode 100644 platformio/registry/access/commands/revoke.py
create mode 100644 platformio/registry/access/validate.py
create mode 100644 platformio/registry/client.py
create mode 100644 platformio/registry/mirror.py
create mode 100644 platformio/remote/__init__.py
create mode 100644 platformio/remote/ac/__init__.py
create mode 100644 platformio/remote/ac/base.py
create mode 100644 platformio/remote/ac/process.py
create mode 100644 platformio/remote/ac/psync.py
create mode 100644 platformio/remote/ac/serial.py
create mode 100644 platformio/remote/cli.py
create mode 100644 platformio/remote/client/__init__.py
create mode 100644 platformio/remote/client/agent_list.py
create mode 100644 platformio/remote/client/agent_service.py
create mode 100644 platformio/remote/client/async_base.py
create mode 100644 platformio/remote/client/base.py
create mode 100644 platformio/remote/client/device_list.py
create mode 100644 platformio/remote/client/device_monitor.py
create mode 100644 platformio/remote/client/run_or_test.py
create mode 100644 platformio/remote/client/update_core.py
create mode 100644 platformio/remote/factory/__init__.py
create mode 100644 platformio/remote/factory/client.py
create mode 100644 platformio/remote/factory/ssl.py
create mode 100644 platformio/remote/projectsync.py
create mode 100644 platformio/run/__init__.py
create mode 100644 platformio/run/cli.py
create mode 100644 platformio/run/helpers.py
create mode 100644 platformio/run/processor.py
create mode 100644 platformio/system/__init__.py
create mode 100644 platformio/system/cli.py
create mode 100644 platformio/system/commands/__init__.py
create mode 100644 platformio/system/commands/completion.py
create mode 100644 platformio/system/commands/info.py
create mode 100644 platformio/system/commands/prune.py
create mode 100644 platformio/system/completion.py
create mode 100644 platformio/system/prune.py
create mode 100644 platformio/telemetry.py
create mode 100644 platformio/test/__init__.py
create mode 100644 platformio/test/cli.py
create mode 100644 platformio/test/exception.py
create mode 100644 platformio/test/helpers.py
create mode 100644 platformio/test/reports/__init__.py
create mode 100644 platformio/test/reports/base.py
create mode 100644 platformio/test/reports/json.py
create mode 100644 platformio/test/reports/junit.py
create mode 100644 platformio/test/reports/stdout.py
create mode 100644 platformio/test/result.py
create mode 100644 platformio/test/runners/__init__.py
create mode 100644 platformio/test/runners/base.py
create mode 100644 platformio/test/runners/doctest.py
create mode 100644 platformio/test/runners/factory.py
create mode 100644 platformio/test/runners/googletest.py
create mode 100644 platformio/test/runners/readers/__init__.py
create mode 100644 platformio/test/runners/readers/native.py
create mode 100644 platformio/test/runners/readers/serial.py
create mode 100644 platformio/test/runners/unity.py
create mode 100644 platformio/util.py
create mode 100644 scripts/docspregen.py
create mode 100644 scripts/fixsymlink.py
create mode 100644 scripts/install_devplatforms.py
create mode 100644 setup.py
create mode 100644 tests/__init__.py
create mode 100644 tests/commands/__init__.py
create mode 100644 tests/commands/pkg/__init__.py
create mode 100644 tests/commands/pkg/test_exec.py
create mode 100644 tests/commands/pkg/test_install.py
create mode 100644 tests/commands/pkg/test_list.py
create mode 100644 tests/commands/pkg/test_outdated.py
create mode 100644 tests/commands/pkg/test_search.py
create mode 100644 tests/commands/pkg/test_show.py
create mode 100644 tests/commands/pkg/test_uninstall.py
create mode 100644 tests/commands/pkg/test_update.py
create mode 100644 tests/commands/test_account_org_team.py
create mode 100644 tests/commands/test_boards.py
create mode 100644 tests/commands/test_check.py
create mode 100644 tests/commands/test_ci.py
create mode 100644 tests/commands/test_init.py
create mode 100644 tests/commands/test_lib.py
create mode 100644 tests/commands/test_lib_complex.py
create mode 100644 tests/commands/test_platform.py
create mode 100644 tests/commands/test_run.py
create mode 100644 tests/commands/test_settings.py
create mode 100644 tests/commands/test_test.py
create mode 100644 tests/conftest.py
create mode 100644 tests/misc/__init__.py
create mode 100644 tests/misc/ino2cpp/__init__.py
create mode 100644 tests/misc/ino2cpp/examples/basic/basic.ino
create mode 100644 tests/misc/ino2cpp/examples/multifiles/bar.ino
create mode 100644 tests/misc/ino2cpp/examples/multifiles/foo.pde
create mode 100644 tests/misc/ino2cpp/examples/strmultilines/main.ino
create mode 100644 tests/misc/ino2cpp/test_ino2cpp.py
create mode 100644 tests/misc/test_maintenance.py
create mode 100644 tests/misc/test_misc.py
create mode 100644 tests/package/__init__.py
create mode 100644 tests/package/test_manager.py
create mode 100644 tests/package/test_manifest.py
create mode 100644 tests/package/test_meta.py
create mode 100644 tests/package/test_pack.py
create mode 100644 tests/project/__init__.py
create mode 100644 tests/project/test_config.py
create mode 100644 tests/project/test_savedeps.py
create mode 100644 tests/test_examples.py
create mode 100644 tox.ini
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..6f70f7e
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: https://platformio.org/donate
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..d490fe6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,63 @@
+What kind of issue is this?
+
+- [ ] **Question**.
+ This issue tracker is not the place for questions. If you want to ask how to do something,
+ or to understand why something isn't working the way you expect it to,
+ use [Community Forums](https://community.platformio.org) or [Premium Support](https://platformio.org/support)
+
+- [ ] **PlatformIO IDE**.
+ All issues related to PlatformIO IDE should be reported to the
+ [PlatformIO IDE for VSCode](https://github.com/platformio/platformio-vscode-ide/issues) repository
+
+- [ ] **Development Platform or Board**.
+ All issues (building, uploading, adding new boards, etc.) related to PlatformIO development platforms
+ should be reported to appropriate repository related to your hardware
+ https://github.com/topics/platformio-platform
+
+- [ ] **Feature Request**.
+ Start by telling us what problem you’re trying to solve. Often a solution
+ already exists! Don’t send pull requests to implement new features without first getting our
+ support. Sometimes we leave features out on purpose to keep the project small.
+
+- [ ] **PlatformIO Core**.
+ If you’ve found a bug, please provide an information below.
+
+
+*You can erase any parts of this template not applicable to your Issue.*
+
+------------------------------------------------------------------
+
+### Configuration
+
+**Operating system**:
+
+**PlatformIO Version** (`platformio --version`):
+
+### Description of problem
+
+
+#### Steps to Reproduce
+
+1.
+2.
+3.
+
+### Actual Results
+
+
+### Expected Results
+
+
+### If problems with PlatformIO Build System:
+
+**The content of `platformio.ini`:**
+```ini
+Insert here...
+```
+
+**Source file to reproduce issue:**
+```cpp
+Insert here...
+```
+
+### Additional info
diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml
new file mode 100644
index 0000000..c7c020a
--- /dev/null
+++ b/.github/workflows/core.yml
@@ -0,0 +1,52 @@
+name: Core
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, windows-latest, macos-latest]
+ python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: "recursive"
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox
+
+ - name: Core System Info
+ run: |
+ tox -e py
+
+ - name: Python Lint
+ if: ${{ matrix.python-version != '3.6' }}
+ run: |
+ tox -e lint
+
+ - name: Integration Tests
+ if: ${{ matrix.python-version == '3.9' }}
+ 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 }}
diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml
new file mode 100644
index 0000000..370333a
--- /dev/null
+++ b/.github/workflows/deployment.yml
@@ -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@v4
+ with:
+ python-version: "3.9"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox wheel
+
+ - 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 bdist_wheel
+
+ - 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 }}
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..9a64d88
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,109 @@
+name: Docs
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ name: Build Docs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: "recursive"
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+ - 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@v3
+ 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@v3
+ 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@v2
+ 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@v3
+ 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
diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml
new file mode 100644
index 0000000..6bb258e
--- /dev/null
+++ b/.github/workflows/examples.yml
@@ -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@v4
+ 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 }}
diff --git a/.github/workflows/projects.yml b/.github/workflows/projects.yml
new file mode 100644
index 0000000..1d37c5a
--- /dev/null
+++ b/.github/workflows/projects.yml
@@ -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"
+ 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-lite"
+ 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@v4
+ with:
+ python-version: 3.9
+
+ - name: Install PlatformIO
+ run: pip install -U .
+
+ - name: Check out ${{ matrix.project.repository }}
+ uses: actions/checkout@v3
+ 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 }}
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ceeaed9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+*.egg-info
+*.pyc
+__pycache__
+.tox
+docs/_build
+dist
+build
+.cache
+coverage.xml
+.coverage
+htmlcov
+.pytest_cache
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..6dac16a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,7 @@
+[submodule "examples"]
+ path = examples
+ url = https://github.com/platformio/platformio-examples.git
+[submodule "docs"]
+ path = docs
+ url = https://github.com/platformio/platformio-docs.git
+ branch = develop
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..172b43a
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,12 @@
+[REPORTS]
+output-format=colorized
+
+[MESSAGES CONTROL]
+disable=
+ missing-docstring,
+ duplicate-code,
+ invalid-name,
+ too-few-public-methods,
+ consider-using-f-string,
+ cyclic-import,
+ use-dict-literal
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..1958f6c
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Code of Conduct
+
+See https://piolabs.com/legal/code-of-conduct.html
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..8deafb9
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,22 @@
+Contributing
+------------
+
+To get started, sign the Contributor License Agreement.
+
+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 the PlatformIO Core project where `tox.ini` is located (``cd platformio-core``) and run `tox -e py39`.
+ You can replace `py39` with your own Python version. For example, `py311` means Python 3.11.
+5. Activate current development environment:
+
+ * Windows: `.tox\py39\Scripts\activate`
+ * Bash/ZSH: `source .tox/py39/bin/activate`
+ * Fish: `source .tox/py39/bin/activate.fish`
+
+6. Make changes to code, documentation, etc.
+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
diff --git a/HISTORY.rst b/HISTORY.rst
new file mode 100644
index 0000000..6a5b2a0
--- /dev/null
+++ b/HISTORY.rst
@@ -0,0 +1,324 @@
+Release Notes
+=============
+
+.. |PIOCONF| replace:: `"platformio.ini" `__ configuration file
+.. |LIBRARYJSON| replace:: `library.json `__
+.. |LDF| replace:: `LDF `__
+.. |INTERPOLATION| replace:: `Interpolation of Values `__
+.. |UNITTESTING| replace:: `Unit Testing `__
+.. |DEBUGGING| replace:: `Debugging `__
+
+.. _release_notes_6:
+
+PlatformIO Core 6
+-----------------
+
+Unlock the true potential of embedded software development with
+PlatformIO's collaborative ecosystem, embracing declarative principles,
+test-driven methodologies, and modern toolchains for unrivaled success.
+
+6.1.11 (2023-08-31)
+~~~~~~~~~~~~~~~~~~~
+
+* Resolved a possible issue that may cause generated projects for `PlatformIO IDE for VSCode `__ to fail to launch a debug session because of a missing "objdump" binary when GDB is not part of the toolchain package
+* Resolved a regression issue that resulted in the malfunction of the Memory Inspection feature within `PIO Home `__
+
+6.1.10 (2023-08-11)
+~~~~~~~~~~~~~~~~~~~
+
+* Resolved an issue that caused generated projects for `PlatformIO IDE for VSCode `__ to break when the ``-iprefix`` compiler flag was used
+* Resolved an issue encountered while utilizing the `pio pkg exec `__ command on the Windows platform to execute Python scripts from a package
+* Implemented a crucial improvement to the `pio run `__ command, guaranteeing that the ``monitor`` target is not executed if any of the preceding targets, such as ``upload``, encounter failures
+* `Cppcheck `__ v2.11 with new checks, CLI commands and various analysis improvements
+* Resolved a critical issue that arose on macOS ARM platforms due to the Python "requests" module, leading to a "ModuleNotFoundError: No module named 'chardet'" (`issue #4702 `_)
+
+6.1.9 (2023-07-06)
+~~~~~~~~~~~~~~~~~~
+
+* Rectified a regression bug that occurred when the ``-include`` flag was passed via the `build_flags `__ option as a relative path and subsequently expanded (`issue #4683 `_)
+* Resolved an issue that resulted in unresolved absolute toolchain paths when generating the `Compilation database "compile_commands.json" `__ (`issue #4684 `_)
+
+6.1.8 (2023-07-05)
+~~~~~~~~~~~~~~~~~~
+
+* Added a new ``--lint`` option to the `pio project config `__ command, enabling users to efficiently perform linting on the |PIOCONF|
+* Enhanced the parsing of the |PIOCONF| to provide comprehensive diagnostic information
+* Expanded the functionality of the |LIBRARYJSON| manifest by allowing the use of the underscore symbol in the `keywords `__ field
+* Optimized project integration templates to address the issue of long paths on Windows (`issue #4652 `_)
+* Refactored |UNITTESTING| engine to resolve compiler warnings with "-Wpedantic" option (`pull #4671 `_)
+* Eliminated erroneous warning regarding the use of obsolete PlatformIO Core when downgrading to the stable version (`issue #4664 `_)
+* Updated the `pio project metadata `__ command to return C/C++ flags as parsed Unix shell arguments when dumping project build metadata
+* Resolved a critical issue related to the usage of the ``-include`` flag within the `build_flags `__ option, specifically when employing dynamic variables (`issue #4682 `_)
+* Removed PlatformIO IDE for Atom from the documentation as `Atom has been deprecated `__
+
+6.1.7 (2023-05-08)
+~~~~~~~~~~~~~~~~~~
+
+* Introduced a new ``--sample-code`` option to the `pio project init `__ command, which allows users to include sample code in the newly created project
+* Added validation for `project working environment names `__ to ensure that they only contain lowercase letters ``a-z``, numbers ``0-9``, and special characters ``_`` (underscore) and ``-`` (hyphen)
+* Added the ability to show a detailed library dependency tree only in `verbose mode `__, which can help you understand the relationship between libraries and troubleshoot issues more effectively (`issue #4517 `_)
+* Added the ability to run only the `device monitor `__ when using the `pio run -t monitor `__ command, saving you time and resources by skipping the build process
+* Implemented a new feature to store device monitor logs in the project's ``logs`` folder, making it easier to access and review device monitor logs for your projects (`issue #4596 `_)
+* Improved support for projects located on Windows network drives, including Network Shared Folder, Dropbox, OneDrive, Google Drive, and other similar services (`issue #3417 `_)
+* Improved source file filtering functionality for the `Static Code Analysis `__ feature, making it easier to analyze only the code you need to
+* Upgraded the build engine to the latest version of SCons (4.5.2) to improve build performance, reliability, and compatibility with other tools and systems (`release notes `__)
+* Implemented a fix for shell injection vulnerabilities when converting INO files to CPP, ensuring your code is safe and secure (`issue #4532 `_)
+* Restored the project generator for the `NetBeans IDE `__, providing you with more flexibility and options for your development workflow
+* Resolved installation issues with PIO Remote on Raspberry Pi and other small form-factor PCs (`issue #4425 `_, `issue #4493 `_, `issue #4607 `_)
+* Resolved an issue where the `build_cache_dir `__ setting was not being recognized consistently across multiple environments (`issue #4574 `_)
+* Resolved an issue where organization details could not be updated using the `pio org update `__ command
+* Resolved an issue where the incorrect debugging environment was generated for VSCode in "Auto" mode (`issue #4597 `_)
+* Resolved an issue where native tests would fail if a custom program name was specified (`issue #4546 `_)
+* Resolved an issue where the PlatformIO |DEBUGGING| solution was not escaping the tool installation process into MI2 correctly (`issue #4565 `_)
+* Resolved an issue where multiple targets were not executed sequentially (`issue #4604 `_)
+* Resolved an issue where upgrading PlatformIO Core fails on Windows with Python 3.11 (`issue #4540 `_)
+
+6.1.6 (2023-01-23)
+~~~~~~~~~~~~~~~~~~
+
+* Added support for Python 3.11
+* Added a new `name `__ configuration option to customize a project name (`pull #4498 `_)
+* Made assets (templates, ``99-platformio-udev.rules``) part of Python's module (`issue #4458 `_)
+* Updated `Clang-Tidy `__ check tool to v15.0.5 with new diagnostics and bugfixes
+* Removed dependency on the "zeroconf" package and install it only when a user lists mDNS devices (issue with zeroconf's LGPL license)
+* Show the real error message instead of "Can not remove temporary directory" when |PIOCONF| is broken (`issue #4480 `_)
+* Fixed an issue with an incorrect test summary when a testcase name includes a colon (`issue #4508 `_)
+* Fixed an issue when `extends `__ did not override options in the right order (`issue #4462 `_)
+* Fixed an issue when `pio pkg list `__ and `pio pkg uninstall `__ commands fail if there are circular dependencies in the |LIBRARYJSON| manifests (`issue #4475 `_)
+
+6.1.5 (2022-11-01)
+~~~~~~~~~~~~~~~~~~
+
+* Added a new `enable_proxy_strict_ssl `__ setting to disable the proxy server certificate verification (`issue #4432 `_)
+* Documented `PlatformIO Core Proxy Configuration `__
+* Speeded up device port finder by avoiding loading board HWIDs from development platforms
+* Improved caching of build metadata in debug mode
+* Fixed an issue when `pio pkg install --storage-dir `__ command requires PlatformIO project (`issue #4410 `_)
+
+6.1.4 (2022-08-12)
+~~~~~~~~~~~~~~~~~~
+
+* Added support for accepting the original FileNode environment in a "callback" function when using `Build Middlewares `__ (`pull #4380 `_)
+* Improved device port finder when using dual channel UART converter (`issue #4367 `_)
+* Improved project dependency resolving when using the `pio project init --ide `__ command
+* Upgraded build engine to the SCons 4.4.0 (`release notes `__)
+* Keep custom "unwantedRecommendations" when generating projects for VSCode (`issue #4383 `_)
+* Do not resolve project dependencies for the ``cleanall`` target (`issue #4344 `_)
+* Warn about calling "env.BuildSources" in a POST-type script (`issue #4385 `_)
+* Fixed an issue when escaping macros/defines for IDE integration (`issue #4360 `_)
+* Fixed an issue when the "cleanall" target removes dependencies from all working environments (`issue #4386 `_)
+
+6.1.3 (2022-07-18)
+~~~~~~~~~~~~~~~~~~
+
+* Fixed a regression bug when opening device monitor without any filters (`issue #4363 `_)
+
+6.1.2 (2022-07-18)
+~~~~~~~~~~~~~~~~~~
+
+* Export a ``PIO_UNIT_TESTING`` macro to the project source files and dependent libraries in the |UNITTESTING| mode
+* Improved detection of Windows architecture (`issue #4353 `_)
+* Warn about unknown `device monitor filters `__ (`issue #4362 `_)
+* Fixed a regression bug when `libArchive `__ option declared in the |LIBRARYJSON| manifest was ignored (`issue #4351 `_)
+* Fixed an issue when the `pio pkg publish `__ command didn't work with Python 3.6 (`issue #4352 `_)
+
+6.1.1 (2022-07-11)
+~~~~~~~~~~~~~~~~~~
+
+* Added new ``monitor_encoding`` project configuration option to configure `Device Monitor `__ (`issue #4350 `_)
+* Allowed specifying project environments for `pio ci `__ command (`issue #4347 `_)
+* Show "TimeoutError" only in the verbose mode when can not find a serial port
+* Fixed an issue when a serial port was not automatically detected if the board has predefined HWIDs
+* Fixed an issue with endless scanning of project dependencies (`issue #4349 `_)
+* Fixed an issue with |LDF| when incompatible libraries were used for the working project environment with the missed framework (`pull #4346 `_)
+
+6.1.0 (2022-07-06)
+~~~~~~~~~~~~~~~~~~
+
+* **Device Manager**
+
+ - Automatically reconnect device monitor if a connection fails
+ - Added new `pio device monitor --no-reconnect `__ option to disable automatic reconnection
+ - Handle device monitor disconnects more gracefully (`issue #3939 `_)
+ - Improved a serial port finder for `Black Magic Probe `__ (`issue #4023 `_)
+ - Improved a serial port finder for a board with predefined HWIDs
+ - Replaced ``monitor_flags`` with independent project configuration options: `monitor_parity `__, `monitor_eol `__, `monitor_raw `__, `monitor_echo `__
+ - Fixed an issue when the monitor filters were not applied in their order (`issue #4320 `_)
+
+* **Unit Testing**
+
+ - Updated "Getting Started" documentation for `GoogleTest `__ testing and mocking framework
+ - Export |UNITTESTING| flags only to the project build environment (``projenv``, files in "src" folder)
+ - Merged the "building" stage with "uploading" for the embedded target (`issue #4307 `_)
+ - Do not resolve dependencies from the project "src" folder when the `test_build_src `__ option is not enabled
+ - Do not immediately terminate a testing program when results are received
+ - Fixed an issue when a custom `pio test --project-config `__ was not handled properly (`issue #4299 `_)
+ - Fixed an issue when testing results were wrong in the verbose mode (`issue #4336 `_)
+
+* **Build System**
+
+ - Significantly improved support for `Pre & Post Actions `__
+
+ * Allowed to declare actions in the `PRE-type scripts `__ even if the target is not ready yet
+ * Allowed library maintainers to use Pre & Post Actions in the library `extraScript `__
+
+ - Documented `Stringification `__ – converting a macro argument into a string constant (`issue #4310 `_)
+ - Added new `pio run --monitor-port `__ option to specify custom device monitor port to the ``monitor`` target (`issue #4337 `_)
+ - Added ``env.StringifyMacro(value)`` helper function for the `Advanced Scripting `__
+ - Allowed to ``Import("projenv")`` in a library extra script (`issue #4305 `_)
+ - Fixed an issue when the `build_unflags `__ operation ignores a flag value (`issue #4309 `_)
+ - Fixed an issue when the `build_unflags `__ option was not applied to the ``ASPPFLAGS`` scope
+ - Fixed an issue on Windows OS when flags were wrapped to the temporary file while generating the `Compilation database "compile_commands.json" `__
+ - Fixed an issue with the |LDF| when recursively scanning dependencies in the ``chain`` mode
+ - Fixed a "PermissionError" on Windows when running "clean" or "cleanall" targets (`issue #4331 `_)
+
+* **Package Management**
+
+ - Fixed an issue when library dependencies were installed for the incompatible project environment (`issue #4338 `_)
+
+* **Miscellaneous**
+
+ - Warn about incompatible Bash version for the `Shell Completion `__ (`issue #4326 `_)
+
+6.0.2 (2022-06-01)
+~~~~~~~~~~~~~~~~~~
+
+* Control |UNITTESTING| verbosity with a new multilevel `pio test -v `__ command option (`issue #4276 `_)
+* Follow symbolic links during searching for the unit test suites (`issue #4288 `_)
+* Show a warning when testing an empty project without a test suite (`issue #4278 `_)
+* Improved support for `Asking for input (prompts) `_
+* Fixed an issue when the `build_src_flags `__ option was applied outside the project scope (`issue #4277 `_)
+* Fixed an issue with debugging assembly files without preprocessor (".s")
+
+6.0.1 (2022-05-17)
+~~~~~~~~~~~~~~~~~~
+
+* Improved support for the renamed configuration options (`issue #4270 `_)
+* Fixed an issue when calling the built-in `pio device monitor `__ filters
+* Fixed an issue when using |INTERPOLATION| and merging str+int options (`issue #4271 `_)
+
+6.0.0 (2022-05-16)
+~~~~~~~~~~~~~~~~~~
+
+Please check the `Migration guide from 5.x to 6.0 `__.
+
+* **Package Management**
+
+ - New unified Package Management CLI (``pio pkg``):
+
+ * `pio pkg exec `_ - run command from package tool (`issue #4163 `_)
+ * `pio pkg install `_ - install the project dependencies or custom packages
+ * `pio pkg list `__ - list installed packages
+ * `pio pkg outdated `__ - check for project outdated packages
+ * `pio pkg search `__ - search for packages
+ * `pio pkg show `__ - show package information
+ * `pio pkg uninstall `_ - uninstall the project dependencies or custom packages
+ * `pio pkg update `__ - update the project dependencies or custom packages
+
+ - Package Manifest
+
+ * Added support for `"scripts" `__ (`issue #485 `_)
+ * Added support for `multi-licensed `__ packages using SPDX Expressions (`issue #4037 `_)
+ * Added support for `"dependencies" `__ declared in a "tool" package manifest
+
+ - Added support for `symbolic links `__ allowing pointing the local source folder to the Package Manager (`issue #3348 `_)
+ - Automatically install dependencies of the local (private) project libraries (`issue #2910 `_)
+ - Improved detection of a package type from the tarball archive (`issue #3828 `_)
+ - Ignore files according to the patterns declared in ".gitignore" when using the `pio package pack `__ command (`issue #4188 `_)
+ - Dropped automatic updates of global libraries and development platforms (`issue #4179 `_)
+ - Dropped support for the "pythonPackages" field in "platform.json" manifest in favor of `Extra Python Dependencies `__
+ - Fixed an issue when manually removed dependencies from the |PIOCONF| were not uninstalled from the storage (`issue #3076 `_)
+
+* **Unit Testing**
+
+ - Refactored from scratch |UNITTESTING| solution and its documentation
+ - New: `Test Hierarchy `_ (`issue #4135 `_)
+ - New: `Doctest `__ testing framework (`issue #4240 `_)
+ - New: `GoogleTest `__ testing and mocking framework (`issue #3572 `_)
+ - New: `Semihosting `__ (`issue #3516 `_)
+ - New: Hardware `Simulators `__ for Unit Testing (QEMU, Renode, SimAVR, and custom solutions)
+ - New: ``test`` `build configuration `__
+ - Added support for a `custom testing framework `_
+ - Added support for a custom `testing command `__
+ - Added support for a `custom Unity library `__ (`issue #3980 `_)
+ - Added support for the ``socket://`` and ``rfc2217://`` protocols using `test_port `__ option (`issue #4229 `_)
+ - List available project tests with a new `pio test --list-tests `__ option
+ - Pass extra arguments to the testing program with a new `pio test --program-arg `__ option (`issue #3132 `_)
+ - Generate reports in JUnit and JSON formats using the `pio test `__ command (`issue #2891 `_)
+ - Provide more information when the native program crashed on a host (errored with a non-zero return code) (`issue #3429 `_)
+ - Improved automatic detection of a testing serial port (`issue #4076 `_)
+ - Fixed an issue when command line parameters (``--ignore``, ``--filter``) do not override values defined in the |PIOCONF| (`issue #3845 `_)
+ - Renamed the "test_build_project_src" project configuration option to the `test_build_src `__
+ - Removed the "test_transport" option in favor of the `Custom "unity_config.h" `_
+
+* **Static Code Analysis**
+
+ - Updated analysis tools:
+
+ * `Cppcheck `__ v2.7 with various checker improvements and fixed false positives
+ * `PVS-Studio `__ v7.18 with improved and updated semantic analysis system
+
+ - Added support for the custom `Clang-Tidy `__ configuration file (`issue #4186 `_)
+ - Added ability to override a tool version using the `platform_packages `__ option (`issue #3798 `_)
+ - Fixed an issue with improper handling of defects that don't specify a source file (`issue #4237 `_)
+
+* **Build System**
+
+ - Show project dependency licenses when building in the verbose mode
+ - Fixed an issue when |LDF| ignores the project `lib_deps `__ while resolving library dependencies (`issue #3598 `_)
+ - Fixed an issue with calling an extra script located outside a project (`issue #4220 `_)
+ - Fixed an issue when GCC preprocessor was applied to the ".s" assembly files on case-sensitive OS such as Window OS (`issue #3917 `_)
+ - Fixed an issue when |LDF| ignores `build_src_flags `__ in the "deep+" mode (`issue #4253 `_)
+
+* **Integration**
+
+ - Added a new build variable (``COMPILATIONDB_INCLUDE_TOOLCHAIN``) to include toolchain paths in the compilation database (`issue #3735 `_)
+ - Changed a default path for compilation database `compile_commands.json `__ to the project root
+ - Enhanced integration for Qt Creator (`issue #3046 `_)
+
+* **Project Configuration**
+
+ - Extended |INTERPOLATION| with ``${this}`` pattern (`issue #3953 `_)
+ - Embed environment name of the current section in the |PIOCONF| using ``${this.__env__}`` pattern
+ - Renamed the "src_build_flags" project configuration option to the `build_src_flags `__
+ - Renamed the "src_filter" project configuration option to the `build_src_filter `__
+
+* **Miscellaneous**
+
+ - Pass extra arguments to the `native `__ program with a new `pio run --program-arg `__ option (`issue #4246 `_)
+ - Improved PIO Remote setup on credit-card sized computers (Raspberry Pi, BeagleBon, etc) (`issue #3865 `_)
+ - Finally removed all tracks to the Python 2.7, the Python 3.6 is the minimum supported version.
+
+.. _release_notes_5:
+
+PlatformIO Core 5
+-----------------
+
+See `PlatformIO Core 5.0 history `__.
+
+.. _release_notes_4:
+
+PlatformIO Core 4
+-----------------
+
+See `PlatformIO Core 4.0 history `__.
+
+PlatformIO Core 3
+-----------------
+
+See `PlatformIO Core 3.0 history `__.
+
+PlatformIO Core 2
+-----------------
+
+See `PlatformIO Core 2.0 history `__.
+
+PlatformIO Core 1
+-----------------
+
+See `PlatformIO Core 1.0 history `__.
+
+PlatformIO Core Preview
+-----------------------
+
+See `PlatformIO Core Preview history `__.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2f79a3b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,174 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction,
+and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by
+the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all
+other entities that control, are controlled by, or are under common
+control with that entity. For the purposes of this definition,
+"control" means (i) the power, direct or indirect, to cause the
+direction or management of such entity, whether by contract or
+otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity
+exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications,
+including but not limited to software source code, documentation
+source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical
+transformation or translation of a Source form, including but
+not limited to compiled object code, generated documentation,
+and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or
+Object form, made available under the License, as indicated by a
+copyright notice that is included in or attached to the work
+(an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object
+form, that is based on (or derived from) the Work and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship. For the purposes
+of this License, Derivative Works shall not include works that remain
+separable from, or merely link (or bind by name) to the interfaces of,
+the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including
+the original version of the Work and any modifications or additions
+to that Work or Derivative Works thereof, that is intentionally
+submitted to Licensor for inclusion in the Work by the copyright owner
+or by an individual or Legal Entity authorized to submit on behalf of
+the copyright owner. For the purposes of this definition, "submitted"
+means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems,
+and issue tracking systems that are managed by, or on behalf of, the
+Licensor for the purpose of discussing and improving the Work, but
+excluding communication that is conspicuously marked or otherwise
+designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity
+on behalf of whom a Contribution has been received by Licensor and
+subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the
+Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except as stated in this section) patent license to make, have made,
+use, offer to sell, sell, import, and otherwise transfer the Work,
+where such license applies only to those patent claims licensable
+by such Contributor that are necessarily infringed by their
+Contribution(s) alone or by combination of their Contribution(s)
+with the Work to which such Contribution(s) was submitted. If You
+institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work
+or a Contribution incorporated within the Work constitutes direct
+or contributory patent infringement, then any patent licenses
+granted to You under this License for that Work shall terminate
+as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+Work or Derivative Works thereof in any medium, with or without
+modifications, and in Source or Object form, provided that You
+meet the following conditions:
+
+(a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+(b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+(c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+(d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+You may add Your own copyright statement to Your modifications and
+may provide additional or different license terms and conditions
+for use, reproduction, or distribution of Your modifications, or
+for any such Derivative Works as a whole, provided Your use,
+reproduction, and distribution of the Work otherwise complies with
+the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+any Contribution intentionally submitted for inclusion in the Work
+by You to the Licensor shall be under the terms and conditions of
+this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify
+the terms of any separate license agreement you may have executed
+with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+names, trademarks, service marks, or product names of the Licensor,
+except as required for reasonable and customary use in describing the
+origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+agreed to in writing, Licensor provides the Work (and each
+Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied, including, without limitation, any warranties or conditions
+of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any
+risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+whether in tort (including negligence), contract, or otherwise,
+unless required by applicable law (such as deliberate and grossly
+negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special,
+incidental, or consequential damages of any character arising as a
+result of this License or out of the use or inability to use the
+Work (including but not limited to damages for loss of goodwill,
+work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses), even if such Contributor
+has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+the Work or Derivative Works thereof, You may choose to offer,
+and charge a fee for, acceptance of support, warranty, indemnity,
+or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only
+on Your own behalf and on Your sole responsibility, not on behalf
+of any other Contributor, and only if You agree to indemnify,
+defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..09c0b83
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,38 @@
+lint:
+ pylint --rcfile=./.pylintrc ./tests
+ pylint --rcfile=./.pylintrc ./platformio
+
+isort:
+ isort ./platformio
+ isort ./tests
+
+format:
+ black ./platformio
+ black ./tests
+
+test:
+ py.test --verbose --exitfirst -n 6 --dist=loadscope tests --ignore tests/test_examples.py
+
+before-commit: isort format lint
+
+clean-docs:
+ rm -rf docs/_build
+
+clean: clean-docs
+ find . -name \*.pyc -delete
+ find . -name __pycache__ -delete
+ rm -rf .cache
+ rm -rf build
+ rm -rf htmlcov
+ rm -f .coverage
+
+profile:
+ # Usage $ > make PIOARGS="boards" profile
+ 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
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..df73525
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,103 @@
+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/PlatformIO-Labs-orange.svg
+ :alt: PlatformIO Labs
+ :target: https://piolabs.com/?utm_source=github&utm_medium=core
+
+**Quick Links:** `Homepage `_ |
+`PlatformIO IDE `_ |
+`Registry `_ |
+`Project Examples `__ |
+`Docs `_ |
+`Donate `_ |
+`Contact Us `_
+
+**Social:** `LinkedIn `_ |
+`Twitter `_ |
+`Facebook `_ |
+`Community Forums `_
+
+.. 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 `_: Your Gateway to Embedded Software Development Excellence.
+
+Unlock the true potential of embedded software development with
+PlatformIO's collaborative ecosystem, embracing declarative principles,
+test-driven methodologies, and modern toolchains for unrivaled success.
+
+* 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? `_
+* `PlatformIO IDE `_
+* `PlatformIO Core (CLI) `_
+* `Project Examples `__
+
+Solutions
+---------
+
+* `Library Management `_
+* `Desktop IDEs Integration `_
+* `Continuous Integration `_
+
+**Advanced**
+
+* `Debugging `_
+* `Unit Testing `_
+* `Static Code Analysis `_
+* `Remote Development `_
+
+Registry
+--------
+
+* `Libraries `_
+* `Development Platforms `_
+* `Development Tools `_
+
+Contributing
+------------
+
+See `contributing guidelines `_.
+
+Telemetry / Privacy Policy
+--------------------------
+
+Share minimal diagnostics and usage information to help us make PlatformIO better.
+It is enabled by default. For more information see:
+
+* `Telemetry Setting `_
+
+License
+-------
+
+Copyright (c) 2014-present PlatformIO
+
+The PlatformIO is licensed under the permissive Apache 2.0 license,
+so you can use it in both commercial and personal projects with confidence.
+
+.. image:: https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg
+ :target: https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md
+ :alt: SWUbanner
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..3d71c1e
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,34 @@
+# Security Policy
+
+## Supported Versions
+
+We are committed to ensuring the security and protection of PlatformIO Core.
+To this end, we support only the following versions:
+
+| Version | Supported |
+| ------- | ------------------ |
+| 6.1.x | :white_check_mark: |
+| < 6.1 | :x: |
+
+Unsupported versions of the PlatformIO Core may have known vulnerabilities or security issues that could compromise the security of our organization's systems and data.
+Therefore, it is important that all developers use only supported versions of the PlatformIO Core.
+
+## Reporting a Vulnerability
+
+We take the security of our systems and data very seriously. We encourage responsible disclosure of any vulnerabilities or security issues that you may find in our systems or applications. If you believe you have discovered a vulnerability, please report it to us immediately.
+
+To report a vulnerability, please send an email to our security team at contact@piolabs.com. Please include as much information as possible, including:
+
+- A description of the vulnerability and how it can be exploited
+- Steps to reproduce the vulnerability
+- Any additional information that can help us understand and reproduce the vulnerability
+
+Once we receive your report, our security team will acknowledge receipt within 24 hours and will work to validate the reported vulnerability. We will provide periodic updates on the progress of the vulnerability assessment, and will notify you once a fix has been deployed.
+
+If the vulnerability is accepted, we will work to remediate the issue as quickly as possible. We may also provide credit or recognition to the individual who reported the vulnerability, at our discretion.
+
+If the vulnerability is declined, we will provide a justification for our decision and may offer guidance on how to improve the report or how to test the system more effectively.
+
+Please note that we will not take any legal action against individuals who report vulnerabilities in good faith and in accordance with this policy.
+
+Thank you for helping us keep our systems and data secure.
diff --git a/platformio/__init__.py b/platformio/__init__.py
new file mode 100644
index 0000000..c0226cf
--- /dev/null
+++ b/platformio/__init__.py
@@ -0,0 +1,73 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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.
+
+VERSION = (6, 1, 11)
+__version__ = ".".join([str(s) for s in VERSION])
+
+__title__ = "platformio"
+__description__ = (
+ "Your Gateway to Embedded Software Development Excellence. "
+ "Unlock the true potential of embedded software development "
+ "with PlatformIO's collaborative ecosystem, embracing "
+ "declarative principles, test-driven methodologies, and "
+ "modern toolchains for unrivaled success."
+)
+__url__ = "https://platformio.org"
+
+__author__ = "PlatformIO Labs"
+__email__ = "contact@piolabs.com"
+
+__license__ = "Apache Software License"
+__copyright__ = "Copyright 2014-present PlatformIO Labs"
+
+__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"
+
+__core_packages__ = {
+ "contrib-piohome": "~3.4.2",
+ "contrib-pioremote": "~1.0.0",
+ "tool-scons": "~4.40502.0",
+ "tool-cppcheck": "~1.21100.0",
+ "tool-clangtidy": "~1.150005.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__
+
+__install_requires__ = [
+ # Core requirements
+ "bottle == 0.12.*",
+ "click >=8.0.4, <=8.2",
+ "colorama",
+ "marshmallow == 3.*",
+ "pyelftools == 0.29",
+ "pyserial == 3.5.*", # keep in sync "device/monitor/terminal.py"
+ "requests == 2.*",
+ "semantic_version == 2.10.*",
+ "tabulate == 0.*",
+] + [
+ # PIO Home requirements
+ "ajsonrpc == 1.2.*",
+ "starlette >=0.19, <0.32",
+ "uvicorn >=0.16, <0.24",
+ "wsproto == 1.*",
+]
diff --git a/platformio/__main__.py b/platformio/__main__.py
new file mode 100644
index 0000000..58cabe8
--- /dev/null
+++ b/platformio/__main__.py
@@ -0,0 +1,144 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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 sys
+import traceback
+
+import click
+
+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 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, no_ansi): # pylint: disable=unused-argument
+ 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_cmd_start(ctx, caller)
+
+
+@cli.result_callback()
+@click.pass_context
+def process_result(*_, **__):
+ maintenance.on_cmd_end()
+
+
+def configure():
+ if IS_CYGWIN:
+ raise exception.CygwinEnvDetected()
+
+ # https://urllib3.readthedocs.org
+ # /en/latest/security.html#insecureplatformwarning
+ try:
+ import urllib3 # pylint: disable=import-outside-toplevel
+
+ urllib3.disable_warnings()
+ except (AttributeError, ImportError):
+ pass
+
+ # Handle IOError issue with VSCode's Terminal (Windows)
+ click_echo_origin = [click.echo, click.secho]
+
+ def _safe_echo(origin, *args, **kwargs):
+ try:
+ 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 "")
+ )
+
+ click.echo = lambda *args, **kwargs: _safe_echo(0, *args, **kwargs)
+ click.secho = lambda *args, **kwargs: _safe_echo(1, *args, **kwargs)
+
+
+def main(argv=None):
+ exit_code = 0
+ prev_sys_argv = sys.argv[:]
+ if argv:
+ assert isinstance(argv, list)
+ sys.argv = argv
+
+ try:
+ ensure_python3(raise_exception=True)
+ configure()
+ 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 = f"{exc.__class__.__name__}: "
+ if isinstance(exc, exception.PlatformioException):
+ error_str += str(exc)
+ else:
+ error_str += traceback.format_exc()
+ error_str += """
+============================================================
+
+An unexpected error occurred. Further steps:
+
+* Verify that you have the latest version of PlatformIO using
+ `python -m pip install -U platformio` command
+
+* Try to find answer in FAQ Troubleshooting section
+ https://docs.platformio.org/page/faq/index.html
+
+* Report this problem to the developers
+ https://github.com/platformio/platformio-core/issues
+
+============================================================
+"""
+ click.secho(error_str, fg="red", err=True)
+ exit_code = int(str(exc)) if str(exc).isdigit() else 1
+
+ maintenance.on_platformio_exit()
+ sys.argv = prev_sys_argv
+ return exit_code
+
+
+def debug_gdb_main():
+ return main([sys.argv[0], "debug", "--interface", "gdb"] + sys.argv[1:])
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/platformio/account/__init__.py b/platformio/account/__init__.py
new file mode 100644
index 0000000..b051490
--- /dev/null
+++ b/platformio/account/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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.
diff --git a/platformio/account/cli.py b/platformio/account/cli.py
new file mode 100644
index 0000000..135445d
--- /dev/null
+++ b/platformio/account/cli.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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
diff --git a/platformio/account/client.py b/platformio/account/client.py
new file mode 100644
index 0000000..0643214
--- /dev/null
+++ b/platformio/account/client.py
@@ -0,0 +1,352 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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, UserSideException
+from platformio.http import HTTPClient, HTTPClientError
+
+
+class AccountError(PlatformioException):
+ MESSAGE = "{0}"
+
+
+class AccountNotAuthorized(AccountError, UserSideException):
+ MESSAGE = "You are not authorized! Please log in to PlatformIO Account."
+
+
+class AccountAlreadyAuthorized(AccountError, UserSideException):
+ 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,
+ params={"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),
+ params={"username": username},
+ x_with_authorization=True,
+ )
diff --git a/platformio/account/commands/__init__.py b/platformio/account/commands/__init__.py
new file mode 100644
index 0000000..b051490
--- /dev/null
+++ b/platformio/account/commands/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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.
diff --git a/platformio/account/commands/destroy.py b/platformio/account/commands/destroy.py
new file mode 100644
index 0000000..5a4f4dd
--- /dev/null
+++ b/platformio/account/commands/destroy.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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",
+ )
diff --git a/platformio/account/commands/forgot.py b/platformio/account/commands/forgot.py
new file mode 100644
index 0000000..4af8f5f
--- /dev/null
+++ b/platformio/account/commands/forgot.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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",
+ )
diff --git a/platformio/account/commands/login.py b/platformio/account/commands/login.py
new file mode 100644
index 0000000..b9471bf
--- /dev/null
+++ b/platformio/account/commands/login.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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")
diff --git a/platformio/account/commands/logout.py b/platformio/account/commands/logout.py
new file mode 100644
index 0000000..243a7f1
--- /dev/null
+++ b/platformio/account/commands/logout.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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("logout", short_help="Log out of PlatformIO Account")
+def account_logout_cmd():
+ client = AccountClient()
+ client.logout()
+ click.secho("Successfully logged out!", fg="green")
diff --git a/platformio/account/commands/password.py b/platformio/account/commands/password.py
new file mode 100644
index 0000000..4f129c0
--- /dev/null
+++ b/platformio/account/commands/password.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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")
diff --git a/platformio/account/commands/register.py b/platformio/account/commands/register.py
new file mode 100644
index 0000000..6fc20ce
--- /dev/null
+++ b/platformio/account/commands/register.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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",
+ )
diff --git a/platformio/account/commands/show.py b/platformio/account/commands/show.py
new file mode 100644
index 0000000..f107f4f
--- /dev/null
+++ b/platformio/account/commands/show.py
@@ -0,0 +1,116 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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"))
diff --git a/platformio/account/commands/token.py b/platformio/account/commands/token.py
new file mode 100644
index 0000000..0f06e36
--- /dev/null
+++ b/platformio/account/commands/token.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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")
diff --git a/platformio/account/commands/update.py b/platformio/account/commands/update.py
new file mode 100644
index 0000000..b386893
--- /dev/null
+++ b/platformio/account/commands/update.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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
diff --git a/platformio/account/org/__init__.py b/platformio/account/org/__init__.py
new file mode 100644
index 0000000..b051490
--- /dev/null
+++ b/platformio/account/org/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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.
diff --git a/platformio/account/org/cli.py b/platformio/account/org/cli.py
new file mode 100644
index 0000000..5f1f0fc
--- /dev/null
+++ b/platformio/account/org/cli.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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
diff --git a/platformio/account/org/commands/__init__.py b/platformio/account/org/commands/__init__.py
new file mode 100644
index 0000000..b051490
--- /dev/null
+++ b/platformio/account/org/commands/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2014-present PlatformIO
+#
+# 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.
diff --git a/platformio/account/org/commands/add.py b/platformio/account/org/commands/add.py
new file mode 100644
index 0000000..55e658e
--- /dev/null
+++ b/platformio/account/org/commands/add.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2014-present PlatformIO