From ee086ff5806a41f1d0a53819c98559794fea5fa1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Dec 2016 14:15:13 +0200 Subject: [PATCH 001/127] =?UTF-8?q?Produce=20less=20noisy=20output=20when?= =?UTF-8?q?=20=E2=80=9C-s/=E2=80=94silent=E2=80=9D=20options=20are=20used?= =?UTF-8?q?=20for=20run=20and=20init=20commands=20//=20Resolve=20#850?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HISTORY.rst | 401 ++++++++++++++++++------------------ docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/init.py | 65 +++--- platformio/commands/run.py | 26 ++- 5 files changed, 257 insertions(+), 239 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 4c504320..83fd6a47 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,16 +4,25 @@ Release Notes PlatformIO 3.0 -------------- +3.2.2 (2016-12-??) +~~~~~~~~~~~~~~~~~~ + +* Produce less noisy output when ``-s/--silent`` options are used for + `platformio init `_ + and `platformio run `_ + commands + (`issue #850 `_) + 3.2.1 (2016-12-07) ~~~~~~~~~~~~~~~~~~ -* Changed default `LDF Mode `__ +* Changed default `LDF Mode `__ from ``chain+`` to ``chain`` 3.2.0 (2016-12-07) ~~~~~~~~~~~~~~~~~~ -* `PIO Remote™ `__. +* `PIO Remote™ `__. **Your devices are always with you!** + Over-The-Air (OTA) Device Manager @@ -22,44 +31,44 @@ PlatformIO 3.0 + Continuous Deployment + Continuous Delivery -* Integration with `Cloud IDEs `__ +* Integration with `Cloud IDEs `__ + Cloud9 + Codeanywhere + Eclipse Che -* `PIO Account `__ - and `PLATFORMIO_AUTH_TOKEN `__ +* `PIO Account `__ + and `PLATFORMIO_AUTH_TOKEN `__ environment variable for CI systems (`issue #808 `_, `issue #467 `_) * Inject system environment variables to configuration settings in - `Project Configuration File "platformio.ini" `__ + `Project Configuration File "platformio.ini" `__ (`issue #792 `_) * Custom boards per project with ``boards_dir`` option in - `Project Configuration File "platformio.ini" `__ + `Project Configuration File "platformio.ini" `__ (`issue #515 `_) -* Unix shell-style wildcards for `upload_port `_ +* Unix shell-style wildcards for `upload_port `_ (`issue #839 `_) -* Refactored `Library Dependency Finder (LDF) `__ +* Refactored `Library Dependency Finder (LDF) `__ C/C++ Preprocessor for conditional syntax (``#ifdef``, ``#if``, ``#else``, ``#elif``, ``#define``, etc.) (`issue #837 `_) -* Added new `LDF Modes `__: +* Added new `LDF Modes `__: ``chain+`` and ``deep+`` and set ``chain+`` as default * Added global ``lib_extra_dirs`` option to ``[platformio]`` section for - `Project Configuration File "platformio.ini" `__ + `Project Configuration File "platformio.ini" `__ (`issue #842 `_) -* Enabled caching by default for API requests and Library Manager (see `enable_cache `__ setting) +* Enabled caching by default for API requests and Library Manager (see `enable_cache `__ setting) * Native integration with VIM/Neovim using `neomake-platformio `__ plugin * Changed a default exit combination for Device Monitor from ``Ctrl+]`` to ``Ctrl+C`` * Improved detecting of ARM mbed media disk for uploading * Improved Project Generator for CLion IDE when source folder contains nested items * Improved handling of library dependencies specified in ``library.json`` manifest (`issue #814 `_) -* Improved `Library Dependency Finder (LDF) `__ +* Improved `Library Dependency Finder (LDF) `__ for circular dependencies -* Show vendor version of a package for `platformio platform show `__ command +* Show vendor version of a package for `platformio platform show `__ command (`issue #838 `_) * Fixed unable to include SSH user in ``lib_deps`` repository url (`issue #830 `_) @@ -158,15 +167,15 @@ PlatformIO 3.0 3.1.0 (2016-09-19) ~~~~~~~~~~~~~~~~~~ -* New! Dynamic variables/templates for `Project Configuration File "platformio.ini" `__ +* New! Dynamic variables/templates for `Project Configuration File "platformio.ini" `__ (`issue #705 `_) * Summary about processed environments (`issue #777 `_) * Implemented LocalCache system for API and improved a work in off-line mode * Improved Project Generator when custom ``--project-option`` is passed to - `platformio init `__ + `platformio init `__ command -* Deprecated ``lib_force`` option, please use `lib_deps `__ instead +* Deprecated ``lib_force`` option, please use `lib_deps `__ instead * Return valid exit code from ``plaformio test`` command * Fixed Project Generator for CLion IDE using Windows OS (`issue #785 `_) @@ -178,7 +187,7 @@ PlatformIO 3.0 * Development platform `Espressif 8266 `__ + Add support for `SparkFun Blynk Board `_ - + Created `staging `__ + + Created `staging `__ branch to work with development version of Arduino Framework * Development platform `Freescale Kinetis `__ @@ -226,7 +235,7 @@ PlatformIO 3.0 * `PlatformIO Plus `__ - + Local and Embedded `Unit Testing `__ + + Local and Embedded `Unit Testing `__ (`issue #408 `_, `issue #519 `_) @@ -244,7 +253,7 @@ PlatformIO 3.0 * Library Manager 3.0 - + Project dependencies per build environment using `lib_deps `__ option + + Project dependencies per build environment using `lib_deps `__ option (`issue #413 `_) + `Semantic Versioning `__ for library commands and dependencies @@ -263,18 +272,18 @@ PlatformIO 3.0 * New Intelligent Library Build System - + `Library Dependency Finder `__ + + `Library Dependency Finder `__ that interprets C/C++ Preprocessor conditional macros with deep search behavior + Check library compatibility with project environment before building (`issue #415 `_) + Control Library Dependency Finder for compatibility using - `lib_compat_mode `__ + `lib_compat_mode `__ option + Custom library storages/directories with - `lib_extra_dirs `__ option + `lib_extra_dirs `__ option (`issue #537 `_) + Handle extra build flags, source filters and build script from - `library.json `__ + `library.json `__ (`issue #289 `_) + Allowed to disable library archiving (``*.ar``) (`issue #719 `_) @@ -296,7 +305,7 @@ PlatformIO 3.0 * Improved INO to CPP converter (`issue #659 `_, `issue #765 `_) -* Added ``license`` field to `library.json `__ +* Added ``license`` field to `library.json `__ (`issue #522 `_) * Warn about unknown options in project configuration file ``platformio.ini`` (`issue #740 `_) @@ -333,11 +342,11 @@ PlatformIO 2.0 2.11.2 (2016-08-02) ~~~~~~~~~~~~~~~~~~~ -* Improved support for `Microchip PIC32 `__ development platform and ChipKIT boards +* Improved support for `Microchip PIC32 `__ development platform and ChipKIT boards (`issue #438 `_) * Added support for Pinoccio Scout board (`issue #52 `_) -* Added support for `Teensy USB Features `__ +* Added support for `Teensy USB Features `__ (HID, SERIAL_HID, DISK, DISK_SDFLASH, MIDI, etc.) (`issue #722 `_) * Switched to built-in GCC LwIP library for Espressif development platform @@ -362,25 +371,25 @@ PlatformIO 2.0 (`issue #472 `_) * Added support for Microchip chipKIT Lenny board * Updated Microchip PIC32 Arduino framework to v1.2.1 -* Documented `uploading of EEPROM data `__ +* Documented `uploading of EEPROM data `__ (from EEMEM directive) * Added ``Rebuild C/C++ Project Index`` target to CLion and Eclipse IDEs -* Improved project generator for `CLion IDE `__ +* Improved project generator for `CLion IDE `__ * Added ``udev`` rules for OpenOCD CMSIS-DAP adapters (`issue #718 `_) * Auto-remove project cache when PlatformIO is upgraded * Keep user changes for ``.gitignore`` file when re-generate/update project data * Ignore ``[platformio]`` section from custom project configuration file when - `platformio ci --project-conf `__ + `platformio ci --project-conf `__ command is used * Fixed missed ``--boot`` flag for the firmware uploader for ATSAM3X8E Cortex-M3 MCU based boards (Arduino Due, etc) (`issue #710 `_) * Fixed missing trailing ``\`` for the source files list when generate project - for `Qt Creator IDE `__ + for `Qt Creator IDE `__ (`issue #711 `_) * Split source files to ``HEADERS`` and ``SOURCES`` when generate project - for `Qt Creator IDE `__ + for `Qt Creator IDE `__ (`issue #713 `_) 2.11.0 (2016-06-28) @@ -457,7 +466,7 @@ PlatformIO 2.0 2.9.2 (2016-06-02) ~~~~~~~~~~~~~~~~~~ -* Simplified `Continuous Integration with AppVeyor `__ +* Simplified `Continuous Integration with AppVeyor `__ (`issue #671 `_) * Automatically add source directory to ``CPPPATH`` of Build System * Added support for Silicon Labs SLSTK3401A (Pearl Gecko) and @@ -491,21 +500,21 @@ PlatformIO 2.0 2.9.0 (2016-04-28) ~~~~~~~~~~~~~~~~~~ -* Project generator for `CodeBlocks IDE `__ +* Project generator for `CodeBlocks IDE `__ (`issue #600 `_) -* New `Lattice iCE40 FPGA `__ +* New `Lattice iCE40 FPGA `__ development platform with support for Lattice iCEstick FPGA Evaluation Kit and BQ IceZUM Alhambra FPGA (`issue #480 `_) -* New `Intel ARC 32-bit `_ +* New `Intel ARC 32-bit `_ development platform with support for Arduino/Genuino 101 board (`issue #535 `_) -* New `Microchip PIC32 `__ +* New `Microchip PIC32 `__ development platform with support for 20+ different PIC32 based boards (`issue #438 `_) -* New RTOS and build Framework named `Simba `__ +* New RTOS and build Framework named `Simba `__ (`issue #412 `_) -* New boards for `ARM mbed `__ +* New boards for `ARM mbed `__ framework: ST Nucleo F410RB, ST Nucleo L073RZ and BBC micro:bit * Added support for Arduino.Org boards: Arduino Leonardo ETH, Arduino Yun Mini, Arduino Industrial 101 and Linino One @@ -516,7 +525,7 @@ PlatformIO 2.0 * Added support for MightyCore boards: ATmega1284, ATmega644, ATmega324, ATmega164, ATmega32, ATmega16 and ATmega8535 (`issue #585 `_) -* Added support for `TI MSP430 `__ +* Added support for `TI MSP430 `__ boards: TI LaunchPad w/ msp430fr4133 and TI LaunchPad w/ msp430fr6989 * Updated Arduino core for Espressif platform to 2.2.0 (`issue #627 `_) @@ -524,14 +533,14 @@ PlatformIO 2.0 (`issue #366 `_) * PlatformIO Library Registry in JSON format! Implemented ``--json-output`` and ``--page`` options for - `platformio lib search `__ + `platformio lib search `__ command (`issue #604 `_) -* Allowed to specify default environments `env_default `__ +* Allowed to specify default environments `env_default `__ which should be processed by default with ``platformio run`` command (`issue #576 `_) * Allowed to unflag(remove) base/initial flags using - `build_unflags `__ + `build_unflags `__ option (`issue #559 `_) * Allowed multiple VID/PID pairs when detecting serial ports @@ -582,7 +591,7 @@ PlatformIO 2.0 2.8.5 (2016-03-07) ~~~~~~~~~~~~~~~~~~ -* Project generator for `NetBeans IDE `__ +* Project generator for `NetBeans IDE `__ (`issue #541 `_) * Created package for Homebrew Mac OS X Package Manager: ``brew install platformio`` @@ -590,21 +599,21 @@ PlatformIO 2.0 * Updated Arduino core for Espressif platform to 2.1.0 (`issue #544 `_) * Added support for the ESP8266 ESP-07 board to - `Espressif `__ + `Espressif `__ (`issue #527 `_) * Improved handling of String-based ``CPPDEFINES`` passed to extra ``build_flags`` (`issue #526 `_) * Generate appropriate project for CLion IDE and CVS (`issue #523 `_) -* Use ``src_dir`` directory from `Project Configuration File platformio.ini `__ +* Use ``src_dir`` directory from `Project Configuration File platformio.ini `__ when initializing project otherwise create base ``src`` directory (`issue #536 `_) * Fixed issue with incorrect handling of user's build flags where the base flags were passed after user's flags to GCC compiler (`issue #528 `_) * Fixed issue with Project Generator when optional build flags were passed using - system environment variables: `PLATFORMIO_BUILD_FLAGS `__ - or `PLATFORMIO_BUILD_SRC_FLAGS `__ + system environment variables: `PLATFORMIO_BUILD_FLAGS `__ + or `PLATFORMIO_BUILD_SRC_FLAGS `__ * Fixed invalid detecting of compiler type (`issue #550 `_) * Fixed issue with updating package which was deleted manually by user @@ -617,18 +626,18 @@ PlatformIO 2.0 * Added support for the new ESP8266-based boards (ESPDuino, ESP-WROOM-02, ESPresso Lite 1.0 & 2.0, SparkFun ESP8266 Thing Dev, ThaiEasyElec ESPino) to - `Espressif `__ + `Espressif `__ development platform -* Added ``board_f_flash`` option to `Project Configuration File platformio.ini `__ - which allows to specify `custom flash chip frequency `_ +* Added ``board_f_flash`` option to `Project Configuration File platformio.ini `__ + which allows to specify `custom flash chip frequency `_ for Espressif development platform (`issue #501 `_) -* Added ``board_flash_mode`` option to `Project Configuration File platformio.ini `__ - which allows to specify `custom flash chip mode `_ +* Added ``board_flash_mode`` option to `Project Configuration File platformio.ini `__ + which allows to specify `custom flash chip mode `_ for Espressif development platform * Handle new environment variables - `PLATFORMIO_UPLOAD_PORT `_ - and `PLATFORMIO_UPLOAD_FLAGS `_ + `PLATFORMIO_UPLOAD_PORT `_ + and `PLATFORMIO_UPLOAD_FLAGS `_ (`issue #518 `_) * Fixed issue with ``CPPDEFINES`` which contain space and break PlatformIO IDE Linter @@ -664,19 +673,19 @@ PlatformIO 2.0 2.8.0 (2016-01-29) ~~~~~~~~~~~~~~~~~~ -* `PlatformIO IDE `_ for +* `PlatformIO IDE `_ for Atom (`issue #470 `_) * Added ``pio`` command line alias for ``platformio`` command (`issue #447 `_) * Added SPL-Framework support for Nucleo F401RE board (`issue #453 `_) -* Added ``upload_resetmethod`` option to `Project Configuration File platformio.ini `__ - which allows to specify `custom upload reset method `_ +* Added ``upload_resetmethod`` option to `Project Configuration File platformio.ini `__ + which allows to specify `custom upload reset method `_ for Espressif development platform (`issue #444 `_) * Allowed to force output of color ANSI-codes or to disable progress bar even - if the output is a ``pipe`` (not a ``tty``) using `Environment variables `__ + if the output is a ``pipe`` (not a ``tty``) using `Environment variables `__ (`issue #465 `_) * Set 1Mb SPIFFS for Espressif boards by default (`issue #458 `_) @@ -691,7 +700,7 @@ PlatformIO 2.0 * Initial support for Arduino Zero board (`issue #356 `_) * Added support for completions to Atom text editor using ``.clang_complete`` -* Generate default targets for `supported IDE `__ +* Generate default targets for `supported IDE `__ (CLion, Eclipse IDE, Emacs, Sublime Text, VIM): Build, Clean, Upload, Upload SPIFFS image, Upload using Programmer, Update installed platforms and libraries @@ -721,12 +730,12 @@ PlatformIO 2.0 (`issue #403 `_) * Added support for RFDuino (`issue #319 `_) -* Project generator for `Emacs `__ +* Project generator for `Emacs `__ text editor (`pull #404 `_) * Updated Arduino framework for Atmel AVR development platform to 1.6.7 * Documented `firmware uploading for Atmel AVR development platform using - Programmers `_: + Programmers `_: AVR ISP, AVRISP mkII, USBtinyISP, USBasp, Parallel Programmer and Arduino as ISP * Fixed issue with current Python interpreter for Python-based tools (`issue #417 `_) @@ -752,13 +761,13 @@ PlatformIO 2.0 * Added support for the new ESP8266-based boards (SparkFun ESP8266 Thing, NodeMCU 0.9 & 1.0, Olimex MOD-WIFI-ESP8266(-DEV), Adafruit HUZZAH ESP8266, ESPino, SweetPea ESP-210, WeMos D1, WeMos D1 mini) to - `Espressif `__ + `Espressif `__ development platform * Created public `platformio-pkg-ldscripts `_ repository for LD scripts. Moved common configuration for ESP8266 MCU to ``esp8266.flash.common.ld`` (`issue #379 `_) -* Improved documentation for `Espressif `__ +* Improved documentation for `Espressif `__ development platform: OTA update, custom Flash Size, Upload Speed and CPU frequency * Fixed reset method for Espressif NodeMCU (ESP-12E Module) @@ -775,17 +784,17 @@ PlatformIO 2.0 * Install only required packages depending on build environment (`issue #308 `_) -* Added support for Raspberry Pi `WiringPi `__ +* Added support for Raspberry Pi `WiringPi `__ framework (`issue #372 `_) -* Implemented Over The Air (OTA) upgrades for `Espressif `__ +* Implemented Over The Air (OTA) upgrades for `Espressif `__ development platform. (`issue #365 `_) -* Updated `CMSIS framework `__ +* Updated `CMSIS framework `__ and added CMSIS support for Nucleo F401RE board (`issue #373 `_) * Added support for Espressif ESP8266 ESP-01-1MB board (ready for OTA) -* Handle ``upload_flags`` option in `platformio.ini `__ +* Handle ``upload_flags`` option in `platformio.ini `__ (`issue #368 `_) * Improved PlatformIO installation on the Mac OS X El Capitan @@ -793,13 +802,13 @@ PlatformIO 2.0 ~~~~~~~~~~~~~~~~~~ * Improved code builder for parallel builds (up to 4 times faster than before) -* Generate `.travis.yml `__ +* Generate `.travis.yml `__ CI and `.gitignore` files for embedded projects by default (`issue #354 `_) -* Removed prompt with "auto-uploading" from `platformio init `__ +* Removed prompt with "auto-uploading" from `platformio init `__ command and added ``--enable-auto-uploading`` option (`issue #352 `_) -* Fixed incorrect behaviour of `platformio serialports monitor `__ +* Fixed incorrect behaviour of `platformio serialports monitor `__ in pair with PySerial 3.0 2.4.1 (2015-12-01) @@ -816,7 +825,7 @@ PlatformIO 2.0 * Updated Arduino core for Espressif platform to 2.0.0 (`issue #345 `_) * Added to FAQ explanation of `Can not compile a library that compiles without issue - with Arduino IDE `_ + with Arduino IDE `_ (`issue #331 `_) * Fixed ESP-12E flash size (`pull #333 `_) @@ -829,7 +838,7 @@ PlatformIO 2.0 2.3.5 (2015-11-18) ~~~~~~~~~~~~~~~~~~ -* Added support of `libOpenCM3 `_ +* Added support of `libOpenCM3 `_ framework for Nucleo F103RB board (`issue #309 `_) * Added support for Espressif ESP8266 ESP-12E board (NodeMCU) @@ -838,13 +847,13 @@ PlatformIO 2.0 (`issue #307 `_) * Updated Arduino AVR/SAM frameworks to 1.6.6 (`issue #321 `_) -* Upload firmware using external programmer via `platformio run --target program `__ +* Upload firmware using external programmer via `platformio run --target program `__ target (`issue #311 `_) * Fixed handling of upload port when ``board`` option is not specified in - `platformio.ini `__ + `platformio.ini `__ (`issue #313 `_) -* Fixed firmware uploading for `nordicrf51 `__ +* Fixed firmware uploading for `nordicrf51 `__ development platform (`issue #316 `_) * Fixed installation on Mac OS X El Capitan @@ -860,18 +869,18 @@ PlatformIO 2.0 2.3.4 (2015-10-13) ~~~~~~~~~~~~~~~~~~ -* Full support of `CLion IDE `_ +* Full support of `CLion IDE `_ including code auto-completion (`issue #132 `_) -* PlatformIO `command completion in Terminal `_ for ``bash`` and ``zsh`` +* PlatformIO `command completion in Terminal `_ for ``bash`` and ``zsh`` * Added support for ubIQio Ardhat board (`pull #302 `_) * Install SCons automatically and avoid ``error: option --single-version-externally-managed not recognized`` (`issue #279 `_) * Use Teensy CLI Loader for upload of .hex files on Mac OS X (`issue #306 `_) -* Fixed missing `framework-mbed `_ - package for `teensy `_ +* Fixed missing `framework-mbed `_ + package for `teensy `_ platform (`issue #305 `_) @@ -893,7 +902,7 @@ PlatformIO 2.0 * Allowed to use ST-Link uploader for mbed-based projects * Explained how to use ``lib`` directory from the PlatformIO based project in ``readme.txt`` which will be automatically generated using - `platformio init `__ + `platformio init `__ command (`issue #273 `_) * Found solution for "pip/scons error: option --single-version-externally-managed not @@ -906,44 +915,44 @@ PlatformIO 2.0 2.3.1 (2015-09-06) ~~~~~~~~~~~~~~~~~~ -* Fixed critical issue when `platformio init --ide `__ command hangs PlatformIO +* Fixed critical issue when `platformio init --ide `__ command hangs PlatformIO (`issue #283 `_) 2.3.0 (2015-09-05) ~~~~~~~~~~~~~~~~~~ * Added - `native `__, - `linux_arm `__, - `linux_i686 `__, - `linux_x86_64 `__, - `windows_x86 `__ + `native `__, + `linux_arm `__, + `linux_i686 `__, + `linux_x86_64 `__, + `windows_x86 `__ development platforms (`issue #263 `_) -* Added `PlatformIO Demo `_ +* Added `PlatformIO Demo `_ page to documentation -* Simplified `installation `__ +* Simplified `installation `__ process of PlatformIO (`issue #274 `_) -* Significantly improved `Project Generator `__ which allows to integrate with `the most popular - IDE `__ +* Significantly improved `Project Generator `__ which allows to integrate with `the most popular + IDE `__ * Added short ``-h`` help option for PlatformIO and sub-commands -* Updated `mbed `__ +* Updated `mbed `__ framework -* Updated ``tool-teensy`` package for `Teensy `__ +* Updated ``tool-teensy`` package for `Teensy `__ platform (`issue #268 `_) -* Added FAQ answer when `Program "platformio" not found in PATH `_ +* Added FAQ answer when `Program "platformio" not found in PATH `_ (`issue #272 `_) * Generate "readme.txt" for project "lib" directory (`issue #273 `_) * Use toolchain's includes pattern ``include*`` for Project Generator (`issue #277 `_) * Added support for Adafruit Gemma board to - `atmelavr `__ + `atmelavr `__ platform (`pull #256 `_) -* Fixed includes list for Windows OS when generating project for `Eclipse IDE `__ +* Fixed includes list for Windows OS when generating project for `Eclipse IDE `__ (`issue #270 `_) * Fixed ``AttributeError: 'module' object has no attribute 'packages'`` (`issue #252 `_) @@ -951,15 +960,15 @@ PlatformIO 2.0 2.2.2 (2015-07-30) ~~~~~~~~~~~~~~~~~~ -* Integration with `Atom IDE `__ +* Integration with `Atom IDE `__ * Support for off-line/unpublished/private libraries (`issue #260 `_) * Disable project auto-clean while building/uploading firmware using - `platformio run --disable-auto-clean `_ option + `platformio run --disable-auto-clean `_ option (`issue #255 `_) -* Show internal errors from "Miniterm" using `platformio serialports monitor `__ command +* Show internal errors from "Miniterm" using `platformio serialports monitor `__ command (`issue #257 `_) -* Fixed `platformio serialports monitor --help `__ information with HEX char for hotkeys +* Fixed `platformio serialports monitor --help `__ information with HEX char for hotkeys (`issue #253 `_) * Handle "OSError: [Errno 13] Permission denied" for PlatformIO installer script (`issue #254 `_) @@ -967,35 +976,35 @@ PlatformIO 2.0 2.2.1 (2015-07-17) ~~~~~~~~~~~~~~~~~~ -* Project generator for `CLion IDE `__ +* Project generator for `CLion IDE `__ (`issue #132 `_) -* Updated ``tool-bossac`` package to 1.5 version for `atmelsam `__ platform +* Updated ``tool-bossac`` package to 1.5 version for `atmelsam `__ platform (`issue #251 `_) -* Updated ``sdk-esp8266`` package for `espressif `__ platform -* Fixed incorrect arguments handling for `platformio serialports monitor `_ command +* Updated ``sdk-esp8266`` package for `espressif `__ platform +* Fixed incorrect arguments handling for `platformio serialports monitor `_ command (`issue #248 `_) 2.2.0 (2015-07-01) ~~~~~~~~~~~~~~~~~~ * Allowed to exclude/include source files from build process using - `src_filter `__ + `src_filter `__ (`issue #240 `_) * Launch own extra script before firmware building/uploading processes (`issue #239 `_) * Specify own path to the linker script (ld) using - `build_flags `__ + `build_flags `__ option (`issue #233 `_) * Specify library compatibility with the all platforms/frameworks using ``*`` symbol in - `library.json `__ + `library.json `__ * Added support for new embedded boards: *ST 32L0538DISCOVERY and Delta DFCM-NNN40* - to `Framework mbed `__ + to `Framework mbed `__ * Updated packages for - `Framework Arduino (AVR, SAM, Espressif and Teensy cores `__, - `Framework mbed `__, - `Espressif ESP8266 SDK `__ + `Framework Arduino (AVR, SAM, Espressif and Teensy cores `__, + `Framework mbed `__, + `Espressif ESP8266 SDK `__ (`issue #246 `_) * Fixed ``stk500v2_command(): command failed`` (`issue #238 `_) @@ -1023,19 +1032,19 @@ PlatformIO 2.0 2.1.0 (2015-06-03) ~~~~~~~~~~~~~~~~~~ -* Added Silicon Labs EFM32 `siliconlabsefm32 `_ +* Added Silicon Labs EFM32 `siliconlabsefm32 `_ development platform (`issue #226 `_) * Integrate PlatformIO with `Circle CI `_ and `Shippable CI `_ -* Described in documentation how to `create/register own board `_ for PlatformIO +* Described in documentation how to `create/register own board `_ for PlatformIO * Disabled "nano.specs" for ARM-based platforms (`issue #219 `_) * Fixed "ConnectionError" when PlatformIO SF Storage is off-line * Fixed resolving of C/C++ std libs by Eclipse IDE (`issue #220 `_) * Fixed firmware uploading using USB programmer (USBasp) for - `atmelavr `_ + `atmelavr `_ platform (`issue #221 `_) @@ -1048,16 +1057,16 @@ PlatformIO 2.0 ~~~~~~~~~~~~~~~~~~ * Handle new environment variable - `PLATFORMIO_BUILD_FLAGS `_ + `PLATFORMIO_BUILD_FLAGS `_ * Pass to API requests information about Continuous Integration system. This information will be used by PlatformIO-API. * Use ``include`` directories from toolchain when initialising project for IDE (`issue #210 `_) * Added support for new WildFire boards from `Wicked Device `_ to - `atmelavr `__ + `atmelavr `__ platform -* Updated `Arduino Framework `__ to +* Updated `Arduino Framework `__ to 1.6.4 version (`issue #212 `_) * Handle Atmel AVR Symbols when initialising project for IDE (`issue #216 `_) @@ -1070,7 +1079,7 @@ PlatformIO 2.0 *Made in* `Paradise `_ -* PlatformIO as `Continuous Integration `_ +* PlatformIO as `Continuous Integration `_ (CI) tool for embedded projects (`issue #108 `_) * Initialise PlatformIO project for the specified IDE @@ -1083,29 +1092,29 @@ PlatformIO 2.0 * Global ``-f, --force`` option which will force to accept any confirmation prompts (`issue #152 `_) -* Run project with `platformio run --project-dir `_ option without changing the current working +* Run project with `platformio run --project-dir `_ option without changing the current working directory (`issue #192 `_) -* Control verbosity of `platformio run `_ command via ``-v/--verbose`` option +* Control verbosity of `platformio run `_ command via ``-v/--verbose`` option * Add library dependencies for build environment using - `lib_install `_ + `lib_install `_ option in ``platformio.ini`` (`issue #134 `_) * Specify libraries which are compatible with build environment using - `lib_use `_ + `lib_use `_ option in ``platformio.ini`` (`issue #148 `_) * Add more boards to PlatformIO project with - `platformio init --board `__ + `platformio init --board `__ command (`issue #167 `_) * Choose which library to update (`issue #168 `_) -* Specify `platformio init --env-prefix `__ when initialise/update project +* Specify `platformio init --env-prefix `__ when initialise/update project (`issue #182 `_) * Added new Armstrap boards (`issue #204 `_) -* Updated SDK for `espressif `__ +* Updated SDK for `espressif `__ development platform to v1.1 (`issue #179 `_) * Disabled automatic updates by default for platforms, packages and libraries @@ -1122,7 +1131,7 @@ PlatformIO 1.0 * Added support of `Framework mbed `_ for Teensy 3.1 (`issue #183 `_) -* Added GDB as alternative uploader to `ststm32 `__ platform +* Added GDB as alternative uploader to `ststm32 `__ platform (`issue #175 `_) * Added `examples `__ with preconfigured IDE projects @@ -1142,22 +1151,22 @@ PlatformIO 1.0 1.4.0 (2015-04-11) ~~~~~~~~~~~~~~~~~~ -* Added `espressif `_ +* Added `espressif `_ development platform with ESP01 board * Integrated PlatformIO with AppVeyor Windows based Continuous Integration system (`issue #149 `_) * Added support for Teensy LC board to - `teensy `__ + `teensy `__ platform * Added support for new Arduino based boards by *SparkFun, BQ, LightUp, LowPowerLab, Quirkbot, RedBearLab, TinyCircuits* to - `atmelavr `__ + `atmelavr `__ platform -* Upgraded `Arduino Framework `__ to +* Upgraded `Arduino Framework `__ to 1.6.3 version (`issue #156 `_) -* Upgraded `Energia Framework `__ to +* Upgraded `Energia Framework `__ to 0101E0015 version (`issue #146 `_) -* Upgraded `Arduino Framework with Teensy Core `_ +* Upgraded `Arduino Framework with Teensy Core `_ to 1.22 version (`issue #162 `_, `issue #170 `_) @@ -1172,12 +1181,12 @@ PlatformIO 1.0 account to `PlatformIO Organisation `_ (`issue #138 `_) * Added support for new Arduino based boards by *SparkFun, RepRap, Sanguino* to - `atmelavr `__ + `atmelavr `__ platform (`issue #127 `_, `issue #131 `_) -* Added integration instructions for `Visual Studio `_ - and `Sublime Text `_ IDEs +* Added integration instructions for `Visual Studio `_ + and `Sublime Text `_ IDEs * Improved handling of multi-file ``*.ino/pde`` sketches (`issue #130 `_) * Fixed wrong insertion of function prototypes converting ``*.ino/pde`` @@ -1189,31 +1198,31 @@ PlatformIO 1.0 1.2.0 (2015-03-20) ~~~~~~~~~~~~~~~~~~ -* Added full support of `mbed `__ +* Added full support of `mbed `__ framework including libraries: *RTOS, Ethernet, DSP, FAT, USB*. -* Added `freescalekinetis `_ +* Added `freescalekinetis `_ development platform with Freescale Kinetis Freedom boards -* Added `nordicnrf51 `_ +* Added `nordicnrf51 `_ development platform with supported boards from *JKSoft, Nordic, RedBearLab, Switch Science* -* Added `nxplpc `_ +* Added `nxplpc `_ development platform with supported boards from *CQ Publishing, Embedded Artists, NGX Technologies, NXP, Outrageous Circuits, SeeedStudio, Solder Splash Labs, Switch Science, u-blox* * Added support for *ST Nucleo* boards to - `ststm32 `__ + `ststm32 `__ development platform -* Created new `Frameworks `__ +* Created new `Frameworks `__ page in documentation and added to `PlatformIO Web Site `_ (`issue #115 `_) * Introduced online `Embedded Boards Explorer `_ * Automatically append define ``-DPLATFORMIO=%version%`` to builder (`issue #105 `_) * Renamed ``stm32`` development platform to - `ststm32 `__ + `ststm32 `__ * Renamed ``opencm3`` framework to - `libopencm3 `__ -* Fixed uploading for `atmelsam `__ + `libopencm3 `__ +* Fixed uploading for `atmelsam `__ development platform * Fixed re-arranging the ``*.ino/pde`` files when converting to ``*.cpp`` (`issue #100 `_) @@ -1224,15 +1233,15 @@ PlatformIO 1.0 * Implemented ``PLATFORMIO_*`` environment variables (`issue #102 `_) * Added support for *SainSmart* boards to - `atmelsam `__ + `atmelsam `__ development platform * Added - `Project Configuration `__ - option named `envs_dir `__ + `Project Configuration `__ + option named `envs_dir `__ * Disabled "prompts" automatically for *Continuous Integration* systems (`issue #103 `_) * Fixed firmware uploading for - `atmelavr `__ + `atmelavr `__ boards which work within ``usbtiny`` protocol * Fixed uploading for *Digispark* board (`issue #106 `_) @@ -1245,26 +1254,26 @@ PlatformIO 1.0 * Added support for *ARM*-based credit-card sized computers: `Raspberry Pi `_, `BeagleBone `_ and `CubieBoard `_ -* Added `atmelsam `__ +* Added `atmelsam `__ development platform with supported boards: *Arduino Due and Digistump DigiX* (`issue #71 `_) -* Added `ststm32 `__ +* Added `ststm32 `__ development platform with supported boards: *Discovery kit for STM32L151/152, STM32F303xx, STM32F407/417 lines* and `libOpenCM3 Framework `_ (`issue #73 `_) -* Added `teensy `_ +* Added `teensy `_ development platform with supported boards: *Teensy 2.x & 3.x* (`issue #72 `_) * Added new *Arduino* boards to - `atmelavr `__ + `atmelavr `__ platform: *Arduino NG, Arduino BT, Arduino Esplora, Arduino Ethernet, Arduino Robot Control, Arduino Robot Motor and Arduino Yun* * Added support for *Adafruit* boards to - `atmelavr `__ + `atmelavr `__ platform: *Adafruit Flora and Adafruit Trinkets* (`issue #65 `_) * Added support for *Digispark* boards to - `atmelavr `__ + `atmelavr `__ platform: *Digispark USB Development Board and Digispark Pro* (`issue #47 `_) * Covered code with tests (`issue #2 `_) @@ -1272,24 +1281,24 @@ PlatformIO 1.0 `#48 `_, `#50 `_, `#55 `_) -* Added `src_dir `__ +* Added `src_dir `__ option to ``[platformio]`` section of - `platformio.ini `__ + `platformio.ini `__ which allows to redefine location to project's source directory (`issue #83 `_) * Added ``--json-output`` option to - `platformio boards `__ - and `platformio search `__ + `platformio boards `__ + and `platformio search `__ commands which allows to return the output in `JSON `_ format (`issue #42 `_) * Allowed to ignore some libs from *Library Dependency Finder* via - `lib_ignore `_ option -* Improved `platformio run `__ + `lib_ignore `_ option +* Improved `platformio run `__ command: asynchronous output for build process, timing and detailed information about environment configuration (`issue #74 `_) * Output compiled size and static memory usage with - `platformio run `__ + `platformio run `__ command (`issue #59 `_) * Updated `framework-arduino` AVR & SAM to 1.6 stable version * Fixed an issue with the libraries that are git repositories @@ -1313,19 +1322,19 @@ PlatformIO 0.0 * Fixed an issue with ``--json-output`` (`issue #42 `_) * Fixed an exception during - `platformio upgrade `__ + `platformio upgrade `__ under Windows OS (`issue #45 `_) 0.10.1 (2015-01-02) ~~~~~~~~~~~~~~~~~~~ * Added ``--json-output`` option to - `platformio list `__, - `platformio serialports list `__ and - `platformio lib list `__ + `platformio list `__, + `platformio serialports list `__ and + `platformio lib list `__ commands which allows to return the output in `JSON `_ format (`issue #42 `_) -* Fixed missing auto-uploading by default after `platformio init `__ +* Fixed missing auto-uploading by default after `platformio init `__ command 0.10.0 (2015-01-01) @@ -1333,19 +1342,19 @@ PlatformIO 0.0 **Happy New Year!** -* Implemented `platformio boards `_ +* Implemented `platformio boards `_ command (`issue #11 `_) * Added support of *Engduino* boards for - `atmelavr `__ + `atmelavr `__ platform (`issue #38 `_) -* Added ``--board`` option to `platformio init `__ +* Added ``--board`` option to `platformio init `__ command which allows to initialise project with the specified embedded boards (`issue #21 `_) -* Added `example with uploading firmware `_ +* Added `example with uploading firmware `_ via USB programmer (USBasp) for - `atmelavr `_ + `atmelavr `_ *MCUs* (`issue #35 `_) -* Automatic detection of port on `platformio serialports monitor `_ +* Automatic detection of port on `platformio serialports monitor `_ (`issue #37 `_) * Allowed auto-installation of platforms when prompts are disabled (`issue #43 `_) * Fixed urllib3's *SSL* warning under Python <= 2.7.2 (`issue #39 `_) @@ -1363,11 +1372,11 @@ PlatformIO 0.0 ~~~~~~~~~~~~~~~~~~ * Ask user to install platform (when it hasn't been installed yet) within - `platformio run `__ - and `platformio show `_ commands + `platformio run `__ + and `platformio show `_ commands * Improved main `documentation `_ * Fixed "*OSError: [Errno 2] No such file or directory*" within - `platformio run `__ + `platformio run `__ command when PlatformIO isn't installed properly * Fixed example for `Eclipse IDE with Tiva board `_ (`issue #32 `_) @@ -1377,8 +1386,8 @@ PlatformIO 0.0 0.9.0 (2014-12-01) ~~~~~~~~~~~~~~~~~~ -* Implemented `platformio settings `_ command -* Improved `platformio init `_ command. +* Implemented `platformio settings `_ command +* Improved `platformio init `_ command. Added new option ``--project-dir`` where you can specify another path to directory where new project will be initialized (`issue #31 `_) * Added *Migration Manager* which simplifies process with upgrading to a @@ -1395,18 +1404,18 @@ PlatformIO 0.0 0.8.0 (2014-10-19) ~~~~~~~~~~~~~~~~~~ -* Avoided trademark issues in `library.json `_ - with the new fields: `frameworks `_, - `platforms `_ - and `dependencies `_ +* Avoided trademark issues in `library.json `_ + with the new fields: `frameworks `_, + `platforms `_ + and `dependencies `_ (`issue #17 `_) * Switched logic from "Library Name" to "Library Registry ID" for all - `platformio lib `_ + `platformio lib `_ commands (install, uninstall, update and etc.) -* Renamed ``author`` field to `authors `_ - and allowed to setup multiple authors per library in `library.json `_ -* Added option to specify "maintainer" status in `authors `_ field -* New filters/options for `platformio lib search `_ +* Renamed ``author`` field to `authors `_ + and allowed to setup multiple authors per library in `library.json `_ +* Added option to specify "maintainer" status in `authors `_ field +* New filters/options for `platformio lib search `_ command: ``--framework`` and ``--platform`` 0.7.1 (2014-10-06) @@ -1420,15 +1429,15 @@ PlatformIO 0.0 0.7.0 (2014-09-24) ~~~~~~~~~~~~~~~~~~ -* Implemented new `[platformio] `_ - section for Configuration File with `home_dir `_ +* Implemented new `[platformio] `_ + section for Configuration File with `home_dir `_ option (`issue #14 `_) * Implemented *Library Manager* (`issue #6 `_) 0.6.0 (2014-08-09) ~~~~~~~~~~~~~~~~~~ -* Implemented `platformio serialports monitor `_ (`issue #10 `_) +* Implemented `platformio serialports monitor `_ (`issue #10 `_) * Fixed an issue ``ImportError: No module named platformio.util`` (`issue #9 `_) * Fixed bug with auto-conversation from Arduino \*.ino to \*.cpp @@ -1441,7 +1450,7 @@ PlatformIO 0.0 frameworks (`issue #7 `_) * Added `Arduino example `_ with external library (*Adafruit CC3000*) -* Implemented `platformio upgrade `_ +* Implemented `platformio upgrade `_ command and "auto-check" for the latest version (`issue #8 `_) * Fixed an issue with "auto-reset" for *Raspduino* board @@ -1450,21 +1459,21 @@ PlatformIO 0.0 0.4.0 (2014-07-31) ~~~~~~~~~~~~~~~~~~ -* Implemented `platformio serialports `_ command +* Implemented `platformio serialports `_ command * Allowed to put special build flags only for ``src`` files via - `src_build_flags `_ + `src_build_flags `_ environment option * Allowed to override some of settings via system environment variables such as: ``PLATFORMIO_SRC_BUILD_FLAGS`` and ``PLATFORMIO_ENVS_DIR`` -* Added ``--upload-port`` option for `platformio run `__ command +* Added ``--upload-port`` option for `platformio run `__ command * Implemented (especially for `SmartAnthill `_) - `platformio run -t uploadlazy `_ + `platformio run -t uploadlazy `_ target (no dependencies to framework libs, ELF and etc.) -* Allowed to skip default packages via `platformio install --skip-default-package `_ +* Allowed to skip default packages via `platformio install --skip-default-package `_ option * Added tools for *Raspberry Pi* platform * Added support for *Microduino* and *Raspduino* boards in - `atmelavr `_ platform + `atmelavr `_ platform 0.3.1 (2014-06-21) diff --git a/docs b/docs index fad663db..b75c7008 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit fad663db0c599d6e5ef42d90263cfdbf686eca4e +Subproject commit b75c70080557136fd6a65b61c9fcc14b9cc0f9a3 diff --git a/platformio/__init__.py b/platformio/__init__.py index b15e769a..7959277b 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 2, 1) +VERSION = (3, 2, "2a1") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/init.py b/platformio/commands/init.py index 3dc454be..c668355b 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -57,6 +57,7 @@ def validate_boards(ctx, param, value): # pylint: disable=W0613 "--ide", type=click.Choice(ProjectGenerator.get_supported_ides())) @click.option("-O", "--project-option", multiple=True) @click.option("--env-prefix", default="") +@click.option("-s", "--silent", is_flag=True) @click.pass_context def cli( ctx, # pylint: disable=R0913 @@ -64,28 +65,31 @@ def cli( board, ide, project_option, - env_prefix): + env_prefix, + silent): - if project_dir == getcwd(): - click.secho("\nThe current working directory", fg="yellow", nl=False) - click.secho(" %s " % project_dir, fg="cyan", nl=False) - click.secho( - "will be used for project.\n" - "You can specify another project directory via\n" - "`platformio init -d %PATH_TO_THE_PROJECT_DIR%` command.", - fg="yellow") - click.echo("") + if not silent: + if project_dir == getcwd(): + click.secho( + "\nThe current working directory", fg="yellow", nl=False) + click.secho(" %s " % project_dir, fg="cyan", nl=False) + click.secho( + "will be used for project.\n" + "You can specify another project directory via\n" + "`platformio init -d %PATH_TO_THE_PROJECT_DIR%` command.", + fg="yellow") + click.echo("") - click.echo("The next files/directories have been created in %s" % - click.style( - project_dir, fg="cyan")) - click.echo("%s - Project Configuration File" % click.style( - "platformio.ini", fg="cyan")) - click.echo("%s - Put your source files here" % click.style( - "src", fg="cyan")) - click.echo("%s - Put here project specific (private) libraries" % - click.style( - "lib", fg="cyan")) + click.echo("The next files/directories have been created in %s" % + click.style( + project_dir, fg="cyan")) + click.echo("%s - Project Configuration File" % click.style( + "platformio.ini", fg="cyan")) + click.echo("%s - Put your source files here" % click.style( + "src", fg="cyan")) + click.echo("%s - Put here project specific (private) libraries" % + click.style( + "lib", fg="cyan")) init_base_project(project_dir) @@ -111,16 +115,17 @@ def cli( pg = ProjectGenerator(project_dir, ide, board[0]) pg.generate() - click.secho( - "\nProject has been successfully initialized!\nUseful commands:\n" - "`platformio run` - process/build project from the current " - "directory\n" - "`platformio run --target upload` or `platformio run -t upload` " - "- upload firmware to embedded board\n" - "`platformio run --target clean` - clean project (remove compiled " - "files)\n" - "`platformio run --help` - additional information", - fg="green") + if not silent: + click.secho( + "\nProject has been successfully initialized!\nUseful commands:\n" + "`platformio run` - process/build project from the current " + "directory\n" + "`platformio run --target upload` or `platformio run -t upload` " + "- upload firmware to embedded board\n" + "`platformio run --target clean` - clean project (remove compiled " + "files)\n" + "`platformio run --help` - additional information", + fg="green") def get_first_board(project_dir): diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 1ed50edf..f270b437 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -95,7 +95,7 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, results.append((envname, None)) continue - if results: + if not silent and results: click.echo() options = {} @@ -108,11 +108,13 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, upload_port, silent, verbose) results.append((envname, ep.process())) - if len(results) > 1: + found_error = any([status is False for (_, status) in results]) + + if (found_error or not silent) and len(results) > 1: click.echo() print_summary(results, start_time) - if any([status is False for (_, status) in results]): + if found_error: raise exception.ReturnErrorCode(1) return True @@ -160,18 +162,20 @@ class EnvironmentProcessor(object): if "\n" in v: self.options[k] = self.options[k].strip().replace("\n", ", ") - click.echo("[%s] Processing %s (%s)" % ( - datetime.now().strftime("%c"), click.style( - self.name, fg="cyan", bold=True), - ", ".join(["%s: %s" % (k, v) for k, v in self.options.items()]))) - click.secho("-" * terminal_width, bold=True) - if self.silent: - click.echo("Please wait...") + if not self.silent: + click.echo("[%s] Processing %s (%s)" % ( + datetime.now().strftime("%c"), click.style( + self.name, fg="cyan", bold=True), ", ".join( + ["%s: %s" % (k, v) for k, v in self.options.items()]))) + click.secho("-" * terminal_width, bold=True) self.options = self._validate_options(self.options) result = self._run() - is_error = result['returncode'] != 0 + + if self.silent and not is_error: + return True + if is_error or "piotest_processor" not in self.cmd_ctx.meta: print_header( "[%s] Took %.2f seconds" % ((click.style( From 7dcddb295ef1e0a1ff0881fe90810be6b37ae2a1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Dec 2016 14:19:47 +0200 Subject: [PATCH 002/127] Use stable version of PIO Core --- scripts/get-platformio.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/get-platformio.py b/scripts/get-platformio.py index 293b06b0..b70c9598 100644 --- a/scripts/get-platformio.py +++ b/scripts/get-platformio.py @@ -114,11 +114,7 @@ def install_platformio(): r = None cmd = ["-m", "pip.__main__" if sys.version_info < (2, 7, 0) else "pip"] try: - # r = exec_python_cmd(cmd + ["install", "-U", "platformio"]) - r = exec_python_cmd(cmd + [ - "install", "-U", - "https://github.com/platformio/platformio-core/archive/develop.zip" - ]) + r = exec_python_cmd(cmd + ["install", "-U", "platformio"]) assert r['returncode'] == 0 except AssertionError: r = exec_python_cmd(cmd + ["--no-cache-dir", "install", "-U", From 4cf542c6f6519b53983fc84c7a91bb7c3cbfa999 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Dec 2016 14:37:24 +0200 Subject: [PATCH 003/127] Use stable version of `get-platformio.py` --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index b75c7008..16451e2c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b75c70080557136fd6a65b61c9fcc14b9cc0f9a3 +Subproject commit 16451e2c05ff33bbb6711b920745c46a6d8e261e From 0286567df87b933549750f3260039567e4a5edd6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Dec 2016 14:43:15 +0200 Subject: [PATCH 004/127] Fix RST warning --- HISTORY.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 83fd6a47..39abf261 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -8,8 +8,8 @@ PlatformIO 3.0 ~~~~~~~~~~~~~~~~~~ * Produce less noisy output when ``-s/--silent`` options are used for - `platformio init `_ - and `platformio run `_ + `platformio init `__ + and `platformio run `__ commands (`issue #850 `_) From 36c0c123d37d6448afaef8743ad9c48fbd3b3c50 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Dec 2016 20:46:09 +0200 Subject: [PATCH 005/127] Update links and data --- README.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 07adc48b..66e6a5a8 100644 --- a/README.rst +++ b/README.rst @@ -7,8 +7,8 @@ PlatformIO .. image:: https://ci.appveyor.com/api/projects/status/unnpw0n3c5k14btn/branch/develop?svg=true :target: https://ci.appveyor.com/project/ivankravets/platformio-core :alt: AppVeyor.CI Build Status -.. image:: https://requires.io/github/platformio/platformio/requirements.svg?branch=develop - :target: https://requires.io/github/platformio/platformio/requirements/?branch=develop +.. image:: https://requires.io/github/platformio/platformio-core/requirements.svg?branch=develop + :target: https://requires.io/github/platformio/platformio-core/requirements/?branch=develop :alt: Requirements Status .. image:: https://img.shields.io/pypi/v/platformio.svg :target: https://pypi.python.org/pypi/platformio/ @@ -26,7 +26,7 @@ PlatformIO **Quick Links:** `Home Page `_ | `PlatformIO Plus `_ | `PlatformIO IDE `_ | -`Project Examples `_ | +`Project Examples `_ | `Docs `_ | `Donate `_ | `Contact Us `_ @@ -98,13 +98,13 @@ settings for most popular `Embedded Boards `_. * Colourful `command-line output `_ * `IDE Integration `_ with - *Arduino, Atom, Eclipse, Emacs, Energia, Qt Creator, Sublime Text, Vim, Visual Studio* + *Cloud9, Codeanywhere, Eclipse Che, Atom, CLion, CodeBlocks, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, Vim, Visual Studio* * Cloud compiling and `Continuous Integration `_ with *AppVeyor, Circle CI, Drone, Shippable, Travis CI* * Built-in `Serial Port Monitor `_ and configurable `build -flags/-options `_ * Automatic **firmware uploading** -* Pre-built tool chains, frameworks for the popular `Hardware Platforms `_ +* Pre-built tool chains, frameworks for the popular `development platforms `_ .. image:: https://raw.githubusercontent.com/platformio/platformio-web/develop/app/images/platformio-embedded-development.png :target: http://platformio.org @@ -116,12 +116,11 @@ The Missing Library Manager. *It's here!* platforms which allows you to organize and have up-to-date external libraries. * Friendly `Command-Line Interface `_ -* Modern `Web 2.0 Library Search `_ +* Modern `Web 2.0 Library Portal `_ * Open Source `Library Registry API `_ * Library Crawler based on `library.json `_ specification -* Library **dependency management** -* Automatic library updating +* Project Dependency Manager with `Semantic Versioning `_ requirements .. image:: https://raw.githubusercontent.com/platformio/platformio-web/develop/app/images/platformio-library-manager.png :target: http://platformio.org @@ -158,7 +157,8 @@ It has support for the most popular embedded platforms: * `Atmel AVR `_ * `Atmel SAM `_ -* `Espressif `_ +* `Espressif 32 `_ +* `Espressif 8266 `_ * `Freescale Kinetis `_ * `Intel ARC32 `_ * `Lattice iCE40 `_ @@ -169,13 +169,14 @@ It has support for the most popular embedded platforms: * `Silicon Labs EFM32 `_ * `Teensy `_ * `TI MSP430 `_ -* `TI TIVA C `_ +* `TI TivaVA C `_ Frameworks: * `Arduino `_ * `CMSIS `_ * `Energia `_ +* `ESP-IDF `_ * `libOpenCM3 `_ * `mbed `_ * `Simba `_ From 65e83af98270bb7ef3377f3619d1cff31a818a21 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 10 Dec 2016 17:49:20 +0200 Subject: [PATCH 006/127] New board Node32s; Update ESP32 Core for Arduino --- HISTORY.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 39abf261..4be9cca4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -13,6 +13,15 @@ PlatformIO 3.0 commands (`issue #850 `_) +------- + +* Development platform `Espressif 32 `__ + + + Added support for Simba Framework + + Added new board Node32s + + Updated ESP32 Core for Arduino + + 3.2.1 (2016-12-07) ~~~~~~~~~~~~~~~~~~ From d2b3ce55e5ec9c787816a4f899bd83ce856ea4aa Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 10 Dec 2016 18:06:05 +0200 Subject: [PATCH 007/127] New board Node32s; Update ESP32 Core for Arduino --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 16451e2c..1eee6fdc 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 16451e2c05ff33bbb6711b920745c46a6d8e261e +Subproject commit 1eee6fdc886d853875b77c1951c0178f0c58b457 From 4a6e644b2f511000bb5baa9a7e4f0f168cc57e0c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 12 Dec 2016 17:13:24 +0200 Subject: [PATCH 008/127] New article by Cuong Tran Viet --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 1eee6fdc..b1de3aaf 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 1eee6fdc886d853875b77c1951c0178f0c58b457 +Subproject commit b1de3aaf003fedfab6189d130b20bba30c19c3ba From f1e06da15627ea4c8d09bce9ad7f7d835d26f0a3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 12 Dec 2016 17:58:01 +0200 Subject: [PATCH 009/127] Update examples with ArduinoJson library --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index b1de3aaf..92536809 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b1de3aaf003fedfab6189d130b20bba30c19c3ba +Subproject commit 925368097831064ee7f3153fa41dee2e6a08ebff From 8869680302ee23d654c6d0141f9bb7a0154ec9a0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 12 Dec 2016 23:26:42 +0200 Subject: [PATCH 010/127] Make workpiece to dump all platform packages --- platformio/commands/platform.py | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 99858b57..fc919405 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -139,6 +139,7 @@ def platform_list(json_output): "description": p.description, "version": p.version, "url": p.vendor_url, + # "packages": p.packages.keys(), # dump all packages "packages": p.get_installed_packages().keys(), 'forDesktop': any([ p.name.startswith(n) for n in ("native", "linux", "windows") From bd7d41ed37b7ac139b4b95a11598f6d8d40404f2 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 13 Dec 2016 19:51:56 +0200 Subject: [PATCH 011/127] Typo fix in docs --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 92536809..72a056d3 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 925368097831064ee7f3153fa41dee2e6a08ebff +Subproject commit 72a056d30019eea6b6d779228a13932a0c0618ba From 0d52147005f8a79d537235bc91f27ef2556085e3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 14 Dec 2016 13:14:40 +0200 Subject: [PATCH 012/127] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 71b72011..9c025651 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -7,7 +7,9 @@ What kind of issue is this? - [ ] PlatformIO IDE. All issues related to PlatformIO IDE should be reported to appropriate repository https://github.com/platformio/platformio-atom-ide/issues -- [ ] Development Platform. All issues related to Development Platform should be reported to appropriate repository. Search it using link below +- [ ] Development Platform or Board. All issues related to Development Platforms or Embedded Boards + should be reported to appropriate repository. + See full list with repositories and search for "platform-xxx" repository related to your hardware https://github.com/platformio?query=platform- - [ ] Feature Request. Start by telling us what problem you’re trying to solve. Often a solution From e9f15ba034f0cf7a891a99860dda08a9ffbd2e8d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 14 Dec 2016 14:01:12 +0200 Subject: [PATCH 013/127] Add example with media disk for upload_port --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 72a056d3..70990265 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 72a056d30019eea6b6d779228a13932a0c0618ba +Subproject commit 709902656eeffc4687df43560a3c7e8dbb31757e From 403da8e22b86e139fbb87ebe6bdddfd5b1bfbc6c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 15 Dec 2016 13:05:55 +0200 Subject: [PATCH 014/127] Allow framework without package --- platformio/managers/platform.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 0ee5a4fb..1e274f38 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -460,8 +460,9 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): framework = framework.lower().strip() if not framework or framework not in self.frameworks: continue - _pkg_name = self.frameworks[framework]['package'] - self.packages[_pkg_name]['optional'] = False + _pkg_name = self.frameworks[framework].get("package") + if _pkg_name: + self.packages[_pkg_name]['optional'] = False # enable upload tools for upload targets if any(["upload" in t for t in targets] + ["program" in targets]): From 99c747320893618b924b3ae6312305dda8ccf800 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 15 Dec 2016 13:17:52 +0200 Subject: [PATCH 015/127] Specify default LED_BUILTIN for Quick Start example and wiring-blink --- docs | 2 +- examples | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs b/docs index 70990265..d12e9d57 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 709902656eeffc4687df43560a3c7e8dbb31757e +Subproject commit d12e9d57f1dc7d88498ad763a82461a63f287854 diff --git a/examples b/examples index 0ac639a8..2a735204 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 0ac639a82b84ad9fc9fe98794cfe5309decf3ad0 +Subproject commit 2a7352043b0e3aa8dfc158e5567c725bab7710e5 From 539ad4b5ee3c1a357e2b6beeb8f4b61c7b1ef2c0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 15 Dec 2016 21:23:46 +0200 Subject: [PATCH 016/127] New article by Dr. Patrick Mineault; Add Unit Testing example with Labmet Weather Station --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index d12e9d57..343ed9c1 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit d12e9d57f1dc7d88498ad763a82461a63f287854 +Subproject commit 343ed9c1d2ebf6321027cebe45284b33b35809af From 8c47814d8d6925fde83aba463b50aadf742f7c22 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 16 Dec 2016 21:33:17 +0200 Subject: [PATCH 017/127] Add support for Samsung ARTIK boards (520, 710, 1020) and ARTIK SDK // Resolve #353 --- HISTORY.rst | 6 ++++++ README.rst | 1 + docs | 2 +- setup.py | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 4be9cca4..47e20789 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -22,6 +22,12 @@ PlatformIO 3.0 + Updated ESP32 Core for Arduino +* Development platform `Linux ARM `__ + + + Added support for Samsung ARTIK boards (520, 710, 1020) and ARTIK SDK + (`issue #353 `_) + + 3.2.1 (2016-12-07) ~~~~~~~~~~~~~~~~~~ diff --git a/README.rst b/README.rst index 66e6a5a8..be79d927 100644 --- a/README.rst +++ b/README.rst @@ -174,6 +174,7 @@ It has support for the most popular embedded platforms: Frameworks: * `Arduino `_ +* `ARTIK SDK `_ * `CMSIS `_ * `Energia `_ * `ESP-IDF `_ diff --git a/docs b/docs index 343ed9c1..f7bf9adf 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 343ed9c1d2ebf6321027cebe45284b33b35809af +Subproject commit f7bf9adf3d44fd60a76126ccbcac00ce1aaaa31d diff --git a/setup.py b/setup.py index b54a4d19..4b71930f 100644 --- a/setup.py +++ b/setup.py @@ -69,6 +69,6 @@ setup( "iot", "ide", "build", "compile", "library manager", "embedded", "ci", "continuous integration", "arduino", "mbed", "esp8266", "framework", "ide", "ide integration", "library.json", - "make", "cmake", "makefile", "mk", "pic32", "fpga" + "make", "cmake", "makefile", "mk", "pic32", "fpga", "artik" ] ) From 2521a2420d37a6c9e11f5d699831d9798f37c54d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 16 Dec 2016 22:41:53 +0200 Subject: [PATCH 018/127] Sync docs and examples --- docs | 2 +- examples | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs b/docs index f7bf9adf..5611531c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit f7bf9adf3d44fd60a76126ccbcac00ce1aaaa31d +Subproject commit 5611531c33386b066296d6346c952e36c4514408 diff --git a/examples b/examples index 2a735204..11947db3 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 2a7352043b0e3aa8dfc158e5567c725bab7710e5 +Subproject commit 11947db3ebb17c828c5ea37ca6e3d80f57cf2c57 From 7f38c85738330d6408444df6a1a2b45fccc65eae Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 18 Dec 2016 20:46:35 +0200 Subject: [PATCH 019/127] Update history and docs --- HISTORY.rst | 31 +++++++++++++++++++++++++++++++ docs | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 47e20789..6b9c5e15 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -15,18 +15,49 @@ PlatformIO 3.0 ------- +* Development platform `Atmel SAM `__ + + + Added support for Atmel ATSAMW25-XPRO board + + Updated ARM mbed OS to 5.3.0/rev131 + * Development platform `Espressif 32 `__ + Added support for Simba Framework + Added new board Node32s + Updated ESP32 Core for Arduino +* Development platform `Freescale Kinetis `__ + + + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `Linux ARM `__ + Added support for Samsung ARTIK boards (520, 710, 1020) and ARTIK SDK (`issue #353 `_) +* Development platform `Nordic nRF51 `__ + + + Updated ARM mbed OS to 5.3.0/rev131 + +* Development platform `NXP LPC `__ + + + Added support for LPCXpresso4337 and y5 LPC11U35 mbug boards + + Updated ARM mbed OS to 5.3.0/rev131 + +* Development platform `Silicon Labs EFM32 `__ + + + Updated ARM mbed OS to 5.3.0/rev131 + +* Development platform `ST STM32 `__ + + + Added support for new boards: Espotel LoRa Module, NAMote72, MTS Dragonfly, + ST Nucleo F303ZE, u-blox EVK-ODIN-W2, MultiTech xDot + + Updated ARM mbed OS to 5.3.0/rev131 + +* Development platform `Teensy `__ + + + Updated ARM mbed OS to 5.3.0/rev131 + 3.2.1 (2016-12-07) ~~~~~~~~~~~~~~~~~~ diff --git a/docs b/docs index 5611531c..c3780c69 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 5611531c33386b066296d6346c952e36c4514408 +Subproject commit c3780c6913f16201da1c29643a8f4ae941d216df From 1a4c5df14da10703e2472661645d3693bc6960e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Thu, 22 Dec 2016 01:15:01 +0100 Subject: [PATCH 020/127] Added support for templated methods in InoToCPPConverter (#858) * Added support for templated methods in InoToCPPConverter --- platformio/builder/tools/piomisc.py | 1 + tests/ino2cpp/basic/basic.ino | 7 +++++-- tests/test_ino2cpp.py | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 99081ada..3b9f34e8 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -32,6 +32,7 @@ from platformio import util class InoToCPPConverter(object): PROTOTYPE_RE = re.compile(r"""^( + (?:template\<.*\>\s*)? # template ([a-z_\d]+\*?\s+){1,2} # return type ([a-z_\d]+\s*) # name of prototype \([a-z_,\.\*\&\[\]\s\d]*\) # arguments diff --git a/tests/ino2cpp/basic/basic.ino b/tests/ino2cpp/basic/basic.ino index b5bd7f2c..88ac301c 100644 --- a/tests/ino2cpp/basic/basic.ino +++ b/tests/ino2cpp/basic/basic.ino @@ -26,12 +26,15 @@ Foo foo(&fooCallback); // +template T Add(T n1, T n2) { + return n1 + n2; +} + void setup() { struct Item item1; myFunction(&item1); } - void loop() { } @@ -40,7 +43,7 @@ void myFunction(struct Item *item) { } -#warning "Line number is 43" +#warning "Line number is 46" void fooCallback(){ diff --git a/tests/test_ino2cpp.py b/tests/test_ino2cpp.py index f3ecb018..337eee72 100644 --- a/tests/test_ino2cpp.py +++ b/tests/test_ino2cpp.py @@ -42,7 +42,7 @@ def test_warning_line(clirunner, validate_cliresult): validate_cliresult(result) assert ('basic.ino:16:14: warning: #warning "Line number is 16"' in result.output) - assert ('basic.ino:43:2: warning: #warning "Line number is 43"' in + assert ('basic.ino:46:2: warning: #warning "Line number is 46"' in result.output) result = clirunner.invoke( cmd_ci, [join(INOTEST_DIR, "strmultilines"), "-b", "uno"]) From c7fba322296e017ad4a84c306e4e7eb4d2aadccb Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 22 Dec 2016 02:15:51 +0200 Subject: [PATCH 021/127] Fix CLA link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e46d388c..0b38098d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ Contributing ------------ -To get started, sign the Contributor License Agreement. +To get started, sign the Contributor License Agreement. 1. Fork the repository on GitHub. 2. Make a branch off of ``develop`` From 80f67df3fa40fe7095b87c7b2fe55c3cfac179d3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 22 Dec 2016 13:10:48 +0200 Subject: [PATCH 022/127] Update history --- HISTORY.rst | 2 ++ examples | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 6b9c5e15..526dfb64 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,6 +7,8 @@ PlatformIO 3.0 3.2.2 (2016-12-??) ~~~~~~~~~~~~~~~~~~ +* Added support for templated methods in "*.ino to *.cpp" convertor + (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for `platformio init `__ and `platformio run `__ diff --git a/examples b/examples index 11947db3..fa891378 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 11947db3ebb17c828c5ea37ca6e3d80f57cf2c57 +Subproject commit fa891378955708aec4d6a0c24bfa5ed9bb0a0dc4 From ede581182ca21d3e6887f44ff1848471ae4d611a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 22 Dec 2016 14:13:56 +0200 Subject: [PATCH 023/127] Fix RST for history --- HISTORY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 526dfb64..25a9d506 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,7 +7,7 @@ PlatformIO 3.0 3.2.2 (2016-12-??) ~~~~~~~~~~~~~~~~~~ -* Added support for templated methods in "*.ino to *.cpp" convertor +* Added support for templated methods in ``*.ino to *.cpp`` convertor (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for `platformio init `__ From c504001f04ec5545855dcd6200766c4f8be648d4 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 23 Dec 2016 21:57:11 +0200 Subject: [PATCH 024/127] PlatformIO Library Registry statistics with new `pio lib stats` --- HISTORY.rst | 9 +++- docs | 2 +- platformio/__init__.py | 2 +- platformio/app.py | 4 +- platformio/commands/lib.py | 84 ++++++++++++++++++++++++++++++++- platformio/commands/platform.py | 5 +- platformio/vcsclient.py | 5 +- 7 files changed, 98 insertions(+), 13 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 25a9d506..859153b4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,9 +4,16 @@ Release Notes PlatformIO 3.0 -------------- -3.2.2 (2016-12-??) +3.3.0 (2016-12-??) ~~~~~~~~~~~~~~~~~~ +* PlatformIO Library Registry statistics with new + `pio lib stats `__ command + + - Recently updated and added libraries + - Recent and popular keywords + - Featured libraries (today, week, month) + * Added support for templated methods in ``*.ino to *.cpp`` convertor (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for diff --git a/docs b/docs index c3780c69..fb1008d6 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit c3780c6913f16201da1c29643a8f4ae941d216df +Subproject commit fb1008d660f0d8a79306fe12319c6075f63b1690 diff --git a/platformio/__init__.py b/platformio/__init__.py index 7959277b..b5eb950a 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 2, "2a1") +VERSION = (3, 3, "0a1") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/app.py b/platformio/app.py index 8df17bb4..dae2141c 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -325,7 +325,7 @@ def get_cid(): except: # pylint: disable=bare-except pass cid = str( - uuid.UUID(bytes=hashlib.md5( - str(_uid if _uid else uuid.getnode())).digest())) + uuid.UUID(bytes=hashlib.md5(str(_uid if _uid else uuid.getnode())) + .digest())) set_state_item("cid", cid) return cid diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 25cc749e..81f6c670 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -13,8 +13,10 @@ # limitations under the License. import json +from datetime import datetime from os.path import join from time import sleep +from urllib import quote import click @@ -44,7 +46,7 @@ from platformio.util import get_api_result @click.pass_context def cli(ctx, **options): # skip commands that don't need storage folder - if ctx.invoked_subcommand in ("search", "register") or \ + if ctx.invoked_subcommand in ("search", "register", "stats") or \ (len(ctx.args) == 2 and ctx.args[1] in ("-h", "--help")): return storage_dir = options['storage_dir'] @@ -116,7 +118,7 @@ def lib_update(lm, libraries, only_check): ####### -LIBLIST_TPL = ("[{id:^14}] {name:<25} {compatibility:<30} " +LIBLIST_TPL = ("[{id:^15}] {name:<25} {compatibility:<30} " "\"{authornames}\": {description}") @@ -317,3 +319,81 @@ def lib_register(config_url): result['message'], fg="green" if "successed" in result and result['successed'] else "red") + + +@cli.command("stats", short_help="Library Registry Statistics") +@click.option("--json-output", is_flag=True) +def lib_stats(json_output): + result = get_api_result("/lib/stats", cache_valid="1h") + + if json_output: + return click.echo(json.dumps(result)) + + printitem_tpl = "{name:<33} {url}" + printitemdate_tpl = "{name:<33} {date:23} {url}" + + def _print_title(title): + click.secho(title.upper(), bold=True) + click.echo("*" * len(title)) + + def _print_header(with_date=False): + click.echo((printitemdate_tpl if with_date else printitem_tpl).format( + name=click.style( + "Name", fg="cyan"), + date="Date", + url=click.style( + "Url", fg="blue"))) + + terminal_width, _ = click.get_terminal_size() + click.echo("-" * terminal_width) + + def _print_lib_item(item): + click.echo((printitemdate_tpl + if "date" in item else printitem_tpl).format( + name=click.style( + item['name'], fg="cyan"), + date=str( + datetime.strptime(item['date'].replace("Z", "UTC"), + "%Y-%m-%dT%H:%M:%S%Z") + if "date" in item else ""), + url=click.style( + "http://platformio.org/lib/show/%s/%s" % (item[ + 'id'], quote(item['name'])), + fg="blue"))) + + def _print_tag_item(name): + click.echo( + printitem_tpl.format( + name=click.style( + name, fg="cyan"), + url=click.style( + "http://platformio.org/lib/search?query=" + quote( + "keyword:%s" % name), + fg="blue"))) + + for key in ("updated", "added"): + _print_title("Recently " + key) + _print_header(with_date=True) + for item in result.get(key, []): + _print_lib_item(item) + click.echo() + + _print_title("Recent keywords") + _print_header(with_date=False) + for item in result.get("lastkeywords"): + _print_tag_item(item) + click.echo() + + _print_title("Popular keywords") + _print_header(with_date=False) + for item in result.get("topkeywords"): + _print_tag_item(item) + click.echo() + + for key, title in (("dlday", "Today"), ("dlweek", "Week"), + ("dlmonth", "Month")): + _print_title("Featured: " + title) + _print_header(with_date=False) + for item in result.get(key, []): + _print_lib_item(item) + click.echo() diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index fc919405..f4a34241 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -141,9 +141,8 @@ def platform_list(json_output): "url": p.vendor_url, # "packages": p.packages.keys(), # dump all packages "packages": p.get_installed_packages().keys(), - 'forDesktop': any([ - p.name.startswith(n) for n in ("native", "linux", "windows") - ]) + 'forDesktop': + any([p.name.startswith(n) for n in ("native", "linux", "windows")]) }) if json_output: diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index 2f271968..c7519e61 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -177,9 +177,8 @@ class SvnClient(VCSClientBase): return self.run_cmd(args) def get_current_revision(self): - output = self.get_cmd_output([ - "info", "--non-interactive", "--trust-server-cert", "-r", "HEAD" - ]) + output = self.get_cmd_output( + ["info", "--non-interactive", "--trust-server-cert", "-r", "HEAD"]) for line in output.split("\n"): line = line.strip() if line.startswith("Revision:"): From 6cad7c01a7d41bfc5f75e5c7af03f783c78036b4 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 24 Dec 2016 14:55:00 +0200 Subject: [PATCH 025/127] New docs: Extra Linker Flags without ``-Wl,`` prefix --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index fb1008d6..f4feb770 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit fb1008d660f0d8a79306fe12319c6075f63b1690 +Subproject commit f4feb7709843a5a05912128bd872ab5ec8df0992 From b6de719f2bcf2ed44d39bd0606bf44b2ef9b6030 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 24 Dec 2016 16:59:31 +0200 Subject: [PATCH 026/127] Add support for Pumbaa Framework --- HISTORY.rst | 2 +- README.rst | 1 + docs | 2 +- examples | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 859153b4..c5bc17b6 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -31,7 +31,7 @@ PlatformIO 3.0 * Development platform `Espressif 32 `__ - + Added support for Simba Framework + + Added support for Simba & Pumbaa Frameworks + Added new board Node32s + Updated ESP32 Core for Arduino diff --git a/README.rst b/README.rst index be79d927..44a24151 100644 --- a/README.rst +++ b/README.rst @@ -180,6 +180,7 @@ Frameworks: * `ESP-IDF `_ * `libOpenCM3 `_ * `mbed `_ +* `Pumbaa `_ * `Simba `_ * `SPL `_ * `WiringPi `_ diff --git a/docs b/docs index f4feb770..30877574 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit f4feb7709843a5a05912128bd872ab5ec8df0992 +Subproject commit 308775747a663039b5210d94f05431b32f7114ae diff --git a/examples b/examples index fa891378..d32be42b 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit fa891378955708aec4d6a0c24bfa5ed9bb0a0dc4 +Subproject commit d32be42b60e88f209d008e5d1578be7b0c823ce9 From b6e09c5da4117f64f1f5ed3c3aa5c642cb0e9462 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 26 Dec 2016 14:44:19 +0200 Subject: [PATCH 027/127] Fix direct access to non-existing ContentCache data --- platformio/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/app.py b/platformio/app.py index dae2141c..dfefb858 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -207,7 +207,7 @@ class ContentCache(object): return None with open(cache_path, "rb") as fp: data = fp.read() - if data[0] in ("{", "["): + if data and data[0] in ("{", "["): return json.loads(data) return data From e7cc94c27e445c0bfed7cba868f9976b77a946df Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 28 Dec 2016 15:55:08 +0200 Subject: [PATCH 028/127] Show detailed info about a library using `pio lib show` command // Resolve #430 --- .isort.cfg | 2 +- HISTORY.rst | 3 ++ docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/lib.py | 94 ++++++++++++++++++++++++-------------- platformio/managers/lib.py | 84 +++++++++++++++++----------------- setup.py | 9 ++-- 7 files changed, 113 insertions(+), 83 deletions(-) diff --git a/.isort.cfg b/.isort.cfg index 9ac98225..d63487e9 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,3 +1,3 @@ [settings] line_length=79 -known_third_party=bottle,click,lockfile,pytest,requests,semantic_version,serial,SCons +known_third_party=arrow,bottle,click,lockfile,pytest,requests,SCons,semantic_version,serial diff --git a/HISTORY.rst b/HISTORY.rst index c5bc17b6..f3d7a843 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,9 @@ PlatformIO 3.0 - Recent and popular keywords - Featured libraries (today, week, month) +* Show detailed info about a library using `pio lib show `__ + command + (`issue #430 `_) * Added support for templated methods in ``*.ino to *.cpp`` convertor (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for diff --git a/docs b/docs index 30877574..b7090644 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 308775747a663039b5210d94f05431b32f7114ae +Subproject commit b709064430b0697353a54b55920ef49aa1062d6d diff --git a/platformio/__init__.py b/platformio/__init__.py index b5eb950a..4d00bb3c 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a1") +VERSION = (3, 3, "0a2") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 81f6c670..1ca3a939 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -12,12 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=too-many-branches, too-many-locals + import json -from datetime import datetime from os.path import join from time import sleep from urllib import quote +import arrow import click from platformio import exception, util @@ -46,7 +48,7 @@ from platformio.util import get_api_result @click.pass_context def cli(ctx, **options): # skip commands that don't need storage folder - if ctx.invoked_subcommand in ("search", "register", "stats") or \ + if ctx.invoked_subcommand in ("search", "show", "register", "stats") or \ (len(ctx.args) == 2 and ctx.args[1] in ("-h", "--help")): return storage_dir = options['storage_dir'] @@ -158,7 +160,7 @@ def echo_liblist_item(item): description=description)) -@cli.command("search", short_help="Search for library") +@cli.command("search", short_help="Search for a library") @click.argument("query", required=False, nargs=-1) @click.option("--json-output", is_flag=True) @click.option("--page", type=click.INT, default=1) @@ -247,8 +249,7 @@ def lib_list(lm, json_output): items = lm.get_installed() if json_output: - click.echo(json.dumps(items)) - return + return click.echo(json.dumps(items)) if not items: return @@ -260,28 +261,40 @@ def lib_list(lm, json_output): echo_liblist_item(item) -@cli.command("show", short_help="Show details about installed library") -@click.pass_obj +@cli.command("show", short_help="Show detailed info about a library") @click.argument("library", metavar="[LIBRARY]") -def lib_show(lm, library): # pylint: disable=too-many-branches - name, requirements, url = lm.parse_pkg_name(library) - package_dir = lm.get_package_dir(name, requirements, url) - if not package_dir: - click.secho( - "%s @ %s is not installed" % (name, requirements or "*"), - fg="yellow") - return +@click.option("--json-output", is_flag=True) +def lib_show(library, json_output): + lm = LibraryManager() + name, requirements, _ = lm.parse_pkg_name(library) + lib_id = lm.get_pkg_id_by_name( + name, requirements, silent=json_output, interactive=not json_output) + lib = get_api_result("/lib/info/%d" % lib_id, cache_valid="1d") + if json_output: + return click.echo(json.dumps(lib)) - manifest = lm.load_manifest(package_dir) - - click.secho(manifest['name'], fg="cyan") - click.echo("=" * len(manifest['name'])) - if "description" in manifest: - click.echo(manifest['description']) + click.secho(lib['name'], fg="cyan") + click.echo("=" * len(lib['name'])) + click.echo(lib['description']) click.echo() + click.echo("Version: %s, released %s" % + (lib['version']['name'], + arrow.get(lib['version']['released']).humanize())) + click.echo("Registry ID: %d" % lib['id']) + click.echo("Manifest: %s" % lib['confurl']) + for key in ("homepage", "repository", "license"): + if key not in lib or not lib[key]: + continue + if isinstance(lib[key], list): + click.echo("%s: %s" % (key.title(), ", ".join(lib[key]))) + else: + click.echo("%s: %s" % (key.title(), lib[key])) + + blocks = [] + _authors = [] - for author in manifest.get("authors", []): + for author in lib.get("authors", []): _data = [] for key in ("name", "email", "url", "maintainer"): if not author[key]: @@ -294,19 +307,33 @@ def lib_show(lm, library): # pylint: disable=too-many-branches _data.append(author[key]) _authors.append(" ".join(_data)) if _authors: - click.echo("Authors: %s" % ", ".join(_authors)) + blocks.append(("Authors", _authors)) - for key in ("keywords", "frameworks", "platforms", "license", "url", - "version"): - if key not in manifest: - continue - if isinstance(manifest[key], list): - click.echo("%s: %s" % (key.title(), ", ".join(manifest[key]))) - else: - click.echo("%s: %s" % (key.title(), manifest[key])) + blocks.append(("Keywords", lib['keywords'])) + if lib['frameworks']: + blocks.append(("Compatible Frameworks", lib['frameworks'])) + if lib['platforms']: + blocks.append(("Compatible Platforms", lib['platforms'])) + blocks.append(("Headers", lib['headers'])) + blocks.append(("Examples", lib['examples'])) + blocks.append(("Versions", [ + "%s, released %s" % (v['name'], arrow.get(v['released']).humanize()) + for v in lib['versions'] + ])) + blocks.append(("Unique Downloads", [ + "Today: %s" % lib['dlstats']['day'], "Week: %s" % + lib['dlstats']['week'], "Month: %s" % lib['dlstats']['month'] + ])) + + for (title, rows) in blocks: + click.echo() + click.secho(title, bold=True) + click.echo("-" * len(title)) + for row in rows: + click.echo(row) -@cli.command("register", short_help="Register new library") +@cli.command("register", short_help="Register a new library") @click.argument("config_url") def lib_register(config_url): if (not config_url.startswith("http://") and @@ -353,8 +380,7 @@ def lib_stats(json_output): name=click.style( item['name'], fg="cyan"), date=str( - datetime.strptime(item['date'].replace("Z", "UTC"), - "%Y-%m-%dT%H:%M:%S%Z") + arrow.get(item['date']).humanize() if "date" in item else ""), url=click.style( "http://platformio.org/lib/show/%s/%s" % (item[ diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 94241a8d..8008c753 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -19,6 +19,7 @@ import os from hashlib import md5 from os.path import dirname, join +import arrow import click import semantic_version @@ -129,13 +130,8 @@ class LibraryManager(BasePkgManager): def max_satisfying_repo_version(versions, requirements=None): def _cmp_dates(datestr1, datestr2): - from datetime import datetime - assert "T" in datestr1 and "T" in datestr2 - dateformat = "%Y-%m-%d %H:%M:%S" - date1 = datetime.strptime(datestr1[:-1].replace("T", " "), - dateformat) - date2 = datetime.strptime(datestr2[:-1].replace("T", " "), - dateformat) + date1 = arrow.get(datestr1) + date2 = arrow.get(datestr2) if date1 == date2: return 0 return -1 if date1 < date2 else 1 @@ -150,7 +146,7 @@ class LibraryManager(BasePkgManager): for v in versions: specver = None try: - specver = semantic_version.Version(v['version'], partial=True) + specver = semantic_version.Version(v['name'], partial=True) except ValueError: pass @@ -158,30 +154,30 @@ class LibraryManager(BasePkgManager): if not specver or specver not in reqspec: continue if not item or semantic_version.Version( - item['version'], partial=True) < specver: + item['name'], partial=True) < specver: item = v elif requirements: - if requirements == v['version']: + if requirements == v['name']: return v else: - if not item or _cmp_dates(item['date'], v['date']) == -1: + if not item or _cmp_dates(item['released'], + v['released']) == -1: item = v return item def get_latest_repo_version(self, name, requirements): item = self.max_satisfying_repo_version( util.get_api_result( - "/lib/versions/%d" % self._get_pkg_id_by_name(name, - requirements), - cache_valid="1h"), + "/lib/info/%d" % self.get_pkg_id_by_name(name, requirements), + cache_valid="1d")['versions'], requirements) - return item['version'] if item else None + return item['name'] if item else None - def _get_pkg_id_by_name(self, - name, - requirements, - silent=False, - interactive=False): + def get_pkg_id_by_name(self, + name, + requirements, + silent=False, + interactive=False): if name.startswith("id="): return int(name[3:]) # try to find ID from installed packages @@ -222,7 +218,7 @@ class LibraryManager(BasePkgManager): try: if not _url: - _name = "id=%d" % self._get_pkg_id_by_name( + _name = "id=%d" % self.get_pkg_id_by_name( _name, _requirements, silent=silent, @@ -299,30 +295,34 @@ class LibraryManager(BasePkgManager): if result['total'] == 1: lib_info = result['items'][0] elif result['total'] > 1: - click.secho( - "Conflict: More than one library has been found " - "by request %s:" % json.dumps(filters), - fg="red", - err=True) - commands.lib.echo_liblist_header() - for item in result['items']: - commands.lib.echo_liblist_item(item) - - if not interactive: - click.secho( - "Automatically chose the first available library " - "(use `--interactive` option to make a choice)", - fg="yellow", - err=True) + if silent and not interactive: lib_info = result['items'][0] else: - deplib_id = click.prompt( - "Please choose library ID", - type=click.Choice([str(i['id']) for i in result['items']])) + click.secho( + "Conflict: More than one library has been found " + "by request %s:" % json.dumps(filters), + fg="red", + err=True) + commands.lib.echo_liblist_header() for item in result['items']: - if item['id'] == int(deplib_id): - lib_info = item - break + commands.lib.echo_liblist_item(item) + + if not interactive: + click.secho( + "Automatically chose the first available library " + "(use `--interactive` option to make a choice)", + fg="yellow", + err=True) + lib_info = result['items'][0] + else: + deplib_id = click.prompt( + "Please choose library ID", + type=click.Choice( + [str(i['id']) for i in result['items']])) + for item in result['items']: + if item['id'] == int(deplib_id): + lib_info = item + break if not lib_info: if filters.keys() == ["name"]: diff --git a/setup.py b/setup.py index 4b71930f..ae4ad614 100644 --- a/setup.py +++ b/setup.py @@ -18,13 +18,14 @@ from platformio import (__author__, __description__, __email__, __license__, __title__, __url__, __version__) install_requires = [ + "arrow<1", "bottle<0.13", "click>=5,<6", - "lockfile>=0.9.1,<0.13", - "requests>=2.4.0,<3", - "semantic_version>=2.5.0", "colorama", - "pyserial>=3,<4" + "lockfile>=0.9.1,<0.13", + "pyserial>=3,<4", + "requests>=2.4.0,<3", + "semantic_version>=2.5.0" ] setup( From 82662d0a094694d7d4d5e3c52b83446cf8c363f1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 28 Dec 2016 16:00:19 +0200 Subject: [PATCH 029/127] Move library manager user guide to upper level --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index b7090644..47c714ca 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b709064430b0697353a54b55920ef49aa1062d6d +Subproject commit 47c714cad73562ae4e46766e24db092a4cb00c90 From 1df89525e61bb3ac2fdbe89c8d6e730dad10e497 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 28 Dec 2016 16:51:28 +0200 Subject: [PATCH 030/127] Fix test for `pio lib show` command --- HISTORY.rst | 2 +- tests/commands/test_lib.py | 29 +++++++++++------------------ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index f3d7a843..6a759f9b 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -17,7 +17,7 @@ PlatformIO 3.0 * Show detailed info about a library using `pio lib show `__ command (`issue #430 `_) -* Added support for templated methods in ``*.ino to *.cpp`` convertor +* Added support for templated methods in ``*.ino to *.cpp`` converter (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for `platformio init `__ diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 75598971..94d932f0 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -100,24 +100,6 @@ def test_global_lib_list(clirunner, validate_cliresult, isolated_pio_home): assert set(items1) == set(items2) -def test_global_lib_show(clirunner, validate_cliresult, isolated_pio_home): - result = clirunner.invoke(cmd_lib, ["-g", "show", "64@5.6.7"]) - validate_cliresult(result) - assert all([ - s in result.output for s in ("Json", "arduino", "atmelavr", "5.6.7") - ]) - - result = clirunner.invoke(cmd_lib, ["-g", "show", "ArduinoJson@>5.6.7"]) - validate_cliresult(result) - assert all( - [s in result.output for s in ("ArduinoJson", "arduino", "atmelavr")]) - assert "5.6.7" not in result.output - - result = clirunner.invoke(cmd_lib, ["-g", "show", "1"]) - validate_cliresult(result) - assert "OneWire" in result.output - - def test_global_lib_update(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["-g", "update"]) validate_cliresult(result) @@ -139,6 +121,17 @@ def test_global_lib_uninstall(clirunner, validate_cliresult, assert set(items1) == set(items2) +def test_lib_show(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cmd_lib, ["show", "64"]) + validate_cliresult(result) + assert all([ + s in result.output for s in ("ArduinoJson", "arduino", "atmelavr") + ]) + result = clirunner.invoke(cmd_lib, ["show", "OneWire"]) + validate_cliresult(result) + assert "OneWire" in result.output + + def test_project_lib_complex(clirunner, validate_cliresult, tmpdir): with tmpdir.as_cwd(): # init From 72e94398bf9fba5045a5c5686754b2c200f01e79 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 29 Dec 2016 01:31:44 +0200 Subject: [PATCH 031/127] Improve output of `pio lib list` and `pio lib search` commands --- docs | 2 +- platformio/commands/lib.py | 85 +++++++++++++++----------------------- platformio/managers/lib.py | 5 +-- tests/commands/test_lib.py | 2 +- 4 files changed, 37 insertions(+), 57 deletions(-) diff --git a/docs b/docs index 47c714ca..19fe2670 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 47c714cad73562ae4e46766e24db092a4cb00c90 +Subproject commit 19fe267062e8e2f33d84d8aedcf7a30f4056c2c4 diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 1ca3a939..d0a22fc8 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -118,46 +118,33 @@ def lib_update(lm, libraries, only_check): lm.update(library, only_check=only_check) -####### +def print_lib_item(item): + click.secho(item['name'], fg="cyan") + click.echo("=" * len(item['name'])) + if "id" in item: + click.secho("#ID: %d" % item['id'], bold=True) + click.echo(item.get("description", item.get("url", "")).encode("utf-8")) + click.echo() -LIBLIST_TPL = ("[{id:^15}] {name:<25} {compatibility:<30} " - "\"{authornames}\": {description}") + for key in ("homepage", "license", "keywords"): + if key not in item or not item[key]: + continue + if isinstance(item[key], list): + click.echo("%s: %s" % (key.title(), ", ".join(item[key]))) + else: + click.echo("%s: %s" % (key.title(), item[key])) + for key in ("frameworks", "platforms"): + if key not in item: + continue + click.echo("Compatible %s: %s" % (key, ", ".join( + [i['title'] if isinstance(i, dict) else i for i in item[key]]))) -def echo_liblist_header(): - click.echo( - LIBLIST_TPL.format( - id=click.style( - "ID", fg="green"), - name=click.style( - "Name", fg="cyan"), - compatibility=click.style( - "Compatibility", fg="yellow"), - authornames="Authors", - description="Description")) - - terminal_width, _ = click.get_terminal_size() - click.echo("-" * terminal_width) - - -def echo_liblist_item(item): - description = item.get("description", item.get("url", "")).encode("utf-8") - if "version" in item: - description += " | @" + click.style(item['version'], fg="yellow") - - click.echo( - LIBLIST_TPL.format( - id=click.style( - str(item.get("id", "-")), fg="green"), - name=click.style( - item['name'], fg="cyan"), - compatibility=click.style( - ", ".join( - item.get("frameworks", ["-"]) + item.get("platforms", [])), - fg="yellow"), - authornames=", ".join(item.get("authornames", ["Unknown"])).encode( - "utf-8"), - description=description)) + if "authors" in item or "authornames" in item: + click.echo("Authors: %s" % ", ".join( + item.get("authornames", + [a.get("name", "") for a in item.get("authors", [])]))) + click.echo() @cli.command("search", short_help="Search for a library") @@ -185,7 +172,7 @@ def lib_search(query, json_output, page, noninteractive, **filters): query.append('%s:"%s"' % (key, value)) result = get_api_result( - "/lib/search", + "/v2/lib/search", dict( query=" ".join(query), page=page), cache_valid="3d") @@ -214,12 +201,9 @@ def lib_search(query, json_output, page, noninteractive, **filters): "Found %d libraries:\n" % result['total'], fg="green" if result['total'] else "yellow") - if result['total']: - echo_liblist_header() - while True: for item in result['items']: - echo_liblist_item(item) + print_lib_item(item) if (int(result['page']) * int(result['perpage']) >= int(result['total'])): @@ -236,7 +220,7 @@ def lib_search(query, json_output, page, noninteractive, **filters): elif not click.confirm("Show next libraries?"): break result = get_api_result( - "/lib/search", + "/v2/lib/search", dict( query=" ".join(query), page=int(result['page']) + 1), cache_valid="3d") @@ -254,11 +238,8 @@ def lib_list(lm, json_output): if not items: return - echo_liblist_header() for item in sorted(items, key=lambda i: i['name']): - if "authors" in item: - item['authornames'] = [i['name'] for i in item['authors']] - echo_liblist_item(item) + print_lib_item(item) @cli.command("show", short_help="Show detailed info about a library") @@ -275,13 +256,13 @@ def lib_show(library, json_output): click.secho(lib['name'], fg="cyan") click.echo("=" * len(lib['name'])) + click.secho("#ID: %d" % lib['id'], bold=True) click.echo(lib['description']) click.echo() click.echo("Version: %s, released %s" % (lib['version']['name'], arrow.get(lib['version']['released']).humanize())) - click.echo("Registry ID: %d" % lib['id']) click.echo("Manifest: %s" % lib['confurl']) for key in ("homepage", "repository", "license"): if key not in lib or not lib[key]: @@ -310,10 +291,10 @@ def lib_show(library, json_output): blocks.append(("Authors", _authors)) blocks.append(("Keywords", lib['keywords'])) - if lib['frameworks']: - blocks.append(("Compatible Frameworks", lib['frameworks'])) - if lib['platforms']: - blocks.append(("Compatible Platforms", lib['platforms'])) + for key in ("frameworks", "platforms"): + if key not in lib or not lib[key]: + continue + blocks.append(("Compatible %s" % key, [i['title'] for i in lib[key]])) blocks.append(("Headers", lib['headers'])) blocks.append(("Examples", lib['examples'])) blocks.append(("Versions", [ diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 8008c753..380afd66 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -291,7 +291,7 @@ class LibraryManager(BasePkgManager): lib_info = None result = util.get_api_result( - "/lib/search", dict(query=" ".join(query)), cache_valid="3d") + "/v2/lib/search", dict(query=" ".join(query)), cache_valid="3d") if result['total'] == 1: lib_info = result['items'][0] elif result['total'] > 1: @@ -303,9 +303,8 @@ class LibraryManager(BasePkgManager): "by request %s:" % json.dumps(filters), fg="red", err=True) - commands.lib.echo_liblist_header() for item in result['items']: - commands.lib.echo_liblist_item(item) + commands.lib.print_lib_item(item) if not interactive: click.secho( diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 94d932f0..47217262 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -125,7 +125,7 @@ def test_lib_show(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["show", "64"]) validate_cliresult(result) assert all([ - s in result.output for s in ("ArduinoJson", "arduino", "atmelavr") + s in result.output for s in ("ArduinoJson", "Arduino", "Atmel AVR") ]) result = clirunner.invoke(cmd_lib, ["show", "OneWire"]) validate_cliresult(result) From ff5fac251ea2a2eef12fb624d5119440edc7769a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 3 Jan 2017 20:15:52 +0200 Subject: [PATCH 032/127] Custom action before building SPIFFS image. For example, compress HTML, etc. --- HISTORY.rst | 2 +- docs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 6a759f9b..1e95091a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,7 +4,7 @@ Release Notes PlatformIO 3.0 -------------- -3.3.0 (2016-12-??) +3.3.0 (2017-??-??) ~~~~~~~~~~~~~~~~~~ * PlatformIO Library Registry statistics with new diff --git a/docs b/docs index 19fe2670..19dc47a3 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 19fe267062e8e2f33d84d8aedcf7a30f4056c2c4 +Subproject commit 19dc47a33e4302c7ba960f7bbe85d143d9da4e08 From 87f3cbdda76fa812d7b209d37c1a272989b7a4fd Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 7 Jan 2017 17:57:40 +0200 Subject: [PATCH 033/127] =?UTF-8?q?Add=20=E2=80=9CFuses=E2=80=9D=20section?= =?UTF-8?q?=20to=20Atmel=20AVR=20development=20platform=20//=20Resolve=20#?= =?UTF-8?q?865?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HISTORY.rst | 5 +++++ docs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 1e95091a..9f50569f 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -27,6 +27,11 @@ PlatformIO 3.0 ------- +* Development platform `Atmel AVR `__ + + + Set fuse bits with new target named ``fuses`` + (`issue #865 `_) + * Development platform `Atmel SAM `__ + Added support for Atmel ATSAMW25-XPRO board diff --git a/docs b/docs index 19dc47a3..4fd745b7 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 19dc47a33e4302c7ba960f7bbe85d143d9da4e08 +Subproject commit 4fd745b7bd80c35a5bf729ae39d9e1ce9413aa7d From fb2f1d35538195094e186fcb208a18a063fa46a3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 12 Jan 2017 20:07:28 +0200 Subject: [PATCH 034/127] Use C++11 by default for CLion IDE based projects // Resolve #873 --- HISTORY.rst | 2 ++ examples | 2 +- platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 9f50569f..acb1f27c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -24,6 +24,8 @@ PlatformIO 3.0 and `platformio run `__ commands (`issue #850 `_) +* Use C++11 by default for CLion IDE based projects + (`pull #873 `_) ------- diff --git a/examples b/examples index d32be42b..463f8557 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit d32be42b60e88f209d008e5d1578be7b0c823ce9 +Subproject commit 463f855761f0af2657e597f6a3cf1b59daecc3fd diff --git a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl b/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl index 658536dd..ca27ad43 100644 --- a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl +++ b/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl @@ -5,6 +5,7 @@ SET(CMAKE_C_COMPILER "{{cc_path.replace("\\", "/")}}") SET(CMAKE_CXX_COMPILER "{{cxx_path.replace("\\", "/")}}") SET(CMAKE_CXX_FLAGS_DISTRIBUTION "{{cxx_flags}}") SET(CMAKE_C_FLAGS_DISTRIBUTION "{{cc_flags}}") +set(CMAKE_CXX_STANDARD 11) % for define in defines: add_definitions(-D{{!define}}) From a9400f5a9c68702f6517715478c430d2fc7d11f2 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 13 Jan 2017 14:20:18 +0200 Subject: [PATCH 035/127] New article by Tiest van Gool --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 4fd745b7..3c0e048d 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 4fd745b7bd80c35a5bf729ae39d9e1ce9413aa7d +Subproject commit 3c0e048d0afe8e3620f76d6c9b450fd1469434bb From b8de4b26b0464e03ba44660cb4baf8c91d8e28a4 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 15 Jan 2017 00:12:41 +0200 Subject: [PATCH 036/127] List built-in libraries based on development platforms with `pio lib builtin` command --- HISTORY.rst | 2 + docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/lib.py | 40 ++++++++++- platformio/exception.py | 2 +- platformio/managers/lib.py | 124 ++++++++++++++++++++------------ platformio/managers/package.py | 45 ++++++++---- platformio/managers/platform.py | 17 ++++- platformio/telemetry.py | 4 +- 9 files changed, 167 insertions(+), 71 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index acb1f27c..99dd7b22 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,8 @@ PlatformIO 3.0 - Recent and popular keywords - Featured libraries (today, week, month) +* List built-in libraries based on development platforms with + `pio lib builtin `__ command * Show detailed info about a library using `pio lib show `__ command (`issue #430 `_) diff --git a/docs b/docs index 3c0e048d..3a9574a2 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 3c0e048d0afe8e3620f76d6c9b450fd1469434bb +Subproject commit 3a9574a2585e41b011c936f9f0093844bfc55696 diff --git a/platformio/__init__.py b/platformio/__init__.py index 4d00bb3c..2d41a8e8 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a2") +VERSION = (3, 3, "0a3") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index d0a22fc8..4134bd6a 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -24,6 +24,7 @@ import click from platformio import exception, util from platformio.managers.lib import LibraryManager +from platformio.managers.platform import PlatformFactory, PlatformManager from platformio.util import get_api_result @@ -47,8 +48,9 @@ from platformio.util import get_api_result help="Manage custom library storage") @click.pass_context def cli(ctx, **options): + non_storage_cmds = ("search", "show", "register", "stats", "builtin") # skip commands that don't need storage folder - if ctx.invoked_subcommand in ("search", "show", "register", "stats") or \ + if ctx.invoked_subcommand in non_storage_cmds or \ (len(ctx.args) == 2 and ctx.args[1] in ("-h", "--help")): return storage_dir = options['storage_dir'] @@ -123,10 +125,10 @@ def print_lib_item(item): click.echo("=" * len(item['name'])) if "id" in item: click.secho("#ID: %d" % item['id'], bold=True) - click.echo(item.get("description", item.get("url", "")).encode("utf-8")) + click.echo(item.get("description", item.get("url", ""))) click.echo() - for key in ("homepage", "license", "keywords"): + for key in ("version", "homepage", "license", "keywords"): if key not in item or not item[key]: continue if isinstance(item[key], list): @@ -242,6 +244,38 @@ def lib_list(lm, json_output): print_lib_item(item) +@cli.command("builtin", short_help="List built-in libraries") +@click.option("--storage", multiple=True) +@click.option("--json-output", is_flag=True) +@click.pass_obj +def lib_builtin(lm, storage, json_output): + items = [] + storage_names = storage or [] + del storage + pm = PlatformManager() + for manifest in pm.get_installed(): + p = PlatformFactory.newPlatform( + pm.get_manifest_path(manifest['__pkg_dir'])) + for storage in p.get_lib_storages(): + if storage_names and storage['name'] not in storage_names: + continue + lm = LibraryManager(storage['path']) + items.append(dict(name=storage['name'], items=lm.get_installed())) + + if json_output: + return click.echo(json.dumps(items)) + + for storage in items: + if not storage['items']: + continue + click.secho(storage['name'], fg="green") + click.echo("*" * len(storage['name'])) + click.echo() + + for item in sorted(storage['items'], key=lambda i: i['name']): + print_lib_item(item) + + @cli.command("show", short_help="Show detailed info about a library") @click.argument("library", metavar="[LIBRARY]") @click.option("--json-output", is_flag=True) diff --git a/platformio/exception.py b/platformio/exception.py index a0c1c10d..7482f233 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -78,7 +78,7 @@ class UnknownPackage(PlatformioException): class MissingPackageManifest(PlatformioException): - MESSAGE = "Could not find '{0}' manifest file in the package" + MESSAGE = "Could not find one of '{0}' manifest files in the package" class UndefinedPackageVersion(PlatformioException): diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 380afd66..b41b0997 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -16,8 +16,9 @@ import json import os +import re from hashlib import md5 -from os.path import dirname, join +from os.path import join import arrow import click @@ -35,70 +36,99 @@ class LibraryManager(BasePkgManager): BasePkgManager.__init__(self, package_dir) @property - def manifest_name(self): - return ".library.json" + def manifest_names(self): + return [ + ".library.json", "library.properties", "library.json", + "module.json" + ] def check_pkg_structure(self, pkg_dir): try: return BasePkgManager.check_pkg_structure(self, pkg_dir) except exception.MissingPackageManifest: # we will generate manifest automatically + # if library doesn't contain any pass manifest = { "name": "Library_" + md5(pkg_dir).hexdigest()[:5], "version": "0.0.0" } - manifest_path = self._find_any_manifest(pkg_dir) - if manifest_path: - _manifest = self._parse_manifest(manifest_path) - pkg_dir = dirname(manifest_path) - for key in ("name", "version"): - if key not in _manifest: - _manifest[key] = manifest[key] - manifest = _manifest - else: - for root, dirs, files in os.walk(pkg_dir): - if len(dirs) == 1 and not files: - manifest['name'] = dirs[0] - continue - if dirs or files: - pkg_dir = root - break + for root, dirs, files in os.walk(pkg_dir): + if len(dirs) == 1 and not files: + manifest['name'] = dirs[0] + continue + if dirs or files: + pkg_dir = root + break - with open(join(pkg_dir, self.manifest_name), "w") as fp: + with open(join(pkg_dir, self.manifest_names[0]), "w") as fp: json.dump(manifest, fp) return pkg_dir - @staticmethod - def _find_any_manifest(pkg_dir): - manifests = ("library.json", "library.properties", "module.json") - for root, _, files in os.walk(pkg_dir): - for manifest in manifests: - if manifest in files: - return join(root, manifest) - return None + def load_manifest(self, path): + manifest = BasePkgManager.load_manifest(self, path) + if not manifest: + return manifest - @staticmethod - def _parse_manifest(path): - manifest = {} - if path.endswith(".json"): - return util.load_json(path) - elif path.endswith("library.properties"): - with open(path) as fp: - for line in fp.readlines(): - if "=" not in line: - continue - key, value = line.split("=", 1) - manifest[key.strip()] = value.strip() + # if Arudino library.properties + if "sentence" in manifest: manifest['frameworks'] = ["arduino"] - if "author" in manifest: - manifest['authors'] = [{"name": manifest['author']}] - del manifest['author'] - if "sentence" in manifest: - manifest['description'] = manifest['sentence'] - del manifest['sentence'] + + if "author" in manifest: + manifest['authors'] = [{"name": manifest['author']}] + del manifest['author'] + + if "sentence" in manifest: + manifest['description'] = manifest['sentence'] + del manifest['sentence'] + + if "keywords" not in manifest: + keywords = [] + for keyword in re.split(r"[\s/]+", + manifest.get("category", "Uncategorized")): + keyword = keyword.strip() + if not keyword: + continue + keywords.append(keyword.lower()) + manifest['keywords'] = keywords + if "category" in manifest: + del manifest['category'] + + # don't replace VCS URL + if "url" in manifest and "description" in manifest: + manifest['homepage'] = manifest['url'] + del manifest['url'] + + if "architectures" in manifest: + platforms = [] + platforms_map = { + "avr": "atmelavr", + "sam": "atmelsam", + "samd": "atmelsam", + "esp8266": "espressif8266", + "arc32": "intel_arc32" + } + for arch in manifest['architectures'].split(","): + arch = arch.strip() + if arch == "*": + platforms = "*" + break + if arch in platforms_map: + platforms.append(platforms_map[arch]) + manifest['platforms'] = platforms + del manifest['architectures'] + + # convert listed items via comma to array + for key in ("keywords", "frameworks", "platforms"): + if key not in manifest or \ + not isinstance(manifest[key], basestring): + continue + manifest[key] = [ + i.strip() for i in manifest[key].split(",") if i.strip() + ] + return manifest @staticmethod @@ -301,7 +331,7 @@ class LibraryManager(BasePkgManager): click.secho( "Conflict: More than one library has been found " "by request %s:" % json.dumps(filters), - fg="red", + fg="yellow", err=True) for item in result['items']: commands.lib.print_lib_item(item) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index d8af4212..062e271e 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import codecs import json import os import shutil @@ -122,10 +123,14 @@ class PkgInstallerMixin(object): def get_manifest_path(self, pkg_dir): if not isdir(pkg_dir): return None - manifest_path = join(pkg_dir, self.manifest_name) - if isfile(manifest_path): + manifest_path = self.get_vcs_manifest_path(pkg_dir) + if manifest_path: return manifest_path - return self.get_vcs_manifest_path(pkg_dir) + for name in self.manifest_names: + manifest_path = join(pkg_dir, name) + if isfile(manifest_path): + return manifest_path + return None def manifest_exists(self, pkg_dir): return self.get_manifest_path(pkg_dir) is not None @@ -135,15 +140,27 @@ class PkgInstallerMixin(object): pkg_dir = path if isdir(path): path = self.get_manifest_path(path) + if not path: + return None else: pkg_dir = dirname(pkg_dir) - if path: - if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): - pkg_dir = dirname(dirname(path)) + + if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): + pkg_dir = dirname(dirname(path)) + + if path.endswith(".json"): manifest = util.load_json(path) - manifest['__pkg_dir'] = pkg_dir - return manifest - return None + else: + manifest = {} + with codecs.open(path, encoding="utf-8") as fp: + for line in fp.readlines(): + if "=" not in line: + continue + key, value = line.split("=", 1) + manifest[key.strip()] = value.strip() + manifest['__pkg_dir'] = pkg_dir + + return manifest def check_pkg_structure(self, pkg_dir): if self.manifest_exists(pkg_dir): @@ -153,7 +170,7 @@ class PkgInstallerMixin(object): if self.manifest_exists(root): return root - raise exception.MissingPackageManifest(self.manifest_name) + raise exception.MissingPackageManifest(", ".join(self.manifest_names)) def _install_from_piorepo(self, name, requirements): pkg_dir = None @@ -273,7 +290,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): assert isdir(self.package_dir) @property - def manifest_name(self): + def manifest_names(self): raise NotImplementedError() def download(self, url, dest_dir, sha1=None): @@ -381,7 +398,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): manifest = self.load_manifest(pkg_dir) if not manifest: continue - assert set(["name", "version"]) <= set(manifest.keys()) + assert "name" in manifest items.append(manifest) BasePkgManager._INSTALLED_CACHE[self.package_dir] = items return items @@ -605,5 +622,5 @@ class PackageManager(BasePkgManager): FILE_CACHE_VALID = None # disable package caching @property - def manifest_name(self): - return "package.json" + def manifest_names(self): + return ["package.json"] diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 1e274f38..53d1b618 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -41,8 +41,8 @@ class PlatformManager(BasePkgManager): repositories) @property - def manifest_name(self): - return "platform.json" + def manifest_names(self): + return ["platform.json"] def install(self, name, @@ -484,6 +484,19 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): "optional": False } + def get_lib_storages(self): + storages = [] + for _, opts in (self.frameworks or {}).items(): + if "package" not in opts: + continue + pkg_dir = self.get_package_dir(opts['package']) + if not pkg_dir or not isdir(join(pkg_dir, "libraries")): + continue + storages.append( + dict( + name=opts['package'], path=join(pkg_dir, "libraries"))) + return storages + class PlatformBoardConfig(object): diff --git a/platformio/telemetry.py b/platformio/telemetry.py index a0fb593b..f0ba2922 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -121,8 +121,8 @@ class MeasurementProtocol(TelemetryBase): "settings", "account"): cmd_path = args[:2] if args[0] == "lib" and len(args) > 1: - lib_subcmds = ("install", "list", "register", "search", "show", - "uninstall", "update") + lib_subcmds = ("builtin", "install", "list", "register", "search", + "show", "stats", "uninstall", "update") sub_cmd = _first_arg_from_list(args[1:], lib_subcmds) if sub_cmd: cmd_path.append(sub_cmd) From 369aff91131687a53337ba5506991a7e9a2c86ac Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 15 Jan 2017 00:19:25 +0200 Subject: [PATCH 037/127] Fix indent level for Options --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 3a9574a2..f07d51a8 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 3a9574a2585e41b011c936f9f0093844bfc55696 +Subproject commit f07d51a851f9652c8f92c00b0ffb9bea785fa6b2 From 6c111959b464159488f8afd054715289d3b3baeb Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 18 Jan 2017 15:19:46 +0200 Subject: [PATCH 038/127] Fix platform installation from VCS // Resolve #878 --- platformio/__init__.py | 2 +- platformio/managers/platform.py | 9 +++++++++ tests/commands/test_platform.py | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index 2d41a8e8..c14da88f 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a3") +VERSION = (3, 3, "0a4") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 53d1b618..5b61aba7 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -44,6 +44,15 @@ class PlatformManager(BasePkgManager): def manifest_names(self): return ["platform.json"] + def get_manifest_path(self, pkg_dir): + if not isdir(pkg_dir): + return None + for name in self.manifest_names: + manifest_path = join(pkg_dir, name) + if isfile(manifest_path): + return manifest_path + return None + def install(self, name, requirements=None, diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index 829e5cdb..57706370 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -60,6 +60,15 @@ def test_install_uknown_from_registry(clirunner, validate_cliresult): assert isinstance(result.exception, exception.UnknownPackage) +def test_install_from_vcs(clirunner, validate_cliresult): + result = clirunner.invoke(cli_platform.platform_install, [ + "https://github.com/platformio/" + "platform-espressif8266.git#feature/stage" + ]) + validate_cliresult(result) + assert "espressif8266_stage" in result.output + + def test_install_uknown_version(clirunner, validate_cliresult): result = clirunner.invoke(cli_platform.platform_install, ["atmelavr@99.99.99"]) From 101ceb538b6309d02c02ae9b03130d7f0e0d5396 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 18 Jan 2017 21:54:04 +0200 Subject: [PATCH 039/127] Update history --- HISTORY.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 99dd7b22..c125907d 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -39,6 +39,7 @@ PlatformIO 3.0 * Development platform `Atmel SAM `__ + Added support for Atmel ATSAMW25-XPRO board + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `Espressif 32 `__ @@ -49,6 +50,7 @@ PlatformIO 3.0 * Development platform `Freescale Kinetis `__ + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `Linux ARM `__ @@ -58,26 +60,32 @@ PlatformIO 3.0 * Development platform `Nordic nRF51 `__ + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `NXP LPC `__ + Added support for LPCXpresso4337 and y5 LPC11U35 mbug boards + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `Silicon Labs EFM32 `__ + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `ST STM32 `__ + Added support for new boards: Espotel LoRa Module, NAMote72, MTS Dragonfly, ST Nucleo F303ZE, u-blox EVK-ODIN-W2, MultiTech xDot + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 * Development platform `Teensy `__ + + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 + + Updated Arduino Core to v1.35 3.2.1 (2016-12-07) From 20246a3481884d51d63fde7d371b48f3f1538b53 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 19 Jan 2017 13:59:02 +0200 Subject: [PATCH 040/127] Update TIVA C Energia Core to 1.0.2 --- HISTORY.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index c125907d..e5496560 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -87,6 +87,10 @@ PlatformIO 3.0 + Updated ARM mbed OS to 5.3.0/rev131 + Updated Arduino Core to v1.35 +* Development platform `TI TIVA `__ + + + Updated Energia Core to 1.0.2 + 3.2.1 (2016-12-07) ~~~~~~~~~~~~~~~~~~ From ddd07138dd2c90a45d8f464e25869f38493981a3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 19 Jan 2017 19:02:37 +0200 Subject: [PATCH 041/127] Escape project path when Glob matching is used --- HISTORY.rst | 1 + platformio/builder/tools/piomisc.py | 7 ++++--- platformio/builder/tools/platformio.py | 4 ++-- platformio/commands/ci.py | 2 +- platformio/util.py | 25 +++++++++++++++++++++++++ 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index e5496560..4df920b0 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -28,6 +28,7 @@ PlatformIO 3.0 (`issue #850 `_) * Use C++11 by default for CLion IDE based projects (`pull #873 `_) +* Escape project path when Glob matching is used ------- diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 3b9f34e8..2aa259e3 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -181,8 +181,9 @@ class InoToCPPConverter(object): def ConvertInoToCpp(env): - ino_nodes = (env.Glob(join("$PROJECTSRC_DIR", "*.ino")) + - env.Glob(join("$PROJECTSRC_DIR", "*.pde"))) + src_dir = util.glob_escape(env.subst("$PROJECTSRC_DIR")) + ino_nodes = ( + env.Glob(join(src_dir, "*.ino")) + env.Glob(join(src_dir, "*.pde"))) if not ino_nodes: return c = InoToCPPConverter(env) @@ -216,7 +217,7 @@ def DumpIDEData(env): for name in p.get_installed_packages(): if p.get_package_type(name) != "toolchain": continue - toolchain_dir = p.get_package_dir(name) + toolchain_dir = util.glob_escape(p.get_package_dir(name)) toolchain_incglobs = [ join(toolchain_dir, "*", "include*"), join(toolchain_dir, "lib", "gcc", "*", "*", "include*") diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index fa39934f..56875c1a 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -25,7 +25,7 @@ from SCons.Script import (COMMAND_LINE_TARGETS, AlwaysBuild, DefaultEnvironment, SConscript) from SCons.Util import case_sensitive_suffixes, is_Sequence -from platformio.util import pioversion_to_intstr +from platformio.util import glob_escape, pioversion_to_intstr SRC_BUILD_EXT = ["c", "cpp", "S", "spp", "SPP", "sx", "s", "asm", "ASM"] SRC_HEADER_EXT = ["h", "hpp"] @@ -191,7 +191,7 @@ def MatchSourceFiles(env, src_dir, src_filter=None): src_filter = src_filter.replace("/", sep).replace("\\", sep) for (action, pattern) in SRC_FILTER_PATTERNS_RE.findall(src_filter): items = set() - for item in glob(join(src_dir, pattern)): + for item in glob(join(glob_escape(src_dir), pattern)): if isdir(item): for root, _, files in walk(item, followlinks=True): for f in files: diff --git a/platformio/commands/ci.py b/platformio/commands/ci.py index e74abb18..82784eb4 100644 --- a/platformio/commands/ci.py +++ b/platformio/commands/ci.py @@ -152,7 +152,7 @@ def _copy_contents(dst_dir, contents): def _exclude_contents(dst_dir, patterns): contents = [] for p in patterns: - contents += glob(join(dst_dir, p)) + contents += glob(join(util.glob_escape(dst_dir), p)) for path in contents: path = abspath(path) if isdir(path): diff --git a/platformio/util.py b/platformio/util.py index c2fe8653..b3406dbf 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -568,3 +568,28 @@ def rmtree_(path): os.remove(name) return rmtree(path, onerror=_onerror) + + +# +# Glob.Escape from Python 3.4 +# https://github.com/python/cpython/blob/master/Lib/glob.py#L161 +# + +try: + from glob import escape as glob_escape # pylint: disable=unused-import +except ImportError: + magic_check = re.compile('([*?[])') + magic_check_bytes = re.compile(b'([*?[])') + + def glob_escape(pathname): + """Escape all special characters. + """ + # Escaping is done by wrapping any of "*?[" between square brackets. + # Metacharacters do not work in the drive part and shouldn't be + # escaped. + drive, pathname = os.path.splitdrive(pathname) + if isinstance(pathname, bytes): + pathname = magic_check_bytes.sub(br'[\1]', pathname) + else: + pathname = magic_check.sub(r'[\1]', pathname) + return drive + pathname From 06209c17b5c7498530baa74e87a8fa6dc22bca86 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 20 Jan 2017 23:47:28 +0200 Subject: [PATCH 042/127] Update Arduino Core for AVR to 1.6.17 --- HISTORY.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 4df920b0..fb8fa6a5 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -36,6 +36,7 @@ PlatformIO 3.0 + Set fuse bits with new target named ``fuses`` (`issue #865 `_) + + Updated Arduino Core to 1.6.17 * Development platform `Atmel SAM `__ @@ -47,7 +48,7 @@ PlatformIO 3.0 + Added support for Simba & Pumbaa Frameworks + Added new board Node32s - + Updated ESP32 Core for Arduino + + Updated Arduino Core * Development platform `Freescale Kinetis `__ From b5ddf380ca3412f5b948550bf59f8dfb9b1d6937 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 21 Jan 2017 19:58:20 +0200 Subject: [PATCH 043/127] =?UTF-8?q?Add=20new=20option=20=E2=80=9C--no-rese?= =?UTF-8?q?t=E2=80=9D=20to=20=E2=80=9Cpio=20test=E2=80=9D=20=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HISTORY.rst | 2 ++ docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/test.py | 1 + platformio/pioplus.py | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index fb8fa6a5..abaadee8 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,6 +19,8 @@ PlatformIO 3.0 * Show detailed info about a library using `pio lib show `__ command (`issue #430 `_) +* Added new option ``--no-reset`` to `pio test `__ + command (allows to avoid automatic board's auto-reset when gathering test results) * Added support for templated methods in ``*.ino to *.cpp`` converter (`pull #858 `_) * Produce less noisy output when ``-s/--silent`` options are used for diff --git a/docs b/docs index f07d51a8..6e750d26 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit f07d51a851f9652c8f92c00b0ffb9bea785fa6b2 +Subproject commit 6e750d26fe6889b1a439750fcbf61ab64bae8039 diff --git a/platformio/__init__.py b/platformio/__init__.py index c14da88f..f62f00ab 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a4") +VERSION = (3, 3, "0a5") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/test.py b/platformio/commands/test.py index 714113ce..99760db6 100644 --- a/platformio/commands/test.py +++ b/platformio/commands/test.py @@ -37,6 +37,7 @@ from platformio.pioplus import pioplus_call resolve_path=True)) @click.option("--without-building", is_flag=True) @click.option("--without-uploading", is_flag=True) +@click.option("--no-reset", is_flag=True) @click.option("--verbose", "-v", is_flag=True) def cli(*args, **kwargs): # pylint: disable=unused-argument pioplus_call(sys.argv[1:]) diff --git a/platformio/pioplus.py b/platformio/pioplus.py index 56fefa66..0008c178 100644 --- a/platformio/pioplus.py +++ b/platformio/pioplus.py @@ -27,7 +27,7 @@ PACKAGE_DEPS = { }, "tool": { "name": "tool-pioplus", - "requirements": ">=0.6.6,<2" + "requirements": ">=0.6.9,<2" } } From 9405ca3dff45b2029a9e938285416bff3f2253bc Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 22 Jan 2017 00:10:39 +0200 Subject: [PATCH 044/127] Update Arduino SAM & SAMD Core to 1.6.11 --- HISTORY.rst | 4 +++- docs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index abaadee8..a482bbf4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -42,9 +42,11 @@ PlatformIO 3.0 * Development platform `Atmel SAM `__ - + Added support for Atmel ATSAMW25-XPRO board + + Added support for Adafruit Circuit Playground Express, Arduino MKRZero, + Atmel ATSAMW25-XPRO boards + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 + + Updated Arduino SAM & SAMD Core to 1.6.11 * Development platform `Espressif 32 `__ diff --git a/docs b/docs index 6e750d26..80a1f6f6 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 6e750d26fe6889b1a439750fcbf61ab64bae8039 +Subproject commit 80a1f6f621fef3b0b9f515eccad0454b6785b46a From ce066417e91f2ea77dcfb797405cca216a4062f0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 23 Jan 2017 00:13:58 +0200 Subject: [PATCH 045/127] Add new options ``--monitor-rts`` and ``--monitor-dtr`` to `pio test` command --- HISTORY.rst | 3 ++- docs | 2 +- examples | 2 +- platformio/__init__.py | 2 +- platformio/commands/device.py | 4 ++-- platformio/commands/remote.py | 4 ++-- platformio/commands/test.py | 15 ++++++++++++++- platformio/pioplus.py | 2 +- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index a482bbf4..e52ded32 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,7 +19,8 @@ PlatformIO 3.0 * Show detailed info about a library using `pio lib show `__ command (`issue #430 `_) -* Added new option ``--no-reset`` to `pio test `__ +* Added new options ``--no-reset``, ``--monitor-rts`` and ``--monitor-dtr`` + to `pio test `__ command (allows to avoid automatic board's auto-reset when gathering test results) * Added support for templated methods in ``*.ino to *.cpp`` converter (`pull #858 `_) diff --git a/docs b/docs index 80a1f6f6..b1a46aac 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 80a1f6f621fef3b0b9f515eccad0454b6785b46a +Subproject commit b1a46aaca7f6b1d9cc1abd1998506f8675ae4151 diff --git a/examples b/examples index 463f8557..e6e0c19b 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 463f855761f0af2657e597f6a3cf1b59daecc3fd +Subproject commit e6e0c19bd1149ae7b5e5b8f72c9ccc98f1690441 diff --git a/platformio/__init__.py b/platformio/__init__.py index f62f00ab..ae264f5e 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a5") +VERSION = (3, 3, "0a6") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/device.py b/platformio/commands/device.py index bf5499ae..cba2054c 100644 --- a/platformio/commands/device.py +++ b/platformio/commands/device.py @@ -61,12 +61,12 @@ def device_list(json_output): @click.option( "--rts", default=None, - type=click.Choice(["0", "1"]), + type=click.IntRange(0, 1), help="Set initial RTS line state") @click.option( "--dtr", default=None, - type=click.Choice(["0", "1"]), + type=click.IntRange(0, 1), help="Set initial DTR line state") @click.option("--echo", is_flag=True, help="Enable local echo, default=Off") @click.option( diff --git a/platformio/commands/remote.py b/platformio/commands/remote.py index 1d57d913..b3d4cbed 100644 --- a/platformio/commands/remote.py +++ b/platformio/commands/remote.py @@ -147,12 +147,12 @@ def device_list(json_output): @click.option( "--rts", default=None, - type=click.Choice(["0", "1"]), + type=click.IntRange(0, 1), help="Set initial RTS line state") @click.option( "--dtr", default=None, - type=click.Choice(["0", "1"]), + type=click.IntRange(0, 1), help="Set initial DTR line state") @click.option("--echo", is_flag=True, help="Enable local echo, default=Off") @click.option( diff --git a/platformio/commands/test.py b/platformio/commands/test.py index 99760db6..d63374c4 100644 --- a/platformio/commands/test.py +++ b/platformio/commands/test.py @@ -37,7 +37,20 @@ from platformio.pioplus import pioplus_call resolve_path=True)) @click.option("--without-building", is_flag=True) @click.option("--without-uploading", is_flag=True) -@click.option("--no-reset", is_flag=True) +@click.option( + "--no-reset", + is_flag=True, + help="Disable software reset via Serial.DTR/RST") +@click.option( + "--monitor-rts", + default=None, + type=click.IntRange(0, 1), + help="Set initial RTS line state for Serial Monitor") +@click.option( + "--monitor-dtr", + default=None, + type=click.IntRange(0, 1), + help="Set initial DTR line state for Serial Monitor") @click.option("--verbose", "-v", is_flag=True) def cli(*args, **kwargs): # pylint: disable=unused-argument pioplus_call(sys.argv[1:]) diff --git a/platformio/pioplus.py b/platformio/pioplus.py index 0008c178..91a7447b 100644 --- a/platformio/pioplus.py +++ b/platformio/pioplus.py @@ -27,7 +27,7 @@ PACKAGE_DEPS = { }, "tool": { "name": "tool-pioplus", - "requirements": ">=0.6.9,<2" + "requirements": ">=0.6.10,<2" } } From 8314e05a7121161dbad2dedae53d0ff5ded867f8 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 23 Jan 2017 00:30:23 +0200 Subject: [PATCH 046/127] Add tip about chat for PIO Plus --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index b1a46aac..d3216643 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b1a46aaca7f6b1d9cc1abd1998506f8675ae4151 +Subproject commit d321664355ef87b7f72ac19265ef160dea0e0a23 From 5d8a17ba6da1c316a7402d56fd0ece26532d96ba Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 23 Jan 2017 14:24:34 +0200 Subject: [PATCH 047/127] Fix issue with empty CPPPATH when processing a library --- platformio/builder/tools/piolib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index 8c1dc924..cd3d53ef 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -571,7 +571,7 @@ class PlatformIOLibBuilder(LibBuilderBase): inc_dirs.append(join(self.path, "utility")) for path in self.env.get("CPPPATH", []): - if path not in self.envorigin['CPPPATH']: + if path not in self.envorigin.get("CPPPATH", []): inc_dirs.append(self.env.subst(path)) return inc_dirs From d31c09f786cc33ec7eb2eaffc0de5287ca68e441 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 24 Jan 2017 01:37:50 +0200 Subject: [PATCH 048/127] Typo fix --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index d3216643..6a31b437 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit d321664355ef87b7f72ac19265ef160dea0e0a23 +Subproject commit 6a31b437c54f81cf106c9c9d227dda2279483712 From 682f1cb798fe84a9b4ed352a2185e1b82d36dcad Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 24 Jan 2017 16:14:31 +0200 Subject: [PATCH 049/127] =?UTF-8?q?Return=20=E2=80=9CFalse=E2=80=9D=20for?= =?UTF-8?q?=20unknown=20outdated=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/managers/package.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 062e271e..a25a9865 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -456,8 +456,8 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): if self.get_vcs_manifest_path(package_dir): return False manifest = self.load_manifest(package_dir) - return manifest['version'] != self.get_latest_repo_version( - name, requirements) + latest = self.get_latest_repo_version(name, requirements) + return latest and manifest['version'] != latest def install(self, name, From 92b2782af82e3de4984fb06bfe7b5fb150376774 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 24 Jan 2017 17:36:34 +0200 Subject: [PATCH 050/127] Fix package installing with VCS branch for Python 2.7.3 // Resolve #885 --- HISTORY.rst | 3 +++ platformio/vcsclient.py | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index e52ded32..19035064 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -32,6 +32,9 @@ PlatformIO 3.0 * Use C++11 by default for CLion IDE based projects (`pull #873 `_) * Escape project path when Glob matching is used +* Fixed package installing with VCS branch for Python 2.7.3 + (`issue #885 `_) + ------- diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index c7519e61..b06df1f3 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -28,18 +28,19 @@ class VCSClientFactory(object): def newClient(src_dir, remote_url): result = urlparse(remote_url) type_ = result.scheme + tag = None if not type_ and remote_url.startswith("git@"): type_ = "git" elif "+" in result.scheme: type_, _ = result.scheme.split("+", 1) remote_url = remote_url[len(type_) + 1:] - if result.fragment: - remote_url = remote_url.rsplit("#", 1)[0] + if "#" in remote_url: + remote_url, tag = remote_url.rsplit("#", 1) if not type_: raise PlatformioException("VCS: Unknown repository type %s" % remote_url) obj = getattr(modules[__name__], "%sClient" % type_.title())( - src_dir, remote_url, result.fragment) + src_dir, remote_url, tag) assert isinstance(obj, VCSClientBase) return obj From a874db38befa6ebf9f1e57cb29e7fbe4cb445177 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 24 Jan 2017 21:54:50 +0200 Subject: [PATCH 051/127] Apply YAPF --- platformio/builder/tools/piolib.py | 4 ++-- platformio/commands/lib.py | 22 +++++++++++----------- platformio/commands/platform.py | 4 ++-- platformio/commands/upgrade.py | 4 ++-- platformio/ide/projectgenerator.py | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index cd3d53ef..32164b16 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -591,8 +591,8 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches if verbose: sys.stderr.write("Ignored library %s\n" % lb.path) return - if compat_mode > 1 and not lb.is_platforms_compatible(env[ - 'PIOPLATFORM']): + if compat_mode > 1 and not lb.is_platforms_compatible( + env['PIOPLATFORM']): if verbose: sys.stderr.write("Platform incompatible library %s\n" % lb.path) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 4134bd6a..43aa962b 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -390,17 +390,17 @@ def lib_stats(json_output): click.echo("-" * terminal_width) def _print_lib_item(item): - click.echo((printitemdate_tpl - if "date" in item else printitem_tpl).format( - name=click.style( - item['name'], fg="cyan"), - date=str( - arrow.get(item['date']).humanize() - if "date" in item else ""), - url=click.style( - "http://platformio.org/lib/show/%s/%s" % (item[ - 'id'], quote(item['name'])), - fg="blue"))) + click.echo(( + printitemdate_tpl if "date" in item else printitem_tpl + ).format( + name=click.style( + item['name'], fg="cyan"), + date=str( + arrow.get(item['date']).humanize() if "date" in item else ""), + url=click.style( + "http://platformio.org/lib/show/%s/%s" % (item['id'], + quote(item['name'])), + fg="blue"))) def _print_tag_item(name): click.echo( diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index f4a34241..7821d68b 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -34,8 +34,8 @@ def _print_platforms(platforms): click.echo("=" * (3 + len(platform['name'] + platform['title']))) click.echo(platform['description']) click.echo() - click.echo("Home: %s" % "http://platformio.org/platforms/" + platform[ - 'name']) + click.echo("Home: %s" % "http://platformio.org/platforms/" + + platform['name']) if platform['packages']: click.echo("Packages: %s" % ", ".join(platform['packages'])) if "version" in platform: diff --git a/platformio/commands/upgrade.py b/platformio/commands/upgrade.py index 5620b10f..41564535 100644 --- a/platformio/commands/upgrade.py +++ b/platformio/commands/upgrade.py @@ -83,8 +83,8 @@ WARNING! Don't use `sudo` for the rest PlatformIO commands. err=True) raise exception.ReturnErrorCode(1) else: - raise exception.UpgradeError("\n".join( - [str(cmd), r['out'], r['err']])) + raise exception.UpgradeError( + "\n".join([str(cmd), r['out'], r['err']])) def get_latest_version(): diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index 5e4b0e8f..e1efa469 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -69,8 +69,8 @@ class ProjectGenerator(object): result = util.exec_command(cmd) if result['returncode'] != 0 or '"includes":' not in result['out']: - raise exception.PlatformioException("\n".join( - [result['out'], result['err']])) + raise exception.PlatformioException( + "\n".join([result['out'], result['err']])) for line in result['out'].split("\n"): line = line.strip() From d64f4778dfa66fab141f44d76e02b62cf00b484c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 24 Jan 2017 22:07:45 +0200 Subject: [PATCH 052/127] Package version as "Repository URL" in manifest of development version --- HISTORY.rst | 2 ++ docs | 2 +- platformio/__init__.py | 2 +- platformio/managers/package.py | 64 +++++++++++++++++++++++----------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 19035064..683f3604 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -24,6 +24,8 @@ PlatformIO 3.0 command (allows to avoid automatic board's auto-reset when gathering test results) * Added support for templated methods in ``*.ino to *.cpp`` converter (`pull #858 `_) +* Package version as "Repository URL" in manifest of development version + (``"version": "https://github.com/user/repo.git"``) * Produce less noisy output when ``-s/--silent`` options are used for `platformio init `__ and `platformio run `__ diff --git a/docs b/docs index 6a31b437..91e3a088 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 6a31b437c54f81cf106c9c9d227dda2279483712 +Subproject commit 91e3a088efd7c3a735467cb2d8be78ed0365cc5b diff --git a/platformio/__init__.py b/platformio/__init__.py index ae264f5e..72ecffd5 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a6") +VERSION = (3, 3, "0a7") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/managers/package.py b/platformio/managers/package.py index a25a9865..ce084ef2 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -13,6 +13,7 @@ # limitations under the License. import codecs +import hashlib import json import os import shutil @@ -233,39 +234,55 @@ class PkgInstallerMixin(object): return pkg_dir def _install_from_tmp_dir(self, tmp_dir, requirements=None): - tmpmanifest = self.load_manifest(tmp_dir) - assert set(["name", "version"]) <= set(tmpmanifest.keys()) - name = tmpmanifest['name'] + tmp_manifest_path = self.get_manifest_path(tmp_dir) + tmp_manifest = self.load_manifest(tmp_manifest_path) + assert set(["name", "version"]) <= set(tmp_manifest.keys()) + + name = tmp_manifest['name'] pkg_dir = join(self.package_dir, name) - if "id" in tmpmanifest: - name += "_ID%d" % tmpmanifest['id'] + if "id" in tmp_manifest: + name += "_ID%d" % tmp_manifest['id'] pkg_dir = join(self.package_dir, name) # package should satisfy requirements if requirements: mismatch_error = ( "Package version %s doesn't satisfy requirements %s" % ( - tmpmanifest['version'], requirements)) + tmp_manifest['version'], requirements)) try: reqspec = semantic_version.Spec(requirements) - tmpmanver = semantic_version.Version( - tmpmanifest['version'], partial=True) - assert tmpmanver in reqspec, mismatch_error + tmp_version = semantic_version.Version( + tmp_manifest['version'], partial=True) + assert tmp_version in reqspec, mismatch_error + except ValueError: + assert tmp_manifest['version'] == requirements, mismatch_error + + if self.manifest_exists(pkg_dir): + cur_manifest_path = self.get_manifest_path(pkg_dir) + cur_manifest = self.load_manifest(cur_manifest_path) + + if tmp_manifest_path.endswith(self.VCS_MANIFEST_NAME): + if cur_manifest.get("url") != tmp_manifest['url']: + pkg_dir = join(self.package_dir, "%s@vcs-%s" % ( + name, hashlib.md5(tmp_manifest['url']).hexdigest())) + else: + try: + tmp_version = semantic_version.Version( + tmp_manifest['version'], partial=True) + cur_version = semantic_version.Version( + cur_manifest['version'], partial=True) - if self.manifest_exists(pkg_dir): - curmanifest = self.load_manifest(pkg_dir) - curmanver = semantic_version.Version( - curmanifest['version'], partial=True) # if current package version < new package, backup it - if tmpmanver > curmanver: + if tmp_version > cur_version: os.rename(pkg_dir, join(self.package_dir, "%s@%s" % - (name, curmanifest['version']))) - elif tmpmanver < curmanver: + (name, cur_manifest['version']))) + elif tmp_version < cur_version: pkg_dir = join(self.package_dir, "%s@%s" % - (name, tmpmanifest['version'])) - except ValueError: - assert tmpmanifest['version'] == requirements, mismatch_error + (name, tmp_manifest['version'])) + except ValueError: + pkg_dir = join(self.package_dir, + "%s@%s" % (name, tmp_manifest['version'])) # remove previous/not-satisfied package if isdir(pkg_dir): @@ -419,7 +436,12 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): elif not pkg_id and manifest['name'] != name: continue elif not reqspec and requirements: - if requirements == manifest['version']: + conds = [ + requirements == manifest['version'], + "://" in requirements and + requirements in manifest.get("url", "") + ] + if any(conds): best = manifest break continue @@ -435,11 +457,13 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): best = manifest except ValueError: pass + if best: # check that URL is the same in installed package (VCS) if url and best.get("url") != url: return None return best + return None def get_package_dir(self, name, requirements=None, url=None): From 162caf61a2d79e158a504507574b81f44e008b41 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 25 Jan 2017 02:08:20 +0200 Subject: [PATCH 053/127] Handle requirements for package defined in platform manifest --- platformio/managers/package.py | 18 +++------- platformio/managers/platform.py | 59 +++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index ce084ef2..cb16d6d4 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -435,15 +435,13 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): continue elif not pkg_id and manifest['name'] != name: continue - elif not reqspec and requirements: + elif not reqspec and (requirements or url): conds = [ - requirements == manifest['version'], - "://" in requirements and - requirements in manifest.get("url", "") + requirements == manifest['version'], url and + url in manifest.get("url", "") ] - if any(conds): + if not best or any(conds): best = manifest - break continue try: if reqspec and not reqspec.match( @@ -458,13 +456,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): except ValueError: pass - if best: - # check that URL is the same in installed package (VCS) - if url and best.get("url") != url: - return None - return best - - return None + return best def get_package_dir(self, name, requirements=None, url=None): package = self.get_package(name, requirements, url) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 5b61aba7..e9bb6c26 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -207,45 +207,82 @@ class PlatformPackagesMixin(object): raise exception.UnknownPackage(", ".join(upkgs - ppkgs)) for name, opts in self.packages.items(): + version = opts.get("version", "") if name in without_packages: continue elif (name in with_packages or not (skip_default_package or opts.get("optional", False))): - if any([s in opts.get("version", "") for s in ("\\", "/")]): - self.pm.install( - "%s=%s" % (name, opts['version']), silent=silent) + if self.validate_version_requirements(version): + self.pm.install(name, version, silent=silent) else: - self.pm.install(name, opts.get("version"), silent=silent) + requirements = None + if "@" in version: + version, requirements = version.rsplit("@", 1) + self.pm.install( + "%s=%s" % (name, version), requirements, silent=silent) return True def get_installed_packages(self): items = {} for name, opts in self.packages.items(): - package = self.pm.get_package(name, opts['version']) + version = opts.get("version", "") + if self.validate_version_requirements(version): + package = self.pm.get_package(name, version) + else: + package = self.pm.get_package(*self._parse_pkg_name(name, + version)) if package: items[name] = package return items def update_packages(self, only_check=False): for name in self.get_installed_packages(): - self.pm.update(name, self.packages[name]['version'], only_check) + version = self.packages[name].get("version", "") + if self.validate_version_requirements(version): + self.pm.update(name, version, only_check) + else: + requirements = None + if "@" in version: + version, requirements = version.rsplit("@", 1) + self.pm.update("%s=%s" % (name, version), requirements, + only_check) def are_outdated_packages(self): for name, opts in self.get_installed_packages().items(): - if (opts['version'] != self.pm.get_latest_repo_version( - name, self.packages[name].get("version"))): + version = self.packages[name].get("version", "") + if not self.validate_version_requirements(version): + continue + if self.pm.is_outdated(name, version): return True return False def get_package_dir(self, name): - return self.pm.get_package_dir(name, - self.packages[name].get("version")) + version = self.packages[name].get("version", "") + if self.validate_version_requirements(version): + return self.pm.get_package_dir(name, version) + else: + return self.pm.get_package_dir(*self._parse_pkg_name(name, + version)) def get_package_version(self, name): - package = self.pm.get_package(name, self.packages[name].get("version")) + version = self.packages[name].get("version", "") + if self.validate_version_requirements(version): + package = self.pm.get_package(name, version) + else: + package = self.pm.get_package(*self._parse_pkg_name(name, version)) return package['version'] if package else None + @staticmethod + def validate_version_requirements(requirements): + return requirements and "://" not in requirements + + def _parse_pkg_name(self, name, version): + requirements = None + if "@" in version: + version, requirements = version.rsplit("@", 1) + return self.pm.parse_pkg_name("%s=%s" % (name, version), requirements) + class PlatformRunMixin(object): From 9cf242ad899d8ebe344a90d55cabbaaf087d22ae Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 25 Jan 2017 15:33:40 +0200 Subject: [PATCH 054/127] Check manifest engines field for PIO Core version --- platformio/exception.py | 7 ++++++- platformio/managers/package.py | 16 ++++++++++++---- platformio/managers/platform.py | 24 ++++++++++++++++++------ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/platformio/exception.py b/platformio/exception.py index 7482f233..f4743d4c 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -40,7 +40,12 @@ class AbortedByUser(PlatformioException): class UnknownPlatform(PlatformioException): - MESSAGE = "Unknown platform '{0}'" + MESSAGE = "Unknown development platform '{0}'" + + +class IncompatiblePlatform(PlatformioException): + + MESSAGE = "Development platform '{0}' is not compatible with PIO Core v{1}" class PlatformNotInstalledYet(PlatformioException): diff --git a/platformio/managers/package.py b/platformio/managers/package.py index cb16d6d4..55d2844f 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -24,7 +24,7 @@ import click import requests import semantic_version -from platformio import app, exception, telemetry, util +from platformio import __version__, app, exception, telemetry, util from platformio.downloader import FileDownloader from platformio.unpacker import FileUnpacker from platformio.vcsclient import VCSClientFactory @@ -75,6 +75,8 @@ class PackageRepoIterator(object): class PkgRepoMixin(object): + PIO_VERSION = semantic_version.Version(util.pepver_to_semver(__version__)) + @staticmethod def max_satisfying_repo_version(versions, requirements=None): item = None @@ -87,9 +89,13 @@ class PkgRepoMixin(object): pass for v in versions: - if ("system" in v and v['system'] not in ("all", "*") and - systype not in v['system']): + if "system" in v and v['system'] not in ("all", "*") and \ + systype not in v['system']: continue + if "platformio" in v.get("engines", {}): + if PkgRepoMixin.PIO_VERSION not in semantic_version.Spec( + v['engines']['platformio']): + continue specver = semantic_version.Version(v['version']) if reqspec and specver not in reqspec: continue @@ -462,9 +468,11 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): package = self.get_package(name, requirements, url) return package.get("__pkg_dir") if package else None - def is_outdated(self, name, requirements=None): + def is_outdated(self, name, requirements=None, silent=False): package_dir = self.get_package_dir(name, requirements) if not package_dir: + if silent: + return click.secho( "%s @ %s is not installed" % (name, requirements or "*"), fg="yellow") diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index e9bb6c26..22838ac6 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -20,8 +20,9 @@ from multiprocessing import cpu_count from os.path import basename, dirname, isdir, isfile, join import click +import semantic_version -from platformio import app, exception, util +from platformio import __version__, app, exception, util from platformio.managers.package import BasePkgManager, PackageManager @@ -91,8 +92,8 @@ class PlatformManager(BasePkgManager): self.cleanup_packages(p.packages.keys()) return True - def is_outdated(self, name, requirements=None): - if BasePkgManager.is_outdated(self, name, requirements): + def is_outdated(self, name, requirements=None, silent=False): + if BasePkgManager.is_outdated(self, name, requirements, silent): return True p = PlatformFactory.newPlatform(name, requirements) return p.are_outdated_packages() @@ -249,11 +250,11 @@ class PlatformPackagesMixin(object): only_check) def are_outdated_packages(self): - for name, opts in self.get_installed_packages().items(): - version = self.packages[name].get("version", "") + for name, opts in self.packages.items(): + version = opts.get("version", "") if not self.validate_version_requirements(version): continue - if self.pm.is_outdated(name, version): + if self.pm.is_outdated(name, version, silent=True): return True return False @@ -364,6 +365,7 @@ class PlatformRunMixin(object): class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): + PIO_VERSION = semantic_version.Version(util.pepver_to_semver(__version__)) _BOARDS_CACHE = {} def __init__(self, manifest_path): @@ -378,6 +380,12 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): self.silent = False self.verbose = False + if self.engines and "platformio" in self.engines: + if self.PIO_VERSION not in semantic_version.Spec( + self.engines['platformio']): + raise exception.IncompatiblePlatform(self.name, + str(self.PIO_VERSION)) + @property def name(self): return self._manifest['name'] @@ -410,6 +418,10 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): def frameworks(self): return self._manifest.get("frameworks") + @property + def engines(self): + return self._manifest.get("engines") + @property def manifest(self): return self._manifest From 6123d055f9c648d0fd94869fa1c6e148805318e2 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 27 Jan 2017 13:36:33 +0200 Subject: [PATCH 055/127] =?UTF-8?q?Update=20Blink=20example=20for=20PIO=20?= =?UTF-8?q?IDE=20with=20default=20value=20for=20=E2=80=9CLED=5FBUILTIN?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 91e3a088..a03ec319 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 91e3a088efd7c3a735467cb2d8be78ed0365cc5b +Subproject commit a03ec319621ef726bbce7111a9123eb730c894fa From 054b5cca6bac12e85ff6cc3c991569c26f3bdef0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 27 Jan 2017 21:08:15 +0200 Subject: [PATCH 056/127] * Added support for EnviroDIY Mayfly board --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index 683f3604..a810cac8 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -42,6 +42,7 @@ PlatformIO 3.0 * Development platform `Atmel AVR `__ + + Added support for EnviroDIY Mayfly board + Set fuse bits with new target named ``fuses`` (`issue #865 `_) + Updated Arduino Core to 1.6.17 From 65db6ce497137a30f783de025322e05d5b9a4f8f Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 27 Jan 2017 21:49:10 +0200 Subject: [PATCH 057/127] Add new boards to docs --- HISTORY.rst | 2 +- docs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index a810cac8..71904a01 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -58,7 +58,7 @@ PlatformIO 3.0 * Development platform `Espressif 32 `__ + Added support for Simba & Pumbaa Frameworks - + Added new board Node32s + + Added new boards: Node32s, Hornbill ESP32 Dev, Hornbill ESP32 Minim + Updated Arduino Core * Development platform `Freescale Kinetis `__ diff --git a/docs b/docs index a03ec319..42fa0462 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a03ec319621ef726bbce7111a9123eb730c894fa +Subproject commit 42fa04626709d55f1bbd3c7bed3b090ebe108bcc From 4d566b81d14b484cd1691971d191f589f51828d1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 27 Jan 2017 23:52:00 +0200 Subject: [PATCH 058/127] Using Arduino Framework with Staging version for ESP32 --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 42fa0462..a86e4c14 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 42fa04626709d55f1bbd3c7bed3b090ebe108bcc +Subproject commit a86e4c14afbdfaf2bc6f56e49b765feed24286f8 From a4d8749e446672dcab01e04cbb8c5286eb91e30c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 28 Jan 2017 15:48:36 +0200 Subject: [PATCH 059/127] =?UTF-8?q?Don=E2=80=99t=20warn=20about=20known=20?= =?UTF-8?q?built-in=20libraries=20while=20building=20a=20project?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/commands/lib.py | 17 ++++++++++------- platformio/commands/run.py | 11 ++++++++++- platformio/managers/platform.py | 19 +++++++++++++++---- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 43aa962b..7b35a1f5 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -244,14 +244,10 @@ def lib_list(lm, json_output): print_lib_item(item) -@cli.command("builtin", short_help="List built-in libraries") -@click.option("--storage", multiple=True) -@click.option("--json-output", is_flag=True) -@click.pass_obj -def lib_builtin(lm, storage, json_output): +@util.memoized +def get_builtin_libs(storage_names=None): items = [] - storage_names = storage or [] - del storage + storage_names = storage_names or [] pm = PlatformManager() for manifest in pm.get_installed(): p = PlatformFactory.newPlatform( @@ -261,7 +257,14 @@ def lib_builtin(lm, storage, json_output): continue lm = LibraryManager(storage['path']) items.append(dict(name=storage['name'], items=lm.get_installed())) + return items + +@cli.command("builtin", short_help="List built-in libraries") +@click.option("--storage", multiple=True) +@click.option("--json-output", is_flag=True) +def lib_builtin(storage, json_output): + items = get_builtin_libs(storage) if json_output: return click.echo(json.dumps(items)) diff --git a/platformio/commands/run.py b/platformio/commands/run.py index f270b437..28196a90 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -22,6 +22,7 @@ import click from platformio import __version__, exception, telemetry, util from platformio.commands.lib import lib_install as cmd_lib_install +from platformio.commands.lib import get_builtin_libs from platformio.commands.platform import \ platform_install as cmd_platform_install from platformio.managers.lib import LibraryManager @@ -279,7 +280,15 @@ def _autoinstall_libdeps(ctx, libraries, verbose=False): try: ctx.invoke(cmd_lib_install, libraries=[lib], silent=not verbose) except exception.LibNotFound as e: - click.secho("Warning! %s" % e, fg="yellow") + if not _is_builtin_lib(lib): + click.secho("Warning! %s" % e, fg="yellow") + + +def _is_builtin_lib(lib_name): + for storage in get_builtin_libs(): + if any([l.get("name") == lib_name for l in storage['items']]): + return True + return False def _clean_pioenvs_dir(pioenvs_dir): diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 22838ac6..a8f04678 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -544,15 +544,26 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): def get_lib_storages(self): storages = [] - for _, opts in (self.frameworks or {}).items(): + for opts in (self.frameworks or {}).values(): if "package" not in opts: continue pkg_dir = self.get_package_dir(opts['package']) if not pkg_dir or not isdir(join(pkg_dir, "libraries")): continue - storages.append( - dict( - name=opts['package'], path=join(pkg_dir, "libraries"))) + libs_dir = join(pkg_dir, "libraries") + storages.append({"name": opts['package'], "path": libs_dir}) + libcores_dir = join(libs_dir, "__cores__") + if not isdir(libcores_dir): + continue + for item in os.listdir(libcores_dir): + libcore_dir = join(libcores_dir, item) + if not isdir(libcore_dir): + continue + storages.append({ + "name": "%s-%s" % (opts['package'], item), + "path": libcore_dir + }) + return storages From 8a7d2553611113ea63b34eeb851d4bfce952c0c6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 28 Jan 2017 17:06:20 +0200 Subject: [PATCH 060/127] Handle libraries without manifests --- platformio/commands/lib.py | 13 ++++-- platformio/managers/lib.py | 71 ++++++++++++++++++++------------- platformio/managers/package.py | 11 +++-- platformio/managers/platform.py | 2 +- 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 7b35a1f5..5e3965fb 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -125,7 +125,8 @@ def print_lib_item(item): click.echo("=" * len(item['name'])) if "id" in item: click.secho("#ID: %d" % item['id'], bold=True) - click.echo(item.get("description", item.get("url", ""))) + if "description" in item or "url" in item: + click.echo(item.get("description", item.get("url", ""))) click.echo() for key in ("version", "homepage", "license", "keywords"): @@ -223,8 +224,8 @@ def lib_search(query, json_output, page, noninteractive, **filters): break result = get_api_result( "/v2/lib/search", - dict( - query=" ".join(query), page=int(result['page']) + 1), + {"query": " ".join(query), + "page": int(result['page']) + 1}, cache_valid="3d") @@ -256,7 +257,11 @@ def get_builtin_libs(storage_names=None): if storage_names and storage['name'] not in storage_names: continue lm = LibraryManager(storage['path']) - items.append(dict(name=storage['name'], items=lm.get_installed())) + items.append({ + "name": storage['name'], + "path": storage['path'], + "items": lm.get_installed() + }) return items diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index b41b0997..92e57a11 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -17,8 +17,9 @@ import json import os import re +from glob import glob from hashlib import md5 -from os.path import join +from os.path import isdir, join import arrow import click @@ -42,30 +43,23 @@ class LibraryManager(BasePkgManager): "module.json" ] - def check_pkg_structure(self, pkg_dir): - try: - return BasePkgManager.check_pkg_structure(self, pkg_dir) - except exception.MissingPackageManifest: - # we will generate manifest automatically - # if library doesn't contain any - pass + def get_manifest_path(self, pkg_dir): + path = BasePkgManager.get_manifest_path(self, pkg_dir) + if path: + return path - manifest = { - "name": "Library_" + md5(pkg_dir).hexdigest()[:5], - "version": "0.0.0" - } - for root, dirs, files in os.walk(pkg_dir): - if len(dirs) == 1 and not files: - manifest['name'] = dirs[0] - continue - if dirs or files: - pkg_dir = root - break + # if library without manifest, returns first source file + src_dir = join(util.glob_escape(pkg_dir)) + if isdir(join(pkg_dir, "src")): + src_dir = join(src_dir, "src") + chs_files = glob(join(src_dir, "*.[chS]")) + if chs_files: + return chs_files[0] + cpp_files = glob(join(src_dir, "*.cpp")) + if cpp_files: + return cpp_files[0] - with open(join(pkg_dir, self.manifest_names[0]), "w") as fp: - json.dump(manifest, fp) - - return pkg_dir + return None def load_manifest(self, path): manifest = BasePkgManager.load_manifest(self, path) @@ -75,15 +69,13 @@ class LibraryManager(BasePkgManager): # if Arudino library.properties if "sentence" in manifest: manifest['frameworks'] = ["arduino"] + manifest['description'] = manifest['sentence'] + del manifest['sentence'] if "author" in manifest: manifest['authors'] = [{"name": manifest['author']}] del manifest['author'] - if "sentence" in manifest: - manifest['description'] = manifest['sentence'] - del manifest['sentence'] - if "keywords" not in manifest: keywords = [] for keyword in re.split(r"[\s/]+", @@ -131,6 +123,31 @@ class LibraryManager(BasePkgManager): return manifest + def check_pkg_structure(self, pkg_dir): + try: + return BasePkgManager.check_pkg_structure(self, pkg_dir) + except exception.MissingPackageManifest: + # we will generate manifest automatically + # if library doesn't contain any + pass + + manifest = { + "name": "Library_" + md5(pkg_dir).hexdigest()[:5], + "version": "0.0.0" + } + for root, dirs, files in os.walk(pkg_dir): + if len(dirs) == 1 and not files: + manifest['name'] = dirs[0] + continue + if dirs or files: + pkg_dir = root + break + + with open(join(pkg_dir, self.manifest_names[0]), "w") as fp: + json.dump(manifest, fp) + + return pkg_dir + @staticmethod def normalize_dependencies(dependencies): if not dependencies: diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 55d2844f..8450ff52 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -155,18 +155,23 @@ class PkgInstallerMixin(object): if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): pkg_dir = dirname(dirname(path)) + manifest = {} if path.endswith(".json"): manifest = util.load_json(path) - else: - manifest = {} + elif path.endswith(".properties"): with codecs.open(path, encoding="utf-8") as fp: for line in fp.readlines(): if "=" not in line: continue key, value = line.split("=", 1) manifest[key.strip()] = value.strip() - manifest['__pkg_dir'] = pkg_dir + else: + if "name" not in manifest: + manifest['name'] = basename(pkg_dir) + if "version" not in manifest: + manifest['version'] = "0.0.0" + manifest['__pkg_dir'] = pkg_dir return manifest def check_pkg_structure(self, pkg_dir): diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index a8f04678..85d963a2 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -560,7 +560,7 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): if not isdir(libcore_dir): continue storages.append({ - "name": "%s-%s" % (opts['package'], item), + "name": "%s-core-%s" % (opts['package'], item), "path": libcore_dir }) From c1e14b671c7bf7adc1ac6a3ec37127c9376da1a6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 28 Jan 2017 21:20:59 +0200 Subject: [PATCH 061/127] Temporary use `develop` version of get-pio script --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index a86e4c14..24e04160 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a86e4c14afbdfaf2bc6f56e49b765feed24286f8 +Subproject commit 24e041602f3d0765963772083b023a00b7cf039f From 34eab69e8521e4782e76b6df467eb1a8326dd5ff Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 30 Jan 2017 01:04:06 +0200 Subject: [PATCH 062/127] =?UTF-8?q?=E2=80=9Cpio=20lib=20update=E2=80=9D=20?= =?UTF-8?q?and=20=E2=80=9Cpio=20platform=20update=E2=80=9D=20in=20JSON=20f?= =?UTF-8?q?ormat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/lib.py | 31 ++++- platformio/commands/platform.py | 41 +++++- platformio/maintenance.py | 2 +- platformio/managers/package.py | 226 +++++++++++++++++--------------- platformio/managers/platform.py | 35 +++-- platformio/vcsclient.py | 32 ++++- 8 files changed, 231 insertions(+), 140 deletions(-) diff --git a/docs b/docs index 24e04160..d019f410 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 24e041602f3d0765963772083b023a00b7cf039f +Subproject commit d019f41070f64d026b80c9cc612015c5b16d1cda diff --git a/platformio/__init__.py b/platformio/__init__.py index 72ecffd5..87c5830d 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a7") +VERSION = (3, 3, "0a8") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 5e3965fb..0e75548d 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -112,12 +112,35 @@ def lib_uninstall(lm, libraries): "--only-check", is_flag=True, help="Do not update, only check for new version") +@click.option("--json-output", is_flag=True) @click.pass_obj -def lib_update(lm, libraries, only_check): +def lib_update(lm, libraries, only_check, json_output): if not libraries: - libraries = [str(m.get("id", m['name'])) for m in lm.get_installed()] - for library in libraries: - lm.update(library, only_check=only_check) + libraries = [] + for manifest in lm.get_installed(): + pkg_dir = manifest['__pkg_dir'] + if "@" in pkg_dir and "@vcs-" not in pkg_dir: + continue + elif "@vcs-" in pkg_dir: + libraries.append("%s=%s" % (manifest['name'], manifest['url'])) + else: + libraries.append(str(manifest.get("id", manifest['name']))) + + if only_check and json_output: + result = [] + for library in libraries: + name, requirements, url = lm.parse_pkg_name(library) + latest = lm.outdated(name, requirements, url) + if latest is False: + continue + manifest = lm.load_manifest( + lm.get_package_dir(name, requirements, url)) + manifest['versionLatest'] = latest or "Unknown" + result.append(manifest) + return click.echo(json.dumps(result)) + else: + for library in libraries: + lm.update(library, only_check=only_check) def print_lib_item(item): diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 7821d68b..4f493229 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -114,15 +114,42 @@ def platform_uninstall(platforms): "--only-check", is_flag=True, help="Do not update, only check for new version") -def platform_update(platforms, only_packages, only_check): +@click.option("--json-output", is_flag=True) +def platform_update(platforms, only_packages, only_check, json_output): pm = PlatformManager() if not platforms: - platforms = set([m['name'] for m in pm.get_installed()]) - for platform in platforms: - click.echo("Platform %s" % click.style(platform, fg="cyan")) - click.echo("--------") - pm.update(platform, only_packages=only_packages, only_check=only_check) - click.echo() + platforms = [] + for manifest in pm.get_installed(): + pkg_dir = manifest['__pkg_dir'] + if "@" in pkg_dir and "@vcs-" not in pkg_dir: + continue + elif "@vcs-" in pkg_dir: + platforms.append("%s=%s" % (manifest['name'], manifest['url'])) + else: + platforms.append(manifest['name']) + + if only_check and json_output: + result = [] + for platform in platforms: + name, requirements, url = pm.parse_pkg_name(platform) + latest = pm.outdated(name, requirements, url) + if latest is False: + continue + manifest = pm.load_manifest( + pm.get_package_dir(name, requirements, url)) + if latest is True: + manifest['versionLatest'] = "Out-of-date" + else: + manifest['versionLatest'] = latest or "Unknown" + result.append(manifest) + return click.echo(json.dumps(result)) + else: + for platform in platforms: + click.echo("Platform %s" % click.style(platform, fg="cyan")) + click.echo("--------") + pm.update( + platform, only_packages=only_packages, only_check=only_check) + click.echo() @cli.command("list", short_help="List installed development platforms") diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 3925741e..cd1e3562 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -268,7 +268,7 @@ def check_internal_updates(ctx, what): outdated_items = [] for manifest in pm.get_installed(): if manifest['name'] not in outdated_items and \ - pm.is_outdated(manifest['name']): + pm.outdated(manifest['name']): outdated_items.append(manifest['name']) if not outdated_items: diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 8450ff52..10b0cd18 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -119,6 +119,47 @@ class PkgInstallerMixin(object): VCS_MANIFEST_NAME = ".piopkgmanager.json" + FILE_CACHE_VALID = "1m" # 1 month + FILE_CACHE_MAX_SIZE = 1024 * 1024 + + _INSTALLED_CACHE = {} + + def reset_cache(self): + if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: + del PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] + + def download(self, url, dest_dir, sha1=None): + cache_key_fname = app.ContentCache.key_from_args(url, "fname") + cache_key_data = app.ContentCache.key_from_args(url, "data") + if self.FILE_CACHE_VALID: + with app.ContentCache() as cc: + fname = cc.get(cache_key_fname) + cache_path = cc.get_cache_path(cache_key_data) + if fname and isfile(cache_path): + dst_path = join(dest_dir, fname) + shutil.copy(cache_path, dst_path) + return dst_path + + fd = FileDownloader(url, dest_dir) + fd.start() + if sha1: + fd.verify(sha1) + dst_path = fd.get_filepath() + if not self.FILE_CACHE_VALID or getsize( + dst_path) > PkgInstallerMixin.FILE_CACHE_MAX_SIZE: + return dst_path + + with app.ContentCache() as cc: + cc.set(cache_key_fname, basename(dst_path), self.FILE_CACHE_VALID) + cc.set(cache_key_data, "DUMMY", self.FILE_CACHE_VALID) + shutil.copy(dst_path, cc.get_cache_path(cache_key_data)) + return dst_path + + @staticmethod + def unpack(source_path, dest_dir): + fu = FileUnpacker(source_path, dest_dir) + return fu.start() + def get_vcs_manifest_path(self, pkg_dir): for item in os.listdir(pkg_dir): if not isdir(join(pkg_dir, item)): @@ -142,7 +183,7 @@ class PkgInstallerMixin(object): def manifest_exists(self, pkg_dir): return self.get_manifest_path(pkg_dir) is not None - def load_manifest(self, path): + def load_manifest(self, path): # pylint: disable=too-many-branches assert path pkg_dir = path if isdir(path): @@ -155,6 +196,13 @@ class PkgInstallerMixin(object): if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): pkg_dir = dirname(dirname(path)) + # return from cache + if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: + for manifest in PkgInstallerMixin._INSTALLED_CACHE[self. + package_dir]: + if manifest['__pkg_dir'] == pkg_dir: + return manifest + manifest = {} if path.endswith(".json"): manifest = util.load_json(path) @@ -174,6 +222,22 @@ class PkgInstallerMixin(object): manifest['__pkg_dir'] = pkg_dir return manifest + def get_installed(self): + if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: + return PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] + items = [] + for p in sorted(os.listdir(self.package_dir)): + pkg_dir = join(self.package_dir, p) + if not isdir(pkg_dir): + continue + manifest = self.load_manifest(pkg_dir) + if not manifest: + continue + assert "name" in manifest + items.append(manifest) + PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] = items + return items + def check_pkg_structure(self, pkg_dir): if self.manifest_exists(pkg_dir): return pkg_dir @@ -305,11 +369,6 @@ class PkgInstallerMixin(object): class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): - _INSTALLED_CACHE = {} - - FILE_CACHE_VALID = "1m" # 1 month - FILE_CACHE_MAX_SIZE = 1024 * 1024 - def __init__(self, package_dir, repositories=None): self.repositories = repositories self.package_dir = package_dir @@ -321,42 +380,6 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): def manifest_names(self): raise NotImplementedError() - def download(self, url, dest_dir, sha1=None): - cache_key_fname = app.ContentCache.key_from_args(url, "fname") - cache_key_data = app.ContentCache.key_from_args(url, "data") - if self.FILE_CACHE_VALID: - with app.ContentCache() as cc: - fname = cc.get(cache_key_fname) - cache_path = cc.get_cache_path(cache_key_data) - if fname and isfile(cache_path): - dst_path = join(dest_dir, fname) - shutil.copy(cache_path, dst_path) - return dst_path - - fd = FileDownloader(url, dest_dir) - fd.start() - if sha1: - fd.verify(sha1) - dst_path = fd.get_filepath() - if not self.FILE_CACHE_VALID or getsize( - dst_path) > BasePkgManager.FILE_CACHE_MAX_SIZE: - return dst_path - - with app.ContentCache() as cc: - cc.set(cache_key_fname, basename(dst_path), self.FILE_CACHE_VALID) - cc.set(cache_key_data, "DUMMY", self.FILE_CACHE_VALID) - shutil.copy(dst_path, cc.get_cache_path(cache_key_data)) - return dst_path - - @staticmethod - def unpack(source_path, dest_dir): - fu = FileUnpacker(source_path, dest_dir) - return fu.start() - - def reset_cache(self): - if self.package_dir in BasePkgManager._INSTALLED_CACHE: - del BasePkgManager._INSTALLED_CACHE[self.package_dir] - def print_message(self, message, nl=True): click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl) @@ -415,22 +438,6 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): url = None return (name or text, requirements, url) - def get_installed(self): - if self.package_dir in BasePkgManager._INSTALLED_CACHE: - return BasePkgManager._INSTALLED_CACHE[self.package_dir] - items = [] - for p in sorted(os.listdir(self.package_dir)): - pkg_dir = join(self.package_dir, p) - if not isdir(pkg_dir): - continue - manifest = self.load_manifest(pkg_dir) - if not manifest: - continue - assert "name" in manifest - items.append(manifest) - BasePkgManager._INSTALLED_CACHE[self.package_dir] = items - return items - def get_package(self, name, requirements=None, url=None): pkg_id = int(name[3:]) if name.startswith("id=") else 0 best = None @@ -473,20 +480,38 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): package = self.get_package(name, requirements, url) return package.get("__pkg_dir") if package else None - def is_outdated(self, name, requirements=None, silent=False): - package_dir = self.get_package_dir(name, requirements) + def outdated(self, name, requirements=None, url=None): + """ + Has 3 different results: + `None` - unknown package, VCS is fixed to commit + `False` - package is up-to-date + `String` - a found latest version + """ + latest = None + package_dir = self.get_package_dir(name, requirements, url) if not package_dir: - if silent: - return - click.secho( - "%s @ %s is not installed" % (name, requirements or "*"), - fg="yellow") - return - if self.get_vcs_manifest_path(package_dir): - return False + return None manifest = self.load_manifest(package_dir) - latest = self.get_latest_repo_version(name, requirements) - return latest and manifest['version'] != latest + if self.get_vcs_manifest_path(package_dir): + vcs = VCSClientFactory.newClient( + package_dir, manifest['url'], silent=True) + if not vcs.can_be_updated: + return None + latest = vcs.get_latest_revision() + else: + try: + latest = self.get_latest_repo_version(name, requirements) + except (exception.PlatformioException, ValueError): + return None + if not latest: + return None + up_to_date = False + try: + up_to_date = (semantic_version.Version.coerce(manifest['version']) + >= semantic_version.Version.coerce(latest)) + except ValueError: + up_to_date = latest == manifest['version'] + return False if up_to_date else latest def install(self, name, @@ -571,7 +596,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): requirements=None, only_check=False): name, requirements, url = self.parse_pkg_name(name, requirements) - package_dir = self.get_package_dir(name, None, url) + package_dir = self.get_package_dir(name, requirements, url) if not package_dir: click.secho( "%s @ %s is not installed" % (name, requirements or "*"), @@ -587,16 +612,29 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): manifest = self.load_manifest(manifest_path) click.echo( - "%s %s @ %s: \t" % ("Checking" - if only_check else "Updating", click.style( - manifest['name'], fg="cyan"), - manifest['version']), + "{} {:<40} @ {:<15}".format( + "Checking" if only_check else "Updating", + click.style( + manifest['name'], fg="cyan"), + manifest['version']), nl=False) + if not util.internet_on(): + click.echo("[%s]" % (click.style("Off-line", fg="yellow"))) + return + latest = self.outdated(name, requirements, url) + if latest is True: + click.echo("[%s]" % (click.style("Out-of-date", fg="red"))) + elif latest: + click.echo("[%s]" % (click.style(latest, fg="red"))) + elif latest is False: + click.echo("[%s]" % (click.style("Up-to-date", fg="green"))) + else: + click.echo("[%s]" % (click.style("Unknown", fg="yellow"))) + + if only_check or latest is False or (not is_vcs_pkg and not latest): + return + if is_vcs_pkg: - if only_check: - click.echo("[%s]" % (click.style("Skip", fg="yellow"))) - return - click.echo("[%s]" % (click.style("VCS", fg="yellow"))) vcs = VCSClientFactory.newClient(package_dir, manifest['url']) if not vcs.can_be_updated: click.secho( @@ -608,36 +646,10 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): with open(manifest_path, "w") as fp: manifest['version'] = vcs.get_current_revision() json.dump(manifest, fp) + self.reset_cache() else: - latest_version = None - try: - latest_version = self.get_latest_repo_version(name, - requirements) - except exception.PlatformioException: - pass - if not latest_version: - click.echo("[%s]" % (click.style( - "Off-line" if not util.internet_on() else "Unknown", - fg="yellow"))) - return - - up_to_date = False - try: - up_to_date = ( - semantic_version.Version.coerce(manifest['version']) >= - semantic_version.Version.coerce(latest_version)) - except ValueError: - up_to_date = latest_version == manifest['version'] - - if up_to_date: - click.echo("[%s]" % (click.style("Up-to-date", fg="green"))) - return - - click.echo("[%s]" % (click.style("Out-of-date", fg="red"))) - if only_check: - return self.uninstall(name, manifest['version'], trigger_event=False) - self.install(name, latest_version, trigger_event=False) + self.install(name, latest, trigger_event=False) telemetry.on_event( category=self.__class__.__name__, diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 85d963a2..caf41b99 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -92,9 +92,10 @@ class PlatformManager(BasePkgManager): self.cleanup_packages(p.packages.keys()) return True - def is_outdated(self, name, requirements=None, silent=False): - if BasePkgManager.is_outdated(self, name, requirements, silent): - return True + def outdated(self, name, requirements=None, url=None): + latest = BasePkgManager.outdated(self, name, requirements, url) + if latest: + return latest p = PlatformFactory.newPlatform(name, requirements) return p.are_outdated_packages() @@ -213,7 +214,7 @@ class PlatformPackagesMixin(object): continue elif (name in with_packages or not (skip_default_package or opts.get("optional", False))): - if self.validate_version_requirements(version): + if self.is_valid_requirements(version): self.pm.install(name, version, silent=silent) else: requirements = None @@ -228,7 +229,7 @@ class PlatformPackagesMixin(object): items = {} for name, opts in self.packages.items(): version = opts.get("version", "") - if self.validate_version_requirements(version): + if self.is_valid_requirements(version): package = self.pm.get_package(name, version) else: package = self.pm.get_package(*self._parse_pkg_name(name, @@ -240,7 +241,7 @@ class PlatformPackagesMixin(object): def update_packages(self, only_check=False): for name in self.get_installed_packages(): version = self.packages[name].get("version", "") - if self.validate_version_requirements(version): + if self.is_valid_requirements(version): self.pm.update(name, version, only_check) else: requirements = None @@ -250,17 +251,23 @@ class PlatformPackagesMixin(object): only_check) def are_outdated_packages(self): - for name, opts in self.packages.items(): - version = opts.get("version", "") - if not self.validate_version_requirements(version): - continue - if self.pm.is_outdated(name, version, silent=True): + latest = None + for name in self.get_installed_packages(): + version = self.packages[name].get("version", "") + if self.is_valid_requirements(version): + latest = self.pm.outdated(name, version) + else: + requirements = None + if "@" in version: + version, requirements = version.rsplit("@", 1) + latest = self.pm.outdated(name, requirements, version) + if latest or latest is None: return True return False def get_package_dir(self, name): version = self.packages[name].get("version", "") - if self.validate_version_requirements(version): + if self.is_valid_requirements(version): return self.pm.get_package_dir(name, version) else: return self.pm.get_package_dir(*self._parse_pkg_name(name, @@ -268,14 +275,14 @@ class PlatformPackagesMixin(object): def get_package_version(self, name): version = self.packages[name].get("version", "") - if self.validate_version_requirements(version): + if self.is_valid_requirements(version): package = self.pm.get_package(name, version) else: package = self.pm.get_package(*self._parse_pkg_name(name, version)) return package['version'] if package else None @staticmethod - def validate_version_requirements(requirements): + def is_valid_requirements(requirements): return requirements and "://" not in requirements def _parse_pkg_name(self, name, version): diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index b06df1f3..a5bba681 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -25,7 +25,7 @@ from platformio.exception import PlatformioException class VCSClientFactory(object): @staticmethod - def newClient(src_dir, remote_url): + def newClient(src_dir, remote_url, silent=False): result = urlparse(remote_url) type_ = result.scheme tag = None @@ -40,7 +40,7 @@ class VCSClientFactory(object): raise PlatformioException("VCS: Unknown repository type %s" % remote_url) obj = getattr(modules[__name__], "%sClient" % type_.title())( - src_dir, remote_url, tag) + src_dir, remote_url, tag, silent) assert isinstance(obj, VCSClientBase) return obj @@ -49,17 +49,21 @@ class VCSClientBase(object): command = None - def __init__(self, src_dir, remote_url=None, tag=None): + def __init__(self, src_dir, remote_url=None, tag=None, silent=False): self.src_dir = src_dir self.remote_url = remote_url self.tag = tag + self.silent = silent self.check_client() def check_client(self): try: assert self.command - assert self.run_cmd(["--version"]) - except (AssertionError, OSError): + if self.silent: + self.get_cmd_output(["--version"]) + else: + assert self.run_cmd(["--version"]) + except (AssertionError, OSError, PlatformioException): raise PlatformioException( "VCS: `%s` client is not installed in your system" % self.command) @@ -82,6 +86,9 @@ class VCSClientBase(object): def get_current_revision(self): raise NotImplementedError + def get_latest_revision(self): + return None if self.can_be_updated else self.get_current_revision() + def run_cmd(self, args, **kwargs): args = [self.command] + args if "cwd" not in kwargs: @@ -141,6 +148,16 @@ class GitClient(VCSClientBase): def get_current_revision(self): return self.get_cmd_output(["rev-parse", "--short", "HEAD"]) + def get_latest_revision(self): + if not self.can_be_updated: + return self.get_latest_revision() + result = self.get_cmd_output(["ls-remote"]) + for line in result.split("\n"): + line = line.strip() + if "HEAD" in line: + return line.split("HEAD", 1)[0].strip()[:7] + return None + class HgClient(VCSClientBase): @@ -160,6 +177,11 @@ class HgClient(VCSClientBase): def get_current_revision(self): return self.get_cmd_output(["identify", "--id"]) + def get_latest_revision(self): + if not self.can_be_updated: + return self.get_latest_revision() + return self.get_cmd_output(["identify", "--id", self.remote_url]) + class SvnClient(VCSClientBase): From 1d1c677c816c4a86c13b0e84b0533c6927ad386b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 30 Jan 2017 15:03:08 +0200 Subject: [PATCH 063/127] Update Quick Start for PIO Remote --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index d019f410..8b01eca1 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit d019f41070f64d026b80c9cc612015c5b16d1cda +Subproject commit 8b01eca1bf01c0e1fecf5d443f519cbb6006400a From 11430122161111a3e7fcdb24ff1e35333cb0cc6a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 30 Jan 2017 20:21:16 +0200 Subject: [PATCH 064/127] Improve Package Manager when check for updates // Resolve #892 --- platformio/__init__.py | 2 +- platformio/managers/lib.py | 5 +- platformio/managers/package.py | 23 ++++-- platformio/vcsclient.py | 15 +++- tests/commands/test_lib.py | 18 +++- tests/commands/test_platform.py | 141 +++++++++++++------------------- tests/test_maintenance.py | 7 +- 7 files changed, 111 insertions(+), 100 deletions(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index 87c5830d..b62446a4 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a8") +VERSION = (3, 3, "0a9") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 92e57a11..ee7b9019 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -212,10 +212,11 @@ class LibraryManager(BasePkgManager): item = v return item - def get_latest_repo_version(self, name, requirements): + def get_latest_repo_version(self, name, requirements, silent=False): item = self.max_satisfying_repo_version( util.get_api_result( - "/lib/info/%d" % self.get_pkg_id_by_name(name, requirements), + "/lib/info/%d" % self.get_pkg_id_by_name( + name, requirements, silent=silent), cache_valid="1d")['versions'], requirements) return item['name'] if item else None diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 10b0cd18..7b5768af 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -103,7 +103,11 @@ class PkgRepoMixin(object): item = v return item - def get_latest_repo_version(self, name, requirements): + def get_latest_repo_version( # pylint: disable=unused-argument + self, + name, + requirements, + silent=False): version = None for versions in PackageRepoIterator(name, self.repositories): pkgdata = self.max_satisfying_repo_version(versions, requirements) @@ -193,14 +197,16 @@ class PkgInstallerMixin(object): else: pkg_dir = dirname(pkg_dir) + is_vcs_pkg = False if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): + is_vcs_pkg = True pkg_dir = dirname(dirname(path)) # return from cache if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: for manifest in PkgInstallerMixin._INSTALLED_CACHE[self. package_dir]: - if manifest['__pkg_dir'] == pkg_dir: + if not is_vcs_pkg and manifest['__pkg_dir'] == pkg_dir: return manifest manifest = {} @@ -491,8 +497,14 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): package_dir = self.get_package_dir(name, requirements, url) if not package_dir: return None - manifest = self.load_manifest(package_dir) - if self.get_vcs_manifest_path(package_dir): + is_vcs_pkg = False + manifest_path = self.get_vcs_manifest_path(package_dir) + if manifest_path: + is_vcs_pkg = True + manifest = self.load_manifest(manifest_path) + else: + manifest = self.load_manifest(package_dir) + if is_vcs_pkg: vcs = VCSClientFactory.newClient( package_dir, manifest['url'], silent=True) if not vcs.can_be_updated: @@ -500,7 +512,8 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): latest = vcs.get_latest_revision() else: try: - latest = self.get_latest_repo_version(name, requirements) + latest = self.get_latest_repo_version( + name, requirements, silent=True) except (exception.PlatformioException, ValueError): return None if not latest: diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index a5bba681..59710802 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -116,6 +116,14 @@ class GitClient(VCSClientBase): output = output.replace("*", "") # fix active branch return [b.strip() for b in output.split("\n")] + def get_current_branch(self): + output = self.get_cmd_output(["branch"]) + for line in output.split("\n"): + line = line.strip() + if line.startswith("*"): + return line[1:].strip() + return None + def get_tags(self): output = self.get_cmd_output(["tag", "-l"]) return [t.strip() for t in output.split("\n")] @@ -151,11 +159,12 @@ class GitClient(VCSClientBase): def get_latest_revision(self): if not self.can_be_updated: return self.get_latest_revision() + branch = self.get_current_branch() result = self.get_cmd_output(["ls-remote"]) for line in result.split("\n"): - line = line.strip() - if "HEAD" in line: - return line.split("HEAD", 1)[0].strip()[:7] + ref_pos = line.strip().find("refs/heads/" + branch) + if ref_pos > 0: + return line[:ref_pos].strip()[:7] return None diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 47217262..c956049c 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -100,10 +100,21 @@ def test_global_lib_list(clirunner, validate_cliresult, isolated_pio_home): assert set(items1) == set(items2) +def test_global_lib_update_check(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke( + cmd_lib, ["-g", "update", "--only-check", "--json-output"]) + validate_cliresult(result) + output = json.loads(result.output) + assert set(["PJON", "RadioHead"]) == set([l['name'] for l in output]) + + def test_global_lib_update(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["-g", "update"]) validate_cliresult(result) - assert all([s in result.output for s in ("[Up-to-date]", "[VCS]")]) + assert "[Up-to-date]" in result.output + assert re.search(r"Updating PJON\s+@ 1fb26fd\s+\[[a-z\d]{7}\]", + result.output) def test_global_lib_uninstall(clirunner, validate_cliresult, @@ -124,9 +135,8 @@ def test_global_lib_uninstall(clirunner, validate_cliresult, def test_lib_show(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["show", "64"]) validate_cliresult(result) - assert all([ - s in result.output for s in ("ArduinoJson", "Arduino", "Atmel AVR") - ]) + assert all( + [s in result.output for s in ("ArduinoJson", "Arduino", "Atmel AVR")]) result = clirunner.invoke(cmd_lib, ["show", "OneWire"]) validate_cliresult(result) assert "OneWire" in result.output diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index 57706370..e6c34011 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -13,30 +13,12 @@ # limitations under the License. import json -import os -from os.path import join -from platformio import exception, util +from platformio import exception from platformio.commands import platform as cli_platform -def test_list_json_output(clirunner, validate_cliresult): - result = clirunner.invoke(cli_platform.platform_list, ["--json-output"]) - validate_cliresult(result) - list_result = json.loads(result.output) - assert isinstance(list_result, list) - assert len(list_result) - platforms = [item['name'] for item in list_result] - assert "titiva" in platforms - - -def test_list_raw_output(clirunner, validate_cliresult): - result = clirunner.invoke(cli_platform.platform_list) - validate_cliresult(result) - assert "teensy" in result.output - - -def test_search_json_output(clirunner, validate_cliresult): +def test_search_json_output(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cli_platform.platform_search, ["arduino", "--json-output"]) validate_cliresult(result) @@ -47,82 +29,75 @@ def test_search_json_output(clirunner, validate_cliresult): assert "atmelsam" in platforms -def test_search_raw_output(clirunner, validate_cliresult): +def test_search_raw_output(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cli_platform.platform_search, ["arduino"]) validate_cliresult(result) assert "teensy" in result.output -def test_install_uknown_from_registry(clirunner, validate_cliresult): - result = clirunner.invoke(cli_platform.platform_install, - ["uknown-platform"]) - assert result.exit_code == -1 - assert isinstance(result.exception, exception.UnknownPackage) - - -def test_install_from_vcs(clirunner, validate_cliresult): - result = clirunner.invoke(cli_platform.platform_install, [ - "https://github.com/platformio/" - "platform-espressif8266.git#feature/stage" - ]) - validate_cliresult(result) - assert "espressif8266_stage" in result.output - - -def test_install_uknown_version(clirunner, validate_cliresult): +def test_install_unknown_version(clirunner, validate_cliresult, + isolated_pio_home): result = clirunner.invoke(cli_platform.platform_install, ["atmelavr@99.99.99"]) assert result.exit_code == -1 assert isinstance(result.exception, exception.UndefinedPackageVersion) -def test_complex(clirunner, validate_cliresult): - with clirunner.isolated_filesystem(): - os.environ["PLATFORMIO_HOME_DIR"] = os.getcwd() - try: - result = clirunner.invoke( - cli_platform.platform_install, - ["teensy", "--with-package", "framework-arduinoteensy"]) - validate_cliresult(result) - assert all([ - s in result.output - for s in ("teensy", "Downloading", "Unpacking") - ]) +def test_install_unknown_from_registry(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_install, + ["unknown-platform"]) + assert result.exit_code == -1 + assert isinstance(result.exception, exception.UnknownPackage) - # show platform information - result = clirunner.invoke(cli_platform.platform_show, ["teensy"]) - validate_cliresult(result) - assert "teensy" in result.output - # list platforms - result = clirunner.invoke(cli_platform.platform_list, - ["--json-output"]) - validate_cliresult(result) - list_result = json.loads(result.output) - assert isinstance(list_result, list) - assert len(list_result) == 1 - assert list_result[0]["name"] == "teensy" - assert list_result[0]["packages"] == ["framework-arduinoteensy"] +def test_install_known_version(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_install, + ["atmelavr@1.1.0", "--skip-default-package"]) + validate_cliresult(result) + assert "atmelavr @ 1.1.0" in result.output - # try to install again - result = clirunner.invoke(cli_platform.platform_install, - ["teensy"]) - validate_cliresult(result) - assert "is already installed" in result.output - # try to update - for _ in range(2): - result = clirunner.invoke(cli_platform.platform_update) - validate_cliresult(result) - assert "teensy" in result.output - assert "Up-to-date" in result.output - assert "Out-of-date" not in result.output +def test_install_from_vcs(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_install, [ + "https://github.com/platformio/" + "platform-espressif8266.git#feature/stage", "--skip-default-package" + ]) + validate_cliresult(result) + assert "espressif8266_stage" in result.output - # try to uninstall - result = clirunner.invoke(cli_platform.platform_uninstall, - ["teensy"]) - validate_cliresult(result) - for folder in ("platforms", "packages"): - assert len(os.listdir(join(util.get_home_dir(), folder))) == 0 - finally: - del os.environ["PLATFORMIO_HOME_DIR"] + +def test_list_json_output(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_list, ["--json-output"]) + validate_cliresult(result) + list_result = json.loads(result.output) + assert isinstance(list_result, list) + assert len(list_result) + platforms = [item['name'] for item in list_result] + assert set(["atmelavr", "espressif8266_stage"]) == set(platforms) + + +def test_list_raw_output(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_list) + validate_cliresult(result) + assert all( + [s in result.output for s in ("atmelavr", "espressif8266_stage")]) + + +def test_update_check(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_update, + ["--only-check", "--json-output"]) + validate_cliresult(result) + output = json.loads(result.output) + assert len(output) == 1 + assert output[0]['name'] == "atmelavr" + + +def test_uninstall(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_uninstall, + ["atmelavr", "espressif8266_stage"]) + validate_cliresult(result) + assert len( + [d.basename + for d in isolated_pio_home.join("platforms").listdir()]) == 0 diff --git a/tests/test_maintenance.py b/tests/test_maintenance.py index d0dd0fd5..ba4e2796 100644 --- a/tests/test_maintenance.py +++ b/tests/test_maintenance.py @@ -13,6 +13,7 @@ # limitations under the License. import json +import re from time import time from platformio import app, maintenance @@ -135,7 +136,8 @@ def test_check_and_update_libraries(clirunner, validate_cliresult, assert ("There are the new updates for libraries (ArduinoJson)" in result.output) assert "Please wait while updating libraries" in result.output - assert "[Out-of-date]" in result.output + assert re.search(r"Updating ArduinoJson\s+@ 5.6.7\s+\[[\d\.]+\]", + result.output) # check updated version result = clirunner.invoke(cli_pio, ["lib", "-g", "list", "--json-output"]) @@ -188,7 +190,8 @@ def test_check_and_update_platforms(clirunner, validate_cliresult, validate_cliresult(result) assert "There are the new updates for platforms (native)" in result.output assert "Please wait while updating platforms" in result.output - assert "[Out-of-date]" in result.output + assert re.search(r"Updating native\s+@ 0.0.0\s+\[[\d\.]+\]", + result.output) # check updated version result = clirunner.invoke(cli_pio, ["platform", "list", "--json-output"]) From 916f4b071c5bfc20e6821883c9f492885813751c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 30 Jan 2017 22:36:25 +0200 Subject: [PATCH 065/127] =?UTF-8?q?Don=E2=80=99t=20check=20packages=20when?= =?UTF-8?q?=20check=20platform=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/commands/platform.py | 5 +---- platformio/managers/package.py | 6 ++--- platformio/managers/platform.py | 39 +++++++++++++++++++++++---------- tests/commands/test_platform.py | 21 +++++++++++++----- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 4f493229..c8bb3374 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -137,10 +137,7 @@ def platform_update(platforms, only_packages, only_check, json_output): continue manifest = pm.load_manifest( pm.get_package_dir(name, requirements, url)) - if latest is True: - manifest['versionLatest'] = "Out-of-date" - else: - manifest['versionLatest'] = latest or "Unknown" + manifest['versionLatest'] = latest or "Unknown" result.append(manifest) return click.echo(json.dumps(result)) else: diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 7b5768af..a38fe067 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -635,9 +635,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): click.echo("[%s]" % (click.style("Off-line", fg="yellow"))) return latest = self.outdated(name, requirements, url) - if latest is True: - click.echo("[%s]" % (click.style("Out-of-date", fg="red"))) - elif latest: + if latest: click.echo("[%s]" % (click.style(latest, fg="red"))) elif latest is False: click.echo("[%s]" % (click.style("Up-to-date", fg="green"))) @@ -659,11 +657,11 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): with open(manifest_path, "w") as fp: manifest['version'] = vcs.get_current_revision() json.dump(manifest, fp) - self.reset_cache() else: self.uninstall(name, manifest['version'], trigger_event=False) self.install(name, latest, trigger_event=False) + self.reset_cache() telemetry.on_event( category=self.__class__.__name__, action="Update", diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index caf41b99..b1b34414 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -60,9 +60,16 @@ class PlatformManager(BasePkgManager): with_packages=None, without_packages=None, skip_default_package=False, + trigger_event=True, **_): # pylint: disable=too-many-arguments platform_dir = BasePkgManager.install(self, name, requirements) p = PlatformFactory.newPlatform(self.get_manifest_path(platform_dir)) + + # @Hook: when 'update' operation (trigger_event is False), + # don't cleanup packages or install them + if not trigger_event: + return True + p.install_packages(with_packages, without_packages, skip_default_package) self.cleanup_packages(p.packages.keys()) @@ -72,10 +79,13 @@ class PlatformManager(BasePkgManager): name, requirements, _ = self.parse_pkg_name(name, requirements) p = PlatformFactory.newPlatform(name, requirements) BasePkgManager.uninstall(self, name, requirements) - # trigger event is disabled when upgrading operation - # don't cleanup packages, "install" will do that - if trigger_event: - self.cleanup_packages(p.packages.keys()) + + # @Hook: when 'update' operation (trigger_event is False), + # don't cleanup packages or install them + if not trigger_event: + return True + + self.cleanup_packages(p.packages.keys()) return True def update( # pylint: disable=arguments-differ @@ -85,19 +95,24 @@ class PlatformManager(BasePkgManager): only_packages=False, only_check=False): name, requirements, _ = self.parse_pkg_name(name, requirements) + + p = PlatformFactory.newPlatform(name, requirements) + pkgs_before = pkgs_after = p.get_installed_packages().keys() + if not only_packages: BasePkgManager.update(self, name, requirements, only_check) - p = PlatformFactory.newPlatform(name, requirements) + p = PlatformFactory.newPlatform(name, requirements) + pkgs_after = p.get_installed_packages().keys() + p.update_packages(only_check) self.cleanup_packages(p.packages.keys()) - return True - def outdated(self, name, requirements=None, url=None): - latest = BasePkgManager.outdated(self, name, requirements, url) - if latest: - return latest - p = PlatformFactory.newPlatform(name, requirements) - return p.are_outdated_packages() + pkgs_missed = set(pkgs_before) - set(pkgs_after) + if pkgs_missed: + p.install_packages( + with_packages=pkgs_missed, skip_default_package=True) + + return True def cleanup_packages(self, names): self.reset_cache() diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index e6c34011..fe29ce58 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -53,10 +53,14 @@ def test_install_unknown_from_registry(clirunner, validate_cliresult, def test_install_known_version(clirunner, validate_cliresult, isolated_pio_home): - result = clirunner.invoke(cli_platform.platform_install, - ["atmelavr@1.1.0", "--skip-default-package"]) + result = clirunner.invoke(cli_platform.platform_install, [ + "atmelavr@1.1.0", "--skip-default-package", "--with-package", + "tool-avrdude" + ]) validate_cliresult(result) assert "atmelavr @ 1.1.0" in result.output + assert "Installing tool-avrdude @" in result.output + assert len(isolated_pio_home.join("packages").listdir()) == 1 def test_install_from_vcs(clirunner, validate_cliresult, isolated_pio_home): @@ -92,12 +96,19 @@ def test_update_check(clirunner, validate_cliresult, isolated_pio_home): output = json.loads(result.output) assert len(output) == 1 assert output[0]['name'] == "atmelavr" + assert len(isolated_pio_home.join("packages").listdir()) == 1 + + +def test_update_raw(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli_platform.platform_update) + validate_cliresult(result) + assert "Uninstalling atmelavr @ 1.1.0:" in result.output + assert "PlatformManager: Installing atmelavr @" in result.output + assert len(isolated_pio_home.join("packages").listdir()) == 1 def test_uninstall(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cli_platform.platform_uninstall, ["atmelavr", "espressif8266_stage"]) validate_cliresult(result) - assert len( - [d.basename - for d in isolated_pio_home.join("platforms").listdir()]) == 0 + assert len(isolated_pio_home.join("platforms").listdir()) == 0 From b5482db58149735d2ce7ef5620e38076d6c010fe Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 30 Jan 2017 23:54:55 +0200 Subject: [PATCH 066/127] =?UTF-8?q?Don=E2=80=99t=20check=20for=20updates?= =?UTF-8?q?=20tagged=20VCS=20repo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/vcsclient.py | 8 ++++++-- tests/commands/test_lib.py | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index 59710802..4b43e0a5 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -121,7 +121,9 @@ class GitClient(VCSClientBase): for line in output.split("\n"): line = line.strip() if line.startswith("*"): - return line[1:].strip() + branch = line[1:].strip() + if branch != "(no branch)": + return branch return None def get_tags(self): @@ -158,8 +160,10 @@ class GitClient(VCSClientBase): def get_latest_revision(self): if not self.can_be_updated: - return self.get_latest_revision() + return self.get_current_revision() branch = self.get_current_branch() + if not branch: + return self.get_current_revision() result = self.get_cmd_output(["ls-remote"]) for line in result.split("\n"): ref_pos = line.strip().find("refs/heads/" + branch) diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index c956049c..264a62ef 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -39,7 +39,7 @@ def test_global_install_registry(clirunner, validate_cliresult, result = clirunner.invoke(cmd_lib, [ "-g", "install", "58", "OneWire", "http://dl.platformio.org/libraries/archives/3/5174.tar.gz", - "ArduinoJson@5.6.7", "ArduinoJson@>5.6" + "ArduinoJson@5.6.7", "ArduinoJson@~5.7.0" ]) validate_cliresult(result) items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] @@ -106,15 +106,15 @@ def test_global_lib_update_check(clirunner, validate_cliresult, cmd_lib, ["-g", "update", "--only-check", "--json-output"]) validate_cliresult(result) output = json.loads(result.output) - assert set(["PJON", "RadioHead"]) == set([l['name'] for l in output]) + assert set(["ArduinoJson", "RadioHead"]) == set( + [l['name'] for l in output]) def test_global_lib_update(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["-g", "update"]) validate_cliresult(result) assert "[Up-to-date]" in result.output - assert re.search(r"Updating PJON\s+@ 1fb26fd\s+\[[a-z\d]{7}\]", - result.output) + assert "Uninstalling ArduinoJson @ 5.7.3" in result.output def test_global_lib_uninstall(clirunner, validate_cliresult, From d99ae7b1a33d09418cc99023814cd5b5621e1c84 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 31 Jan 2017 01:02:41 +0200 Subject: [PATCH 067/127] Bump new alpha 10 --- platformio/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index b62446a4..5692677f 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a9") +VERSION = (3, 3, "0a10") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" From cbb46fe7b6c4f822aa83ece7931607596b2af922 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 31 Jan 2017 01:58:10 +0200 Subject: [PATCH 068/127] Fix PEP to SemVer converting --- platformio/maintenance.py | 4 ++-- platformio/util.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index cd1e3562..b9ccf050 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -98,8 +98,8 @@ class Upgrader(object): util.pepver_to_semver(to_version)) self._upgraders = [ - (semantic_version.Version("3.0.0-a1"), self._upgrade_to_3_0_0), - (semantic_version.Version("3.0.0-b11"), self._upgrade_to_3_0_0) + (semantic_version.Version("3.0.0-a.1"), self._upgrade_to_3_0_0), + (semantic_version.Version("3.0.0-b.11"), self._upgrade_to_3_0_0) ] def run(self, ctx): diff --git a/platformio/util.py b/platformio/util.py index b3406dbf..46c11965 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -558,7 +558,7 @@ def where_is_program(program, envpath=None): def pepver_to_semver(pepver): - return re.sub(r"(\.\d+)\.?(dev|a|b|rc|post)", r"\1-\2", pepver, 1) + return re.sub(r"(\.\d+)\.?(dev|a|b|rc|post)", r"\1-\2.", pepver, 1) def rmtree_(path): From ba58b4ba8a8813dbb9d917f1f5ffd98e66965c0c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 1 Feb 2017 00:58:12 +0200 Subject: [PATCH 069/127] Skip bad requests --- platformio/telemetry.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/platformio/telemetry.py b/platformio/telemetry.py index f0ba2922..b35ea2d9 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -227,8 +227,13 @@ class MPDataPusher(object): timeout=1) r.raise_for_status() return True + except requests.exceptions.HTTPError as e: + # skip Bad Request + if 400 >= e.response.status_code < 500: + return True except: # pylint: disable=W0702 - self._http_offline = True + pass + self._http_offline = True return False @@ -304,7 +309,8 @@ def on_exception(e): "Error" in e.__class__.__name__ ]) mp = MeasurementProtocol() - mp['exd'] = "%s: %s" % (type(e).__name__, format_exc() if is_crash else e) + mp['exd'] = ("%s: %s" % (type(e).__name__, format_exc() + if is_crash else e))[:150] mp['exf'] = 1 if is_crash else 0 mp.send("exception") From 3d6dab39ca4331f9f4e278025dc750643e0f608b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 1 Feb 2017 02:49:25 +0200 Subject: [PATCH 070/127] Minor fixes for content cacher --- platformio/app.py | 17 +++++++++-------- platformio/maintenance.py | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/platformio/app.py b/platformio/app.py index dfefb858..b1017b16 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -137,8 +137,6 @@ class ContentCache(object): return self.cache_dir = cache_dir or join(util.get_home_dir(), ".cache") - if not self.cache_dir: - os.makedirs(self.cache_dir) self._db_path = join(self.cache_dir, "db.data") def __enter__(self): @@ -152,7 +150,7 @@ class ContentCache(object): continue line = line.strip() expire, path = line.split("=") - if time() < int(expire): + if time() < int(expire) and isfile(path): newlines.append(line) continue found = True @@ -172,6 +170,8 @@ class ContentCache(object): pass def _lock_dbindex(self): + if not self.cache_dir: + os.makedirs(self.cache_dir) self._lockfile = LockFile(self.cache_dir) if self._lockfile.is_locked() and \ (time() - getmtime(self._lockfile.lock_file)) > 10: @@ -200,8 +200,6 @@ class ContentCache(object): return h.hexdigest() def get(self, key): - if not self.cache_dir: - return None cache_path = self.get_cache_path(key) if not isfile(cache_path): return None @@ -212,7 +210,7 @@ class ContentCache(object): return data def set(self, key, data, valid): - if not self.cache_dir or not data: + if not data: return if not isdir(self.cache_dir): os.makedirs(self.cache_dir) @@ -238,8 +236,11 @@ class ContentCache(object): return True def clean(self): - if self.cache_dir and isdir(self.cache_dir): - util.rmtree_(self.cache_dir) + if not self.cache_dir or not isdir(self.cache_dir): + return + if not self._lock_dbindex(): + return + util.rmtree_(self.cache_dir) def sanitize_setting(name, value): diff --git a/platformio/maintenance.py b/platformio/maintenance.py index b9ccf050..df74231f 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -64,7 +64,7 @@ def on_platformio_start(ctx, force, caller): app.set_session_var("caller_id", caller) telemetry.on_command() - if ctx.args and (ctx.args[0] == "upgrade" or "update" in ctx.args): + if ctx.args and ctx.args[0] == "upgrade": clean_cache() if not in_silence(ctx): after_upgrade(ctx) From 50dc608456e17696e630b5a1393553196bf9bebb Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 1 Feb 2017 14:52:32 +0200 Subject: [PATCH 071/127] Cleanup cache on platform update --- platformio/app.py | 5 +++++ platformio/commands/platform.py | 7 +++++-- platformio/maintenance.py | 9 ++------- platformio/managers/platform.py | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/platformio/app.py b/platformio/app.py index b1017b16..4104dae4 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -243,6 +243,11 @@ class ContentCache(object): util.rmtree_(self.cache_dir) +def clean_cache(): + with ContentCache() as cc: + cc.clean() + + def sanitize_setting(name, value): if name not in DEFAULT_SETTINGS: raise InvalidSettingName(name) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index c8bb3374..b5a46625 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -16,7 +16,7 @@ import json import click -from platformio import exception, util +from platformio import app, exception, util from platformio.managers.platform import PlatformFactory, PlatformManager @@ -48,7 +48,7 @@ def _print_platforms(platforms): @click.option("--json-output", is_flag=True) def platform_search(query, json_output): platforms = [] - for platform in util.get_api_result("/platforms", cache_valid="365d"): + for platform in util.get_api_result("/platforms", cache_valid="30d"): if query == "all": query = "" @@ -116,6 +116,9 @@ def platform_uninstall(platforms): help="Do not update, only check for new version") @click.option("--json-output", is_flag=True) def platform_update(platforms, only_packages, only_check, json_output): + # cleanup cached board and platform lists + app.clean_cache() + pm = PlatformManager() if not platforms: platforms = [] diff --git a/platformio/maintenance.py b/platformio/maintenance.py index df74231f..afe3cd23 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -42,11 +42,6 @@ def in_silence(ctx=None): (ctx.args[0] == "upgrade" or "--json-output" in ctx_args)) -def clean_cache(): - with app.ContentCache() as cc: - cc.clean() - - def on_platformio_start(ctx, force, caller): if not caller: if getenv("PLATFORMIO_CALLER"): @@ -65,7 +60,7 @@ def on_platformio_start(ctx, force, caller): telemetry.on_command() if ctx.args and ctx.args[0] == "upgrade": - clean_cache() + app.clean_cache() if not in_silence(ctx): after_upgrade(ctx) @@ -160,7 +155,7 @@ def after_upgrade(ctx): app.set_state_item("last_version", __version__) else: click.secho("Please wait while upgrading PlatformIO ...", fg="yellow") - clean_cache() + app.clean_cache() u = Upgrader(last_version, __version__) if u.run(ctx): app.set_state_item("last_version", __version__) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index b1b34414..ac5cfd58 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -149,7 +149,7 @@ class PlatformManager(BasePkgManager): @staticmethod @util.memoized def get_registered_boards(): - return util.get_api_result("/boards", cache_valid="365d") + return util.get_api_result("/boards", cache_valid="30d") def board_config(self, id_): for manifest in self.get_installed_boards(): From 20d9f7dae7c39d761ec6af0122d7025ca320c5f8 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 1 Feb 2017 19:07:53 +0200 Subject: [PATCH 072/127] =?UTF-8?q?Don=E2=80=99t=20return=20something=20wh?= =?UTF-8?q?en=20can=E2=80=99t=20retrieve=20latest=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/commands/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 0e75548d..ab097e6c 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -135,7 +135,7 @@ def lib_update(lm, libraries, only_check, json_output): continue manifest = lm.load_manifest( lm.get_package_dir(name, requirements, url)) - manifest['versionLatest'] = latest or "Unknown" + manifest['versionLatest'] = latest result.append(manifest) return click.echo(json.dumps(result)) else: From 84d5fbcfe50ee719faa5e8156e317de4fce57cf3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Feb 2017 02:52:07 +0200 Subject: [PATCH 073/127] =?UTF-8?q?Don=E2=80=99t=20lock=20cache=20director?= =?UTF-8?q?y=20while=20cleaning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/app.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/platformio/app.py b/platformio/app.py index 4104dae4..e6cbc0b2 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -238,8 +238,6 @@ class ContentCache(object): def clean(self): if not self.cache_dir or not isdir(self.cache_dir): return - if not self._lock_dbindex(): - return util.rmtree_(self.cache_dir) From c03d7bd1c42af7582f388350c6eb554c020098b4 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Feb 2017 13:44:52 +0200 Subject: [PATCH 074/127] Cleanup check only on `update` command --- platformio/maintenance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index afe3cd23..72614271 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -59,7 +59,7 @@ def on_platformio_start(ctx, force, caller): app.set_session_var("caller_id", caller) telemetry.on_command() - if ctx.args and ctx.args[0] == "upgrade": + if ctx.args and ctx.args[0] == "update": app.clean_cache() if not in_silence(ctx): after_upgrade(ctx) From ec88b719f64123f7bd29f6a15776326d0f651d9d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Feb 2017 17:35:05 +0200 Subject: [PATCH 075/127] Add info about ability to ignore built-in mbed libraries --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 8b01eca1..8960db2c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 8b01eca1bf01c0e1fecf5d443f519cbb6006400a +Subproject commit 8960db2c7d840b3f02912b3c3fa1f5c4b0f071c5 From b3ee14bf558dc1b3d1d260457f27e88a912bb173 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Feb 2017 17:39:08 +0200 Subject: [PATCH 076/127] Add example with ignoring mbed-fs --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 8960db2c..a76bcca2 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 8960db2c7d840b3f02912b3c3fa1f5c4b0f071c5 +Subproject commit a76bcca289b84db4ef49185ea444934ebbc48faa From e180f1cf4588d83c5376727938a8927a5fc9da7f Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 4 Feb 2017 17:14:42 +0200 Subject: [PATCH 077/127] =?UTF-8?q?Add=20example=20with=20=E2=80=9Clib=5Fe?= =?UTF-8?q?xtra=5Fdirs=E2=80=9D=20for=20Windows=20to=20platformio.ini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index a76bcca2..fb310a5c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a76bcca289b84db4ef49185ea444934ebbc48faa +Subproject commit fb310a5c739bc66b55f4b9ce2becf83b36f61c5b From 6ede03f880c554e2185adda5610b22b901225361 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 10 Feb 2017 12:50:42 +0200 Subject: [PATCH 078/127] Explain how to uninstall Atom with PlatformIO IDE --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index fb310a5c..84b8931f 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit fb310a5c739bc66b55f4b9ce2becf83b36f61c5b +Subproject commit 84b8931f93bd90cb0a612f2bc091dacaa62a1fb6 From ea6bf48b3d5f7fd5a1940b4d8a9a9908318c8389 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 18 Feb 2017 15:15:36 +0200 Subject: [PATCH 079/127] Fix Shippable link in a history --- HISTORY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 71904a01..2b13a6e4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1128,7 +1128,7 @@ PlatformIO 2.0 development platform (`issue #226 `_) * Integrate PlatformIO with `Circle CI `_ and - `Shippable CI `_ + `Shippable CI `_ * Described in documentation how to `create/register own board `_ for PlatformIO * Disabled "nano.specs" for ARM-based platforms (`issue #219 `_) From c098b8bbcaaa7f4683a0c56b1a0c5352f0623e97 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 18 Feb 2017 17:38:45 +0200 Subject: [PATCH 080/127] Fix incorrect example with library dependencies using GIT url and branch/tag/commit // Resolve #902 --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 84b8931f..3fa11c3c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 84b8931f93bd90cb0a612f2bc091dacaa62a1fb6 +Subproject commit 3fa11c3cca33a9ab7a8469b69141ee49bb2100a2 From 2467d5a5d097d583fffeef78eb2e027d50a745d2 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 18 Feb 2017 18:28:05 +0200 Subject: [PATCH 081/127] Do not overwrite project configuration variables when system environment variables are set --- HISTORY.rst | 4 +++- platformio/__init__.py | 2 +- platformio/builder/main.py | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 2b13a6e4..119c651f 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -34,6 +34,8 @@ PlatformIO 3.0 * Use C++11 by default for CLion IDE based projects (`pull #873 `_) * Escape project path when Glob matching is used +* Do not overwrite project configuration variables when system environment + variables are set * Fixed package installing with VCS branch for Python 2.7.3 (`issue #885 `_) @@ -68,7 +70,7 @@ PlatformIO 3.0 * Development platform `Linux ARM `__ - + Added support for Samsung ARTIK boards (520, 710, 1020) and ARTIK SDK + + Added support for Samsung ARTIK boards (520, 530, 710, 1020) and ARTIK SDK (`issue #353 `_) * Development platform `Nordic nRF51 `__ diff --git a/platformio/__init__.py b/platformio/__init__.py index 5692677f..847dc6e1 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a10") +VERSION = (3, 3, "0a11") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 13201f48..5fbc2174 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -117,8 +117,13 @@ elif not int(ARGUMENTS.get("PIOVERBOSE", 0)): for var in ("BUILD_FLAGS", "SRC_BUILD_FLAGS", "SRC_FILTER", "EXTRA_SCRIPT", "UPLOAD_PORT", "UPLOAD_FLAGS", "LIB_EXTRA_DIRS"): k = "PLATFORMIO_%s" % var - if environ.get(k): + if k not in environ: + continue + if var in ("UPLOAD_PORT", "EXTRA_SCRIPT") or not env.get(var): env[var] = environ.get(k) + else: + env[var] = "%s%s%s" % (environ.get(k), ", " + if var == "LIB_EXTRA_DIRS" else " ", env[var]) # Parse comma separated items for opt in ("PIOFRAMEWORK", "LIB_DEPS", "LIB_IGNORE", "LIB_EXTRA_DIRS"): From bcb265b42d0ece0c7f18d25595bc1cb9f29279ff Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 21 Feb 2017 11:54:04 +0200 Subject: [PATCH 082/127] Update history --- HISTORY.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 119c651f..5eef5bfc 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -44,10 +44,12 @@ PlatformIO 3.0 * Development platform `Atmel AVR `__ - + Added support for EnviroDIY Mayfly board + + Added support for EnviroDIY Mayfly, The Things Uno, SparkFun Qduino Mini, + SparkFun ATmega128RFA1 Dev Board, SparkFun Serial 7-Segment Display boards + Set fuse bits with new target named ``fuses`` (`issue #865 `_) + Updated Arduino Core to 1.6.17 + + Fixed ISO C99 warning for EnviroDIY Mayfly board * Development platform `Atmel SAM `__ From a817ec19ed618a8bcecc30ef1d21b508f21985b6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 22 Feb 2017 15:50:23 +0200 Subject: [PATCH 083/127] Improve docs for PIO Remote --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 3fa11c3c..93d642c2 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 3fa11c3cca33a9ab7a8469b69141ee49bb2100a2 +Subproject commit 93d642c2df8f86b4280e6d2fa2a63b013a993bf8 From 024d830621d5427365fcc1bacadf72f2a7beb5b9 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 22 Feb 2017 16:58:28 +0200 Subject: [PATCH 084/127] New ESP IDF examples: BLE, Coap Server, Peripherals UART, Storage SDCard --- HISTORY.rst | 2 ++ docs | 2 +- examples | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 5eef5bfc..2b870cb1 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -64,6 +64,8 @@ PlatformIO 3.0 + Added support for Simba & Pumbaa Frameworks + Added new boards: Node32s, Hornbill ESP32 Dev, Hornbill ESP32 Minim + Updated Arduino Core + + Updated ESP-IDF framework to the latest v2.0 Release Candidate 1 + + New ESP IDF examples: BLE, Coap Server, Peripherals UART, Storage SDCard * Development platform `Freescale Kinetis `__ diff --git a/docs b/docs index 93d642c2..f685b8bf 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 93d642c2df8f86b4280e6d2fa2a63b013a993bf8 +Subproject commit f685b8bffe879c85b64282332b51f3b7ba57bfdf diff --git a/examples b/examples index e6e0c19b..60609b12 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit e6e0c19bd1149ae7b5e5b8f72c9ccc98f1690441 +Subproject commit 60609b12231c46df6be2c8a0a5a7d42ca3bcc65d From 570b72f4c2d7d10d95d1e29c0ce8c13545d45b9a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 22 Feb 2017 23:41:36 +0200 Subject: [PATCH 085/127] Remove PlatformIO title from navbar --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index f685b8bf..7bbde597 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit f685b8bffe879c85b64282332b51f3b7ba57bfdf +Subproject commit 7bbde59753db060f6b27afe07c5f293b99a3574f From 2f6c594ee6bef2ff1a5713230815b5da11937388 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 23 Feb 2017 16:49:26 +0200 Subject: [PATCH 086/127] Fix PIO IDE uninstallation steps for macOS --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 7bbde597..b3912c06 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 7bbde59753db060f6b27afe07c5f293b99a3574f +Subproject commit b3912c06f56039ada6252035e8f9dcce3787690d From 8e0ad0224946867553eba156b7d8ae402bd7daf5 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 23 Feb 2017 19:00:26 +0200 Subject: [PATCH 087/127] New article by Bastiaan Vise --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index b3912c06..341c8552 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b3912c06f56039ada6252035e8f9dcce3787690d +Subproject commit 341c8552cf86bc64fa2fb7a123a84e54e78db266 From d4cd3dd600408872dfd5d7b4168203f48f5822db Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 25 Feb 2017 13:12:52 +0200 Subject: [PATCH 088/127] A few notes about PIO remote Cloud IDE integration --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 341c8552..c3e1b71f 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 341c8552cf86bc64fa2fb7a123a84e54e78db266 +Subproject commit c3e1b71f7c07429e271ef7bfdf7e025be23e900f From 30f698ddf04a0c5eb54413ecfe5b0506f25d108b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 25 Feb 2017 14:04:09 +0200 Subject: [PATCH 089/127] Typo fix in RST --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index c3e1b71f..59026068 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit c3e1b71f7c07429e271ef7bfdf7e025be23e900f +Subproject commit 59026068c1d05c820da020c02cac612a673fd499 From 8f5e23ae95de447439c34fea45513525503a567c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 25 Feb 2017 21:28:35 +0200 Subject: [PATCH 090/127] Update PIO IDE installation guide --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 59026068..dcdff193 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 59026068c1d05c820da020c02cac612a673fd499 +Subproject commit dcdff1934265d9a7ea119e756e09ec80b0ad3fb1 From 8f79d865aa2874d00b82a74a179d0403219f8bb0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Feb 2017 17:53:41 +0200 Subject: [PATCH 091/127] List supported frameworks, SDKs with a new `pio platform frameworks` command --- HISTORY.rst | 4 ++- docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/platform.py | 43 +++++++++++++++++++++++---------- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 2b870cb1..99702e63 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,11 +14,13 @@ PlatformIO 3.0 - Recent and popular keywords - Featured libraries (today, week, month) -* List built-in libraries based on development platforms with +* List built-in libraries based on development platforms with a new `pio lib builtin `__ command * Show detailed info about a library using `pio lib show `__ command (`issue #430 `_) +* List supported frameworks, SDKs with a new + `pio platform frameworks `__ command * Added new options ``--no-reset``, ``--monitor-rts`` and ``--monitor-dtr`` to `pio test `__ command (allows to avoid automatic board's auto-reset when gathering test results) diff --git a/docs b/docs index dcdff193..57f270e4 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit dcdff1934265d9a7ea119e756e09ec80b0ad3fb1 +Subproject commit 57f270e4750d53d26899ef764e9e54cd44a43967 diff --git a/platformio/__init__.py b/platformio/__init__.py index 847dc6e1..4500069a 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a11") +VERSION = (3, 3, "0a12") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index b5a46625..1a575978 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -28,15 +28,14 @@ def cli(): def _print_platforms(platforms): for platform in platforms: click.echo("{name} ~ {title}".format( - name=click.style( - platform['name'], fg="cyan"), + name=click.style(platform['name'], fg="cyan"), title=platform['title'])) click.echo("=" * (3 + len(platform['name'] + platform['title']))) click.echo(platform['description']) click.echo() - click.echo("Home: %s" % "http://platformio.org/platforms/" + - platform['name']) - if platform['packages']: + if "homepage" in platform: + click.echo("Home: %s" % platform['homepage']) + if "packages" in platform: click.echo("Packages: %s" % ", ".join(platform['packages'])) if "version" in platform: click.echo("Version: " + platform['version']) @@ -51,17 +50,13 @@ def platform_search(query, json_output): for platform in util.get_api_result("/platforms", cache_valid="30d"): if query == "all": query = "" - search_data = json.dumps(platform) if query and query.lower() not in search_data.lower(): continue - - platforms.append({ - "name": platform['name'], - "title": platform['title'], - "description": platform['description'], - "packages": platform['packages'] - }) + platform['homepage'] = ( + "http://platformio.org/platforms/" + platform['name']) + del platform['version'] + platforms.append(platform) if json_output: click.echo(json.dumps(platforms)) @@ -69,6 +64,27 @@ def platform_search(query, json_output): _print_platforms(platforms) +@cli.command("frameworks", short_help="List supported frameworks, SDKs") +@click.argument("query", required=False) +@click.option("--json-output", is_flag=True) +def platform_frameworks(query, json_output): + frameworks = [] + for framework in util.get_api_result("/frameworks", cache_valid="30d"): + if query == "all": + query = "" + search_data = json.dumps(framework) + if query and query.lower() not in search_data.lower(): + continue + framework['homepage'] = ( + "http://platformio.org/frameworks/" + framework['name']) + frameworks.append(framework) + + if json_output: + click.echo(json.dumps(frameworks)) + else: + _print_platforms(frameworks) + + @cli.command("install", short_help="Install new development platform") @click.argument("platforms", nargs=-1, required=True, metavar="[PLATFORM...]") @click.option("--with-package", multiple=True) @@ -166,6 +182,7 @@ def platform_list(json_output): "description": p.description, "version": p.version, "url": p.vendor_url, + "homepage": p.homepage, # "packages": p.packages.keys(), # dump all packages "packages": p.get_installed_packages().keys(), 'forDesktop': From c0c83689058910184335ea7892d9c8d266e9aa5c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Feb 2017 19:37:26 +0200 Subject: [PATCH 092/127] Code cleanup --- platformio/commands/boards.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio/commands/boards.py b/platformio/commands/boards.py index 2da6cdf6..dfe4db54 100644 --- a/platformio/commands/boards.py +++ b/platformio/commands/boards.py @@ -66,8 +66,6 @@ def cli(query, installed, json_output): # pylint: disable=R0912 if query.lower() not in search_data.lower(): continue - flash_size = "%dkB" % (board['rom'] / 1024) - ram_size = board['ram'] if ram_size >= 1024: if ram_size % 1024: @@ -83,7 +81,7 @@ def cli(query, installed, json_output): # pylint: disable=R0912 board['id'], fg="cyan"), mcu=board['mcu'], frequency="%dMhz" % (board['fcpu'] / 1000000), - flash=flash_size, + flash="%dkB" % (board['rom'] / 1024), ram=ram_size, name=board['name'])) From 2e6d66fcd42f984251c01fd17785e2bce0a9df7b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Feb 2017 23:47:04 +0200 Subject: [PATCH 093/127] Sort boards by name --- platformio/commands/boards.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio/commands/boards.py b/platformio/commands/boards.py index dfe4db54..5af3cf77 100644 --- a/platformio/commands/boards.py +++ b/platformio/commands/boards.py @@ -59,7 +59,7 @@ def cli(query, installed, json_output): # pylint: disable=R0912 name="Name")) click.echo("-" * terminal_width) - for board in sorted(pboards, key=lambda b: b['id']): + for board in pboards: if query: search_data = "%s %s" % (board['id'], json.dumps(board).lower()) @@ -97,7 +97,7 @@ def _get_boards(installed=False): boards.append(board) except InternetIsOffline: pass - return boards + return sorted(boards, key=lambda b: b['name']) def _ouput_boards_json(query, installed=False): From a119fdfc484056b80d10752cde218ba374712097 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 28 Feb 2017 00:26:28 +0200 Subject: [PATCH 094/127] =?UTF-8?q?temporary=20use=20=E2=80=9Cdevelop?= =?UTF-8?q?=E2=80=9D=20version=20of=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 57f270e4..e204e5d9 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 57f270e4750d53d26899ef764e9e54cd44a43967 +Subproject commit e204e5d94fc44f62d8ae3a08a216089e8318de1f From ba750f0eee749863f827728c3725b8d5a14b0f63 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 28 Feb 2017 19:25:48 +0200 Subject: [PATCH 095/127] =?UTF-8?q?Add=20warning=20about=20=E2=80=9C.gcc-f?= =?UTF-8?q?lags.json=E2=80=9D=20file=20and=20custom=20flags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index e204e5d9..c605ca2f 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit e204e5d94fc44f62d8ae3a08a216089e8318de1f +Subproject commit c605ca2f9b55701f3daff51f81efcd06e84dd3ec From cfd1f03023870952836aa3643a5d41f9eecbb97c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Mar 2017 16:11:23 +0200 Subject: [PATCH 096/127] Switch to new Packages API --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index c605ca2f..b25d5c17 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit c605ca2f9b55701f3daff51f81efcd06e84dd3ec +Subproject commit b25d5c17fe09e750b4e105a45890285aeaab34d1 From fe1846c2e1b42fc0171308e6efa90c07602a2566 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Mar 2017 17:09:22 +0200 Subject: [PATCH 097/127] YAPF formatting --- platformio/builder/tools/piolib.py | 10 ++++------ platformio/builder/tools/platformio.py | 3 +-- platformio/commands/init.py | 6 ++---- platformio/commands/lib.py | 15 +++++---------- platformio/commands/run.py | 4 +--- platformio/commands/settings.py | 11 ++++------- platformio/commands/upgrade.py | 12 +++++++----- platformio/downloader.py | 5 ++--- platformio/maintenance.py | 11 +++++------ platformio/managers/lib.py | 3 +-- platformio/util.py | 11 ++++++----- 11 files changed, 38 insertions(+), 53 deletions(-) diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index 32164b16..57163ee9 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -46,9 +46,8 @@ class LibBuilderFactory(object): elif used_frameworks: clsname = "%sLibBuilder" % used_frameworks[0].title() - obj = getattr(sys.modules[__name__], clsname)(env, - path, - verbose=verbose) + obj = getattr(sys.modules[__name__], clsname)( + env, path, verbose=verbose) assert isinstance(obj, LibBuilderBase) return obj @@ -614,9 +613,8 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches if item == "__cores__" or not isdir(join(libs_dir, item)): continue try: - lb = LibBuilderFactory.new(env, - join(libs_dir, item), - verbose=verbose) + lb = LibBuilderFactory.new( + env, join(libs_dir, item), verbose=verbose) except ValueError: if verbose: sys.stderr.write("Skip library with broken manifest: %s\n" diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 56875c1a..e23d78d0 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -266,8 +266,7 @@ def BuildLibrary(env, variant_dir, src_dir, src_filter=None): lib = env.Clone() return lib.StaticLibrary( lib.subst(variant_dir), - lib.CollectBuildFiles( - variant_dir, src_dir, src_filter=src_filter)) + lib.CollectBuildFiles(variant_dir, src_dir, src_filter=src_filter)) def BuildSources(env, variant_dir, src_dir, src_filter=None): diff --git a/platformio/commands/init.py b/platformio/commands/init.py index c668355b..fb303641 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -81,15 +81,13 @@ def cli( click.echo("") click.echo("The next files/directories have been created in %s" % - click.style( - project_dir, fg="cyan")) + click.style(project_dir, fg="cyan")) click.echo("%s - Project Configuration File" % click.style( "platformio.ini", fg="cyan")) click.echo("%s - Put your source files here" % click.style( "src", fg="cyan")) click.echo("%s - Put here project specific (private) libraries" % - click.style( - "lib", fg="cyan")) + click.style("lib", fg="cyan")) init_base_project(project_dir) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index ab097e6c..f3b62be8 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -199,8 +199,7 @@ def lib_search(query, json_output, page, noninteractive, **filters): result = get_api_result( "/v2/lib/search", - dict( - query=" ".join(query), page=page), + dict(query=" ".join(query), page=page), cache_valid="3d") if json_output: @@ -411,11 +410,9 @@ def lib_stats(json_output): def _print_header(with_date=False): click.echo((printitemdate_tpl if with_date else printitem_tpl).format( - name=click.style( - "Name", fg="cyan"), + name=click.style("Name", fg="cyan"), date="Date", - url=click.style( - "Url", fg="blue"))) + url=click.style("Url", fg="blue"))) terminal_width, _ = click.get_terminal_size() click.echo("-" * terminal_width) @@ -424,8 +421,7 @@ def lib_stats(json_output): click.echo(( printitemdate_tpl if "date" in item else printitem_tpl ).format( - name=click.style( - item['name'], fg="cyan"), + name=click.style(item['name'], fg="cyan"), date=str( arrow.get(item['date']).humanize() if "date" in item else ""), url=click.style( @@ -436,8 +432,7 @@ def lib_stats(json_output): def _print_tag_item(name): click.echo( printitem_tpl.format( - name=click.style( - name, fg="cyan"), + name=click.style(name, fg="cyan"), url=click.style( "http://platformio.org/lib/search?query=" + quote( "keyword:%s" % name), diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 28196a90..36e56ff6 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -342,9 +342,7 @@ def print_summary(results, start_time): format_str = ( "Environment {0:<" + str(envname_max_len + 9) + "}\t[{1}]") click.echo( - format_str.format( - click.style( - envname, fg="cyan"), status_str), + format_str.format(click.style(envname, fg="cyan"), status_str), err=status is False) print_header( diff --git a/platformio/commands/settings.py b/platformio/commands/settings.py index 478ed527..08649221 100644 --- a/platformio/commands/settings.py +++ b/platformio/commands/settings.py @@ -31,11 +31,9 @@ def settings_get(name): click.echo( list_tpl.format( - name=click.style( - "Name", fg="cyan"), - value=(click.style( - "Value", fg="green") + click.style( - " [Default]", fg="yellow")), + name=click.style("Name", fg="cyan"), + value=(click.style("Value", fg="green") + click.style( + " [Default]", fg="yellow")), description="Description")) click.echo("-" * terminal_width) @@ -59,8 +57,7 @@ def settings_get(name): click.echo( list_tpl.format( - name=click.style( - _name, fg="cyan"), + name=click.style(_name, fg="cyan"), value=_value_str, description=_data['description'])) diff --git a/platformio/commands/upgrade.py b/platformio/commands/upgrade.py index 41564535..cc735393 100644 --- a/platformio/commands/upgrade.py +++ b/platformio/commands/upgrade.py @@ -101,9 +101,10 @@ def get_latest_version(): def get_develop_latest_version(): version = None - r = requests.get("https://raw.githubusercontent.com/platformio/platformio" - "/develop/platformio/__init__.py", - headers=util.get_request_defheaders()) + r = requests.get( + "https://raw.githubusercontent.com/platformio/platformio" + "/develop/platformio/__init__.py", + headers=util.get_request_defheaders()) r.raise_for_status() for line in r.text.split("\n"): line = line.strip() @@ -121,7 +122,8 @@ def get_develop_latest_version(): def get_pypi_latest_version(): - r = requests.get("https://pypi.python.org/pypi/platformio/json", - headers=util.get_request_defheaders()) + r = requests.get( + "https://pypi.python.org/pypi/platformio/json", + headers=util.get_request_defheaders()) r.raise_for_status() return r.json()['info']['version'] diff --git a/platformio/downloader.py b/platformio/downloader.py index b96edda8..356413c2 100644 --- a/platformio/downloader.py +++ b/platformio/downloader.py @@ -31,9 +31,8 @@ class FileDownloader(object): def __init__(self, url, dest_dir=None): # make connection - self._request = requests.get(url, - stream=True, - headers=util.get_request_defheaders()) + self._request = requests.get( + url, stream=True, headers=util.get_request_defheaders()) if self._request.status_code != 200: raise FDUnrecognizedStatusCode(self._request.status_code, url) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 72614271..af98280b 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -191,14 +191,13 @@ def after_upgrade(ctx): "on the latest project news > %s" % (click.style( "follow", fg="cyan"), click.style( "https://twitter.com/PlatformIO_Org", fg="cyan"))) - click.echo("- %s it on GitHub > %s" % (click.style( - "star", fg="cyan"), click.style( - "https://github.com/platformio/platformio", fg="cyan"))) + click.echo("- %s it on GitHub > %s" % + (click.style("star", fg="cyan"), click.style( + "https://github.com/platformio/platformio", fg="cyan"))) if not getenv("PLATFORMIO_IDE"): click.echo("- %s PlatformIO IDE for IoT development > %s" % - (click.style( - "try", fg="cyan"), click.style( - "http://platformio.org/platformio-ide", fg="cyan"))) + (click.style("try", fg="cyan"), click.style( + "http://platformio.org/platformio-ide", fg="cyan"))) if not util.is_ci(): click.echo("- %s us with PlatformIO Plus > %s" % (click.style( "support", fg="cyan"), click.style( diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index ee7b9019..0e9a5457 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -217,8 +217,7 @@ class LibraryManager(BasePkgManager): util.get_api_result( "/lib/info/%d" % self.get_pkg_id_by_name( name, requirements, silent=silent), - cache_valid="1d")['versions'], - requirements) + cache_valid="1d")['versions'], requirements) return item['name'] if item else None def get_pkg_id_by_name(self, diff --git a/platformio/util.py b/platformio/util.py index 46c11965..1e70b471 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -458,11 +458,12 @@ def _get_api_result( auth=auth, verify=disable_ssl_check) else: - r = _api_request_session().get(url, - params=params, - headers=headers, - auth=auth, - verify=disable_ssl_check) + r = _api_request_session().get( + url, + params=params, + headers=headers, + auth=auth, + verify=disable_ssl_check) result = r.json() r.raise_for_status() except requests.exceptions.HTTPError as e: From 3adc3eace390ae6b3f71a07ff79a6c00b0838f33 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 2 Mar 2017 17:09:32 +0200 Subject: [PATCH 098/127] Switch to new Packages API --- scripts/docspregen.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/scripts/docspregen.py b/scripts/docspregen.py index eb61ac96..e67c9e50 100644 --- a/scripts/docspregen.py +++ b/scripts/docspregen.py @@ -93,16 +93,15 @@ Packages :header-rows: 1 * - Name - - Contents""") + - Description""") for name in sorted(packagenames): assert name in API_PACKAGES, name - contitems = [ - "`{name} <{url}>`_".format(**item) for item in API_PACKAGES[name] - ] lines.append(""" - * - ``{name}`` - - {contents}""".format( - name=name, contents=", ".join(contitems))) + * - `{name} <{url}>`__ + - {description}""".format( + name=name, + url=API_PACKAGES[name]['url'], + description=API_PACKAGES[name]['description'])) if is_embedded: lines.append(""" @@ -172,8 +171,8 @@ For more detailed information please visit `vendor site <%s>`_.""" % # # Packages # - _packages_content = generate_packages(name, p.packages.keys(), - p.is_embedded()) + _packages_content = generate_packages(name, + p.packages.keys(), p.is_embedded()) if _packages_content: lines.append(_packages_content) @@ -288,10 +287,11 @@ Platforms continue _found_platform = True p = PlatformFactory.newPlatform(manifest['name']) - lines.append(""" + lines.append( + """ * - :ref:`platform_{type_}` - - {description}""".format( - type_=manifest['name'], description=p.description)) + - {description}""" + .format(type_=manifest['name'], description=p.description)) if not _found_platform: del lines[-1] @@ -347,19 +347,21 @@ Packages :header-rows: 1 * - Name - - Contents""") + - Description""") for name, items in sorted(API_PACKAGES.iteritems()): - contitems = ["`{name} <{url}>`_".format(**item) for item in items] lines.append(""" - * - ``{name}`` - - {contents}""".format( - name=name, contents=", ".join(contitems))) + * - `{name} <{url}>`__ + - {description}""".format( + name=name, + url=API_PACKAGES[name]['url'], + description=API_PACKAGES[name]['description'])) with open( join(util.get_source_dir(), "..", "docs", "platforms", "creating_platform.rst"), "r+") as fp: content = fp.read() - fp.seek(0, 0) + fp.seek(0) + fp.truncate() fp.write(content[:content.index(".. _platform_creating_packages:")] + "\n".join(lines) + "\n\n" + content[content.index( ".. _platform_creating_manifest_file:"):]) From cb927c276c1ff8d7d6167d4d836340682e0fa064 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 3 Mar 2017 23:29:17 +0200 Subject: [PATCH 099/127] Improve JSON support for `pio platform` sub-commands --- HISTORY.rst | 9 + docs | 2 +- platformio/__init__.py | 2 +- platformio/commands/boards.py | 87 +++++---- platformio/commands/platform.py | 303 ++++++++++++++++++++++---------- platformio/commands/update.py | 2 +- platformio/managers/package.py | 14 +- platformio/managers/platform.py | 11 +- tests/commands/test_lib.py | 2 +- 9 files changed, 281 insertions(+), 151 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 99702e63..a2a5fdb7 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -52,6 +52,7 @@ PlatformIO 3.0 (`issue #865 `_) + Updated Arduino Core to 1.6.17 + Fixed ISO C99 warning for EnviroDIY Mayfly board + + Fixed firmware uploading to Arduino Leonardo * Development platform `Atmel SAM `__ @@ -74,6 +75,14 @@ PlatformIO 3.0 + Added support for ARM mbed events library + Updated ARM mbed OS to 5.3.0/rev131 +* Development platform `Lattice iCE40 `__ + + + Improved path management for Windows + + Custom uploader using ``$UPLOAD`` build variable + (`issue #865 `_) + + Updated toolchain-icestorm to 1.10.0 (added -C option to "time" target) + + Updated toolchain-iverilog to 1.1.0 (loaed all vlib/\*.v files in "iverilog" builder) + * Development platform `Linux ARM `__ + Added support for Samsung ARTIK boards (520, 530, 710, 1020) and ARTIK SDK diff --git a/docs b/docs index b25d5c17..60fe1ac9 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b25d5c17fe09e750b4e105a45890285aeaab34d1 +Subproject commit 60fe1ac9a59c9a611512ba6250a012b39a0614fb diff --git a/platformio/__init__.py b/platformio/__init__.py index 4500069a..b715f822 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a12") +VERSION = (3, 3, "0a13") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/boards.py b/platformio/commands/boards.py index 5af3cf77..5f5921c9 100644 --- a/platformio/commands/boards.py +++ b/platformio/commands/boards.py @@ -20,70 +20,63 @@ from platformio.exception import APIRequestError, InternetIsOffline from platformio.managers.platform import PlatformManager -@click.command("boards", short_help="Pre-configured Embedded Boards") +@click.command("boards", short_help="Embedded Board Explorer") @click.argument("query", required=False) @click.option("--installed", is_flag=True) @click.option("--json-output", is_flag=True) def cli(query, installed, json_output): # pylint: disable=R0912 if json_output: - return _ouput_boards_json(query, installed) - - BOARDLIST_TPL = ("{type:<30} {mcu:<14} {frequency:<8} " - " {flash:<7} {ram:<6} {name}") - terminal_width, _ = click.get_terminal_size() + return _print_boards_json(query, installed) grpboards = {} for board in _get_boards(installed): + if query and query.lower() not in json.dumps(board).lower(): + continue if board['platform'] not in grpboards: grpboards[board['platform']] = [] grpboards[board['platform']].append(board) - for (platform, pboards) in sorted(grpboards.items()): - if query: - search_data = json.dumps(pboards).lower() - if query.lower() not in search_data.lower(): - continue - + terminal_width, _ = click.get_terminal_size() + for (platform, boards) in sorted(grpboards.items()): click.echo("") click.echo("Platform: ", nl=False) click.secho(platform, bold=True) click.echo("-" * terminal_width) + print_boards(boards) + + +def print_boards(boards): + terminal_width, _ = click.get_terminal_size() + BOARDLIST_TPL = ("{type:<30} {mcu:<14} {frequency:<8} " + " {flash:<7} {ram:<6} {name}") + click.echo( + BOARDLIST_TPL.format( + type=click.style("ID", fg="cyan"), + mcu="MCU", + frequency="Frequency", + flash="Flash", + ram="RAM", + name="Name")) + click.echo("-" * terminal_width) + + for board in boards: + ram_size = board['ram'] + if ram_size >= 1024: + if ram_size % 1024: + ram_size = "%.1fkB" % (ram_size / 1024.0) + else: + ram_size = "%dkB" % (ram_size / 1024) + else: + ram_size = "%dB" % ram_size + click.echo( BOARDLIST_TPL.format( - type=click.style( - "ID", fg="cyan"), - mcu="MCU", - frequency="Frequency", - flash="Flash", - ram="RAM", - name="Name")) - click.echo("-" * terminal_width) - - for board in pboards: - if query: - search_data = "%s %s" % (board['id'], - json.dumps(board).lower()) - if query.lower() not in search_data.lower(): - continue - - ram_size = board['ram'] - if ram_size >= 1024: - if ram_size % 1024: - ram_size = "%.1fkB" % (ram_size / 1024.0) - else: - ram_size = "%dkB" % (ram_size / 1024) - else: - ram_size = "%dB" % ram_size - - click.echo( - BOARDLIST_TPL.format( - type=click.style( - board['id'], fg="cyan"), - mcu=board['mcu'], - frequency="%dMhz" % (board['fcpu'] / 1000000), - flash="%dkB" % (board['rom'] / 1024), - ram=ram_size, - name=board['name'])) + type=click.style(board['id'], fg="cyan"), + mcu=board['mcu'], + frequency="%dMhz" % (board['fcpu'] / 1000000), + flash="%dkB" % (board['rom'] / 1024), + ram=ram_size, + name=board['name'])) def _get_boards(installed=False): @@ -100,7 +93,7 @@ def _get_boards(installed=False): return sorted(boards, key=lambda b: b['name']) -def _ouput_boards_json(query, installed=False): +def _print_boards_json(query, installed=False): result = [] try: boards = _get_boards(installed) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 1a575978..2ff50df1 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -13,10 +13,12 @@ # limitations under the License. import json +from os.path import dirname, isfile, join import click from platformio import app, exception, util +from platformio.commands.boards import print_boards from platformio.managers.platform import PlatformFactory, PlatformManager @@ -35,6 +37,8 @@ def _print_platforms(platforms): click.echo() if "homepage" in platform: click.echo("Home: %s" % platform['homepage']) + if "frameworks" in platform and platform['frameworks']: + click.echo("Frameworks: %s" % ", ".join(platform['frameworks'])) if "packages" in platform: click.echo("Packages: %s" % ", ".join(platform['packages'])) if "version" in platform: @@ -42,21 +46,134 @@ def _print_platforms(platforms): click.echo() +def _get_registry_platforms(): + platforms = util.get_api_result("/platforms", cache_valid="30d") + pm = PlatformManager() + for platform in platforms or []: + platform['versions'] = pm.get_all_repo_versions(platform['name']) + return platforms + + +def _original_version(version): + if version.count(".") != 2: + return None + _, y = version.split(".")[:2] + if int(y) < 100: + return None + if len(y) % 2 != 0: + y = "0" + y + parts = [str(int(y[i * 2:i * 2 + 2])) for i in range(len(y) / 2)] + return ".".join(parts) + + +def _get_platform_data(*args, **kwargs): + try: + return _get_installed_platform_data(*args, **kwargs) + except exception.UnknownPlatform: + return _get_registry_platform_data(*args, **kwargs) + + +def _get_installed_platform_data(platform, + with_boards=True, + expose_packages=True): + p = PlatformFactory.newPlatform(platform) + data = dict( + name=p.name, + title=p.title, + description=p.description, + version=p.version, # comment before dump + homepage=p.homepage, + repository=p.repository_url, + url=p.vendor_url, + license=p.license, + forDesktop=not p.is_embedded(), + frameworks=sorted(p.frameworks.keys() if p.frameworks else []), + packages=p.packages.keys() if p.packages else []) + + # if dump to API + # del data['version'] + # return data + + data['__pkg_dir'] = dirname(p.manifest_path) + # if VCS cloned platform + if not isfile(join(data['__pkg_dir'], "platform.json")): + data['__pkg_dir'] = dirname(data['__pkg_dir']) + + if with_boards: + data['boards'] = [c.get_brief_data() for c in p.get_boards().values()] + + if not data['packages'] or not expose_packages: + return data + + data['packages'] = [] + installed_pkgs = p.get_installed_packages() + for name, opts in p.packages.items(): + item = dict( + name=name, + type=p.get_package_type(name), + requirements=opts.get("version"), + optional=opts.get("optional") is True) + if name in installed_pkgs: + for key, value in installed_pkgs[name].items(): + if key not in ("url", "version", "description"): + continue + item[key] = value + if key == "version": + item["originalVersion"] = _original_version(value) + data['packages'].append(item) + + return data + + +def _get_registry_platform_data( # pylint: disable=unused-argument + platform, + with_boards=True, + expose_packages=True): + _data = None + for p in _get_registry_platforms(): + if p['name'] == platform: + _data = p + break + + if not _data: + return None + + data = dict( + name=_data['name'], + title=_data['title'], + description=_data['description'], + homepage=_data['homepage'], + repository=_data['repository'], + url=_data['url'], + license=_data['license'], + forDesktop=_data['forDesktop'], + frameworks=_data['frameworks'], + packages=_data['packages'], + versions=_data['versions']) + + if with_boards: + data['boards'] = [ + board for board in PlatformManager().get_registered_boards() + if board['platform'] == _data['name'] + ] + + return data + + @cli.command("search", short_help="Search for development platform") @click.argument("query", required=False) @click.option("--json-output", is_flag=True) def platform_search(query, json_output): platforms = [] - for platform in util.get_api_result("/platforms", cache_valid="30d"): + for platform in _get_registry_platforms(): if query == "all": query = "" search_data = json.dumps(platform) if query and query.lower() not in search_data.lower(): continue - platform['homepage'] = ( - "http://platformio.org/platforms/" + platform['name']) - del platform['version'] - platforms.append(platform) + platforms.append( + _get_registry_platform_data( + platform['name'], with_boards=False, expose_packages=False)) if json_output: click.echo(json.dumps(platforms)) @@ -77,6 +194,10 @@ def platform_frameworks(query, json_output): continue framework['homepage'] = ( "http://platformio.org/frameworks/" + framework['name']) + framework['platforms'] = [ + platform['name'] for platform in _get_registry_platforms() + if framework['name'] in platform['frameworks'] + ] frameworks.append(framework) if json_output: @@ -85,6 +206,83 @@ def platform_frameworks(query, json_output): _print_platforms(frameworks) +@cli.command("list", short_help="List installed development platforms") +@click.option("--json-output", is_flag=True) +def platform_list(json_output): + platforms = [] + pm = PlatformManager() + for manifest in pm.get_installed(): + platforms.append( + _get_installed_platform_data( + pm.get_manifest_path(manifest['__pkg_dir']), + with_boards=False, + expose_packages=False)) + if json_output: + click.echo(json.dumps(platforms)) + else: + _print_platforms(platforms) + + +@cli.command("show", short_help="Show details about development platform") +@click.argument("platform") +@click.option("--json-output", is_flag=True) +def platform_show(platform, json_output): # pylint: disable=too-many-branches + data = _get_platform_data(platform) + if not data: + raise exception.UnknownPlatform(platform) + if json_output: + return click.echo(json.dumps(data)) + + click.echo("{name} ~ {title}".format( + name=click.style(data['name'], fg="cyan"), title=data['title'])) + click.echo("=" * (3 + len(data['name'] + data['title']))) + click.echo(data['description']) + click.echo() + if "version" in data: + click.echo("Version: %s" % data['version']) + if data['homepage']: + click.echo("Home: %s" % data['homepage']) + if data['repository']: + click.echo("Repository: %s" % data['repository']) + if data['url']: + click.echo("Vendor: %s" % data['url']) + if data['license']: + click.echo("License: %s" % data['license']) + if data['frameworks']: + click.echo("Frameworks: %s" % ", ".join(data['frameworks'])) + + if not data['packages']: + return + + if not isinstance(data['packages'][0], dict): + click.echo("Packages: %s" % ", ".join(data['packages'])) + else: + click.echo() + click.secho("Packages", bold=True) + click.echo("--------") + for item in data['packages']: + click.echo() + click.echo("Package %s" % click.style(item['name'], fg="yellow")) + click.echo("-" * (8 + len(item['name']))) + if item['type']: + click.echo("Type: %s" % item['type']) + click.echo("Requirements: %s" % item['requirements']) + click.echo("Installed: %s" % ("Yes" if item.get("version") else + "No (optional)")) + if "version" in item: + click.echo("Version: %s" % item['version']) + if "originalVersion" in item: + click.echo("Original version: %s" % item['originalVersion']) + if "description" in item: + click.echo("Description: %s" % item['description']) + + if data['boards']: + click.echo() + click.secho("Boards", bold=True) + click.echo("------") + print_boards(data['boards']) + + @cli.command("install", short_help="Install new development platform") @click.argument("platforms", nargs=-1, required=True, metavar="[PLATFORM...]") @click.option("--with-package", multiple=True) @@ -124,12 +322,12 @@ def platform_uninstall(platforms): "-p", "--only-packages", is_flag=True, - help="Update only platform packages") + help="Update only the platform packages") @click.option( "-c", "--only-check", is_flag=True, - help="Do not update, only check for new version") + help="Do not update, only check for a new version") @click.option("--json-output", is_flag=True) def platform_update(platforms, only_packages, only_check, json_output): # cleanup cached board and platform lists @@ -140,6 +338,7 @@ def platform_update(platforms, only_packages, only_check, json_output): platforms = [] for manifest in pm.get_installed(): pkg_dir = manifest['__pkg_dir'] + # don't check fixed platforms if "@" in pkg_dir and "@vcs-" not in pkg_dir: continue elif "@vcs-" in pkg_dir: @@ -154,10 +353,10 @@ def platform_update(platforms, only_packages, only_check, json_output): latest = pm.outdated(name, requirements, url) if latest is False: continue - manifest = pm.load_manifest( - pm.get_package_dir(name, requirements, url)) - manifest['versionLatest'] = latest or "Unknown" - result.append(manifest) + data = _get_installed_platform_data( + name, with_boards=False, expose_packages=False) + data['versionLatest'] = latest or "Unknown" + result.append(data) return click.echo(json.dumps(result)) else: for platform in platforms: @@ -166,85 +365,3 @@ def platform_update(platforms, only_packages, only_check, json_output): pm.update( platform, only_packages=only_packages, only_check=only_check) click.echo() - - -@cli.command("list", short_help="List installed development platforms") -@click.option("--json-output", is_flag=True) -def platform_list(json_output): - platforms = [] - pm = PlatformManager() - for manifest in pm.get_installed(): - p = PlatformFactory.newPlatform( - pm.get_manifest_path(manifest['__pkg_dir'])) - platforms.append({ - "name": p.name, - "title": p.title, - "description": p.description, - "version": p.version, - "url": p.vendor_url, - "homepage": p.homepage, - # "packages": p.packages.keys(), # dump all packages - "packages": p.get_installed_packages().keys(), - 'forDesktop': - any([p.name.startswith(n) for n in ("native", "linux", "windows")]) - }) - - if json_output: - click.echo(json.dumps(platforms)) - else: - _print_platforms(platforms) - - -@cli.command("show", short_help="Show details about installed platform") -@click.argument("platform") -def platform_show(platform): - - def _detail_version(version): - if version.count(".") != 2: - return version - _, y = version.split(".")[:2] - if int(y) < 100: - return version - if len(y) % 2 != 0: - y = "0" + y - parts = [str(int(y[i * 2:i * 2 + 2])) for i in range(len(y) / 2)] - return "%s (%s)" % (version, ".".join(parts)) - - try: - p = PlatformFactory.newPlatform(platform) - except exception.UnknownPlatform: - raise exception.PlatformNotInstalledYet(platform) - - click.echo("{name} ~ {title}".format( - name=click.style( - p.name, fg="cyan"), title=p.title)) - click.echo("=" * (3 + len(p.name + p.title))) - click.echo(p.description) - click.echo() - click.echo("Version: %s" % p.version) - if p.homepage: - click.echo("Home: %s" % p.homepage) - if p.license: - click.echo("License: %s" % p.license) - if p.frameworks: - click.echo("Frameworks: %s" % ", ".join(p.frameworks.keys())) - - if not p.packages: - return - - installed_pkgs = p.get_installed_packages() - for name, opts in p.packages.items(): - click.echo() - click.echo("Package %s" % click.style(name, fg="yellow")) - click.echo("-" * (8 + len(name))) - if p.get_package_type(name): - click.echo("Type: %s" % p.get_package_type(name)) - click.echo("Requirements: %s" % opts.get("version")) - click.echo("Installed: %s" % ("Yes" if name in installed_pkgs else - "No (optional)")) - if name in installed_pkgs: - for key, value in installed_pkgs[name].items(): - if key in ("url", "version", "description"): - if key == "version": - value = _detail_version(value) - click.echo("%s: %s" % (key.title(), value)) diff --git a/platformio/commands/update.py b/platformio/commands/update.py index 2d32ef48..5d6dedb6 100644 --- a/platformio/commands/update.py +++ b/platformio/commands/update.py @@ -21,7 +21,7 @@ from platformio.pioplus import pioplus_update @click.command( - "update", short_help="Update installed Platforms, Packages and Libraries") + "update", short_help="Update installed platforms, packages and libraries") @click.option( "-c", "--only-check", diff --git a/platformio/managers/package.py b/platformio/managers/package.py index a38fe067..7097d10a 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -118,6 +118,12 @@ class PkgRepoMixin(object): version = pkgdata['version'] return version + def get_all_repo_versions(self, name): + result = [] + for versions in PackageRepoIterator(name, self.repositories): + result.extend([v['version'] for v in versions]) + return sorted(set(result)) + class PkgInstallerMixin(object): @@ -204,8 +210,8 @@ class PkgInstallerMixin(object): # return from cache if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: - for manifest in PkgInstallerMixin._INSTALLED_CACHE[self. - package_dir]: + for manifest in PkgInstallerMixin._INSTALLED_CACHE[ + self.package_dir]: if not is_vcs_pkg and manifest['__pkg_dir'] == pkg_dir: return manifest @@ -627,9 +633,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): click.echo( "{} {:<40} @ {:<15}".format( "Checking" if only_check else "Updating", - click.style( - manifest['name'], fg="cyan"), - manifest['version']), + click.style(manifest['name'], fg="cyan"), manifest['version']), nl=False) if not util.internet_on(): click.echo("[%s]" % (click.style("Off-line", fg="yellow"))) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index ac5cfd58..78516b73 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -143,7 +143,9 @@ class PlatformManager(BasePkgManager): p = PlatformFactory.newPlatform( self.get_manifest_path(manifest['__pkg_dir'])) for config in p.get_boards().values(): - boards.append(config.get_brief_data()) + board = config.get_brief_data() + if board not in boards: + boards.append(board) return boards @staticmethod @@ -385,7 +387,8 @@ class PlatformRunMixin(object): return 1 -class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): +class PlatformBase( # pylint: disable=too-many-public-methods + PlatformPackagesMixin, PlatformRunMixin): PIO_VERSION = semantic_version.Version(util.pepver_to_semver(__version__)) _BOARDS_CACHE = {} @@ -432,6 +435,10 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): def vendor_url(self): return self._manifest.get("url") + @property + def repository_url(self): + return self._manifest.get("repository", {}).get("url") + @property def license(self): return self._manifest.get("license") diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 264a62ef..79db2e28 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -106,7 +106,7 @@ def test_global_lib_update_check(clirunner, validate_cliresult, cmd_lib, ["-g", "update", "--only-check", "--json-output"]) validate_cliresult(result) output = json.loads(result.output) - assert set(["ArduinoJson", "RadioHead"]) == set( + assert set(["ArduinoJson", "ESPAsyncTCP", "RadioHead"]) == set( [l['name'] for l in output]) From 20d6b2ebbb865ed4c821721a24968873e7657ff1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 3 Mar 2017 23:40:35 +0200 Subject: [PATCH 100/127] Fix duplicate explicit target name: "issue #865 in history --- HISTORY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index a2a5fdb7..fa6f3a30 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -79,7 +79,7 @@ PlatformIO 3.0 + Improved path management for Windows + Custom uploader using ``$UPLOAD`` build variable - (`issue #865 `_) + (`issue #6 `__) + Updated toolchain-icestorm to 1.10.0 (added -C option to "time" target) + Updated toolchain-iverilog to 1.1.0 (loaed all vlib/\*.v files in "iverilog" builder) From 3c10e84deff2189c650ce78e52117d72da46e062 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 4 Mar 2017 17:36:21 +0200 Subject: [PATCH 101/127] Skip projects examples from test on macOS --- .travis.yml | 2 +- tox.ini | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4acf44fb..a0515311 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ matrix: env: TOX_ENV=py27 - os: osx language: generic - env: TOX_ENV=py27 + env: TOX_ENV=skipexamples install: - git submodule update --init --recursive diff --git a/tox.ini b/tox.ini index 13c4e891..1f19bf1f 100644 --- a/tox.ini +++ b/tox.ini @@ -61,6 +61,13 @@ commands = {envpython} --version py.test -v --basetemp="{envtmpdir}" tests +[testenv:skipexamples] +basepython = python2.7 +deps = + pytest +commands = + py.test -v --basetemp="{envtmpdir}" tests --ignore tests/test_examples.py + [testenv:coverage] basepython = python2.7 passenv = * From 93ce65b28b11463e4a161e5b3b0ed9a221210556 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 4 Mar 2017 18:37:03 +0200 Subject: [PATCH 102/127] Unfix installed package when the latest version is uninstalled --- platformio/commands/lib.py | 7 ++----- platformio/commands/platform.py | 8 ++------ platformio/managers/package.py | 13 ++++++++++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index f3b62be8..d418221e 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -118,10 +118,7 @@ def lib_update(lm, libraries, only_check, json_output): if not libraries: libraries = [] for manifest in lm.get_installed(): - pkg_dir = manifest['__pkg_dir'] - if "@" in pkg_dir and "@vcs-" not in pkg_dir: - continue - elif "@vcs-" in pkg_dir: + if "@vcs-" in manifest['__pkg_dir']: libraries.append("%s=%s" % (manifest['name'], manifest['url'])) else: libraries.append(str(manifest.get("id", manifest['name']))) @@ -131,7 +128,7 @@ def lib_update(lm, libraries, only_check, json_output): for library in libraries: name, requirements, url = lm.parse_pkg_name(library) latest = lm.outdated(name, requirements, url) - if latest is False: + if not latest: continue manifest = lm.load_manifest( lm.get_package_dir(name, requirements, url)) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 2ff50df1..0d138633 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -337,11 +337,7 @@ def platform_update(platforms, only_packages, only_check, json_output): if not platforms: platforms = [] for manifest in pm.get_installed(): - pkg_dir = manifest['__pkg_dir'] - # don't check fixed platforms - if "@" in pkg_dir and "@vcs-" not in pkg_dir: - continue - elif "@vcs-" in pkg_dir: + if "@vcs-" in manifest['__pkg_dir']: platforms.append("%s=%s" % (manifest['name'], manifest['url'])) else: platforms.append(manifest['name']) @@ -351,7 +347,7 @@ def platform_update(platforms, only_packages, only_check, json_output): for platform in platforms: name, requirements, url = pm.parse_pkg_name(platform) latest = pm.outdated(name, requirements, url) - if latest is False: + if not latest: continue data = _get_installed_platform_data( name, with_boards=False, expose_packages=False) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 7097d10a..8350c330 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -501,7 +501,8 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): """ latest = None package_dir = self.get_package_dir(name, requirements, url) - if not package_dir: + if not package_dir or ("@" in package_dir and + "@vcs-" not in package_dir): return None is_vcs_pkg = False manifest_path = self.get_vcs_manifest_path(package_dir) @@ -598,10 +599,16 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): os.unlink(package_dir) else: util.rmtree_(package_dir) + self.reset_cache() + + # unfix package with the same name + package_dir = self.get_package_dir(manifest['name']) + if package_dir and "@" in package_dir: + os.rename(package_dir, join(self.package_dir, manifest['name'])) + self.reset_cache() click.echo("[%s]" % click.style("OK", fg="green")) - self.reset_cache() if trigger_event: telemetry.on_event( category=self.__class__.__name__, @@ -644,7 +651,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): elif latest is False: click.echo("[%s]" % (click.style("Up-to-date", fg="green"))) else: - click.echo("[%s]" % (click.style("Unknown", fg="yellow"))) + click.echo("[%s]" % (click.style("Skip", fg="yellow"))) if only_check or latest is False or (not is_vcs_pkg and not latest): return From 5e5c9d3bcf548c96c300aa0bd97f9316bcd50fc1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 5 Mar 2017 00:14:05 +0200 Subject: [PATCH 103/127] Generate valid directory name when move package --- platformio/managers/package.py | 16 +++++++++++----- tests/commands/test_lib.py | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 8350c330..76cac33c 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -170,6 +170,13 @@ class PkgInstallerMixin(object): fu = FileUnpacker(source_path, dest_dir) return fu.start() + @staticmethod + def generate_install_dirname(manifest): + name = manifest['name'] + if "id" in manifest: + name += "_ID%d" % manifest['id'] + return name + def get_vcs_manifest_path(self, pkg_dir): for item in os.listdir(pkg_dir): if not isdir(join(pkg_dir, item)): @@ -325,11 +332,8 @@ class PkgInstallerMixin(object): tmp_manifest = self.load_manifest(tmp_manifest_path) assert set(["name", "version"]) <= set(tmp_manifest.keys()) - name = tmp_manifest['name'] + name = self.generate_install_dirname(tmp_manifest) pkg_dir = join(self.package_dir, name) - if "id" in tmp_manifest: - name += "_ID%d" % tmp_manifest['id'] - pkg_dir = join(self.package_dir, name) # package should satisfy requirements if requirements: @@ -604,7 +608,9 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): # unfix package with the same name package_dir = self.get_package_dir(manifest['name']) if package_dir and "@" in package_dir: - os.rename(package_dir, join(self.package_dir, manifest['name'])) + os.rename(package_dir, + join(self.package_dir, + self.generate_install_dirname(manifest))) self.reset_cache() click.echo("[%s]" % click.style("OK", fg="green")) diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 79db2e28..3b3a213a 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -126,7 +126,7 @@ def test_global_lib_uninstall(clirunner, validate_cliresult, validate_cliresult(result) items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] items2 = [ - "DHT22_ID58", "ArduinoJson_ID64@5.6.7", "ESPAsyncTCP_ID305", + "DHT22_ID58", "ArduinoJson_ID64", "ESPAsyncTCP_ID305", "pubsubclient", "PJON", "rs485-nodeproto", "RadioHead_ID124" ] assert set(items1) == set(items2) From a235c532e409556b03cc7759fb6955aad6c6e0b4 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 6 Mar 2017 17:08:05 +0200 Subject: [PATCH 104/127] Add example how to get VCS revision "on-the-fly" for the Windows // Resolve #901 --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 60fe1ac9..dd49b472 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 60fe1ac9a59c9a611512ba6250a012b39a0614fb +Subproject commit dd49b472e66b43e9b361085821c0b498c50329a3 From 41cea7660356312d2c0b52a648790253eb705be0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 6 Mar 2017 17:45:38 +0200 Subject: [PATCH 105/127] =?UTF-8?q?New=20section=20for=20=E2=80=9Cplatform?= =?UTF-8?q?io.ini=E2=80=9D=20Dynamic=20build=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index dd49b472..5505597f 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit dd49b472e66b43e9b361085821c0b498c50329a3 +Subproject commit 5505597f60652bcb1571387e95c89c676ebc897e From 58942c3f38ac2d48622784ebcc0b6fe37f7a8d0f Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 8 Mar 2017 17:24:58 +0200 Subject: [PATCH 106/127] Significantly improve Package Manager // Resolve #913 * Handle dependencies when installing non-registry package/library (VCS, archive, local folder) --- HISTORY.rst | 1 + platformio/commands/lib.py | 31 +- platformio/commands/platform.py | 35 ++- platformio/maintenance.py | 5 +- platformio/managers/lib.py | 53 +--- platformio/managers/package.py | 498 +++++++++++++++++--------------- platformio/managers/platform.py | 96 +++--- platformio/util.py | 7 +- tests/commands/test_lib.py | 163 ++++++++--- tests/test_maintenance.py | 2 +- tests/test_managers.py | 162 +++++++++-- tests/test_pkgmanifest.py | 36 +-- tox.ini | 1 + 13 files changed, 657 insertions(+), 433 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index fa6f3a30..d535501a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -38,6 +38,7 @@ PlatformIO 3.0 * Escape project path when Glob matching is used * Do not overwrite project configuration variables when system environment variables are set +* Handle dependencies when installing non-registry package/library (VCS, archive, local folder) * Fixed package installing with VCS branch for Python 2.7.3 (`issue #885 `_) diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index d418221e..068c96b5 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -15,7 +15,7 @@ # pylint: disable=too-many-branches, too-many-locals import json -from os.path import join +from os.path import isdir, join from time import sleep from urllib import quote @@ -116,22 +116,23 @@ def lib_uninstall(lm, libraries): @click.pass_obj def lib_update(lm, libraries, only_check, json_output): if not libraries: - libraries = [] - for manifest in lm.get_installed(): - if "@vcs-" in manifest['__pkg_dir']: - libraries.append("%s=%s" % (manifest['name'], manifest['url'])) - else: - libraries.append(str(manifest.get("id", manifest['name']))) + libraries = [manifest['__pkg_dir'] for manifest in lm.get_installed()] if only_check and json_output: result = [] for library in libraries: - name, requirements, url = lm.parse_pkg_name(library) - latest = lm.outdated(name, requirements, url) + pkg_dir = library if isdir(library) else None + requirements = None + url = None + if not pkg_dir: + name, requirements, url = lm.parse_pkg_input(library) + pkg_dir = lm.get_package_dir(name, requirements, url) + if not pkg_dir: + continue + latest = lm.outdated(pkg_dir, requirements) if not latest: continue - manifest = lm.load_manifest( - lm.get_package_dir(name, requirements, url)) + manifest = lm.load_manifest(pkg_dir) manifest['versionLatest'] = latest result.append(manifest) return click.echo(json.dumps(result)) @@ -167,6 +168,9 @@ def print_lib_item(item): click.echo("Authors: %s" % ", ".join( item.get("authornames", [a.get("name", "") for a in item.get("authors", [])]))) + + if "__src_url" in item: + click.secho("Source: %s" % item['__src_url']) click.echo() @@ -270,8 +274,7 @@ def get_builtin_libs(storage_names=None): storage_names = storage_names or [] pm = PlatformManager() for manifest in pm.get_installed(): - p = PlatformFactory.newPlatform( - pm.get_manifest_path(manifest['__pkg_dir'])) + p = PlatformFactory.newPlatform(manifest['__pkg_dir']) for storage in p.get_lib_storages(): if storage_names and storage['name'] not in storage_names: continue @@ -308,7 +311,7 @@ def lib_builtin(storage, json_output): @click.option("--json-output", is_flag=True) def lib_show(library, json_output): lm = LibraryManager() - name, requirements, _ = lm.parse_pkg_name(library) + name, requirements, _ = lm.parse_pkg_input(library) lib_id = lm.get_pkg_id_by_name( name, requirements, silent=json_output, interactive=not json_output) lib = get_api_result("/lib/info/%d" % lib_id, cache_valid="1d") diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 0d138633..0d01cc6d 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -13,7 +13,7 @@ # limitations under the License. import json -from os.path import dirname, isfile, join +from os.path import dirname, isdir import click @@ -94,10 +94,12 @@ def _get_installed_platform_data(platform, # del data['version'] # return data - data['__pkg_dir'] = dirname(p.manifest_path) - # if VCS cloned platform - if not isfile(join(data['__pkg_dir'], "platform.json")): - data['__pkg_dir'] = dirname(data['__pkg_dir']) + # overwrite VCS version and add extra fields + manifest = PlatformManager().load_manifest(dirname(p.manifest_path)) + assert manifest + for key in manifest: + if key == "version" or key.startswith("__"): + data[key] = manifest[key] if with_boards: data['boards'] = [c.get_brief_data() for c in p.get_boards().values()] @@ -214,7 +216,7 @@ def platform_list(json_output): for manifest in pm.get_installed(): platforms.append( _get_installed_platform_data( - pm.get_manifest_path(manifest['__pkg_dir']), + manifest['__pkg_dir'], with_boards=False, expose_packages=False)) if json_output: @@ -336,22 +338,25 @@ def platform_update(platforms, only_packages, only_check, json_output): pm = PlatformManager() if not platforms: platforms = [] - for manifest in pm.get_installed(): - if "@vcs-" in manifest['__pkg_dir']: - platforms.append("%s=%s" % (manifest['name'], manifest['url'])) - else: - platforms.append(manifest['name']) + platforms = [manifest['__pkg_dir'] for manifest in pm.get_installed()] if only_check and json_output: result = [] for platform in platforms: - name, requirements, url = pm.parse_pkg_name(platform) - latest = pm.outdated(name, requirements, url) + pkg_dir = platform if isdir(platform) else None + requirements = None + url = None + if not pkg_dir: + name, requirements, url = pm.parse_pkg_input(platform) + pkg_dir = pm.get_package_dir(name, requirements, url) + if not pkg_dir: + continue + latest = pm.outdated(pkg_dir, requirements) if not latest: continue data = _get_installed_platform_data( - name, with_boards=False, expose_packages=False) - data['versionLatest'] = latest or "Unknown" + pkg_dir, with_boards=False, expose_packages=False) + data['versionLatest'] = latest result.append(data) return click.echo(json.dumps(result)) else: diff --git a/platformio/maintenance.py b/platformio/maintenance.py index af98280b..2acc8ef1 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -163,8 +163,7 @@ def after_upgrade(ctx): # update development platforms pm = PlatformManager() for manifest in pm.get_installed(): - # pm.update(manifest['name'], "^" + manifest['version']) - pm.update(manifest['name']) + pm.update(manifest['__pkg_dir']) # update PlatformIO Plus tool if installed pioplus_update() @@ -262,7 +261,7 @@ def check_internal_updates(ctx, what): outdated_items = [] for manifest in pm.get_installed(): if manifest['name'] not in outdated_items and \ - pm.outdated(manifest['name']): + pm.outdated(manifest['__pkg_dir']): outdated_items.append(manifest['name']) if not outdated_items: diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 0e9a5457..2b466c62 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -15,10 +15,8 @@ # pylint: disable=too-many-arguments, too-many-locals, too-many-branches import json -import os import re from glob import glob -from hashlib import md5 from os.path import isdir, join import arrow @@ -61,8 +59,8 @@ class LibraryManager(BasePkgManager): return None - def load_manifest(self, path): - manifest = BasePkgManager.load_manifest(self, path) + def load_manifest(self, pkg_dir): + manifest = BasePkgManager.load_manifest(self, pkg_dir) if not manifest: return manifest @@ -76,6 +74,9 @@ class LibraryManager(BasePkgManager): manifest['authors'] = [{"name": manifest['author']}] del manifest['author'] + if "authors" in manifest and not isinstance(manifest['authors'], list): + manifest['authors'] = [manifest['authors']] + if "keywords" not in manifest: keywords = [] for keyword in re.split(r"[\s/]+", @@ -123,31 +124,6 @@ class LibraryManager(BasePkgManager): return manifest - def check_pkg_structure(self, pkg_dir): - try: - return BasePkgManager.check_pkg_structure(self, pkg_dir) - except exception.MissingPackageManifest: - # we will generate manifest automatically - # if library doesn't contain any - pass - - manifest = { - "name": "Library_" + md5(pkg_dir).hexdigest()[:5], - "version": "0.0.0" - } - for root, dirs, files in os.walk(pkg_dir): - if len(dirs) == 1 and not files: - manifest['name'] = dirs[0] - continue - if dirs or files: - pkg_dir = root - break - - with open(join(pkg_dir, self.manifest_names[0]), "w") as fp: - json.dump(manifest, fp) - - return pkg_dir - @staticmethod def normalize_dependencies(dependencies): if not dependencies: @@ -239,7 +215,7 @@ class LibraryManager(BasePkgManager): }, silent, interactive)['id']) def _install_from_piorepo(self, name, requirements): - assert name.startswith("id=") + assert name.startswith("id="), name version = self.get_latest_repo_version(name, requirements) if not version: raise exception.UndefinedPackageVersion(requirements or "latest", @@ -260,28 +236,23 @@ class LibraryManager(BasePkgManager): silent=False, trigger_event=True, interactive=False): - already_installed = False - _name, _requirements, _url = self.parse_pkg_name(name, requirements) - try: + _name, _requirements, _url = self.parse_pkg_input(name, + requirements) if not _url: - _name = "id=%d" % self.get_pkg_id_by_name( + name = "id=%d" % self.get_pkg_id_by_name( _name, _requirements, silent=silent, interactive=interactive) - already_installed = self.get_package(_name, _requirements, _url) - pkg_dir = BasePkgManager.install( - self, _name - if not _url else name, _requirements, silent, trigger_event) + requirements = _requirements + pkg_dir = BasePkgManager.install(self, name, requirements, silent, + trigger_event) except exception.InternetIsOffline as e: if not silent: click.secho(str(e), fg="yellow") return - if already_installed: - return - manifest = self.load_manifest(pkg_dir) if "dependencies" not in manifest: return pkg_dir diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 76cac33c..94e59e87 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -17,7 +17,7 @@ import hashlib import json import os import shutil -from os.path import basename, dirname, getsize, isdir, isfile, islink, join +from os.path import basename, getsize, isdir, isfile, islink, join from tempfile import mkdtemp import click @@ -127,16 +127,36 @@ class PkgRepoMixin(object): class PkgInstallerMixin(object): - VCS_MANIFEST_NAME = ".piopkgmanager.json" + SRC_MANIFEST_NAME = ".piopkgmanager.json" FILE_CACHE_VALID = "1m" # 1 month FILE_CACHE_MAX_SIZE = 1024 * 1024 - _INSTALLED_CACHE = {} + MEMORY_CACHE = {} - def reset_cache(self): - if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: - del PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] + @staticmethod + def cache_get(key, default=None): + return PkgInstallerMixin.MEMORY_CACHE.get(key, default) + + @staticmethod + def cache_set(key, value): + PkgInstallerMixin.MEMORY_CACHE[key] = value + + @staticmethod + def cache_reset(): + PkgInstallerMixin.MEMORY_CACHE = {} + + def read_dirs(self, src_dir): + cache_key = "read_dirs-%s" % src_dir + result = self.cache_get(cache_key) + if result: + return result + result = [ + join(src_dir, name) for name in sorted(os.listdir(src_dir)) + if isdir(join(src_dir, name)) + ] + self.cache_set(cache_key, result) + return result def download(self, url, dest_dir, sha1=None): cache_key_fname = app.ContentCache.key_from_args(url, "fname") @@ -171,26 +191,23 @@ class PkgInstallerMixin(object): return fu.start() @staticmethod - def generate_install_dirname(manifest): + def get_install_dirname(manifest): name = manifest['name'] if "id" in manifest: name += "_ID%d" % manifest['id'] return name - def get_vcs_manifest_path(self, pkg_dir): + def get_src_manifest_path(self, pkg_dir): for item in os.listdir(pkg_dir): if not isdir(join(pkg_dir, item)): continue - if isfile(join(pkg_dir, item, self.VCS_MANIFEST_NAME)): - return join(pkg_dir, item, self.VCS_MANIFEST_NAME) + if isfile(join(pkg_dir, item, self.SRC_MANIFEST_NAME)): + return join(pkg_dir, item, self.SRC_MANIFEST_NAME) return None def get_manifest_path(self, pkg_dir): if not isdir(pkg_dir): return None - manifest_path = self.get_vcs_manifest_path(pkg_dir) - if manifest_path: - return manifest_path for name in self.manifest_names: manifest_path = join(pkg_dir, name) if isfile(manifest_path): @@ -198,73 +215,104 @@ class PkgInstallerMixin(object): return None def manifest_exists(self, pkg_dir): - return self.get_manifest_path(pkg_dir) is not None + return self.get_manifest_path(pkg_dir) or \ + self.get_src_manifest_path(pkg_dir) - def load_manifest(self, path): # pylint: disable=too-many-branches - assert path - pkg_dir = path - if isdir(path): - path = self.get_manifest_path(path) - if not path: - return None - else: - pkg_dir = dirname(pkg_dir) + def load_manifest(self, pkg_dir): + cache_key = "load_manifest-%s" % pkg_dir + result = self.cache_get(cache_key) + if result: + return result - is_vcs_pkg = False - if isfile(path) and path.endswith(self.VCS_MANIFEST_NAME): - is_vcs_pkg = True - pkg_dir = dirname(dirname(path)) + manifest_path = self.get_manifest_path(pkg_dir) + if not manifest_path: + return None - # return from cache - if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: - for manifest in PkgInstallerMixin._INSTALLED_CACHE[ - self.package_dir]: - if not is_vcs_pkg and manifest['__pkg_dir'] == pkg_dir: - return manifest + # if non-registry packages: VCS or archive + src_manifest_path = self.get_src_manifest_path(pkg_dir) + src_manifest = None + if src_manifest_path: + src_manifest = util.load_json(src_manifest_path) manifest = {} - if path.endswith(".json"): - manifest = util.load_json(path) - elif path.endswith(".properties"): - with codecs.open(path, encoding="utf-8") as fp: + if manifest_path.endswith(".json"): + manifest = util.load_json(manifest_path) + elif manifest_path.endswith(".properties"): + with codecs.open(manifest_path, encoding="utf-8") as fp: for line in fp.readlines(): if "=" not in line: continue key, value = line.split("=", 1) manifest[key.strip()] = value.strip() - else: + + if src_manifest: if "name" not in manifest: - manifest['name'] = basename(pkg_dir) - if "version" not in manifest: - manifest['version'] = "0.0.0" + manifest['name'] = src_manifest['name'] + if "version" in src_manifest: + manifest['version'] = src_manifest['version'] + manifest['__src_url'] = src_manifest['url'] + + if "name" not in manifest: + manifest['name'] = basename(pkg_dir) + if "version" not in manifest: + manifest['version'] = "0.0.0" manifest['__pkg_dir'] = pkg_dir + self.cache_set(cache_key, manifest) return manifest def get_installed(self): - if self.package_dir in PkgInstallerMixin._INSTALLED_CACHE: - return PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] items = [] - for p in sorted(os.listdir(self.package_dir)): - pkg_dir = join(self.package_dir, p) - if not isdir(pkg_dir): - continue + for pkg_dir in self.read_dirs(self.package_dir): manifest = self.load_manifest(pkg_dir) if not manifest: continue assert "name" in manifest items.append(manifest) - PkgInstallerMixin._INSTALLED_CACHE[self.package_dir] = items return items - def check_pkg_structure(self, pkg_dir): - if self.manifest_exists(pkg_dir): - return pkg_dir + def get_package(self, name, requirements=None, url=None): + pkg_id = int(name[3:]) if name.startswith("id=") else 0 + best = None + for manifest in self.get_installed(): + if url: + if manifest.get("__src_url") != url: + continue + elif pkg_id and manifest.get("id") != pkg_id: + continue + elif not pkg_id and manifest['name'] != name: + continue - for root, _, _ in os.walk(pkg_dir): + # strict version or VCS HASH + if requirements and requirements == manifest['version']: + return manifest + + try: + if requirements and not semantic_version.Spec( + requirements).match( + semantic_version.Version( + manifest['version'], partial=True)): + continue + elif not best or (semantic_version.Version( + manifest['version'], partial=True) > + semantic_version.Version( + best['version'], partial=True)): + best = manifest + except ValueError: + pass + + return best + + def get_package_dir(self, name, requirements=None, url=None): + manifest = self.get_package(name, requirements, url) + return manifest.get("__pkg_dir") if manifest else None + + def find_pkg_root(self, src_dir): + if self.manifest_exists(src_dir): + return src_dir + for root, _, _ in os.walk(src_dir): if self.manifest_exists(root): return root - raise exception.MissingPackageManifest(", ".join(self.manifest_names)) def _install_from_piorepo(self, name, requirements): @@ -291,18 +339,25 @@ class PkgInstallerMixin(object): util.get_systype()) return pkg_dir - def _install_from_url(self, name, url, requirements=None, sha1=None): + def _install_from_url(self, + name, + url, + requirements=None, + sha1=None, + track=False): pkg_dir = None tmp_dir = mkdtemp("-package", "installing-", self.package_dir) + src_manifest_dir = None + src_manifest = {"name": name, "url": url, "requirements": requirements} try: if url.startswith("file://"): - url = url[7:] - if isfile(url): - self.unpack(url, tmp_dir) + _url = url[7:] + if isfile(_url): + self.unpack(_url, tmp_dir) else: util.rmtree_(tmp_dir) - shutil.copytree(url, tmp_dir) + shutil.copytree(_url, tmp_dir) elif url.startswith(("http://", "https://")): dlpath = self.download(url, tmp_dir, sha1) assert isfile(dlpath) @@ -311,29 +366,52 @@ class PkgInstallerMixin(object): else: vcs = VCSClientFactory.newClient(tmp_dir, url) assert vcs.export() - with open(join(vcs.storage_dir, self.VCS_MANIFEST_NAME), - "w") as fp: - json.dump({ - "name": name, - "version": vcs.get_current_revision(), - "url": url, - "requirements": requirements - }, fp) + src_manifest_dir = vcs.storage_dir + src_manifest['version'] = vcs.get_current_revision() + + pkg_dir = self.find_pkg_root(tmp_dir) + + # write source data to a special manifest + if track: + if not src_manifest_dir: + src_manifest_dir = join(pkg_dir, ".pio") + self._update_src_manifest(src_manifest, src_manifest_dir) - pkg_dir = self.check_pkg_structure(tmp_dir) pkg_dir = self._install_from_tmp_dir(pkg_dir, requirements) finally: if isdir(tmp_dir): util.rmtree_(tmp_dir) return pkg_dir - def _install_from_tmp_dir(self, tmp_dir, requirements=None): - tmp_manifest_path = self.get_manifest_path(tmp_dir) - tmp_manifest = self.load_manifest(tmp_manifest_path) + def _update_src_manifest(self, data, src_dir): + if not isdir(src_dir): + os.makedirs(src_dir) + src_manifest_path = join(src_dir, self.SRC_MANIFEST_NAME) + _data = data + if isfile(src_manifest_path): + _data.update(util.load_json(src_manifest_path)) + with open(src_manifest_path, "w") as fp: + json.dump(_data, fp) + + def _install_from_tmp_dir( # pylint: disable=too-many-branches + self, tmp_dir, requirements=None): + tmp_manifest = self.load_manifest(tmp_dir) assert set(["name", "version"]) <= set(tmp_manifest.keys()) - name = self.generate_install_dirname(tmp_manifest) - pkg_dir = join(self.package_dir, name) + pkg_dirname = self.get_install_dirname(tmp_manifest) + pkg_dir = join(self.package_dir, pkg_dirname) + cur_manifest = self.load_manifest(pkg_dir) + + tmp_semver = None + cur_semver = None + try: + tmp_semver = semantic_version.Version( + tmp_manifest['version'], partial=True) + if cur_manifest: + cur_semver = semantic_version.Version( + cur_manifest['version'], partial=True) + except ValueError: + pass # package should satisfy requirements if requirements: @@ -341,45 +419,51 @@ class PkgInstallerMixin(object): "Package version %s doesn't satisfy requirements %s" % ( tmp_manifest['version'], requirements)) try: - reqspec = semantic_version.Spec(requirements) - tmp_version = semantic_version.Version( - tmp_manifest['version'], partial=True) - assert tmp_version in reqspec, mismatch_error - except ValueError: + assert tmp_semver and tmp_semver in semantic_version.Spec( + requirements), mismatch_error + except (AssertionError, ValueError): assert tmp_manifest['version'] == requirements, mismatch_error - if self.manifest_exists(pkg_dir): - cur_manifest_path = self.get_manifest_path(pkg_dir) - cur_manifest = self.load_manifest(cur_manifest_path) - - if tmp_manifest_path.endswith(self.VCS_MANIFEST_NAME): - if cur_manifest.get("url") != tmp_manifest['url']: - pkg_dir = join(self.package_dir, "%s@vcs-%s" % ( - name, hashlib.md5(tmp_manifest['url']).hexdigest())) + # check if package already exists + if cur_manifest: + # 0-overwrite, 1-rename, 2-fix to a version + action = 0 + if "__src_url" in cur_manifest: + if cur_manifest['__src_url'] != tmp_manifest.get("__src_url"): + action = 1 + elif "__src_url" in tmp_manifest: + action = 2 else: - try: - tmp_version = semantic_version.Version( - tmp_manifest['version'], partial=True) - cur_version = semantic_version.Version( - cur_manifest['version'], partial=True) + if tmp_semver and (not cur_semver or tmp_semver > cur_semver): + action = 1 + elif tmp_semver and cur_semver and tmp_semver != cur_semver: + action = 2 - # if current package version < new package, backup it - if tmp_version > cur_version: - os.rename(pkg_dir, - join(self.package_dir, "%s@%s" % - (name, cur_manifest['version']))) - elif tmp_version < cur_version: - pkg_dir = join(self.package_dir, "%s@%s" % - (name, tmp_manifest['version'])) - except ValueError: - pkg_dir = join(self.package_dir, - "%s@%s" % (name, tmp_manifest['version'])) + # rename + if action == 1: + target_dirname = "%s@%s" % (pkg_dirname, + cur_manifest['version']) + if "__src_url" in cur_manifest: + target_dirname = "%s@src-%s" % ( + pkg_dirname, + hashlib.md5(cur_manifest['__src_url']).hexdigest()) + os.rename(pkg_dir, join(self.package_dir, target_dirname)) + # fix to a version + elif action == 2: + target_dirname = "%s@%s" % (pkg_dirname, + tmp_manifest['version']) + if "__src_url" in tmp_manifest: + target_dirname = "%s@src-%s" % ( + pkg_dirname, + hashlib.md5(tmp_manifest['__src_url']).hexdigest()) + pkg_dir = join(self.package_dir, target_dirname) # remove previous/not-satisfied package if isdir(pkg_dir): util.rmtree_(pkg_dir) os.rename(tmp_dir, pkg_dir) assert isdir(pkg_dir) + self.cache_reset() return pkg_dir @@ -400,14 +484,20 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl) @staticmethod - def parse_pkg_name( # pylint: disable=too-many-branches + def parse_pkg_input( # pylint: disable=too-many-branches text, requirements=None): text = str(text) - url_marker = "://" - if not any([ - requirements, "@" not in text, text.startswith("git@"), - url_marker in text - ]): + # git@github.com:user/package.git + url_marker = text[:4] + if url_marker not in ("git@", "git+") or ":" not in text: + url_marker = "://" + + req_conditions = [ + not requirements, "@" in text, + (url_marker != "git@" and "://git@" not in text) or + text.count("@") > 1 + ] + if all(req_conditions): text, requirements = text.rsplit("@", 1) if text.isdigit(): text = "id=" + text @@ -423,22 +513,18 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): url.startswith("http") and (url.split("#", 1)[0] if "#" in url else url).endswith(".git") ] - if any(git_conditions): url = "git+" + url + # Handle Developer Mbed URL # (https://developer.mbed.org/users/user/code/package/) - elif url.startswith("https://developer.mbed.org"): + if url.startswith("https://developer.mbed.org"): url = "hg+" + url - # git@github.com:user/package.git - if url.startswith("git@"): - url_marker = "git@" - if any([s in url for s in ("\\", "/")]) and url_marker not in url: if isfile(url) or isdir(url): url = "file://" + url - elif url.count("/") == 1 and not url.startswith("git@"): + elif url.count("/") == 1 and "git" not in url_marker: url = "git+https://github.com/" + url # determine name @@ -448,55 +534,13 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): _url = _url[:-1] name = basename(_url) if "." in name and not name.startswith("."): - name = name.split(".", 1)[0] + name = name.rsplit(".", 1)[0] if url_marker not in url: url = None return (name or text, requirements, url) - def get_package(self, name, requirements=None, url=None): - pkg_id = int(name[3:]) if name.startswith("id=") else 0 - best = None - reqspec = None - if requirements: - try: - reqspec = semantic_version.Spec(requirements) - except ValueError: - pass - - for manifest in self.get_installed(): - if pkg_id and manifest.get("id") != pkg_id: - continue - elif not pkg_id and manifest['name'] != name: - continue - elif not reqspec and (requirements or url): - conds = [ - requirements == manifest['version'], url and - url in manifest.get("url", "") - ] - if not best or any(conds): - best = manifest - continue - try: - if reqspec and not reqspec.match( - semantic_version.Version( - manifest['version'], partial=True)): - continue - elif not best or (semantic_version.Version( - manifest['version'], partial=True) > - semantic_version.Version( - best['version'], partial=True)): - best = manifest - except ValueError: - pass - - return best - - def get_package_dir(self, name, requirements=None, url=None): - package = self.get_package(name, requirements, url) - return package.get("__pkg_dir") if package else None - - def outdated(self, name, requirements=None, url=None): + def outdated(self, pkg_dir, requirements=None): """ Has 3 different results: `None` - unknown package, VCS is fixed to commit @@ -504,27 +548,26 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): `String` - a found latest version """ latest = None - package_dir = self.get_package_dir(name, requirements, url) - if not package_dir or ("@" in package_dir and - "@vcs-" not in package_dir): + manifest = self.load_manifest(pkg_dir) + # skip a fixed package to a specific version + if "@" in pkg_dir and "__src_url" not in manifest: return None - is_vcs_pkg = False - manifest_path = self.get_vcs_manifest_path(package_dir) - if manifest_path: - is_vcs_pkg = True - manifest = self.load_manifest(manifest_path) - else: - manifest = self.load_manifest(package_dir) - if is_vcs_pkg: - vcs = VCSClientFactory.newClient( - package_dir, manifest['url'], silent=True) + if "__src_url" in manifest: + try: + vcs = VCSClientFactory.newClient( + pkg_dir, manifest['__src_url'], silent=True) + except (AttributeError, exception.PlatformioException): + return None if not vcs.can_be_updated: return None latest = vcs.get_latest_revision() else: try: latest = self.get_latest_repo_version( - name, requirements, silent=True) + "id=%d" % manifest['id'] + if "id" in manifest else manifest['name'], + requirements, + silent=True) except (exception.PlatformioException, ValueError): return None if not latest: @@ -543,7 +586,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): silent=False, trigger_event=True, interactive=False): # pylint: disable=unused-argument - name, requirements, url = self.parse_pkg_name(name, requirements) + name, requirements, url = self.parse_pkg_input(name, requirements) package_dir = self.get_package_dir(name, requirements, url) if not package_dir or not silent: @@ -560,15 +603,16 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): return package_dir if url: - pkg_dir = self._install_from_url(name, url, requirements) + pkg_dir = self._install_from_url( + name, url, requirements, track=True) else: pkg_dir = self._install_from_piorepo(name, requirements) if not pkg_dir or not self.manifest_exists(pkg_dir): raise exception.PackageInstallError(name, requirements or "*", util.get_systype()) - self.reset_cache() manifest = self.load_manifest(pkg_dir) + assert manifest if trigger_event: telemetry.on_event( @@ -576,42 +620,45 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): action="Install", label=manifest['name']) - click.secho( - "{name} @ {version} has been successfully installed!".format( - **manifest), - fg="green") + if not silent: + click.secho( + "{name} @ {version} has been successfully installed!".format( + **manifest), + fg="green") return pkg_dir - def uninstall(self, name, requirements=None, trigger_event=True): - name, requirements, url = self.parse_pkg_name(name, requirements) - package_dir = self.get_package_dir(name, requirements, url) - if not package_dir: - click.secho( - "%s @ %s is not installed" % (name, requirements or "*"), - fg="yellow") - return + def uninstall(self, package, requirements=None, trigger_event=True): + if isdir(package): + pkg_dir = package + else: + name, requirements, url = self.parse_pkg_input(package, + requirements) + pkg_dir = self.get_package_dir(name, requirements, url) - manifest = self.load_manifest(package_dir) + if not pkg_dir: + raise exception.UnknownPackage("%s @ %s" % + (package, requirements or "*")) + + manifest = self.load_manifest(pkg_dir) click.echo( "Uninstalling %s @ %s: \t" % (click.style( manifest['name'], fg="cyan"), manifest['version']), nl=False) - if isdir(package_dir): - if islink(package_dir): - os.unlink(package_dir) - else: - util.rmtree_(package_dir) - self.reset_cache() + if islink(pkg_dir): + os.unlink(pkg_dir) + else: + util.rmtree_(pkg_dir) + self.cache_reset() # unfix package with the same name - package_dir = self.get_package_dir(manifest['name']) - if package_dir and "@" in package_dir: - os.rename(package_dir, - join(self.package_dir, - self.generate_install_dirname(manifest))) - self.reset_cache() + pkg_dir = self.get_package_dir(manifest['name']) + if pkg_dir and "@" in pkg_dir: + os.rename( + pkg_dir, + join(self.package_dir, self.get_install_dirname(manifest))) + self.cache_reset() click.echo("[%s]" % click.style("OK", fg="green")) @@ -624,25 +671,23 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): def update( # pylint: disable=too-many-return-statements self, - name, + package, requirements=None, only_check=False): - name, requirements, url = self.parse_pkg_name(name, requirements) - package_dir = self.get_package_dir(name, requirements, url) - if not package_dir: - click.secho( - "%s @ %s is not installed" % (name, requirements or "*"), - fg="yellow") - return - - is_vcs_pkg = False - if self.get_vcs_manifest_path(package_dir): - is_vcs_pkg = True - manifest_path = self.get_vcs_manifest_path(package_dir) + if isdir(package): + pkg_dir = package else: - manifest_path = self.get_manifest_path(package_dir) + name, requirements, url = self.parse_pkg_input(package, + requirements) + pkg_dir = self.get_package_dir(name, requirements, url) + + if not pkg_dir: + raise exception.UnknownPackage("%s @ %s" % + (package, requirements or "*")) + + manifest = self.load_manifest(pkg_dir) + name = manifest['name'] - manifest = self.load_manifest(manifest_path) click.echo( "{} {:<40} @ {:<15}".format( "Checking" if only_check else "Updating", @@ -651,7 +696,8 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): if not util.internet_on(): click.echo("[%s]" % (click.style("Off-line", fg="yellow"))) return - latest = self.outdated(name, requirements, url) + + latest = self.outdated(pkg_dir, requirements) if latest: click.echo("[%s]" % (click.style(latest, fg="red"))) elif latest is False: @@ -659,26 +705,18 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): else: click.echo("[%s]" % (click.style("Skip", fg="yellow"))) - if only_check or latest is False or (not is_vcs_pkg and not latest): + if only_check or not latest: return - if is_vcs_pkg: - vcs = VCSClientFactory.newClient(package_dir, manifest['url']) - if not vcs.can_be_updated: - click.secho( - "Skip update because repository is fixed " - "to %s revision" % manifest['version'], - fg="yellow") - return + if "__src_url" in manifest: + vcs = VCSClientFactory.newClient(pkg_dir, manifest['__vcs_url']) assert vcs.update() - with open(manifest_path, "w") as fp: - manifest['version'] = vcs.get_current_revision() - json.dump(manifest, fp) + self._update_src_manifest( + dict(version=vcs.get_current_revision()), vcs.storage_dir) else: - self.uninstall(name, manifest['version'], trigger_event=False) + self.uninstall(pkg_dir, trigger_event=False) self.install(name, latest, trigger_event=False) - self.reset_cache() telemetry.on_event( category=self.__class__.__name__, action="Update", diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 78516b73..dddafc45 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -63,7 +63,7 @@ class PlatformManager(BasePkgManager): trigger_event=True, **_): # pylint: disable=too-many-arguments platform_dir = BasePkgManager.install(self, name, requirements) - p = PlatformFactory.newPlatform(self.get_manifest_path(platform_dir)) + p = PlatformFactory.newPlatform(platform_dir) # @Hook: when 'update' operation (trigger_event is False), # don't cleanup packages or install them @@ -75,10 +75,16 @@ class PlatformManager(BasePkgManager): self.cleanup_packages(p.packages.keys()) return True - def uninstall(self, name, requirements=None, trigger_event=True): - name, requirements, _ = self.parse_pkg_name(name, requirements) - p = PlatformFactory.newPlatform(name, requirements) - BasePkgManager.uninstall(self, name, requirements) + def uninstall(self, package, requirements=None, trigger_event=True): + if isdir(package): + pkg_dir = package + else: + name, requirements, url = self.parse_pkg_input(package, + requirements) + pkg_dir = self.get_package_dir(name, requirements, url) + + p = PlatformFactory.newPlatform(pkg_dir) + BasePkgManager.uninstall(self, pkg_dir, requirements) # @Hook: when 'update' operation (trigger_event is False), # don't cleanup packages or install them @@ -90,18 +96,23 @@ class PlatformManager(BasePkgManager): def update( # pylint: disable=arguments-differ self, - name, + package, requirements=None, - only_packages=False, - only_check=False): - name, requirements, _ = self.parse_pkg_name(name, requirements) + only_check=False, + only_packages=False): + if isdir(package): + pkg_dir = package + else: + name, requirements, url = self.parse_pkg_input(package, + requirements) + pkg_dir = self.get_package_dir(name, requirements, url) - p = PlatformFactory.newPlatform(name, requirements) + p = PlatformFactory.newPlatform(pkg_dir) pkgs_before = pkgs_after = p.get_installed_packages().keys() if not only_packages: - BasePkgManager.update(self, name, requirements, only_check) - p = PlatformFactory.newPlatform(name, requirements) + BasePkgManager.update(self, pkg_dir, requirements, only_check) + p = PlatformFactory.newPlatform(pkg_dir) pkgs_after = p.get_installed_packages().keys() p.update_packages(only_check) @@ -115,11 +126,10 @@ class PlatformManager(BasePkgManager): return True def cleanup_packages(self, names): - self.reset_cache() + self.cache_reset() deppkgs = {} for manifest in PlatformManager().get_installed(): - p = PlatformFactory.newPlatform(manifest['name'], - manifest['version']) + p = PlatformFactory.newPlatform(manifest['__pkg_dir']) for pkgname, pkgmanifest in p.get_installed_packages().items(): if pkgname not in deppkgs: deppkgs[pkgname] = set() @@ -131,17 +141,15 @@ class PlatformManager(BasePkgManager): continue if (manifest['name'] not in deppkgs or manifest['version'] not in deppkgs[manifest['name']]): - pm.uninstall( - manifest['name'], manifest['version'], trigger_event=False) + pm.uninstall(manifest['__pkg_dir'], trigger_event=False) - self.reset_cache() + self.cache_reset() return True def get_installed_boards(self): boards = [] for manifest in self.get_installed(): - p = PlatformFactory.newPlatform( - self.get_manifest_path(manifest['__pkg_dir'])) + p = PlatformFactory.newPlatform(manifest['__pkg_dir']) for config in p.get_boards().values(): board = config.get_brief_data() if board not in boards: @@ -183,7 +191,10 @@ class PlatformFactory(object): @classmethod def newPlatform(cls, name, requirements=None): platform_dir = None - if name.endswith("platform.json") and isfile(name): + if isdir(name): + platform_dir = name + name = PlatformManager().load_manifest(platform_dir)['name'] + elif name.endswith("platform.json") and isfile(name): platform_dir = dirname(name) name = util.load_json(name)['name'] else: @@ -249,8 +260,8 @@ class PlatformPackagesMixin(object): if self.is_valid_requirements(version): package = self.pm.get_package(name, version) else: - package = self.pm.get_package(*self._parse_pkg_name(name, - version)) + package = self.pm.get_package(*self._parse_pkg_input(name, + version)) if package: items[name] = package return items @@ -267,46 +278,47 @@ class PlatformPackagesMixin(object): self.pm.update("%s=%s" % (name, version), requirements, only_check) - def are_outdated_packages(self): - latest = None - for name in self.get_installed_packages(): - version = self.packages[name].get("version", "") - if self.is_valid_requirements(version): - latest = self.pm.outdated(name, version) - else: - requirements = None - if "@" in version: - version, requirements = version.rsplit("@", 1) - latest = self.pm.outdated(name, requirements, version) - if latest or latest is None: - return True - return False + # def are_outdated_packages(self): + # latest = None + # for name in self.get_installed_packages(): + # version = self.packages[name].get("version", "") + # if self.is_valid_requirements(version): + # latest = self.pm.outdated(name, version) + # else: + # requirements = None + # if "@" in version: + # version, requirements = version.rsplit("@", 1) + # latest = self.pm.outdated(name, requirements, version) + # if latest or latest is None: + # return True + # return False def get_package_dir(self, name): version = self.packages[name].get("version", "") if self.is_valid_requirements(version): return self.pm.get_package_dir(name, version) else: - return self.pm.get_package_dir(*self._parse_pkg_name(name, - version)) + return self.pm.get_package_dir(*self._parse_pkg_input(name, + version)) def get_package_version(self, name): version = self.packages[name].get("version", "") if self.is_valid_requirements(version): package = self.pm.get_package(name, version) else: - package = self.pm.get_package(*self._parse_pkg_name(name, version)) + package = self.pm.get_package(*self._parse_pkg_input(name, + version)) return package['version'] if package else None @staticmethod def is_valid_requirements(requirements): return requirements and "://" not in requirements - def _parse_pkg_name(self, name, version): + def _parse_pkg_input(self, name, version): requirements = None if "@" in version: version, requirements = version.rsplit("@", 1) - return self.pm.parse_pkg_name("%s=%s" % (name, version), requirements) + return self.pm.parse_pkg_input("%s=%s" % (name, version), requirements) class PlatformRunMixin(object): diff --git a/platformio/util.py b/platformio/util.py index 1e70b471..20d6214a 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -141,7 +141,12 @@ class memoized(object): def __get__(self, obj, objtype): '''Support instance methods.''' - return functools.partial(self.__call__, obj) + fn = functools.partial(self.__call__, obj) + fn.reset = self._reset + return fn + + def _reset(self): + self.cache = {} def singleton(cls): diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 3b3a213a..d0ae5665 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -16,7 +16,7 @@ import json import re from os.path import basename -from platformio import util +from platformio import exception, util from platformio.commands.init import cli as cmd_init from platformio.commands.lib import cli as cmd_lib @@ -37,15 +37,35 @@ def test_search(clirunner, validate_cliresult): def test_global_install_registry(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, [ - "-g", "install", "58", "OneWire", + "-g", "install", "58", "547@2.2.4", "DallasTemperature", "http://dl.platformio.org/libraries/archives/3/5174.tar.gz", - "ArduinoJson@5.6.7", "ArduinoJson@~5.7.0" + "ArduinoJson@5.6.7", "ArduinoJson@~5.7.0", "1089@fee16e880b" ]) validate_cliresult(result) + + # check lib with duplicate URL + result = clirunner.invoke(cmd_lib, [ + "-g", "install", + "http://dl.platformio.org/libraries/archives/3/5174.tar.gz" + ]) + validate_cliresult(result) + assert "is already installed" in result.output + + # check lib with duplicate ID + result = clirunner.invoke(cmd_lib, ["-g", "install", "305"]) + validate_cliresult(result) + assert "is already installed" in result.output + + # install unknown library + result = clirunner.invoke(cmd_lib, ["-g", "install", "Unknown"]) + assert result.exit_code != 0 + assert isinstance(result.exception, exception.LibNotFound) + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] items2 = [ - "DHT22_ID58", "ArduinoJson_ID64", "ArduinoJson_ID64@5.6.7", - "OneWire_ID1", "ESPAsyncTCP_ID305" + "ArduinoJson_ID64", "ArduinoJson_ID64@5.6.7", "DallasTemperature_ID54", + "DHT22_ID58", "ESPAsyncTCP_ID305", "NeoPixelBus_ID547", "OneWire_ID1", + "IRremoteESP8266_ID1089" ] assert set(items1) == set(items2) @@ -55,11 +75,29 @@ def test_global_install_archive(clirunner, validate_cliresult, result = clirunner.invoke(cmd_lib, [ "-g", "install", "https://github.com/adafruit/Adafruit-ST7735-Library/" "archive/master.zip", + "http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.62.zip", + "https://github.com/bblanchon/ArduinoJson/archive/v5.8.2.zip", + "https://github.com/bblanchon/ArduinoJson/archive/v5.8.2.zip@5.8.2" + ]) + validate_cliresult(result) + + # incorrect requirements + result = clirunner.invoke(cmd_lib, [ + "-g", "install", + "https://github.com/bblanchon/ArduinoJson/archive/v5.8.2.zip@1.2.3" + ]) + assert result.exit_code != 0 + + # check lib with duplicate URL + result = clirunner.invoke(cmd_lib, [ + "-g", "install", "http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.62.zip" ]) validate_cliresult(result) + assert "is already installed" in result.output + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] - items2 = ["Adafruit ST7735 Library", "RadioHead"] + items2 = ["Adafruit ST7735 Library", "RadioHead-1.62"] assert set(items1) >= set(items2) @@ -71,14 +109,20 @@ def test_global_install_repository(clirunner, validate_cliresult, "-g", "install", "https://github.com/gioblu/PJON.git#3.0", + "https://github.com/gioblu/PJON.git#6.2", + "https://github.com/bblanchon/ArduinoJson.git", "https://gitlab.com/ivankravets/rs485-nodeproto.git", # "https://developer.mbed.org/users/simon/code/TextLCD/", "knolleary/pubsubclient" ]) validate_cliresult(result) items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] - items2 = ["PJON", "ESPAsyncTCP", "PubSubClient"] - assert set(items2) & set(items1) + items2 = [ + "PJON", "PJON@src-79de467ebe19de18287becff0a1fb42d", + "ArduinoJson@src-69ebddd821f771debe7ee734d3c7fa81", "rs485-nodeproto", + "PubSubClient" + ] + assert set(items1) >= set(items2) def test_global_lib_list(clirunner, validate_cliresult, isolated_pio_home): @@ -89,13 +133,15 @@ def test_global_lib_list(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["-g", "list", "--json-output"]) assert all([ n in result.output - for n in ("PJON", "git+https://github.com/knolleary/pubsubclient") + for n in ("PJON", "git+https://github.com/knolleary/pubsubclient", + "https://github.com/bblanchon/ArduinoJson/archive/v5.8.2.zip" + ) ]) items1 = [i['name'] for i in json.loads(result.output)] items2 = [ "OneWire", "DHT22", "PJON", "ESPAsyncTCP", "ArduinoJson", - "pubsubclient", "rs485-nodeproto", "Adafruit ST7735 Library", - "RadioHead" + "PubSubClient", "rs485-nodeproto", "Adafruit ST7735 Library", + "RadioHead-1.62", "DallasTemperature", "NeoPixelBus", "IRremoteESP8266" ] assert set(items1) == set(items2) @@ -106,31 +152,71 @@ def test_global_lib_update_check(clirunner, validate_cliresult, cmd_lib, ["-g", "update", "--only-check", "--json-output"]) validate_cliresult(result) output = json.loads(result.output) - assert set(["ArduinoJson", "ESPAsyncTCP", "RadioHead"]) == set( + assert set(["ArduinoJson", "IRremoteESP8266", "NeoPixelBus"]) == set( [l['name'] for l in output]) def test_global_lib_update(clirunner, validate_cliresult, isolated_pio_home): + # update library using package directory + result = clirunner.invoke( + cmd_lib, + ["-g", "update", "NeoPixelBus", "--only-check", "--json-output"]) + validate_cliresult(result) + oudated = json.loads(result.output) + assert len(oudated) == 1 + assert "__pkg_dir" in oudated[0] + result = clirunner.invoke(cmd_lib, + ["-g", "update", oudated[0]['__pkg_dir']]) + validate_cliresult(result) + assert "Uninstalling NeoPixelBus @ 2.2.4" in result.output + + # update rest libraries result = clirunner.invoke(cmd_lib, ["-g", "update"]) validate_cliresult(result) - assert "[Up-to-date]" in result.output + validate_cliresult(result) + assert result.output.count("[Skip]") == 5 + assert result.output.count("[Up-to-date]") == 9 assert "Uninstalling ArduinoJson @ 5.7.3" in result.output + assert "Uninstalling IRremoteESP8266 @ fee16e880b" in result.output + + # update unknown library + result = clirunner.invoke(cmd_lib, ["-g", "update", "Unknown"]) + assert result.exit_code != 0 + assert isinstance(result.exception, exception.UnknownPackage) def test_global_lib_uninstall(clirunner, validate_cliresult, isolated_pio_home): + # uninstall using package directory + result = clirunner.invoke(cmd_lib, ["-g", "list", "--json-output"]) + validate_cliresult(result) + items = json.loads(result.output) + result = clirunner.invoke(cmd_lib, + ["-g", "uninstall", items[0]['__pkg_dir']]) + validate_cliresult(result) + assert "Uninstalling Adafruit ST7735 Library" in result.output + + # uninstall the rest libraries result = clirunner.invoke(cmd_lib, [ - "-g", "uninstall", "1", "ArduinoJson@!=5.6.7", "TextLCD", - "Adafruit ST7735 Library" + "-g", "uninstall", "1", "ArduinoJson@!=5.6.7", + "https://github.com/bblanchon/ArduinoJson.git", "IRremoteESP8266@>=0.2" ]) validate_cliresult(result) + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] items2 = [ - "DHT22_ID58", "ArduinoJson_ID64", "ESPAsyncTCP_ID305", - "pubsubclient", "PJON", "rs485-nodeproto", "RadioHead_ID124" + "ArduinoJson", "ArduinoJson_ID64@5.6.7", "DallasTemperature_ID54", + "DHT22_ID58", "ESPAsyncTCP_ID305", "NeoPixelBus_ID547", "PJON", + "PJON@src-79de467ebe19de18287becff0a1fb42d", "PubSubClient", + "RadioHead-1.62", "rs485-nodeproto" ] assert set(items1) == set(items2) + # uninstall unknown library + result = clirunner.invoke(cmd_lib, ["-g", "uninstall", "Unknown"]) + assert result.exit_code != 0 + assert isinstance(result.exception, exception.UnknownPackage) + def test_lib_show(clirunner, validate_cliresult, isolated_pio_home): result = clirunner.invoke(cmd_lib, ["show", "64"]) @@ -142,31 +228,24 @@ def test_lib_show(clirunner, validate_cliresult, isolated_pio_home): assert "OneWire" in result.output -def test_project_lib_complex(clirunner, validate_cliresult, tmpdir): - with tmpdir.as_cwd(): - # init - result = clirunner.invoke(cmd_init) - validate_cliresult(result) +def test_lib_builtin(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cmd_lib, ["builtin"]) + validate_cliresult(result) + result = clirunner.invoke(cmd_lib, ["builtin", "--json-output"]) + validate_cliresult(result) - # isntall - result = clirunner.invoke(cmd_lib, ["install", "54", "ArduinoJson"]) - validate_cliresult(result) - items1 = [ - d.basename - for d in tmpdir.join(basename(util.get_projectlibdeps_dir())) - .listdir() - ] - items2 = ["DallasTemperature_ID54", "OneWire_ID1", "ArduinoJson_ID64"] - assert set(items1) == set(items2) - # list - result = clirunner.invoke(cmd_lib, ["list", "--json-output"]) - validate_cliresult(result) - items1 = [i['name'] for i in json.loads(result.output)] - items2 = ["DallasTemperature", "OneWire", "ArduinoJson"] - assert set(items1) == set(items2) +def test_lib_stats(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cmd_lib, ["stats"]) + validate_cliresult(result) + assert all([ + s in result.output + for s in ("UPDATED", "ago", "http://platformio.org/lib/show") + ]) - # update - result = clirunner.invoke(cmd_lib, ["update"]) - validate_cliresult(result) - assert "[Up-to-date]" in result.output + result = clirunner.invoke(cmd_lib, ["stats", "--json-output"]) + validate_cliresult(result) + assert set([ + "dlweek", "added", "updated", "topkeywords", "dlmonth", "dlday", + "lastkeywords" + ]) == set(json.loads(result.output).keys()) diff --git a/tests/test_maintenance.py b/tests/test_maintenance.py index ba4e2796..fd71acf1 100644 --- a/tests/test_maintenance.py +++ b/tests/test_maintenance.py @@ -156,7 +156,7 @@ def test_check_platform_updates(clirunner, validate_cliresult, manifest['version'] = "0.0.0" manifest_path.write(json.dumps(manifest)) # reset cached manifests - PlatformManager().reset_cache() + PlatformManager().cache_reset() # reset check time interval = int(app.get_setting("check_platforms_interval")) * 3600 * 24 diff --git a/tests/test_managers.py b/tests/test_managers.py index 14ee9e38..a9320def 100644 --- a/tests/test_managers.py +++ b/tests/test_managers.py @@ -12,70 +12,118 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json +from os.path import join + from platformio import util -from platformio.managers.package import BasePkgManager +from platformio.managers.package import PackageManager -def test_pkg_name_parser(): +def test_pkg_input_parser(): items = [ ["PkgName", ("PkgName", None, None)], [("PkgName", "!=1.2.3,<2.0"), ("PkgName", "!=1.2.3,<2.0", None)], ["PkgName@1.2.3", ("PkgName", "1.2.3", None)], [("PkgName@1.2.3", "1.2.5"), ("PkgName@1.2.3", "1.2.5", None)], ["id:13", ("id:13", None, None)], - ["id:13@~1.2.3", ("id:13", "~1.2.3", None)], [ + ["id:13@~1.2.3", ("id:13", "~1.2.3", None)], + [ util.get_home_dir(), (".platformio", None, "file://" + util.get_home_dir()) - ], [ + ], + [ "LocalName=" + util.get_home_dir(), ("LocalName", None, "file://" + util.get_home_dir()) - ], [ + ], + [ + "LocalName=%s@>2.3.0" % util.get_home_dir(), + ("LocalName", ">2.3.0", "file://" + util.get_home_dir()) + ], + [ "https://github.com/user/package.git", ("package", None, "git+https://github.com/user/package.git") - ], [ - "https://gitlab.com/user/package.git", - ("package", None, "git+https://gitlab.com/user/package.git") - ], [ + ], + [ + "MyPackage=https://gitlab.com/user/package.git", + ("MyPackage", None, "git+https://gitlab.com/user/package.git") + ], + [ + "MyPackage=https://gitlab.com/user/package.git@3.2.1,!=2", + ("MyPackage", "3.2.1,!=2", + "git+https://gitlab.com/user/package.git") + ], + [ + "https://somedomain.com/path/LibraryName-1.2.3.zip", + ("LibraryName-1.2.3", None, + "https://somedomain.com/path/LibraryName-1.2.3.zip") + ], + [ "https://github.com/user/package/archive/branch.zip", ("branch", None, "https://github.com/user/package/archive/branch.zip") - ], [ + ], + [ + "https://github.com/user/package/archive/branch.zip@~1.2.3", + ("branch", "~1.2.3", + "https://github.com/user/package/archive/branch.zip") + ], + [ "https://github.com/user/package/archive/branch.tar.gz", - ("branch", None, + ("branch.tar", None, "https://github.com/user/package/archive/branch.tar.gz") - ], [ + ], + [ + "https://github.com/user/package/archive/branch.tar.gz@!=5", + ("branch.tar", "!=5", + "https://github.com/user/package/archive/branch.tar.gz") + ], + [ "https://developer.mbed.org/users/user/code/package/", ("package", None, "hg+https://developer.mbed.org/users/user/code/package/") - ], [ + ], + [ "https://github.com/user/package#v1.2.3", ("package", None, "git+https://github.com/user/package#v1.2.3") - ], [ + ], + [ "https://github.com/user/package.git#branch", ("package", None, "git+https://github.com/user/package.git#branch") - ], [ + ], + [ "PkgName=https://github.com/user/package.git#a13d344fg56", ("PkgName", None, "git+https://github.com/user/package.git#a13d344fg56") - ], [ + ], + [ + "user/package", + ("package", None, "git+https://github.com/user/package") + ], + [ "PkgName=user/package", ("PkgName", None, "git+https://github.com/user/package") - ], [ + ], + [ "PkgName=user/package#master", ("PkgName", None, "git+https://github.com/user/package#master") - ], [ + ], + [ "git+https://github.com/user/package", ("package", None, "git+https://github.com/user/package") - ], [ + ], + [ "hg+https://example.com/user/package", ("package", None, "hg+https://example.com/user/package") - ], [ + ], + [ "git@github.com:user/package.git", ("package", None, "git@github.com:user/package.git") - ], [ + ], + [ "git@github.com:user/package.git#v1.2.0", ("package", None, "git@github.com:user/package.git#v1.2.0") - ], [ + ], + [ "git+ssh://git@gitlab.private-server.com/user/package#1.2.0", ("package", None, "git+ssh://git@gitlab.private-server.com/user/package#1.2.0") @@ -83,6 +131,72 @@ def test_pkg_name_parser(): ] for params, result in items: if isinstance(params, tuple): - assert BasePkgManager.parse_pkg_name(*params) == result + assert PackageManager.parse_pkg_input(*params) == result else: - assert BasePkgManager.parse_pkg_name(params) == result + assert PackageManager.parse_pkg_input(params) == result + + +def test_install_packages(isolated_pio_home, tmpdir): + packages = [ + dict(id=1, name="name_1", version="shasum"), + dict(id=1, name="name_1", version="2.0.0"), + dict(id=1, name="name_1", version="2.1.0"), + dict(id=1, name="name_1", version="1.2.0"), + dict(id=1, name="name_1", version="1.0.0"), + dict(name="name_2", version="1.0.0"), + dict(name="name_2", version="2.0.0", + __src_url="git+https://github.com"), + dict(name="name_2", version="3.0.0", + __src_url="git+https://github2.com"), + dict(name="name_2", version="4.0.0", + __src_url="git+https://github2.com") + ] + + pm = PackageManager(join(util.get_home_dir(), "packages")) + for package in packages: + tmp_dir = tmpdir.mkdir("tmp-package") + tmp_dir.join("package.json").write(json.dumps(package)) + pm._install_from_url(package['name'], "file://%s" % str(tmp_dir)) + tmp_dir.remove(rec=1) + + assert len(pm.get_installed()) == len(packages) - 1 + + pkg_dirnames = [ + 'name_1_ID1', 'name_1_ID1@1.0.0', 'name_1_ID1@1.2.0', + 'name_1_ID1@2.0.0', 'name_1_ID1@shasum', 'name_2', + 'name_2@src-177cbce1f0705580d17790fda1cc2ef5', + 'name_2@src-f863b537ab00f4c7b5011fc44b120e1f' + ] + assert set([p.basename for p in isolated_pio_home.join( + "packages").listdir()]) == set(pkg_dirnames) + + +def test_get_package(isolated_pio_home): + tests = [ + [("unknown", ), None], + [("1", ), None], + [("id=1", "shasum"), dict(id=1, name="name_1", version="shasum")], + [("id=1", "*"), dict(id=1, name="name_1", version="2.1.0")], + [("id=1", "^1"), dict(id=1, name="name_1", version="1.2.0")], + [("id=1", "^1"), dict(id=1, name="name_1", version="1.2.0")], + [("name_1", "<2"), dict(id=1, name="name_1", version="1.2.0")], + [("name_1", ">2"), None], + [("name_1", "2-0-0"), dict(id=1, name="name_1", version="2.1.0")], + [("name_1", "2-0-0"), dict(id=1, name="name_1", version="2.1.0")], + [("name_2", ), dict(name="name_2", version="4.0.0")], + [("url_has_higher_priority", None, "git+https://github.com"), + dict(name="name_2", version="2.0.0", + __src_url="git+https://github.com")], + [("name_2", None, "git+https://github.com"), + dict(name="name_2", version="2.0.0", + __src_url="git+https://github.com")], + ] + + pm = PackageManager(join(util.get_home_dir(), "packages")) + for test in tests: + manifest = pm.get_package(*test[0]) + if test[1] is None: + assert manifest is None, test + continue + for key, value in test[1].items(): + assert manifest[key] == value, test diff --git a/tests/test_pkgmanifest.py b/tests/test_pkgmanifest.py index 8793f9ab..f70dccde 100644 --- a/tests/test_pkgmanifest.py +++ b/tests/test_pkgmanifest.py @@ -16,19 +16,6 @@ import pytest import requests -def pytest_generate_tests(metafunc): - if "package_data" not in metafunc.fixturenames: - return - pkgs_manifest = requests.get( - "https://dl.bintray.com/platformio/dl-packages/manifest.json").json() - assert isinstance(pkgs_manifest, dict) - packages = [] - for _, variants in pkgs_manifest.iteritems(): - for item in variants: - packages.append(item) - metafunc.parametrize("package_data", packages) - - def validate_response(req): assert req.status_code == 200 assert int(req.headers['Content-Length']) > 0 @@ -36,13 +23,22 @@ def validate_response(req): "application/octet-stream") -def test_package(package_data): - assert package_data['url'].endswith(".tar.gz") +def test_packages(): + pkgs_manifest = requests.get( + "https://dl.bintray.com/platformio/dl-packages/manifest.json").json() + assert isinstance(pkgs_manifest, dict) + items = [] + for _, variants in pkgs_manifest.iteritems(): + for item in variants: + items.append(item) - r = requests.head(package_data['url'], allow_redirects=True) - validate_response(r) + for item in items: + assert item['url'].endswith(".tar.gz"), item - if "X-Checksum-Sha1" not in r.headers: - return pytest.skip("X-Checksum-Sha1 is not provided") + r = requests.head(item['url'], allow_redirects=True) + validate_response(r) - assert package_data['sha1'] == r.headers.get("X-Checksum-Sha1") + if "X-Checksum-Sha1" not in r.headers: + return pytest.skip("X-Checksum-Sha1 is not provided") + + assert item['sha1'] == r.headers.get("X-Checksum-Sha1"), item diff --git a/tox.ini b/tox.ini index 1f19bf1f..0c09acce 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,7 @@ deps = yapf pylint pytest + show commands = python --version [testenv:docs] From 2fe4b7c0ec7c8fa086ee3dceac2812dd8f3f930a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 8 Mar 2017 17:33:25 +0200 Subject: [PATCH 107/127] Change manifests order for Library Manager --- HISTORY.rst | 1 + platformio/managers/lib.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index d535501a..5608de8b 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -39,6 +39,7 @@ PlatformIO 3.0 * Do not overwrite project configuration variables when system environment variables are set * Handle dependencies when installing non-registry package/library (VCS, archive, local folder) + (`issue #913 `_) * Fixed package installing with VCS branch for Python 2.7.3 (`issue #885 `_) diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 2b466c62..553f0803 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -37,7 +37,7 @@ class LibraryManager(BasePkgManager): @property def manifest_names(self): return [ - ".library.json", "library.properties", "library.json", + ".library.json", "library.json", "library.properties", "module.json" ] From d994da9d53f7a34456fb40e11b4237c0fe260901 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 8 Mar 2017 19:52:11 +0200 Subject: [PATCH 108/127] Check outdated packages for development platform --- platformio/commands/platform.py | 15 +++++--- platformio/maintenance.py | 12 +++++-- platformio/managers/package.py | 3 +- platformio/managers/platform.py | 63 ++++++++++++--------------------- 4 files changed, 44 insertions(+), 49 deletions(-) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 0d01cc6d..5d44417e 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -336,9 +336,13 @@ def platform_update(platforms, only_packages, only_check, json_output): app.clean_cache() pm = PlatformManager() + pkg_dir_to_name = {} if not platforms: platforms = [] - platforms = [manifest['__pkg_dir'] for manifest in pm.get_installed()] + for manifest in pm.get_installed(): + platforms.append(manifest['__pkg_dir']) + pkg_dir_to_name[manifest['__pkg_dir']] = manifest.get( + "title", manifest['name']) if only_check and json_output: result = [] @@ -352,16 +356,19 @@ def platform_update(platforms, only_packages, only_check, json_output): if not pkg_dir: continue latest = pm.outdated(pkg_dir, requirements) - if not latest: + if (not latest and not PlatformFactory.newPlatform(pkg_dir) + .are_outdated_packages()): continue data = _get_installed_platform_data( pkg_dir, with_boards=False, expose_packages=False) - data['versionLatest'] = latest + if latest: + data['versionLatest'] = latest result.append(data) return click.echo(json.dumps(result)) else: for platform in platforms: - click.echo("Platform %s" % click.style(platform, fg="cyan")) + click.echo("Platform %s" % click.style( + pkg_dir_to_name.get(platform, platform), fg="cyan")) click.echo("--------") pm.update( platform, only_packages=only_packages, only_check=only_check) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 2acc8ef1..da6c1329 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -30,7 +30,7 @@ from platformio.commands.platform import \ from platformio.commands.platform import platform_update as cmd_platform_update from platformio.commands.upgrade import get_latest_version from platformio.managers.lib import LibraryManager -from platformio.managers.platform import PlatformManager +from platformio.managers.platform import PlatformFactory, PlatformManager from platformio.pioplus import pioplus_update @@ -260,8 +260,14 @@ def check_internal_updates(ctx, what): pm = PlatformManager() if what == "platforms" else LibraryManager() outdated_items = [] for manifest in pm.get_installed(): - if manifest['name'] not in outdated_items and \ - pm.outdated(manifest['__pkg_dir']): + if manifest['name'] in outdated_items: + continue + conds = [ + pm.outdated(manifest['__pkg_dir']), what == "platforms" and + PlatformFactory.newPlatform( + manifest['__pkg_dir']).are_outdated_packages() + ] + if any(conds): outdated_items.append(manifest['name']) if not outdated_items: diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 94e59e87..539c5ab8 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -547,6 +547,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): `False` - package is up-to-date `String` - a found latest version """ + assert isdir(pkg_dir) latest = None manifest = self.load_manifest(pkg_dir) # skip a fixed package to a specific version @@ -709,7 +710,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): return if "__src_url" in manifest: - vcs = VCSClientFactory.newClient(pkg_dir, manifest['__vcs_url']) + vcs = VCSClientFactory.newClient(pkg_dir, manifest['__src_url']) assert vcs.update() self._update_src_manifest( dict(version=vcs.get_current_revision()), vcs.storage_dir) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index dddafc45..0283fdd1 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -253,45 +253,29 @@ class PlatformPackagesMixin(object): return True + def update_packages(self, only_check=False): + for name, manifest in self.get_installed_packages().items(): + version = self.packages[name].get("version", "") + if "@" in version: + _, version = version.rsplit("@", 1) + self.pm.update(manifest['__pkg_dir'], version, only_check) + def get_installed_packages(self): items = {} - for name, opts in self.packages.items(): - version = opts.get("version", "") - if self.is_valid_requirements(version): - package = self.pm.get_package(name, version) - else: - package = self.pm.get_package(*self._parse_pkg_input(name, - version)) - if package: - items[name] = package + for name in self.packages: + pkg_dir = self.get_package_dir(name) + if pkg_dir: + items[name] = self.pm.load_manifest(pkg_dir) return items - def update_packages(self, only_check=False): - for name in self.get_installed_packages(): + def are_outdated_packages(self): + for name, manifest in self.get_installed_packages().items(): version = self.packages[name].get("version", "") - if self.is_valid_requirements(version): - self.pm.update(name, version, only_check) - else: - requirements = None - if "@" in version: - version, requirements = version.rsplit("@", 1) - self.pm.update("%s=%s" % (name, version), requirements, - only_check) - - # def are_outdated_packages(self): - # latest = None - # for name in self.get_installed_packages(): - # version = self.packages[name].get("version", "") - # if self.is_valid_requirements(version): - # latest = self.pm.outdated(name, version) - # else: - # requirements = None - # if "@" in version: - # version, requirements = version.rsplit("@", 1) - # latest = self.pm.outdated(name, requirements, version) - # if latest or latest is None: - # return True - # return False + if "@" in version: + _, version = version.rsplit("@", 1) + if self.pm.outdated(manifest['__pkg_dir'], version): + return True + return False def get_package_dir(self, name): version = self.packages[name].get("version", "") @@ -302,13 +286,10 @@ class PlatformPackagesMixin(object): version)) def get_package_version(self, name): - version = self.packages[name].get("version", "") - if self.is_valid_requirements(version): - package = self.pm.get_package(name, version) - else: - package = self.pm.get_package(*self._parse_pkg_input(name, - version)) - return package['version'] if package else None + pkg_dir = self.get_package_dir(name) + if not pkg_dir: + return None + return self.pm.load_manifest(pkg_dir).get("version") @staticmethod def is_valid_requirements(requirements): From 8c283dc8a0d23f36ac19200c2388aa4b08a90a46 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 8 Mar 2017 19:55:56 +0200 Subject: [PATCH 109/127] Inform about broken manifest while loading it // Resolve #899 --- platformio/util.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platformio/util.py b/platformio/util.py index 20d6214a..4d345830 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -162,8 +162,12 @@ def singleton(cls): def load_json(file_path): - with open(file_path, "r") as f: - return json.load(f) + try: + with open(file_path, "r") as f: + return json.load(f) + except ValueError: + raise exception.PlatformioException("Could not load broken JSON: %s" % + file_path) def get_systype(): From 36d6421312987c5eb34838af608feff3c1583678 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 8 Mar 2017 20:00:00 +0200 Subject: [PATCH 110/127] Bump version to 3.3.0a14 --- platformio/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index b715f822..d05313bd 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a13") +VERSION = (3, 3, "0a14") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" From f8b2902c91f5247b4d5ae653cf9b214a7170bd4f Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 9 Mar 2017 23:24:50 +0200 Subject: [PATCH 111/127] =?UTF-8?q?Don=E2=80=99t=20update=20development=20?= =?UTF-8?q?platforms=20after=20PIO=20upgrade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/maintenance.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index da6c1329..b0485fc3 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -154,17 +154,12 @@ def after_upgrade(ctx): if last_version == "0.0.0": app.set_state_item("last_version", __version__) else: - click.secho("Please wait while upgrading PlatformIO ...", fg="yellow") + click.secho("Please wait while upgrading PlatformIO...", fg="yellow") app.clean_cache() u = Upgrader(last_version, __version__) if u.run(ctx): app.set_state_item("last_version", __version__) - # update development platforms - pm = PlatformManager() - for manifest in pm.get_installed(): - pm.update(manifest['__pkg_dir']) - # update PlatformIO Plus tool if installed pioplus_update() From 2cd3592a499d131142cc35a52ec68b3ce51603cd Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 10 Mar 2017 00:29:22 +0200 Subject: [PATCH 112/127] Fix issue with an update operation for package manager --- platformio/maintenance.py | 4 ++-- platformio/managers/package.py | 4 +--- platformio/pioplus.py | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index b0485fc3..9e56a396 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -94,7 +94,7 @@ class Upgrader(object): self._upgraders = [ (semantic_version.Version("3.0.0-a.1"), self._upgrade_to_3_0_0), - (semantic_version.Version("3.0.0-b.11"), self._upgrade_to_3_0_0) + (semantic_version.Version("3.0.0-b.11"), self._upgrade_to_3_0_0b11) ] def run(self, ctx): @@ -160,7 +160,7 @@ def after_upgrade(ctx): if u.run(ctx): app.set_state_item("last_version", __version__) - # update PlatformIO Plus tool if installed + # update PlatformIO Plus tool if it's installed pioplus_update() click.secho( diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 539c5ab8..8e1b9725 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -678,9 +678,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): if isdir(package): pkg_dir = package else: - name, requirements, url = self.parse_pkg_input(package, - requirements) - pkg_dir = self.get_package_dir(name, requirements, url) + pkg_dir = self.get_package_dir(*self.parse_pkg_input(package)) if not pkg_dir: raise exception.UnknownPackage("%s @ %s" % diff --git a/platformio/pioplus.py b/platformio/pioplus.py index 91a7447b..bdd76bb5 100644 --- a/platformio/pioplus.py +++ b/platformio/pioplus.py @@ -49,14 +49,14 @@ class PioPlusPackageManager(PackageManager): def pioplus_install(): pm = PioPlusPackageManager() for item in PACKAGE_DEPS.values(): - pm.install(item['name'], item['requirements'], silent=True) + if not pm.get_package(item['name'], item['requirements']): + pm.install(item['name'], item['requirements']) def pioplus_update(): pm = PioPlusPackageManager() for item in PACKAGE_DEPS.values(): - package_dir = pm.get_package_dir(item['name']) - if package_dir: + if pm.get_package(item['name']): pm.update(item['name'], item['requirements']) From 23ac02bea1b65a40ac1c68a554302b92c6b92271 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 10 Mar 2017 00:38:04 +0200 Subject: [PATCH 113/127] =?UTF-8?q?Note=20about=20Antivirus=20when=20can?= =?UTF-8?q?=E2=80=99t=20install=20a=20package=20//=20Resolve=20#916?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/__init__.py | 2 +- platformio/exception.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index d05313bd..e7774802 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a14") +VERSION = (3, 3, "0a15") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/exception.py b/platformio/exception.py index f4743d4c..bc16f2e2 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -94,8 +94,10 @@ class UndefinedPackageVersion(PlatformioException): class PackageInstallError(PlatformioException): - MESSAGE = "Can not install '{0}' with version requirements '{1}' "\ - "for your system '{2}'" + MESSAGE = "Could not install '{0}' with version requirements '{1}' "\ + "for your system '{2}'.\n"\ + "If you use Antivirus, it can block PlatformIO Package "\ + "Manager. Try to disable it for a while." class FDUnrecognizedStatusCode(PlatformioException): From 09e15f6d2ab82c0e897ca8390efe095709f7293d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 10 Mar 2017 01:18:33 +0200 Subject: [PATCH 114/127] Fix Upgrade for 3.0.0b1 --- platformio/maintenance.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 9e56a396..9cca7e3a 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -141,9 +141,10 @@ class Upgrader(object): m['name'] for m in PlatformManager().get_installed() ] if "espressif" not in current_platforms: - return + return True ctx.invoke(cmd_platform_install, platforms=["espressif8266"]) ctx.invoke(cmd_platform_uninstall, platforms=["espressif"]) + return True def after_upgrade(ctx): From f39cda041c6598c70c3cffcdcc9ca748bb0e0def Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 11 Mar 2017 13:11:58 +0200 Subject: [PATCH 115/127] Fix issue when check updates for VCS repository // Resolve #917 --- platformio/__init__.py | 2 +- platformio/managers/package.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index e7774802..6d0d609a 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a15") +VERSION = (3, 3, "0a16") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 8e1b9725..5f7b37d8 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -553,6 +553,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): # skip a fixed package to a specific version if "@" in pkg_dir and "__src_url" not in manifest: return None + if "__src_url" in manifest: try: vcs = VCSClientFactory.newClient( @@ -571,14 +572,18 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): silent=True) except (exception.PlatformioException, ValueError): return None + if not latest: return None + up_to_date = False try: + assert "__src_url" not in manifest up_to_date = (semantic_version.Version.coerce(manifest['version']) >= semantic_version.Version.coerce(latest)) - except ValueError: + except (AssertionError, ValueError): up_to_date = latest == manifest['version'] + return False if up_to_date else latest def install(self, From 31715e937b10decd36b7c2a9d34a6f423a06290e Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 11 Mar 2017 13:12:41 +0200 Subject: [PATCH 116/127] Check that PIO Plus could be updated before do update --- platformio/pioplus.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio/pioplus.py b/platformio/pioplus.py index bdd76bb5..932605be 100644 --- a/platformio/pioplus.py +++ b/platformio/pioplus.py @@ -56,7 +56,8 @@ def pioplus_install(): def pioplus_update(): pm = PioPlusPackageManager() for item in PACKAGE_DEPS.values(): - if pm.get_package(item['name']): + pkg_dir = pm.get_package_dir(item['name']) + if pkg_dir and pm.outdated(pkg_dir, item['requirements']): pm.update(item['name'], item['requirements']) From a20434ace597fb61cbe40bb1123c0f4528d51dd1 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 11 Mar 2017 13:41:25 +0200 Subject: [PATCH 117/127] New boards: Generic ATTiny2313 and ATTiny4313 --- HISTORY.rst | 5 +++-- docs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 5608de8b..f2a6750c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -48,8 +48,9 @@ PlatformIO 3.0 * Development platform `Atmel AVR `__ - + Added support for EnviroDIY Mayfly, The Things Uno, SparkFun Qduino Mini, - SparkFun ATmega128RFA1 Dev Board, SparkFun Serial 7-Segment Display boards + + New boards: EnviroDIY Mayfly, The Things Uno, SparkFun Qduino Mini, + SparkFun ATmega128RFA1 Dev Board, SparkFun Serial 7-Segment Display, + Generic ATTiny2313 and ATTiny4313 + Set fuse bits with new target named ``fuses`` (`issue #865 `_) + Updated Arduino Core to 1.6.17 diff --git a/docs b/docs index 5505597f..dc82d8b8 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 5505597f60652bcb1571387e95c89c676ebc897e +Subproject commit dc82d8b835fbe754c02220342038c4f1197d813b From 571a52b4321364c8545aa0ba75b9ca8f7de15e71 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 11 Mar 2017 23:28:55 +0200 Subject: [PATCH 118/127] Move core packages to the one place; Bump to 3.0.0a17 --- platformio/__init__.py | 2 +- platformio/builder/tools/piotest.py | 5 +- platformio/commands/account.py | 2 +- platformio/commands/remote.py | 2 +- platformio/commands/test.py | 2 +- platformio/commands/update.py | 6 ++- platformio/maintenance.py | 11 ++-- platformio/{pioplus.py => managers/core.py} | 57 ++++++++++----------- platformio/managers/package.py | 5 +- platformio/managers/platform.py | 22 +++----- 10 files changed, 52 insertions(+), 62 deletions(-) rename platformio/{pioplus.py => managers/core.py} (61%) diff --git a/platformio/__init__.py b/platformio/__init__.py index 6d0d609a..ea0e7f69 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a16") +VERSION = (3, 3, "0a17") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/tools/piotest.py b/platformio/builder/tools/piotest.py index 573f562f..04035e9c 100644 --- a/platformio/builder/tools/piotest.py +++ b/platformio/builder/tools/piotest.py @@ -16,14 +16,15 @@ from __future__ import absolute_import from os.path import join, sep +from platformio.managers.core import get_core_package_dir + def ProcessTest(env): env.Append( CPPDEFINES=["UNIT_TEST", "UNITY_INCLUDE_CONFIG_H"], CPPPATH=[join("$BUILD_DIR", "UnityTestLib")]) unitylib = env.BuildLibrary( - join("$BUILD_DIR", "UnityTestLib"), - env.PioPlatform().get_package_dir("tool-unity")) + join("$BUILD_DIR", "UnityTestLib"), get_core_package_dir("tool-unity")) env.Prepend(LIBS=[unitylib]) src_filter = None diff --git a/platformio/commands/account.py b/platformio/commands/account.py index 1481b1be..6c48539a 100644 --- a/platformio/commands/account.py +++ b/platformio/commands/account.py @@ -18,7 +18,7 @@ import sys import click -from platformio.pioplus import pioplus_call +from platformio.managers.core import pioplus_call @click.group("account", short_help="Manage PIO Account") diff --git a/platformio/commands/remote.py b/platformio/commands/remote.py index b3d4cbed..1945bf87 100644 --- a/platformio/commands/remote.py +++ b/platformio/commands/remote.py @@ -23,7 +23,7 @@ import click from platformio import exception, util from platformio.commands.device import device_monitor as cmd_device_monitor -from platformio.pioplus import pioplus_call +from platformio.managers.core import pioplus_call # pylint: disable=unused-argument diff --git a/platformio/commands/test.py b/platformio/commands/test.py index d63374c4..34b30ec9 100644 --- a/platformio/commands/test.py +++ b/platformio/commands/test.py @@ -17,7 +17,7 @@ from os import getcwd import click -from platformio.pioplus import pioplus_call +from platformio.managers.core import pioplus_call @click.command("test", short_help="Local Unit Testing") diff --git a/platformio/commands/update.py b/platformio/commands/update.py index 5d6dedb6..95511e44 100644 --- a/platformio/commands/update.py +++ b/platformio/commands/update.py @@ -16,8 +16,8 @@ import click from platformio.commands.lib import lib_update as cmd_lib_update from platformio.commands.platform import platform_update as cmd_platform_update +from platformio.managers.core import update_core_packages from platformio.managers.lib import LibraryManager -from platformio.pioplus import pioplus_update @click.command( @@ -29,10 +29,12 @@ from platformio.pioplus import pioplus_update help="Do not update, only check for new version") @click.pass_context def cli(ctx, only_check): + update_core_packages(only_check) + + click.echo() click.echo("Platform Manager") click.echo("================") ctx.invoke(cmd_platform_update, only_check=only_check) - pioplus_update() click.echo() click.echo("Library Manager") diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 9cca7e3a..9cd95719 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -29,9 +29,9 @@ from platformio.commands.platform import \ platform_uninstall as cmd_platform_uninstall from platformio.commands.platform import platform_update as cmd_platform_update from platformio.commands.upgrade import get_latest_version +from platformio.managers.core import update_core_packages from platformio.managers.lib import LibraryManager from platformio.managers.platform import PlatformFactory, PlatformManager -from platformio.pioplus import pioplus_update def in_silence(ctx=None): @@ -157,18 +157,17 @@ def after_upgrade(ctx): else: click.secho("Please wait while upgrading PlatformIO...", fg="yellow") app.clean_cache() + + # Update PlatformIO's Core packages + update_core_packages() + u = Upgrader(last_version, __version__) if u.run(ctx): app.set_state_item("last_version", __version__) - - # update PlatformIO Plus tool if it's installed - pioplus_update() - click.secho( "PlatformIO has been successfully upgraded to %s!\n" % __version__, fg="green") - telemetry.on_event( category="Auto", action="Upgrade", diff --git a/platformio/pioplus.py b/platformio/managers/core.py similarity index 61% rename from platformio/pioplus.py rename to platformio/managers/core.py index 932605be..fabe449e 100644 --- a/platformio/pioplus.py +++ b/platformio/managers/core.py @@ -20,21 +20,18 @@ from os.path import join from platformio import exception, util from platformio.managers.package import PackageManager -PACKAGE_DEPS = { - "pysite": { - "name": "pysite-pioplus", - "requirements": ">=0.3.0,<2" - }, - "tool": { - "name": "tool-pioplus", - "requirements": ">=0.6.10,<2" - } +CORE_PACKAGES = { + "project-templates": "*", + "pysite-pioplus": ">=0.3.0,<2", + "tool-pioplus": ">=0.6.10,<2", + "tool-unity": "~1.20302.1", + "tool-scons": "~3.20501.2" } -AUTO_UPDATES_MAX = 100 +PIOPLUS_AUTO_UPDATES_MAX = 100 -class PioPlusPackageManager(PackageManager): +class CorePackageManager(PackageManager): def __init__(self): PackageManager.__init__( @@ -46,30 +43,28 @@ class PioPlusPackageManager(PackageManager): ]) -def pioplus_install(): - pm = PioPlusPackageManager() - for item in PACKAGE_DEPS.values(): - if not pm.get_package(item['name'], item['requirements']): - pm.install(item['name'], item['requirements']) +def get_core_package_dir(name): + assert name in CORE_PACKAGES + requirements = CORE_PACKAGES[name] + pm = CorePackageManager() + pkg_dir = pm.get_package_dir(name, requirements) + if pkg_dir: + return pkg_dir + return pm.install(name, requirements) -def pioplus_update(): - pm = PioPlusPackageManager() - for item in PACKAGE_DEPS.values(): - pkg_dir = pm.get_package_dir(item['name']) - if pkg_dir and pm.outdated(pkg_dir, item['requirements']): - pm.update(item['name'], item['requirements']) +def update_core_packages(only_check=False): + pm = CorePackageManager() + for name, requirements in CORE_PACKAGES.items(): + pkg_dir = pm.get_package_dir(name) + if pkg_dir and pm.outdated(pkg_dir, requirements): + pm.update(name, requirements, only_check=only_check) def pioplus_call(args, **kwargs): - pioplus_install() - pm = PioPlusPackageManager() - pioplus_path = join( - pm.get_package_dir(PACKAGE_DEPS['tool']['name'], - PACKAGE_DEPS['tool']['requirements']), "pioplus") + pioplus_path = join(get_core_package_dir("tool-pioplus"), "pioplus") os.environ['PYTHONEXEPATH'] = util.get_pythonexe_path() - os.environ['PYTHONPYSITEDIR'] = pm.get_package_dir( - PACKAGE_DEPS['pysite']['name'], PACKAGE_DEPS['pysite']['requirements']) + os.environ['PYTHONPYSITEDIR'] = get_core_package_dir("pysite-pioplus") util.copy_pythonpath_to_osenv() code = subprocess.call([pioplus_path] + args, **kwargs) @@ -83,8 +78,8 @@ def pioplus_call(args, **kwargs): setattr(pioplus_call, count_attr, 1) count_value += 1 setattr(pioplus_call, count_attr, count_value) - if count_value < AUTO_UPDATES_MAX: - pioplus_update() + if count_value < PIOPLUS_AUTO_UPDATES_MAX: + update_core_packages() return pioplus_call(args, **kwargs) # handle reload request diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 5f7b37d8..6cfdacb8 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -387,9 +387,10 @@ class PkgInstallerMixin(object): if not isdir(src_dir): os.makedirs(src_dir) src_manifest_path = join(src_dir, self.SRC_MANIFEST_NAME) - _data = data + _data = {} if isfile(src_manifest_path): - _data.update(util.load_json(src_manifest_path)) + _data = util.load_json(src_manifest_path) + _data.update(data) with open(src_manifest_path, "w") as fp: json.dump(_data, fp) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 0283fdd1..9c68d2bc 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -23,6 +23,7 @@ import click import semantic_version from platformio import __version__, app, exception, util +from platformio.managers.core import get_core_package_dir from platformio.managers.package import BasePkgManager, PackageManager @@ -161,12 +162,14 @@ class PlatformManager(BasePkgManager): def get_registered_boards(): return util.get_api_result("/boards", cache_valid="30d") - def board_config(self, id_): + def board_config(self, id_, platform=None): for manifest in self.get_installed_boards(): - if manifest['id'] == id_: + if manifest['id'] == id_ and (not platform or + manifest['platform'] == platform): return manifest for manifest in self.get_registered_boards(): - if manifest['id'] == id_: + if manifest['id'] == id_ and (not platform or + manifest['platform'] == platform): return manifest raise exception.UnknownBoard(id_) @@ -334,7 +337,7 @@ class PlatformRunMixin(object): def _run_scons(self, variables, targets): cmd = [ util.get_pythonexe_path(), - join(self.get_package_dir("tool-scons"), "script", "scons"), "-Q", + join(get_core_package_dir("tool-scons"), "script", "scons"), "-Q", "-j %d" % self.get_job_nums(), "--warn=no-no-parallel-support", "-f", join(util.get_source_dir(), "builder", "main.py") ] @@ -553,17 +556,6 @@ class PlatformBase( # pylint: disable=too-many-public-methods # skip all packages, allow only upload tools self.packages[_name]['optional'] = True - if "__test" in targets and "tool-unity" not in self.packages: - self.packages['tool-unity'] = { - "version": "~1.20302.1", - "optional": False - } - if "tool-scons" not in self.packages: - self.packages['tool-scons'] = { - "version": "~3.20501.2", - "optional": False - } - def get_lib_storages(self): storages = [] for opts in (self.frameworks or {}).values(): From d3679671ac5b2d860633920a7c59062e06975ff5 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 23 Mar 2017 22:11:48 +0200 Subject: [PATCH 119/127] Increase exception description length for report --- platformio/telemetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/telemetry.py b/platformio/telemetry.py index b35ea2d9..8b3fd7a1 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -310,7 +310,7 @@ def on_exception(e): ]) mp = MeasurementProtocol() mp['exd'] = ("%s: %s" % (type(e).__name__, format_exc() - if is_crash else e))[:150] + if is_crash else e))[:2048] mp['exf'] = 1 if is_crash else 0 mp.send("exception") From bb124ce6816b1bc1591e1b0b28f541a16d8d6875 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2017 00:43:11 +0200 Subject: [PATCH 120/127] Update history --- HISTORY.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index f2a6750c..58768b0b 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -62,7 +62,7 @@ PlatformIO 3.0 + Added support for Adafruit Circuit Playground Express, Arduino MKRZero, Atmel ATSAMW25-XPRO boards + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 + Updated Arduino SAM & SAMD Core to 1.6.11 * Development platform `Espressif 32 `__ @@ -76,7 +76,7 @@ PlatformIO 3.0 * Development platform `Freescale Kinetis `__ + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 * Development platform `Lattice iCE40 `__ @@ -94,30 +94,30 @@ PlatformIO 3.0 * Development platform `Nordic nRF51 `__ + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 * Development platform `NXP LPC `__ + Added support for LPCXpresso4337 and y5 LPC11U35 mbug boards + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 * Development platform `Silicon Labs EFM32 `__ + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 * Development platform `ST STM32 `__ + Added support for new boards: Espotel LoRa Module, NAMote72, MTS Dragonfly, ST Nucleo F303ZE, u-blox EVK-ODIN-W2, MultiTech xDot + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 * Development platform `Teensy `__ + Added support for ARM mbed events library - + Updated ARM mbed OS to 5.3.0/rev131 + + Updated ARM mbed OS to 5.3.6/rev137 + Updated Arduino Core to v1.35 * Development platform `TI TIVA `__ From 4e5f34ec195b068bde37794561472c08fcd892d0 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2017 19:43:00 +0300 Subject: [PATCH 121/127] Allow installing package by framework name --- platformio/exception.py | 2 +- platformio/managers/lib.py | 13 ++++----- platformio/managers/package.py | 5 ++-- platformio/managers/platform.py | 47 +++++++++++++++++++-------------- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/platformio/exception.py b/platformio/exception.py index bc16f2e2..0f0530b6 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -58,7 +58,7 @@ class BoardNotDefined(PlatformioException): MESSAGE = "You need to specify board ID using `-b` or `--board` "\ "option. Supported boards list is available via "\ - " `platformio boards` command" + "`platformio boards` command" class UnknownBoard(PlatformioException): diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 553f0803..ea5b343f 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -230,12 +230,13 @@ class LibraryManager(BasePkgManager): name, dl_data['url'].replace("http://", "https://") if app.get_setting("enable_ssl") else dl_data['url'], requirements) - def install(self, - name, - requirements=None, - silent=False, - trigger_event=True, - interactive=False): + def install( # pylint: disable=arguments-differ + self, + name, + requirements=None, + silent=False, + trigger_event=True, + interactive=False): try: _name, _requirements, _url = self.parse_pkg_input(name, requirements) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 6cfdacb8..1f9bffd6 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -346,7 +346,7 @@ class PkgInstallerMixin(object): sha1=None, track=False): pkg_dir = None - tmp_dir = mkdtemp("-package", "installing-", self.package_dir) + tmp_dir = mkdtemp("-package", "_tmp_installing-", self.package_dir) src_manifest_dir = None src_manifest = {"name": name, "url": url, "requirements": requirements} @@ -591,8 +591,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): name, requirements=None, silent=False, - trigger_event=True, - interactive=False): # pylint: disable=unused-argument + trigger_event=True): name, requirements, url = self.parse_pkg_input(name, requirements) package_dir = self.get_package_dir(name, requirements, url) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 9c68d2bc..99a38d86 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -62,17 +62,21 @@ class PlatformManager(BasePkgManager): without_packages=None, skip_default_package=False, trigger_event=True, + silent=False, **_): # pylint: disable=too-many-arguments - platform_dir = BasePkgManager.install(self, name, requirements) + platform_dir = BasePkgManager.install( + self, name, requirements, silent=silent) p = PlatformFactory.newPlatform(platform_dir) # @Hook: when 'update' operation (trigger_event is False), # don't cleanup packages or install them if not trigger_event: return True - - p.install_packages(with_packages, without_packages, - skip_default_package) + p.install_packages( + with_packages, + without_packages, + skip_default_package, + silent=silent) self.cleanup_packages(p.packages.keys()) return True @@ -231,8 +235,8 @@ class PlatformPackagesMixin(object): without_packages=None, skip_default_package=False, silent=False): - with_packages = set(self.pkg_types_to_names(with_packages or [])) - without_packages = set(self.pkg_types_to_names(without_packages or [])) + with_packages = set(self.find_pkg_names(with_packages or [])) + without_packages = set(self.find_pkg_names(without_packages or [])) upkgs = with_packages | without_packages ppkgs = set(self.packages.keys()) @@ -256,6 +260,23 @@ class PlatformPackagesMixin(object): return True + def find_pkg_names(self, items): + result = [] + for item in items: + candidate = item + + # lookup by package types + for _name, _opts in self.packages.items(): + if _opts.get("type") == item: + candidate = _name + + if (self.frameworks and item.startswith("framework-") and + item[10:] in self.frameworks): + candidate = self.frameworks[item[10:]]['package'] + + result.append(candidate) + return result + def update_packages(self, only_check=False): for name, manifest in self.get_installed_packages().items(): version = self.packages[name].get("version", "") @@ -518,20 +539,6 @@ class PlatformBase( # pylint: disable=too-many-public-methods def get_package_type(self, name): return self.packages[name].get("type") - def pkg_types_to_names(self, types): - names = [] - for type_ in types: - name = type_ - # lookup by package types - for _name, _opts in self.packages.items(): - if _opts.get("type") == type_: - name = None - names.append(_name) - # if type is the right name - if name: - names.append(name) - return names - def configure_default_packages(self, variables, targets): # enable used frameworks frameworks = variables.get("pioframework", []) From 64eaa1516be671314330f9fea9b0120c65154777 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2017 20:45:08 +0300 Subject: [PATCH 122/127] Add information about VSCode integration // Resolve #619 --- HISTORY.rst | 2 ++ docs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 58768b0b..75b385da 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -21,6 +21,8 @@ PlatformIO 3.0 (`issue #430 `_) * List supported frameworks, SDKs with a new `pio platform frameworks `__ command +* Visual Studio Code extension for PlatformIO + (`issue #619 `_) * Added new options ``--no-reset``, ``--monitor-rts`` and ``--monitor-dtr`` to `pio test `__ command (allows to avoid automatic board's auto-reset when gathering test results) diff --git a/docs b/docs index dc82d8b8..b130133b 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit dc82d8b835fbe754c02220342038c4f1197d813b +Subproject commit b130133bb73cc5f2b8c2b2288c11b5385a22c7d7 From ac245ad0a4bda20ffbdbd3a512d4a40025ffcb62 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2017 21:04:16 +0300 Subject: [PATCH 123/127] Handle circle dependencies for package // Resolve #919 --- platformio/managers/lib.py | 4 ++++ platformio/managers/package.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index ea5b343f..68bc1ce7 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -237,6 +237,7 @@ class LibraryManager(BasePkgManager): silent=False, trigger_event=True, interactive=False): + pkg_dir = None try: _name, _requirements, _url = self.parse_pkg_input(name, requirements) @@ -254,6 +255,9 @@ class LibraryManager(BasePkgManager): click.secho(str(e), fg="yellow") return + if not pkg_dir: + return + manifest = self.load_manifest(pkg_dir) if "dependencies" not in manifest: return pkg_dir diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 1f9bffd6..69fd0d83 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -470,6 +470,9 @@ class PkgInstallerMixin(object): class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): + # Handle circle dependencies + INSTALL_HISTORY = None + def __init__(self, package_dir, repositories=None): self.repositories = repositories self.package_dir = package_dir @@ -592,6 +595,15 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): requirements=None, silent=False, trigger_event=True): + + # avoid circle dependencies + if not BasePkgManager.INSTALL_HISTORY: + BasePkgManager.INSTALL_HISTORY = [] + history_key = "%s-%s" % (name, requirements) if requirements else name + if history_key in BasePkgManager.INSTALL_HISTORY: + return + BasePkgManager.INSTALL_HISTORY.append(history_key) + name, requirements, url = self.parse_pkg_input(name, requirements) package_dir = self.get_package_dir(name, requirements, url) From b7a61f12e8cb3cdc3d62ff8bd7c8f21f5481d34a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2017 21:32:54 +0300 Subject: [PATCH 124/127] =?UTF-8?q?Don=E2=80=99t=20use=20global=20install?= =?UTF-8?q?=20history=20when=20check=20circle=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio/managers/package.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 69fd0d83..6adb753e 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -597,12 +597,12 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): trigger_event=True): # avoid circle dependencies - if not BasePkgManager.INSTALL_HISTORY: - BasePkgManager.INSTALL_HISTORY = [] + if not self.INSTALL_HISTORY: + self.INSTALL_HISTORY = [] history_key = "%s-%s" % (name, requirements) if requirements else name - if history_key in BasePkgManager.INSTALL_HISTORY: + if history_key in self.INSTALL_HISTORY: return - BasePkgManager.INSTALL_HISTORY.append(history_key) + self.INSTALL_HISTORY.append(history_key) name, requirements, url = self.parse_pkg_input(name, requirements) package_dir = self.get_package_dir(name, requirements, url) From e736b08a4920421d517a992a89ba8b80706fcc3b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 27 Mar 2017 14:14:29 +0300 Subject: [PATCH 125/127] Allow to update only the PIO Core packages --- docs | 2 +- platformio/commands/platform.py | 5 ++--- platformio/commands/update.py | 11 ++++++++++- platformio/maintenance.py | 4 +--- platformio/managers/core.py | 7 ++++--- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/docs b/docs index b130133b..a5a47214 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit b130133bb73cc5f2b8c2b2288c11b5385a22c7d7 +Subproject commit a5a472148cf06a33a65e5cdd2edcaab5cc6e689a diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 5d44417e..70ac4b39 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -332,9 +332,6 @@ def platform_uninstall(platforms): help="Do not update, only check for a new version") @click.option("--json-output", is_flag=True) def platform_update(platforms, only_packages, only_check, json_output): - # cleanup cached board and platform lists - app.clean_cache() - pm = PlatformManager() pkg_dir_to_name = {} if not platforms: @@ -366,6 +363,8 @@ def platform_update(platforms, only_packages, only_check, json_output): result.append(data) return click.echo(json.dumps(result)) else: + # cleanup cached board and platform lists + app.clean_cache() for platform in platforms: click.echo("Platform %s" % click.style( pkg_dir_to_name.get(platform, platform), fg="cyan")) diff --git a/platformio/commands/update.py b/platformio/commands/update.py index 95511e44..41d0185d 100644 --- a/platformio/commands/update.py +++ b/platformio/commands/update.py @@ -14,6 +14,7 @@ import click +from platformio import app from platformio.commands.lib import lib_update as cmd_lib_update from platformio.commands.platform import platform_update as cmd_platform_update from platformio.managers.core import update_core_packages @@ -22,15 +23,23 @@ from platformio.managers.lib import LibraryManager @click.command( "update", short_help="Update installed platforms, packages and libraries") +@click.option( + "--core-packages", is_flag=True, help="Update only the core packages") @click.option( "-c", "--only-check", is_flag=True, help="Do not update, only check for new version") @click.pass_context -def cli(ctx, only_check): +def cli(ctx, core_packages, only_check): update_core_packages(only_check) + if core_packages: + return + + # cleanup lib search results, cached board and platform lists + app.clean_cache() + click.echo() click.echo("Platform Manager") click.echo("================") diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 9cd95719..df811972 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -59,8 +59,6 @@ def on_platformio_start(ctx, force, caller): app.set_session_var("caller_id", caller) telemetry.on_command() - if ctx.args and ctx.args[0] == "update": - app.clean_cache() if not in_silence(ctx): after_upgrade(ctx) @@ -159,7 +157,7 @@ def after_upgrade(ctx): app.clean_cache() # Update PlatformIO's Core packages - update_core_packages() + update_core_packages(silent=True) u = Upgrader(last_version, __version__) if u.run(ctx): diff --git a/platformio/managers/core.py b/platformio/managers/core.py index fabe449e..c711fcc6 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -21,7 +21,6 @@ from platformio import exception, util from platformio.managers.package import PackageManager CORE_PACKAGES = { - "project-templates": "*", "pysite-pioplus": ">=0.3.0,<2", "tool-pioplus": ">=0.6.10,<2", "tool-unity": "~1.20302.1", @@ -53,11 +52,13 @@ def get_core_package_dir(name): return pm.install(name, requirements) -def update_core_packages(only_check=False): +def update_core_packages(only_check=False, silent=False): pm = CorePackageManager() for name, requirements in CORE_PACKAGES.items(): pkg_dir = pm.get_package_dir(name) - if pkg_dir and pm.outdated(pkg_dir, requirements): + if not pkg_dir: + continue + if not silent or pm.outdated(pkg_dir, requirements): pm.update(name, requirements, only_check=only_check) From 3721a8f039e2d5e2df1adee0ff00aef0be96534c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 27 Mar 2017 14:33:51 +0300 Subject: [PATCH 126/127] Move Python installation to FAQ --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index a5a47214..d20acf36 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a5a472148cf06a33a65e5cdd2edcaab5cc6e689a +Subproject commit d20acf36318cda3594f03e7fb075810e9180d64c From aedbda8d7a89ec2b1bdc04c7d0e3325ec6175efe Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 27 Mar 2017 14:39:20 +0300 Subject: [PATCH 127/127] Bump version to 3.3.0 --- HISTORY.rst | 2 +- platformio/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 75b385da..e10513ed 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,7 +4,7 @@ Release Notes PlatformIO 3.0 -------------- -3.3.0 (2017-??-??) +3.3.0 (2017-03-27) ~~~~~~~~~~~~~~~~~~ * PlatformIO Library Registry statistics with new diff --git a/platformio/__init__.py b/platformio/__init__.py index ea0e7f69..d5bbee86 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 3, "0a17") +VERSION = (3, 3, 0) __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio"