diff --git a/HISTORY.rst b/HISTORY.rst index e6bea3a7..880f3c02 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,14 +1,30 @@ Release History =============== -2.2.1 (2015-??-??) +2.2.2 (2015-07-30) +------------------ + +* 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 + (`issue #255 `_) +* Show internal errors from "Miniterm" using `platformio serialports monitor `__ command + (`issue #257 `_) +* 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 `_) + +2.2.1 (2015-07-17) ------------------ * Project generator for `CLion IDE `__ (`issue #132 `_) * Updated ``tool-bossac`` package to 1.5 version for `atmelsam `__ platform -* Updated ``sdk-esp8266`` package for `espressif `__ platform (`issue #251 `_) +* Updated ``sdk-esp8266`` package for `espressif `__ platform * Fixed incorrect arguments handling for `platformio serialports monitor `_ command (`issue #248 `_) diff --git a/README.rst b/README.rst index 05c80928..b18d99bf 100644 --- a/README.rst +++ b/README.rst @@ -7,9 +7,6 @@ PlatformIO .. image:: https://ci.appveyor.com/api/projects/status/dku0h2rutfj0ctls/branch/develop?svg=true :target: https://ci.appveyor.com/project/ivankravets/platformio :alt: AppVeyor.CI Build Status -.. image:: https://api.shippable.com/projects/555b0ceeedd7f2c052f3c2d0/badge?branchName=develop - :target: https://app.shippable.com/projects/555b0ceeedd7f2c052f3c2d0 - :alt: Shippable Build Status .. image:: https://circleci.com/gh/platformio/platformio/tree/develop.svg?style=svg :target: https://circleci.com/gh/platformio/platformio/tree/develop :alt: Circle.CI Build Status diff --git a/docs/_static/ide-platformio-atom-1.gif b/docs/_static/ide-platformio-atom-1.gif new file mode 100644 index 00000000..3ee6c899 Binary files /dev/null and b/docs/_static/ide-platformio-atom-1.gif differ diff --git a/docs/_static/ide-platformio-atom-2.gif b/docs/_static/ide-platformio-atom-2.gif new file mode 100644 index 00000000..2a367374 Binary files /dev/null and b/docs/_static/ide-platformio-atom-2.gif differ diff --git a/docs/articles.rst b/docs/articles.rst index 62099544..eead4cbe 100644 --- a/docs/articles.rst +++ b/docs/articles.rst @@ -9,6 +9,7 @@ Articles about us Here are recent articles about PlatformIO: +* Jul 20, 2015 - **Eli Fatsi** - `Arduino Development in Atom Editor `_ * Jun 02, 2015 - **Alejandro Guirao Rodriguez** - `Discovering PlatformIO: The RaspberryPi / Arduino combo kit is a winner option when prototyping an IoT-style project `_ * May 11, 2015 - **IT Hare** - `From Web Developer to Embedded One: Interview with Ivan Kravets, The Guy Behind PlatformIO. Part II `_ * May 4, 2015 - **IT Hare** - `From Web Developer to Embedded One: Interview with Ivan Kravets, The Guy Behind PlatformIO. Part I `_ diff --git a/docs/ide.rst b/docs/ide.rst index 6e5623fe..aa76637b 100644 --- a/docs/ide.rst +++ b/docs/ide.rst @@ -7,6 +7,7 @@ IDE Integration :maxdepth: 2 ide/arduino + ide/atom ide/clion ide/eclipse ide/energia diff --git a/docs/ide/atom.rst b/docs/ide/atom.rst new file mode 100644 index 00000000..c4fa674c --- /dev/null +++ b/docs/ide/atom.rst @@ -0,0 +1,39 @@ +.. _ide_atom: + +Atom +==== + +`Atom `_ is a text editor that's modern, approachable, +yet hackable to the core—a tool you can customize to do anything but also use +productively without ever touching a config file. + +This software can be used with: + +* all available :ref:`platforms` +* all available :ref:`frameworks` + +Refer to the `Atom Documentation `_ +page for more detailed information. + +.. contents:: + +Integration +----------- + +Using `Atom Packages `_ +please install `platomformio `_ package. + +Screenshot +---------- + +Building +^^^^^^^^ + +.. image:: ../_static/ide-platformio-atom-1.gif + :target: https://atom.io/packages/platomformio + +Uploading +^^^^^^^^^ + +.. image:: ../_static/ide-platformio-atom-2.gif + :target: https://atom.io/packages/platomformio diff --git a/docs/installation.rst b/docs/installation.rst index 0dbb97e6..20e447de 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -55,11 +55,11 @@ Super-Quick (Mac / Linux) ~~~~~~~~~~~~~~~~~~~~~~~~~ To install or upgrade *PlatformIO* paste that at a *Terminal* prompt -(**you might need** to run ``sudo`` first): +(**you MIGHT need** to run ``sudo`` first, just for installation): .. code-block:: bash - python -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" + [sudo] python -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" Installer Script (Mac / Linux / Windows) @@ -67,12 +67,13 @@ Installer Script (Mac / Linux / Windows) To install or upgrade *PlatformIO*, download `get-platformio.py `_ -script. Then run the following (you might need to run ``sudo`` first): +script. Then run the following (**you MIGHT need** to run ``sudo`` first, +just for installation): .. code-block:: bash # change directory to folder where is located downloaded "get-platformio.py" - cd /path/to/dir/where/is/installer/script + cd /path/to/dir/where/is/located/get-platformio.py/script # run it python get-platformio.py @@ -83,7 +84,7 @@ On *Windows OS* it may look like: .. code-block:: bash # change directory to folder where is located downloaded "get-platformio.py" - cd C:\path\to\dir\where\is\installer\script + cd C:\path\to\dir\where\is\located\get-platformio.py\script # run it C:\Python27\python.exe get-platformio.py diff --git a/docs/platforms/creating_platform.rst b/docs/platforms/creating_platform.rst index 3497fe88..dfbd0bdc 100644 --- a/docs/platforms/creating_platform.rst +++ b/docs/platforms/creating_platform.rst @@ -145,6 +145,8 @@ Example of the **test** platform (``test.py``): .. code-block:: python + import os + from platformio.platforms.base import BasePlatform class TestPlatform(BasePlatform): diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 66c8cd0c..34c0feeb 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -57,6 +57,11 @@ A default value is ``%home_dir%/lib``. This option can be overridden by global environment variable :ref:`envvar_PLATFORMIO_LIB_DIR`. +.. note:: + You can put here your own/private libraries. The source code of each + library should be placed in separate directory. For example, + ``%lib_dir%/private_lib/[here are source files]``. + .. _projectconf_pio_src_dir: ``src_dir`` diff --git a/docs/userguide/cmd_run.rst b/docs/userguide/cmd_run.rst index 468f22cd..62cd265c 100644 --- a/docs/userguide/cmd_run.rst +++ b/docs/userguide/cmd_run.rst @@ -62,6 +62,12 @@ There 3 levels of verbosity: By default, verbosity level is set to 3 (maximum information). +.. option:: + --disable-auto-clean + +Disable auto-clean of :ref:`projectconf_pio_envs_dir` when :ref:`projectconf` +or :ref:`projectconf_pio_src_dir` (project structure) have been modified. + Examples -------- diff --git a/examples/teensy/teensy-hid-usb-mouse/README.rst b/examples/teensy/teensy-hid-usb-mouse/README.rst new file mode 100644 index 00000000..e2950ca7 --- /dev/null +++ b/examples/teensy/teensy-hid-usb-mouse/README.rst @@ -0,0 +1,21 @@ +How to build PlatformIO based project +===================================== + +1. `Install PlatformIO `_ +2. Download `source code with examples `_ +3. Extract ZIP archive +4. Run these commands: + +.. code-block:: bash + + # Change directory to example + > cd platformio-develop/examples/teensy/teensy-hid-usb-mouse + + # Process example project + > platformio run + + # Upload firmware + > platformio run --target upload + + # Clean build files + > platformio run --target clean diff --git a/examples/teensy/teensy-hid-usb-mouse/platformio.ini b/examples/teensy/teensy-hid-usb-mouse/platformio.ini new file mode 100644 index 00000000..2b1c160f --- /dev/null +++ b/examples/teensy/teensy-hid-usb-mouse/platformio.ini @@ -0,0 +1,24 @@ +# +# Project Configuration File +# +# A detailed documentation with the EXAMPLES is located here: +# http://docs.platformio.org/en/latest/projectconf.html +# + +# A sign `#` at the beginning of the line indicates a comment +# Comment lines are ignored. + +# Simple and base environment +# [env:mybaseenv] +# platform = %INSTALLED_PLATFORM_NAME_HERE% +# framework = +# board = +# +# Automatic targets - enable auto-uploading +# targets = upload + +[env:teensy31] +platform = teensy +framework = arduino +board = teensy31 +build_flags = -DTEENSY31 -UUSB_SERIAL -DUSB_SERIAL_HID diff --git a/examples/teensy/teensy-hid-usb-mouse/src/TriangleMove.ino b/examples/teensy/teensy-hid-usb-mouse/src/TriangleMove.ino new file mode 100644 index 00000000..9461825c --- /dev/null +++ b/examples/teensy/teensy-hid-usb-mouse/src/TriangleMove.ino @@ -0,0 +1,24 @@ +/* Simple USB Mouse Example + Teensy becomes a USB mouse and moves the cursor in a triangle + + You must select Mouse from the "Tools > USB Type" menu + + This example code is in the public domain. +*/ + +void setup() { } // no setup needed +void loop() { + int i; + for (i=0; i<40; i++) { + Mouse.move(2, -1); + delay(25); + } + for (i=0; i<40; i++) { + Mouse.move(2, 2); + delay(25); + } + for (i=0; i<40; i++) { + Mouse.move(-4, -1); + delay(25); + } +} \ No newline at end of file diff --git a/platformio/__init__.py b/platformio/__init__.py index bf88694a..48b1e7d2 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, 1) +VERSION = (2, 2, 2) __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/__main__.py b/platformio/__main__.py index 9721e794..a298502e 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -82,7 +82,8 @@ def main(): else: error_str += format_exc() click.secho(error_str, fg="red", err=True) - sys_exit(1) + return 1 + return 0 if __name__ == "__main__": diff --git a/platformio/app.py b/platformio/app.py index c7776827..b77e481d 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -7,7 +7,7 @@ from os.path import isfile, join from platformio import __version__ from platformio.exception import InvalidSettingName, InvalidSettingValue -from platformio.util import get_home_dir +from platformio.util import get_home_dir, is_ci DEFAULT_SETTINGS = { "check_platformio_interval": { @@ -109,8 +109,7 @@ def get_setting(name): if name == "enable_prompts": # disable prompts for Continuous Integration systems # and when global "--force" option is set - if any([getenv("CI", "").lower() == "true", - get_session_var("force_option")]): + if any([is_ci(), get_session_var("force_option")]): return False _env_name = "PLATFORMIO_SETTING_%s" % name.upper() diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 0098d63b..851b1f97 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -22,7 +22,7 @@ class InoToCPPConverter(object): DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I) - STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|(^|\s+)//[^\r\n]*$)", + STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|^\s*//[^\r\n]*$)", re.M | re.S) def __init__(self, nodes): diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 3ea18f9f..a2c9746a 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -43,12 +43,13 @@ def BuildFirmware(env): ) # enable "cyclic reference" for linker - env.Prepend( - _LIBFLAGS="-Wl,--start-group " - ) - env.Append( - _LIBFLAGS=" -Wl,--end-group" - ) + if env.get("LIBS", deplibs): + env.Prepend( + _LIBFLAGS="-Wl,--start-group " + ) + env.Append( + _LIBFLAGS=" -Wl,--end-group" + ) # Handle SRC_BUILD_FLAGS if getenv("PLATFORMIO_SRC_BUILD_FLAGS", None): diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 4b8ec5b2..14ab8271 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -26,9 +26,10 @@ from platformio.platforms.base import PlatformFactory type=click.Path(exists=True, file_okay=False, dir_okay=True, writable=True, resolve_path=True)) @click.option("--verbose", "-v", count=True, default=3) +@click.option("--disable-auto-clean", is_flag=True) @click.pass_context def cli(ctx, environment, target, upload_port, # pylint: disable=R0913,R0914 - project_dir, verbose): + project_dir, verbose, disable_auto_clean): with util.cd(project_dir): config = util.get_project_config() @@ -40,7 +41,8 @@ def cli(ctx, environment, target, upload_port, # pylint: disable=R0913,R0914 raise exception.UnknownEnvNames(", ".join(unknown)) # clean obsolete .pioenvs dir - _clean_pioenvs_dir() + if not disable_auto_clean: + _clean_pioenvs_dir() results = [] for section in config.sections(): diff --git a/platformio/commands/serialports.py b/platformio/commands/serialports.py index 820f4b4a..33dea746 100644 --- a/platformio/commands/serialports.py +++ b/platformio/commands/serialports.py @@ -7,6 +7,7 @@ import sys import click from serial.tools import miniterm +from platformio.exception import PlatformioException from platformio.util import get_serialports @@ -59,12 +60,12 @@ def serialports_list(json_output): # 1: escape non-printable characters, do newlines as unusual # 2: escape non-printable characters, newlines too # 3: hex dump everything""") -@click.option("--exit-char", type=int, default=0x1d, +@click.option("--exit-char", type=int, default=29, help="ASCII code of special character that is used to exit the " - "application, default=0x1d") -@click.option("--menu-char", type=int, default=0x14, + "application, default=19 (DEC)") +@click.option("--menu-char", type=int, default=20, help="ASCII code of special character that is used to control " - "miniterm (menu), default=0x14") + "miniterm (menu), default=20 (DEC)") @click.option("--quiet", is_flag=True, help="Diagnostics: suppress non-error messages, default=Off") def serialports_monitor(**kwargs): @@ -78,5 +79,5 @@ def serialports_monitor(**kwargs): try: miniterm.main() - except: # pylint: disable=W0702 - pass + except Exception as e: # pylint: disable=W0702 + raise PlatformioException(str(e)) diff --git a/platformio/telemetry.py b/platformio/telemetry.py index 6c666943..3426e9d5 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -7,6 +7,7 @@ import re import sys import threading import uuid +from os import getenv from time import time import click @@ -197,6 +198,32 @@ def _finalize(): def on_command(ctx): # pylint: disable=W0613 mp = MeasurementProtocol() mp.send("screenview") + if util.is_ci(): + measure_ci() + + +def measure_ci(): + event = { + "category": "CI", + "action": "NoName", + "label": None + } + + envmap = { + "APPVEYOR": {"label": getenv("APPVEYOR_REPO_NAME")}, + "CIRCLECI": {"label": "%s/%s" % (getenv("CIRCLE_PROJECT_USERNAME"), + getenv("CIRCLE_PROJECT_REPONAME"))}, + "TRAVIS": {"label": getenv("TRAVIS_REPO_SLUG")}, + "SHIPPABLE": {"label": getenv("REPO_NAME")}, + "DRONE": {"label": getenv("DRONE_REPO_SLUG")} + } + + for key, value in envmap.iteritems(): + if getenv(key, "").lower() != "true": + continue + event.update({"action": key, "label": value['label']}) + + on_event(**event) def on_run_environment(options, targets): diff --git a/scripts/get-platformio.py b/scripts/get-platformio.py index a8ccd81c..3054d2bb 100644 --- a/scripts/get-platformio.py +++ b/scripts/get-platformio.py @@ -9,7 +9,7 @@ from tempfile import NamedTemporaryFile CURINTERPRETER_PATH = os.path.normpath(sys.executable) -IS_WINDOWS = system() == "Windows" +IS_WINDOWS = system().lower() == "windows" def fix_winpython_pathenv(): @@ -61,12 +61,12 @@ def exec_command(*args, **kwargs): out, err = p.communicate() if p.returncode != 0: - raise Exception(err) + raise Exception("\n".join([out, err])) return out def exec_python_cmd(args): - return exec_command([CURINTERPRETER_PATH] + args, shell=IS_WINDOWS).strip() + return exec_command([CURINTERPRETER_PATH] + args).strip() def install_pip(): @@ -89,8 +89,7 @@ def install_pip(): def install_pypi_packages(packages): for pipargs in packages: print (exec_python_cmd([ - "-m", - "pip.__main__" if sys.version_info < (2, 7, 0) else "pip", + "-m", "pip.__main__" if sys.version_info < (2, 7, 0) else "pip", "install", "-U"] + pipargs)) @@ -110,14 +109,27 @@ def main(): is_error = False for s in steps: + if is_error: + break print ("\n==> %s ..." % s[0]) try: s[1](*s[2]) print ("[SUCCESS]") except Exception, e: is_error = True - print (e) + print (str(e)) print ("[FAILURE]") + if "Permission denied" in str(e) and not IS_WINDOWS: + print (""" +----------------- +Permission denied +----------------- + +You need the `sudo` permission to install Python packages. Try + +$ sudo python -c "$(curl -fsSL +https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" +""") if is_error: print ("The installation process has been FAILED!\n" @@ -129,16 +141,25 @@ def main(): "successfully FINISHED! <==\n") try: - print (exec_command("platformio", shell=IS_WINDOWS)) + print (exec_command("platformio")) except: try: print (exec_python_cmd([ "-m", "platformio.__main__" if sys.version_info < (2, 7, 0) else "platformio"])) - finally: - print ("\n Please RESTART your Terminal Application and run " - "`platformio --help` command.") + except: + pass + finally: + print (""" + +---------------------------------------- +Please RESTART your Terminal Application +---------------------------------------- + +Then run `platformio --help` command. + +""") if __name__ == "__main__": diff --git a/tests/test_pkgmanifest.py b/tests/test_pkgmanifest.py index f8f8efc4..b59062b0 100644 --- a/tests/test_pkgmanifest.py +++ b/tests/test_pkgmanifest.py @@ -52,19 +52,25 @@ def validate_package(url, sfpkglist): def test_package(package_data, sfpkglist): assert package_data['url'].endswith("%d.tar.gz" % package_data['version']) + sf_package = "sourceforge.net" in package_data['url'] # check content type and that file exists try: r = requests.head(package_data['url'], allow_redirects=True) if 500 <= r.status_code <= 599: raise requests.exceptions.ConnectionError() - except requests.exceptions.ConnectionError: - return pytest.skip("SF is off-line") + except requests.exceptions.ConnectionError as e: + if sf_package: + return pytest.skip("SF is off-line") + raise Exception(e) validate_response(r) assert r.headers['Content-Type'] in ("application/x-gzip", "application/octet-stream") + if not sf_package: + return + # check sha1 sum if sfpkglist is None: return pytest.skip("SF is off-line")