Merge branch 'release/v3.6.1'

This commit is contained in:
Ivan Kravets
2018-10-29 14:10:56 +02:00
56 changed files with 1194 additions and 832 deletions

View File

@ -1,12 +1,18 @@
build: off
environment:
platform:
- x86
- x64
environment:
matrix:
- TOXENV: "py27"
install:
- cmd: git submodule update --init --recursive
- cmd: SET PATH=%PATH%;C:\Python27\Scripts;C:\MinGW\bin
- cmd: SET PATH=C:\MinGW\bin;%PATH%
- if %PLATFORM% == x64 SET PATH=C:\Python27-x64;C:\Python27-x64\Scripts;%PATH%
- if %PLATFORM% == x86 SET PATH=C:\Python27;C:\Python27\Scripts;%PATH%
- cmd: pip install tox
test_script:

View File

@ -20,4 +20,4 @@ confidence=
# --disable=W"
# disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating
disable=locally-disabled,missing-docstring,invalid-name,too-few-public-methods,redefined-variable-type,import-error,similarities,unsupported-membership-test,unsubscriptable-object,ungrouped-imports,cyclic-import
disable=locally-disabled,missing-docstring,invalid-name,too-few-public-methods,redefined-variable-type,import-error,similarities,unsupported-membership-test,unsubscriptable-object,ungrouped-imports,cyclic-import,superfluous-parens

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ PlatformIO
`PIO Plus <https://platformio.org/pricing?utm_source=github&utm_medium=core>`_ |
`PlatformIO IDE <https://platformio.org/platformio-ide?utm_source=github&utm_medium=core>`_ |
`Project Examples <https://github.com/platformio/platformio-examples/>`_ |
`Docs <http://docs.platformio.org?utm_source=github&utm_medium=core>`_ |
`Docs <https://docs.platformio.org?utm_source=github&utm_medium=core>`_ |
`Donate <https://platformio.org/donate?utm_source=github&utm_medium=core>`_ |
`Contact Us <https://platformio.org/contact?utm_source=github&utm_medium=core>`_
@ -45,26 +45,26 @@ firmware updates.
Get Started
-----------
* `What is PlatformIO? <http://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=core>`_
* `What is PlatformIO? <https://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=core>`_
Open Source
-----------
* `PlatformIO IDE <https://platformio.org/platformio-ide?utm_source=github&utm_medium=core>`_
* `PlatformIO Core (CLI) <http://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=core>`_
* `Library Management <http://docs.platformio.org/page/librarymanager/index.html?utm_source=github&utm_medium=core>`_
* `PlatformIO Core (CLI) <https://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=core>`_
* `Library Management <https://docs.platformio.org/page/librarymanager/index.html?utm_source=github&utm_medium=core>`_
* `Project Examples <https://github.com/platformio/platformio-examples?utm_source=github&utm_medium=core>`_
* `Desktop IDEs Integration <http://docs.platformio.org/page/ide.html?utm_source=github&utm_medium=core>`_
* `Continuous Integration <http://docs.platformio.org/page/ci/index.html?utm_source=github&utm_medium=core>`_
* `Advanced Scripting API <http://docs.platformio.org/page/projectconf/advanced_scripting.html?utm_source=github&utm_medium=core>`_
* `Desktop IDEs Integration <https://docs.platformio.org/page/ide.html?utm_source=github&utm_medium=core>`_
* `Continuous Integration <https://docs.platformio.org/page/ci/index.html?utm_source=github&utm_medium=core>`_
* `Advanced Scripting API <https://docs.platformio.org/page/projectconf/advanced_scripting.html?utm_source=github&utm_medium=core>`_
PIO Plus
--------
* `PIO Remote <http://docs.platformio.org/page/plus/pio-remote.html?utm_source=github&utm_medium=core>`_
* `PIO Unified Debugger <http://docs.platformio.org/page/plus/debugging.html?utm_source=github&utm_medium=core>`_
* `PIO Unit Testing <http://docs.platformio.org/en/latest/plus/unit-testing.html?utm_source=github&utm_medium=core>`_
* `Cloud IDEs Integration <http://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=core#solution-pio-delivery>`_
* `PIO Remote <https://docs.platformio.org/page/plus/pio-remote.html?utm_source=github&utm_medium=core>`_
* `PIO Unified Debugger <https://docs.platformio.org/page/plus/debugging.html?utm_source=github&utm_medium=core>`_
* `PIO Unit Testing <https://docs.platformio.org/en/latest/plus/unit-testing.html?utm_source=github&utm_medium=core>`_
* `Cloud IDEs Integration <https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=core#solution-pio-delivery>`_
* `Integration Services <https://platformio.org/pricing?utm_source=github&utm_medium=core#enterprise-features>`_
Registry
@ -85,6 +85,7 @@ Development Platforms
* `Freescale Kinetis <https://platformio.org/platforms/freescalekinetis?utm_source=github&utm_medium=core>`_
* `Infineon XMC <https://platformio.org/platforms/infineonxmc?utm_source=github&utm_medium=core>`_
* `Intel ARC32 <https://platformio.org/platforms/intel_arc32?utm_source=github&utm_medium=core>`_
* `Intel MCS-51 (8051) <https://platformio.org/platforms/intel_mcs51?utm_source=github&utm_medium=core>`_
* `Lattice iCE40 <https://platformio.org/platforms/lattice_ice40?utm_source=github&utm_medium=core>`_
* `Maxim 32 <https://platformio.org/platforms/maxim32?utm_source=github&utm_medium=core>`_
* `Microchip PIC32 <https://platformio.org/platforms/microchippic32?utm_source=github&utm_medium=core>`_

2
docs

Submodule docs updated: 21c1cf522c...30c88f6247

View File

@ -14,7 +14,7 @@
import sys
VERSION = (3, 6, 0)
VERSION = (3, 6, 1)
__version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio"
@ -26,8 +26,8 @@ __description__ = (
"FPGA, CMSIS, SPL, AVR, Samsung ARTIK, libOpenCM3")
__url__ = "https://platformio.org"
__author__ = "Ivan Kravets"
__email__ = "me@ikravets.com"
__author__ = "PlatformIO"
__email__ = "contact@platformio.org"
__license__ = "Apache Software License"
__copyright__ = "Copyright 2014-present PlatformIO"

View File

@ -107,8 +107,8 @@ def configure():
try:
click_echo_origin[origin](*args, **kwargs)
except IOError:
(sys.stderr.write if kwargs.get("err") else
sys.stdout.write)("%s\n" % (args[0] if args else ""))
(sys.stderr.write if kwargs.get("err") else sys.stdout.write)(
"%s\n" % (args[0] if args else ""))
click.echo = lambda *args, **kwargs: _safe_echo(0, *args, **kwargs)
click.secho = lambda *args, **kwargs: _safe_echo(1, *args, **kwargs)
@ -135,7 +135,7 @@ An unexpected error occurred. Further steps:
`pip install -U platformio` command
* Try to find answer in FAQ Troubleshooting section
http://docs.platformio.org/page/faq.html
https://docs.platformio.org/page/faq.html
* Report this problem to the developers
https://github.com/platformio/platformio-core/issues

View File

@ -63,7 +63,7 @@ DEFAULT_SETTINGS = {
},
"enable_telemetry": {
"description":
("Telemetry service <http://docs.platformio.org/page/"
("Telemetry service <https://docs.platformio.org/page/"
"userguide/cmd_settings.html?#enable-telemetry> (Yes/No)"),
"value":
True
@ -352,8 +352,8 @@ def get_cid():
pass
cid = str(
uuid.UUID(
bytes=hashlib.md5(str(_uid if _uid else uuid.getnode()))
.digest()))
bytes=hashlib.md5(str(_uid if _uid else uuid.getnode())).
digest()))
if "windows" in util.get_systype() or os.getuid() > 0:
set_state_item("cid", cid)
return cid

View File

@ -135,7 +135,7 @@ if env.GetOption('clean'):
env.PioClean(env.subst("$BUILD_DIR"))
env.Exit(0)
elif not int(ARGUMENTS.get("PIOVERBOSE", 0)):
print "Verbose mode can be enabled via `-v, --verbose` option"
print("Verbose mode can be enabled via `-v, --verbose` option")
# Handle custom variables from system environment
for var in ("BUILD_FLAGS", "SRC_BUILD_FLAGS", "SRC_FILTER", "EXTRA_SCRIPTS",
@ -191,24 +191,25 @@ env.AddPreAction(
env.VerboseAction(lambda source, target, env: env.PrintUploadInfo(),
"Configuring upload protocol..."))
AlwaysBuild(env.Alias("debug", DEFAULT_TARGETS))
AlwaysBuild(env.Alias("__debug", DEFAULT_TARGETS))
AlwaysBuild(env.Alias("__test", DEFAULT_TARGETS))
##############################################################################
if "envdump" in COMMAND_LINE_TARGETS:
print env.Dump()
print(env.Dump())
env.Exit(0)
if "idedata" in COMMAND_LINE_TARGETS:
try:
print "\n%s\n" % util.path_to_unicode(
json.dumps(env.DumpIDEData(), ensure_ascii=False))
print("\n%s\n" % util.path_to_unicode(
json.dumps(env.DumpIDEData(), ensure_ascii=False)))
env.Exit(0)
except UnicodeDecodeError:
sys.stderr.write(
"\nUnicodeDecodeError: Non-ASCII characters found in build "
"environment\n"
"See explanation in FAQ > Troubleshooting > Building\n"
"http://docs.platformio.org/page/faq.html\n\n")
"https://docs.platformio.org/page/faq.html\n\n")
env.Exit(1)

View File

@ -25,7 +25,7 @@ from platformio.managers.core import get_core_package_dir
def _dump_includes(env):
includes = []
includes = [env.subst("$PROJECTINCLUDE_DIR"), env.subst("$PROJECTSRC_DIR")]
for item in env.get("CPPPATH", []):
includes.append(env.subst(item))
@ -97,8 +97,8 @@ def _dump_defines(env):
board_mcu = env.BoardConfig().get("build.mcu")
if board_mcu:
defines.append(
str("__AVR_%s__" % board_mcu.upper()
.replace("ATMEGA", "ATmega").replace("ATTINY", "ATtiny")))
str("__AVR_%s__" % board_mcu.upper().replace(
"ATMEGA", "ATmega").replace("ATTINY", "ATtiny")))
# built-in GCC marcos
# if env.GetCompilerType() == "gcc":

View File

@ -373,7 +373,7 @@ class LibBuilderBase(object):
if isfile("%s.%s" % (_f_part, ext)):
incs.append(
self.env.File("%s.%s" % (_f_part, ext)))
# print path, map(lambda n: n.get_abspath(), incs)
# print(path, map(lambda n: n.get_abspath(), incs))
for inc in incs:
if inc not in result:
result.append(inc)
@ -808,7 +808,7 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches
if verbose and found_incompat:
sys.stderr.write(
"More details about \"Library Compatibility Mode\": "
"http://docs.platformio.org/page/librarymanager/ldf.html#"
"https://docs.platformio.org/page/librarymanager/ldf.html#"
"ldf-compat-mode\n")
DefaultEnvironment()['__PIO_LIB_BUILDERS'] = items
@ -851,24 +851,24 @@ def ConfigureProjectLibBuilder(env):
project = ProjectAsLibBuilder(env, "$PROJECT_DIR")
ldf_mode = LibBuilderBase.lib_ldf_mode.fget(project)
print "Library Dependency Finder -> http://bit.ly/configure-pio-ldf"
print "LDF MODES: FINDER(%s) COMPATIBILITY(%s)" % (ldf_mode,
project.lib_compat_mode)
print("Library Dependency Finder -> http://bit.ly/configure-pio-ldf")
print("LDF MODES: FINDER(%s) COMPATIBILITY(%s)" %
(ldf_mode, project.lib_compat_mode))
lib_builders = env.GetLibBuilders()
print "Collected %d compatible libraries" % len(lib_builders)
print("Collected %d compatible libraries" % len(lib_builders))
print "Scanning dependencies..."
print("Scanning dependencies...")
project.search_deps_recursive()
if ldf_mode.startswith("chain") and project.depbuilders:
correct_found_libs(lib_builders)
if project.depbuilders:
print "Dependency Graph"
print("Dependency Graph")
print_deps_tree(project)
else:
print "No dependencies"
print("No dependencies")
return project

View File

@ -274,13 +274,13 @@ def VerboseAction(_, act, actstr):
def PioClean(env, clean_dir):
if not isdir(clean_dir):
print "Build environment is clean"
print("Build environment is clean")
env.Exit(0)
for root, _, files in walk(clean_dir):
for file_ in files:
remove(join(root, file_))
print "Removed %s" % relpath(join(root, file_))
print "Done cleaning"
print("Removed %s" % relpath(join(root, file_)))
print("Done cleaning")
util.rmtree_(clean_dir)
env.Exit(0)
@ -288,10 +288,14 @@ def PioClean(env, clean_dir):
def ProcessDebug(env):
if not env.subst("$PIODEBUGFLAGS"):
env.Replace(PIODEBUGFLAGS=["-Og", "-g3", "-ggdb3"])
env.Append(PIODEBUGFLAGS=["-D__PLATFORMIO_DEBUG__"])
env.Append(
BUILD_FLAGS=env.get("PIODEBUGFLAGS", []),
BUILD_UNFLAGS=["-Os", "-O0", "-O1", "-O2", "-O3"])
PIODEBUGFLAGS=["-D__PLATFORMIO_DEBUG__"],
BUILD_FLAGS=env.get("PIODEBUGFLAGS", []))
unflags = ["-Os"]
for level in [0, 1, 2]:
for flag in ("O", "g", "ggdb"):
unflags.append("-%s%d" % (flag, level))
env.Append(BUILD_UNFLAGS=unflags)
def ProcessTest(env):

View File

@ -23,7 +23,7 @@ from SCons.Script import COMMAND_LINE_TARGETS
from platformio import exception, util
from platformio.managers.platform import PlatformFactory
# pylint: disable=too-many-branches
# pylint: disable=too-many-branches, too-many-locals
@util.memoized()
@ -122,8 +122,10 @@ def LoadPioPlatform(env, variables):
def PrintConfiguration(env):
platform_data = ["PLATFORM: %s >" % env.PioPlatform().title]
platform = env.PioPlatform()
platform_data = ["PLATFORM: %s >" % platform.title]
system_data = ["SYSTEM:"]
configuration_data = ["CONFIGURATION:"]
mcu = env.subst("$BOARD_MCU")
f_cpu = env.subst("$BOARD_F_CPU")
if mcu:
@ -142,11 +144,13 @@ def PrintConfiguration(env):
flash = board_config.get("upload", {}).get("maximum_size")
system_data.append("%s RAM (%s Flash)" % (util.format_filesize(ram),
util.format_filesize(flash)))
configuration_data.append(
"https://docs.platformio.org/page/boards/%s/%s.html" %
(platform.name, board_config.id))
if platform_data:
print " ".join(platform_data)
if system_data:
print " ".join(system_data)
for data in (configuration_data, platform_data, system_data):
if len(data) > 1:
print(" ".join(data))
# Debugging
if not debug_tools:
@ -168,7 +172,7 @@ def PrintConfiguration(env):
if external:
data.append("EXTERNAL(%s)" % ", ".join(sorted(external)))
print "DEBUG: %s" % " ".join(data)
print("DEBUG: %s" % " ".join(data))
def exists(_):

View File

@ -25,7 +25,7 @@ from time import sleep
from SCons.Script import ARGUMENTS
from serial import Serial, SerialException
from platformio import util
from platformio import exception, util
# pylint: disable=unused-argument
@ -43,7 +43,7 @@ def FlushSerialBuffer(env, port):
def TouchSerialPort(env, port, baudrate):
port = env.subst(port)
print "Forcing reset using %dbps open/close on port %s" % (baudrate, port)
print("Forcing reset using %dbps open/close on port %s" % (baudrate, port))
try:
s = Serial(port=port, baudrate=baudrate)
s.setDTR(False)
@ -54,7 +54,7 @@ def TouchSerialPort(env, port, baudrate):
def WaitForNewSerialPort(env, before):
print "Waiting for the new upload port..."
print("Waiting for the new upload port...")
prev_port = env.subst("$UPLOAD_PORT")
new_port = None
elapsed = 0
@ -146,7 +146,7 @@ def AutodetectUploadPort(*args, **kwargs):
return port
if "UPLOAD_PORT" in env and not _get_pattern():
print env.subst("Use manually specified: $UPLOAD_PORT")
print(env.subst("Use manually specified: $UPLOAD_PORT"))
return
if (env.subst("$UPLOAD_PROTOCOL") == "mbed"
@ -154,19 +154,14 @@ def AutodetectUploadPort(*args, **kwargs):
and not env.subst("$UPLOAD_PROTOCOL"))):
env.Replace(UPLOAD_PORT=_look_for_mbed_disk())
else:
if ("linux" in util.get_systype() and not any([
isfile("/etc/udev/rules.d/99-platformio-udev.rules"),
isfile("/lib/udev/rules.d/99-platformio-udev.rules")
])):
sys.stderr.write(
"\nWarning! Please install `99-platformio-udev.rules` and "
"check that your board's PID and VID are listed in the rules."
"\n http://docs.platformio.org/en/latest/faq.html"
"#platformio-udev-rules\n")
try:
util.ensure_udev_rules()
except exception.InvalidUdevRules as e:
sys.stderr.write("\n%s\n\n" % e)
env.Replace(UPLOAD_PORT=_look_for_serial_port())
if env.subst("$UPLOAD_PORT"):
print env.subst("Auto-detected: $UPLOAD_PORT")
print(env.subst("Auto-detected: $UPLOAD_PORT"))
else:
sys.stderr.write(
"Error: Please specify `upload_port` for environment or use "
@ -185,8 +180,8 @@ def UploadToDisk(_, target, source, env):
continue
copyfile(fpath,
join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)))
print "Firmware has been successfully uploaded.\n"\
"(Some boards may require manual hard reset)"
print("Firmware has been successfully uploaded.\n"
"(Some boards may require manual hard reset)")
def CheckUploadSize(_, target, source, env):
@ -251,14 +246,14 @@ def CheckUploadSize(_, target, source, env):
program_size = _calculate_size(output, env.get("SIZEPROGREGEXP"))
data_size = _calculate_size(output, env.get("SIZEDATAREGEXP"))
print "Memory Usage -> http://bit.ly/pio-memory-usage"
print("Memory Usage -> http://bit.ly/pio-memory-usage")
if data_max_size and data_size > -1:
print "DATA: %s" % _format_availale_bytes(data_size, data_max_size)
print("DATA: %s" % _format_availale_bytes(data_size, data_max_size))
if program_size > -1:
print "PROGRAM: %s" % _format_availale_bytes(program_size,
program_max_size)
print("PROGRAM: %s" % _format_availale_bytes(program_size,
program_max_size))
if int(ARGUMENTS.get("PIOVERBOSE", 0)):
print output
print(output)
# raise error
# if data_max_size and data_size > data_max_size:
@ -280,9 +275,9 @@ def PrintUploadInfo(env):
available.extend(env.BoardConfig().get("upload", {}).get(
"protocols", []))
if available:
print "AVAILABLE: %s" % ", ".join(sorted(set(available)))
print("AVAILABLE: %s" % ", ".join(sorted(set(available))))
if configured:
print "CURRENT: upload_protocol = %s" % configured
print("CURRENT: upload_protocol = %s" % configured)
def exists(_):

View File

@ -93,7 +93,7 @@ def BuildProgram(env):
if not Util.case_sensitive_suffixes(".s", ".S"):
env.Replace(AS="$CC", ASCOM="$ASPPCOM")
if "__debug" in COMMAND_LINE_TARGETS:
if set(["__debug", "debug"]) & set(COMMAND_LINE_TARGETS):
env.ProcessDebug()
# process extra flags from board
@ -141,10 +141,15 @@ def BuildProgram(env):
return program
def ParseFlagsExtended(env, flags):
if isinstance(flags, list):
flags = " ".join(flags)
result = env.ParseFlags(str(flags))
def ParseFlagsExtended(env, flags): # pylint: disable=too-many-branches
if not isinstance(flags, list):
flags = [flags]
result = {}
for raw in flags:
for key, value in env.ParseFlags(str(raw)).items():
if key not in result:
result[key] = []
result[key].extend(value)
cppdefines = []
for item in result['CPPDEFINES']:
@ -319,6 +324,7 @@ def BuildFrameworks(env, frameworks):
def BuildLibrary(env, variant_dir, src_dir, src_filter=None):
env.ProcessUnFlags(env.get("BUILD_UNFLAGS"))
return env.StaticLibrary(
env.subst(variant_dir),
env.CollectBuildFiles(variant_dir, src_dir, src_filter))

View File

@ -86,7 +86,7 @@ def cli( # pylint: disable=too-many-arguments
app.set_session_var("force_option", True)
_clean_dir(build_dir)
for dir_name, patterns in dict(lib=lib, src=src).iteritems():
for dir_name, patterns in dict(lib=lib, src=src).items():
if not patterns:
continue
contents = []

View File

@ -55,7 +55,7 @@ def device_list( # pylint: disable=too-many-branches
"mdns": "Multicast DNS Services"
}
for key, value in data.iteritems():
for key, value in data.items():
if not single_key:
click.secho(titles[key], bold=True)
click.echo("=" * len(titles[key]))
@ -85,7 +85,7 @@ def device_list( # pylint: disable=too-many-branches
if item['properties']:
click.echo("Properties: %s" % ("; ".join([
"%s=%s" % (k, v)
for k, v in item['properties'].iteritems()
for k, v in item['properties'].items()
])))
click.echo("")
@ -182,7 +182,7 @@ def device_monitor(**kwargs): # pylint: disable=too-many-branches
kwargs['port'] = ports[0]['port']
sys.argv = ["monitor"]
for k, v in kwargs.iteritems():
for k, v in kwargs.items():
if k in ("port", "baud", "rts", "dtr", "environment", "project_dir"):
continue
k = "--" + k.replace("_", "-")

View File

@ -15,7 +15,6 @@
import sys
import click
import requests
from platformio.managers.core import pioplus_call
@ -30,13 +29,3 @@ from platformio.managers.core import pioplus_call
@click.option("--no-open", is_flag=True)
def cli(*args, **kwargs): # pylint: disable=unused-argument
pioplus_call(sys.argv[1:])
def shutdown_servers():
port = 8010
while port < 9000:
try:
requests.get("http://127.0.0.1:%d?__shutdown__=1" % port)
port += 1
except: # pylint: disable=bare-except
return

View File

@ -73,22 +73,21 @@ def cli(
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.secho("will be used for the project.", 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 project header files here" % click.style(
"include", fg="cyan"))
click.echo("%s - Put here project specific (private) libraries" %
click.style("lib", fg="cyan"))
click.echo("%s - Put project source files here" % click.style(
"src", fg="cyan"))
click.echo("%s - Project Configuration File" % click.style(
"platformio.ini", fg="cyan"))
is_new_project = util.is_platformio_project(project_dir)
init_base_project(project_dir)
if board:
@ -102,16 +101,28 @@ def cli(
pg = ProjectGenerator(project_dir, ide, env_name)
pg.generate()
if not silent:
if is_new_project:
init_ci_conf(project_dir)
init_cvs_ignore(project_dir)
if silent:
return
if ide:
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",
"\nProject has been successfully %s including configuration files "
"for `%s` IDE." % ("initialized" if is_new_project else "updated",
ide),
fg="green")
else:
click.secho(
"\nProject has been successfully %s! Useful commands:\n"
"`pio run` - process/build project from the current directory\n"
"`pio run --target upload` or `pio run -t upload` "
"- upload firmware to a target\n"
"`pio run --target clean` - clean project (remove compiled files)"
"\n`pio run --help` - additional information" %
("initialized" if is_new_project else "updated"),
fg="green")
@ -134,35 +145,82 @@ def get_best_envname(project_dir, boards=None):
def init_base_project(project_dir):
if not util.is_platformio_project(project_dir):
copyfile(
join(util.get_source_dir(), "projectconftpl.ini"),
join(project_dir, "platformio.ini"))
if util.is_platformio_project(project_dir):
return
copyfile(
join(util.get_source_dir(), "projectconftpl.ini"),
join(project_dir, "platformio.ini"))
with util.cd(project_dir):
lib_dir = util.get_projectlib_dir()
src_dir = util.get_projectsrc_dir()
for d in (src_dir, lib_dir):
if not isdir(d):
makedirs(d)
dir_to_readme = [
(util.get_projectsrc_dir(), None),
(util.get_projectinclude_dir(), init_include_readme),
(util.get_projectlib_dir(), init_lib_readme),
(util.get_projecttest_dir(), init_test_readme),
]
for (path, cb) in dir_to_readme:
if isdir(path):
continue
makedirs(path)
if cb:
cb(path)
init_lib_readme(lib_dir)
init_ci_conf(project_dir)
init_cvs_ignore(project_dir)
def init_include_readme(include_dir):
with open(join(include_dir, "README"), "w") as f:
f.write("""
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
""")
def init_lib_readme(lib_dir):
if isfile(join(lib_dir, "readme.txt")):
return
with open(join(lib_dir, "readme.txt"), "w") as f:
with open(join(lib_dir, "README"), "w") as f:
f.write("""
This directory is intended for the project specific (private) libraries.
PlatformIO will compile them to static libraries and link to executable file.
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in separate directory, like
"lib/private_lib/[here are source files]".
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see how can be organized `Foo` and `Bar` libraries:
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
@ -172,40 +230,62 @@ For example, see how can be organized `Foo` and `Bar` libraries:
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- readme.txt --> THIS FILE
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Then in `src/main.c` you should use:
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
// rest H/C/CPP code
int main (void)
{
...
}
PlatformIO will find your libraries automatically, configure preprocessor's
include paths and build them.
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- http://docs.platformio.org/page/librarymanager/ldf.html
- https://docs.platformio.org/page/librarymanager/ldf.html
""")
def init_test_readme(test_dir):
with open(join(test_dir, "README"), "w") as f:
f.write("""
This directory is intended for PIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html
""")
def init_ci_conf(project_dir):
if isfile(join(project_dir, ".travis.yml")):
conf_path = join(project_dir, ".travis.yml")
if isfile(conf_path):
return
with open(join(project_dir, ".travis.yml"), "w") as f:
with open(conf_path, "w") as f:
f.write("""# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < http://docs.platformio.org/page/ci/index.html >
# several times a day < https://docs.platformio.org/page/ci/index.html >
#
# Documentation:
#
@ -213,13 +293,13 @@ def init_ci_conf(project_dir):
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < http://docs.platformio.org/page/ci/travis.html >
# < https://docs.platformio.org/page/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < http://docs.platformio.org/page/userguide/cmd_ci.html >
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
#
#
# Please choice one of the following templates (proposed below) and uncomment
# Please choose one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
@ -247,7 +327,7 @@ def init_ci_conf(project_dir):
#
# Template #2: The project is intended to by used as a library with examples
# Template #2: The project is intended to be used as a library with examples.
#
# language: python
@ -274,23 +354,11 @@ def init_ci_conf(project_dir):
def init_cvs_ignore(project_dir):
ignore_path = join(project_dir, ".gitignore")
default = [".pioenvs\n", ".piolibdeps\n"]
current = []
modified = False
if isfile(ignore_path):
with open(ignore_path) as fp:
current = fp.readlines()
if current and not current[-1].endswith("\n"):
current[-1] += "\n"
for d in default:
if d not in current:
modified = True
current.append(d)
if not modified:
conf_path = join(project_dir, ".gitignore")
if isfile(conf_path):
return
with open(ignore_path, "w") as fp:
fp.writelines(current)
with open(conf_path, "w") as fp:
fp.writelines([".pio\n", ".pioenvs\n", ".piolibdeps\n"])
def fill_project_envs(ctx, project_dir, board_ids, project_option, env_prefix,

View File

@ -203,7 +203,7 @@ def lib_search(query, json_output, page, noninteractive, **filters):
if not isinstance(query, list):
query = list(query)
for key, values in filters.iteritems():
for key, values in filters.items():
for value in values:
query.append('%s:"%s"' % (key, value))
@ -228,7 +228,7 @@ def lib_search(query, json_output, page, noninteractive, **filters):
click.echo("For more examples and advanced search syntax, "
"please use documentation:")
click.secho(
"http://docs.platformio.org/page/userguide/lib/cmd_search.html\n",
"https://docs.platformio.org/page/userguide/lib/cmd_search.html\n",
fg="cyan")
return
@ -307,13 +307,12 @@ def lib_builtin(storage, json_output):
def lib_show(library, json_output):
lm = LibraryManager()
name, requirements, _ = lm.parse_pkg_uri(library)
lib_id = lm.search_lib_id(
{
"name": name,
"requirements": requirements
},
silent=json_output,
interactive=not json_output)
lib_id = lm.search_lib_id({
"name": name,
"requirements": 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))
@ -423,16 +422,16 @@ 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(
time.strftime("%c", util.parse_date(item['date']))
if "date" in item else ""),
url=click.style(
"https://platformio.org/lib/show/%s/%s" %
(item['id'], quote(item['name'])),
fg="blue")))
date = str(
time.strftime("%c", util.parse_date(item['date'])) if "date" in
item else "")
url = click.style(
"https://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=date, url=url))
def _print_tag_item(name):
click.echo(

View File

@ -273,8 +273,8 @@ def platform_show(platform, json_output): # pylint: disable=too-many-branches
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)"))
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:
@ -365,8 +365,8 @@ def platform_update(platforms, only_packages, only_check, json_output):
if not pkg_dir:
continue
latest = pm.outdated(pkg_dir, requirements)
if (not latest and not PlatformFactory.newPlatform(pkg_dir)
.are_outdated_packages()):
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)

View File

@ -108,7 +108,9 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose,
results.append(result)
if result[1] and "monitor" in ep.get_build_targets() and \
"nobuild" not in ep.get_build_targets():
ctx.invoke(cmd_device_monitor)
ctx.invoke(
cmd_device_monitor,
environment=environment[0] if environment else None)
found_error = any(status is False for (_, status) in results)
@ -210,10 +212,10 @@ class EnvironmentProcessor(object):
if is_error or "piotest_processor" not in self.cmd_ctx.meta:
print_header(
"[%s] Took %.2f seconds" %
((click.style("ERROR", fg="red", bold=True)
if is_error else click.style(
"SUCCESS", fg="green", bold=True)), time() - start_time),
"[%s] Took %.2f seconds" % (
(click.style("ERROR", fg="red", bold=True) if is_error else
click.style("SUCCESS", fg="green", bold=True)),
time() - start_time),
is_error=is_error)
return not is_error
@ -384,9 +386,8 @@ def print_summary(results, start_time):
print_header(
"[%s] Took %.2f seconds" % (
(click.style("SUCCESS", fg="green", bold=True)
if successed else click.style("ERROR", fg="red", bold=True)),
time() - start_time),
(click.style("SUCCESS", fg="green", bold=True) if successed else
click.style("ERROR", fg="red", bold=True)), time() - start_time),
is_error=not successed)

View File

@ -32,14 +32,14 @@ from platformio.managers.lib import LibraryManager
help="Do not update, only check for new version")
@click.pass_context
def cli(ctx, core_packages, only_check):
# cleanup lib search results, cached board and platform lists
app.clean_cache()
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("================")

View File

@ -20,7 +20,7 @@ import click
import requests
from platformio import VERSION, __version__, exception, util
from platformio.commands.home import shutdown_servers
from platformio.managers.core import shutdown_piohome_servers
@click.command(
@ -36,7 +36,7 @@ def cli(dev):
click.secho("Please wait while upgrading PlatformIO ...", fg="yellow")
# kill all PIO Home servers, they block `pioplus` binary
shutdown_servers()
shutdown_piohome_servers()
to_develop = dev or not all(c.isdigit() for c in __version__ if c != ".")
cmds = (["pip", "install", "--upgrade",
@ -63,7 +63,7 @@ def cli(dev):
fg="green")
click.echo("Release notes: ", nl=False)
click.secho(
"http://docs.platformio.org/en/latest/history.html", fg="cyan")
"https://docs.platformio.org/en/latest/history.html", fg="cyan")
except Exception as e: # pylint: disable=broad-except
if not r:
raise exception.UpgradeError("\n".join([str(cmd), str(e)]))
@ -102,8 +102,9 @@ def get_pip_package(to_develop):
pkg_name = os.path.join(cache_dir, "piocoredevelop.zip")
try:
with open(pkg_name, "w") as fp:
r = util.exec_command(
["curl", "-fsSL", dl_url], stdout=fp, universal_newlines=True)
r = util.exec_command(["curl", "-fsSL", dl_url],
stdout=fp,
universal_newlines=True)
assert r['returncode'] == 0
# check ZIP structure
with ZipFile(pkg_name) as zp:

View File

@ -178,7 +178,7 @@ class InternetIsOffline(PlatformioException):
MESSAGE = (
"You are not connected to the Internet.\n"
"If you build a project first time, we need Internet connection "
"to install all dependencies and toolchain.")
"to install all dependencies and toolchains.")
class LibNotFound(PlatformioException):
@ -235,13 +235,32 @@ class CIBuildEnvsEmpty(PlatformioException):
"predefined environments using `--project-conf` option")
class InvalidUdevRules(PlatformioException):
pass
class MissedUdevRules(InvalidUdevRules):
MESSAGE = (
"Warning! Please install `99-platformio-udev.rules`. \nMode details: "
"https://docs.platformio.org/en/latest/faq.html#platformio-udev-rules")
class OutdatedUdevRules(InvalidUdevRules):
MESSAGE = (
"Warning! Your `{0}` are outdated. Please update or reinstall them."
"\n Mode details: https://docs.platformio.org"
"/en/latest/faq.html#platformio-udev-rules")
class UpgradeError(PlatformioException):
MESSAGE = """{0}
* Upgrade using `pip install -U platformio`
* Try different installation/upgrading steps:
http://docs.platformio.org/page/installation.html
https://docs.platformio.org/page/installation.html
"""
@ -265,7 +284,7 @@ class DebugSupportError(PlatformioException):
MESSAGE = ("Currently, PlatformIO does not support debugging for `{0}`.\n"
"Please contact support@pioplus.com or visit "
"< http://docs.platformio.org/page/plus/debugging.html >")
"< https://docs.platformio.org/page/plus/debugging.html >")
class DebugInvalidOptions(PlatformioException):

View File

@ -127,22 +127,8 @@ class ProjectGenerator(object):
@staticmethod
def _merge_contents(dst_path, contents):
file_name = basename(dst_path)
# merge .gitignore
if file_name == ".gitignore" and isfile(dst_path):
modified = False
default = [l.strip() for l in contents.split("\n")]
with open(dst_path) as fp:
current = [l.strip() for l in fp.readlines()]
for d in default:
if d and d not in current:
modified = True
current.append(d)
if not modified:
return
contents = "\n".join(current) + "\n"
if basename(dst_path) == ".gitignore" and isfile(dst_path):
return
with open(dst_path, "w") as f:
f.write(contents)

View File

@ -3,4 +3,4 @@
% end
% for define in defines:
-D{{!define}}
% end
% end

View File

@ -1,3 +1,4 @@
.pio
.pioenvs
.piolibdeps
.clang_complete

View File

@ -1,3 +1,4 @@
.pio
.pioenvs
.piolibdeps
CMakeListsPrivate.txt

View File

@ -9,6 +9,9 @@
<file path="$PROJECT_DIR$/lib" />
<file path="$PROJECT_DIR$/.piolibdeps" />
</libraryRoots>
<excludeRoots>
<file path="$PROJECT_DIR$/.pio" />
</excludeRoots>
<excludeRoots>
<file path="$PROJECT_DIR$/.pioenvs" />
</excludeRoots>

View File

@ -1,6 +1,6 @@
% for include in includes:
-I{{include}}
-I"{{include}}"
% end
% for define in defines:
-D{{!define}}
% end
% end

View File

@ -1,3 +1,4 @@
.pio
.pioenvs
.piolibdeps
.clang_complete

View File

@ -11,7 +11,7 @@
<itemPath>nbproject/private/launcher.properties</itemPath>
</logicalFolder>
</logicalFolder>
<sourceFolderFilter>^(nbproject|.pioenvs)$</sourceFolderFilter>
<sourceFolderFilter>^(nbproject|.pio|.pioenvs)$</sourceFolderFilter>
<sourceRootList>
<Elem>.</Elem>
</sourceRootList>

View File

@ -1,6 +1,6 @@
% for include in includes:
-I{{include}}
-I"{{include}}"
% end
% for define in defines:
-D{{!define}}
% end
% end

View File

@ -3,6 +3,6 @@
"gccDefaultCFlags": "-fsyntax-only {{! cc_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}",
"gccDefaultCppFlags": "-fsyntax-only {{! cxx_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}",
"gccErrorLimit": 15,
"gccIncludePaths": "{{ ','.join(includes).replace("\\", "/") }}",
"gccIncludePaths": "{{! ','.join("'{}'".format(w.replace("\\", '/')) for w in includes)}}",
"gccSuppressWarnings": false
}

View File

@ -1,3 +1,4 @@
.pio
.pioenvs
.piolibdeps
.clang_complete

View File

@ -1,3 +1,4 @@
.pio
.pioenvs
.piolibdeps
.vscode/.browse.c_cpp.db*

View File

@ -1,5 +1,5 @@
{
"!!! WARNING !!!": "PLEASE DO NOT MODIFY THIS FILE! USE http://docs.platformio.org/page/projectconf/section_env_build.html#build-flags",
"!!! WARNING !!!": "PLEASE DO NOT MODIFY THIS FILE! USE https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags",
"configurations": [
{
% import platform

View File

@ -2,8 +2,8 @@
// PIO Unified Debugger
//
// Documentation: http://docs.platformio.org/page/plus/debugging.html
// Configuration: http://docs.platformio.org/page/projectconf/section_env_debug.html
// Documentation: https://docs.platformio.org/page/plus/debugging.html
// Configuration: https://docs.platformio.org/page/projectconf/section_env_debug.html
% from os.path import dirname, join
%
@ -23,13 +23,16 @@
% if svd_path:
"svdPath": "{{ _escape_path(svd_path) }}",
% end
"preLaunchTask": "PlatformIO: Pre-Debug",
"preLaunchTask": {
"type": "PlatformIO",
"task": "Pre-Debug"
},
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug (Skip Pre-Debug)",
"name": "PIO Debug (skip Pre-Debug)",
"executable": "{{ _escape_path(prog_path) }}",
"toolchainBinDir": "{{ _escape_path(dirname(gdb_path)) }}",
% if svd_path:

View File

@ -179,7 +179,7 @@ def after_upgrade(ctx):
click.secho(
"Please remove multiple PIO Cores from a system:", fg="yellow")
click.secho(
"http://docs.platformio.org/page/faq.html"
"https://docs.platformio.org/page/faq.html"
"#multiple-pio-cores-in-a-system",
fg="cyan")
click.secho("*" * terminal_width, fg="yellow")
@ -274,7 +274,8 @@ def check_platformio_upgrade():
click.secho("pip install -U platformio", fg="cyan", nl=False)
click.secho("` command.", fg="yellow")
click.secho("Changes: ", fg="yellow", nl=False)
click.secho("http://docs.platformio.org/en/latest/history.html", fg="cyan")
click.secho(
"https://docs.platformio.org/en/latest/history.html", fg="cyan")
click.echo("*" * terminal_width)
click.echo("")
@ -318,8 +319,8 @@ def check_internal_updates(ctx, what):
if not app.get_setting("auto_update_" + what):
click.secho("Please update them via ", fg="yellow", nl=False)
click.secho(
"`platformio %s update`" % ("lib --global" if what == "libraries"
else "platform"),
"`platformio %s update`" %
("lib --global" if what == "libraries" else "platform"),
fg="cyan",
nl=False)
click.secho(" command.\n", fg="yellow")

View File

@ -16,6 +16,9 @@ import os
import subprocess
import sys
from os.path import dirname, join
from time import sleep
import requests
from platformio import __version__, exception, util
from platformio.managers.package import PackageManager
@ -23,7 +26,7 @@ from platformio.managers.package import PackageManager
CORE_PACKAGES = {
"contrib-piohome": "^1.0.2",
"contrib-pysite": ">=0.3.2,<2",
"tool-pioplus": "^1.4.5",
"tool-pioplus": "^1.5.0",
"tool-unity": "~1.20403.0",
"tool-scons": "~2.20501.4"
}
@ -36,11 +39,12 @@ PIOPLUS_AUTO_UPDATES_MAX = 100
class CorePackageManager(PackageManager):
def __init__(self):
PackageManager.__init__(self, join(util.get_home_dir(), "packages"), [
"https://dl.bintray.com/platformio/dl-packages/manifest.json",
"http%s://dl.platformio.org/packages/manifest.json" %
("" if sys.version_info < (2, 7, 9) else "s")
])
super(CorePackageManager, self).__init__(
join(util.get_home_dir(), "packages"), [
"https://dl.bintray.com/platformio/dl-packages/manifest.json",
"http%s://dl.platformio.org/packages/manifest.json" %
("" if sys.version_info < (2, 7, 9) else "s")
])
def install( # pylint: disable=keyword-arg-before-vararg
self,
@ -92,10 +96,24 @@ def update_core_packages(only_check=False, silent=False):
if not pkg_dir:
continue
if not silent or pm.outdated(pkg_dir, requirements):
if name == "tool-pioplus" and not only_check:
shutdown_piohome_servers()
if "windows" in util.get_systype():
sleep(1)
pm.update(name, requirements, only_check=only_check)
return True
def shutdown_piohome_servers():
port = 8010
while port < 9000:
try:
requests.get("http://127.0.0.1:%d?__shutdown__=1" % port)
port += 1
except: # pylint: disable=bare-except
return
def pioplus_call(args, **kwargs):
if "windows" in util.get_systype() and sys.version_info < (2, 7, 6):
raise exception.PlatformioException(

View File

@ -32,7 +32,7 @@ class LibraryManager(BasePkgManager):
def __init__(self, package_dir=None):
if not package_dir:
package_dir = join(util.get_home_dir(), "lib")
BasePkgManager.__init__(self, package_dir)
super(LibraryManager, self).__init__(package_dir)
@property
def manifest_names(self):
@ -237,9 +237,8 @@ class LibraryManager(BasePkgManager):
if not isinstance(values, list):
values = [v.strip() for v in values.split(",") if v]
for value in values:
query.append(
'%s:"%s"' % (key[:-1]
if key.endswith("s") else key, value))
query.append('%s:"%s"' %
(key[:-1] if key.endswith("s") else key, value))
lib_info = None
result = util.get_api_result(
@ -337,13 +336,12 @@ class LibraryManager(BasePkgManager):
force=False):
_name, _requirements, _url = self.parse_pkg_uri(name, requirements)
if not _url:
name = "id=%d" % self.search_lib_id(
{
"name": _name,
"requirements": _requirements
},
silent=silent,
interactive=interactive)
name = "id=%d" % self.search_lib_id({
"name": _name,
"requirements": _requirements
},
silent=silent,
interactive=interactive)
requirements = _requirements
pkg_dir = BasePkgManager.install(
self,

View File

@ -259,6 +259,69 @@ class PkgInstallerMixin(object):
raise e
return None
@staticmethod
def parse_pkg_uri( # pylint: disable=too-many-branches
text, requirements=None):
text = str(text)
name, url = None, None
# Parse requirements
req_conditions = [
"@" in text, not requirements, ":" not in text
or text.rfind("/") < text.rfind("@")
]
if all(req_conditions):
text, requirements = text.rsplit("@", 1)
# Handle PIO Library Registry ID
if text.isdigit():
text = "id=" + text
# Parse custom name
elif "=" in text and not text.startswith("id="):
name, text = text.split("=", 1)
# Parse URL
# if valid URL with scheme vcs+protocol://
if "+" in text and text.find("+") < text.find("://"):
url = text
elif "/" in text or "\\" in text:
git_conditions = [
# Handle GitHub URL (https://github.com/user/package)
text.startswith("https://github.com/") and not text.endswith(
(".zip", ".tar.gz")),
(text.split("#", 1)[0]
if "#" in text else text).endswith(".git")
]
hg_conditions = [
# Handle Developer Mbed URL
# (https://developer.mbed.org/users/user/code/package/)
# (https://os.mbed.com/users/user/code/package/)
text.startswith("https://developer.mbed.org"),
text.startswith("https://os.mbed.com")
]
if any(git_conditions):
url = "git+" + text
elif any(hg_conditions):
url = "hg+" + text
elif "://" not in text and (isfile(text) or isdir(text)):
url = "file://" + text
elif "://" in text:
url = text
# Handle short version of GitHub URL
elif text.count("/") == 1:
url = "git+https://github.com/" + text
# Parse name from URL
if url and not name:
_url = url.split("#", 1)[0] if "#" in url else url
if _url.endswith(("\\", "/")):
_url = _url[:-1]
name = basename(_url)
if "." in name and not name.startswith("."):
name = name.rsplit(".", 1)[0]
return (name or text, requirements, url)
@staticmethod
def get_install_dirname(manifest):
name = re.sub(r"[^\da-z\_\-\. ]", "_", manifest['name'], flags=re.I)
@ -316,11 +379,13 @@ class PkgInstallerMixin(object):
manifest[key.strip()] = value.strip()
if src_manifest:
if "name" not in manifest:
manifest['name'] = src_manifest['name']
if "version" in src_manifest:
manifest['version'] = src_manifest['version']
manifest['__src_url'] = src_manifest['url']
# handle a custom package name
autogen_name = self.parse_pkg_uri(manifest['__src_url'])[0]
if "name" not in manifest or autogen_name != src_manifest['name']:
manifest['name'] = src_manifest['name']
if "name" not in manifest:
manifest['name'] = basename(pkg_dir)
@ -414,6 +479,7 @@ class PkgInstallerMixin(object):
click.secho("Looking for another mirror...", fg="yellow")
if versions is None:
util.internet_on(raise_exception=True)
raise exception.UnknownPackage(name)
elif not pkgdata:
raise exception.UndefinedPackageVersion(requirements or "latest",
@ -562,73 +628,10 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
def print_message(self, message, nl=True):
click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl)
@staticmethod
def parse_pkg_uri( # pylint: disable=too-many-branches
text, requirements=None):
text = str(text)
name, url = None, None
# Parse requirements
req_conditions = [
"@" in text, not requirements, ":" not in text
or text.rfind("/") < text.rfind("@")
]
if all(req_conditions):
text, requirements = text.rsplit("@", 1)
# Handle PIO Library Registry ID
if text.isdigit():
text = "id=" + text
# Parse custom name
elif "=" in text and not text.startswith("id="):
name, text = text.split("=", 1)
# Parse URL
# if valid URL with scheme vcs+protocol://
if "+" in text and text.find("+") < text.find("://"):
url = text
elif "/" in text or "\\" in text:
git_conditions = [
# Handle GitHub URL (https://github.com/user/package)
text.startswith("https://github.com/") and not text.endswith(
(".zip", ".tar.gz")),
(text.split("#", 1)[0]
if "#" in text else text).endswith(".git")
]
hg_conditions = [
# Handle Developer Mbed URL
# (https://developer.mbed.org/users/user/code/package/)
# (https://os.mbed.com/users/user/code/package/)
text.startswith("https://developer.mbed.org"),
text.startswith("https://os.mbed.com")
]
if any(git_conditions):
url = "git+" + text
elif any(hg_conditions):
url = "hg+" + text
elif "://" not in text and (isfile(text) or isdir(text)):
url = "file://" + text
elif "://" in text:
url = text
# Handle short version of GitHub URL
elif text.count("/") == 1:
url = "git+https://github.com/" + text
# Parse name from URL
if url and not name:
_url = url.split("#", 1)[0] if "#" in url else url
if _url.endswith(("\\", "/")):
_url = _url[:-1]
name = basename(_url)
if "." in name and not name.startswith("."):
name = name.rsplit(".", 1)[0]
return (name or text, requirements, url)
def outdated(self, pkg_dir, requirements=None):
"""
Has 3 different results:
`None` - unknown package, VCS is fixed to commit
`None` - unknown package, VCS is detached to commit
`False` - package is up-to-date
`String` - a found latest version
"""
@ -636,7 +639,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
return None
latest = None
manifest = self.load_manifest(pkg_dir)
# skip fixed package to a specific version
# skip detached package to a specific version
if "@" in pkg_dir and "__src_url" not in manifest and not requirements:
return None
@ -814,7 +817,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("Fixed", fg="yellow")))
click.echo("[%s]" % (click.style("Detached", fg="yellow")))
if only_check or not latest:
return True

View File

@ -235,8 +235,8 @@ class PlatformFactory(object):
name = pm.load_manifest(platform_dir)['name']
if not platform_dir:
raise exception.UnknownPlatform(name if not requirements else
"%s@%s" % (name, requirements))
raise exception.UnknownPlatform(
name if not requirements else "%s@%s" % (name, requirements))
platform_cls = None
if isfile(join(platform_dir, "platform.py")):
@ -604,7 +604,7 @@ class PlatformBase( # pylint: disable=too-many-public-methods
# enable upload tools for upload targets
if any(["upload" in t for t in targets] + ["program" in targets]):
for name, opts in self.packages.iteritems():
for name, opts in self.packages.items():
if opts.get("type") == "uploader":
self.packages[name]['optional'] = False
# skip all packages in "nobuild" mode

View File

@ -6,4 +6,4 @@
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html
; https://docs.platformio.org/page/projectconf.html

View File

@ -61,7 +61,7 @@ class MeasurementProtocol(TelemetryBase):
}
def __init__(self):
TelemetryBase.__init__(self)
super(MeasurementProtocol, self).__init__()
self['v'] = 1
self['tid'] = self.TID
self['cid'] = app.get_cid()
@ -112,8 +112,8 @@ class MeasurementProtocol(TelemetryBase):
self['cd2'] = "Python/%s %s" % (platform.python_version(),
platform.platform())
# self['cd3'] = " ".join(_filter_args(sys.argv[1:]))
self['cd4'] = 1 if (not util.is_ci()
and (caller_id or not util.is_container())) else 0
self['cd4'] = 1 if (not util.is_ci() and
(caller_id or not util.is_container())) else 0
if caller_id:
self['cd5'] = caller_id.lower()
@ -291,7 +291,7 @@ def measure_ci():
}
}
for key, value in envmap.iteritems():
for key, value in envmap.items():
if getenv(key, "").lower() != "true":
continue
event.update({"action": key, "label": value['label']})

View File

@ -48,7 +48,7 @@ class ArchiveBase(object):
class TARArchive(ArchiveBase):
def __init__(self, archpath):
ArchiveBase.__init__(self, tarfile_open(archpath))
super(TARArchive, self).__init__(tarfile_open(archpath))
def get_items(self):
return self._afo.getmembers()
@ -60,7 +60,7 @@ class TARArchive(ArchiveBase):
class ZIPArchive(ArchiveBase):
def __init__(self, archpath):
ArchiveBase.__init__(self, ZipFile(archpath))
super(ZIPArchive, self).__init__(ZipFile(archpath))
@staticmethod
def preserve_permissions(item, dest_dir):

View File

@ -23,6 +23,7 @@ import sys
import time
from functools import wraps
from glob import glob
from hashlib import sha1
from os.path import (abspath, basename, dirname, expanduser, isdir, isfile,
join, normpath, splitdrive)
from shutil import rmtree
@ -77,7 +78,7 @@ class ProjectConfig(ConfigParser.ConfigParser):
class AsyncPipe(Thread):
def __init__(self, outcallback=None):
Thread.__init__(self)
super(AsyncPipe, self).__init__()
self.outcallback = outcallback
self._fd_read, self._fd_write = os.pipe()
@ -99,7 +100,7 @@ class AsyncPipe(Thread):
if self.outcallback:
self.outcallback(line)
else:
print line
print(line)
self._pipe_reader.close()
def close(self):
@ -137,8 +138,12 @@ class memoized(object):
self.cache[key] = (time.time(), func(*args, **kwargs))
return self.cache[key][1]
wrapper.reset = self._reset
return wrapper
def _reset(self):
self.cache = {}
class throttle(object):
@ -309,6 +314,9 @@ def get_projectboards_dir():
def get_projectbuild_dir(force=False):
path = get_project_optional_dir("build_dir",
join(get_project_dir(), ".pioenvs"))
if "$PROJECT_HASH" in path:
path = path.replace("$PROJECT_HASH",
sha1(get_project_dir()).hexdigest()[:10])
try:
if not isdir(path):
os.makedirs(path)
@ -317,7 +325,7 @@ def get_projectbuild_dir(force=False):
with open(dontmod_path, "w") as fp:
fp.write("""
[InternetShortcut]
URL=http://docs.platformio.org/page/projectconf/section_platformio.html#build-dir
URL=https://docs.platformio.org/page/projectconf/section_platformio.html#build-dir
""")
except Exception as e: # pylint: disable=broad-except
if not force:
@ -349,12 +357,19 @@ def load_project_config(path=None):
def parse_conf_multi_values(items):
result = []
if not items:
return []
return [
item.strip() for item in items.split("\n" if "\n" in items else ", ")
if item.strip()
]
return result
inline_comment_re = re.compile(r"\s+;.*$")
for item in items.split("\n" if "\n" in items else ", "):
item = item.strip()
# comment
if not item or item.startswith((";", "#")):
continue
if ";" in item:
item = inline_comment_re.sub("", item).strip()
result.append(item)
return result
def change_filemtime(path, mtime):
@ -398,7 +413,7 @@ def exec_command(*args, **kwargs):
if isinstance(kwargs[s], AsyncPipe):
result[s[3:]] = "\n".join(kwargs[s].get_buffer())
for k, v in result.iteritems():
for k, v in result.items():
if v and isinstance(v, basestring):
result[k].strip()
@ -779,6 +794,43 @@ def merge_dicts(d1, d2, path=None):
return d1
def ensure_udev_rules():
def _rules_to_set(rules_path):
result = set([])
with open(rules_path, "rb") as fp:
for line in fp.readlines():
line = line.strip()
if not line or line.startswith("#"):
continue
result.add(line)
return result
if "linux" not in get_systype():
return None
installed_rules = [
"/etc/udev/rules.d/99-platformio-udev.rules",
"/lib/udev/rules.d/99-platformio-udev.rules"
]
if not any(isfile(p) for p in installed_rules):
raise exception.MissedUdevRules
origin_path = abspath(
join(get_source_dir(), "..", "scripts", "99-platformio-udev.rules"))
if not isfile(origin_path):
return None
origin_rules = _rules_to_set(origin_path)
for rules_path in installed_rules:
if not isfile(rules_path):
continue
current_rules = _rules_to_set(rules_path)
if not origin_rules <= current_rules:
raise exception.OutdatedUdevRules(rules_path)
return True
def rmtree_(path):
def _onerror(_, name, __):
@ -787,8 +839,9 @@ def rmtree_(path):
os.remove(name)
except Exception as e: # pylint: disable=broad-except
click.secho(
"Please manually remove file `%s`" % name, fg="red", err=True)
raise e
"%s \nPlease manually remove the file `%s`" % (str(e), name),
fg="red",
err=True)
return rmtree(path, onerror=_onerror)
@ -805,8 +858,7 @@ except ImportError:
magic_check_bytes = re.compile(b'([*?[])')
def glob_escape(pathname):
"""Escape all special characters.
"""
"""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.

View File

@ -16,7 +16,7 @@
#
# INSTALLATION
#
# Please visit > http://docs.platformio.org/en/latest/faq.html#platformio-udev-rules
# Please visit > https://docs.platformio.org/en/latest/faq.html#platformio-udev-rules
#
#####################################################################################

View File

@ -23,18 +23,28 @@ path.append("..")
from platformio import util
from platformio.managers.platform import PlatformFactory, PlatformManager
RST_COPYRIGHT = """.. Copyright (c) 2014-present PlatformIO <contact@platformio.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
API_PACKAGES = util.get_api_result("/packages")
API_FRAMEWORKS = util.get_api_result("/frameworks")
BOARDS = PlatformManager().get_installed_boards()
PLATFORM_MANIFESTS = PlatformManager().get_installed()
DOCS_ROOT_DIR = realpath(join(dirname(realpath(__file__)), "..", "docs"))
def is_compat_platform_and_framework(platform, framework):
p = PlatformFactory.newPlatform(platform)
for pkg in p.packages.keys():
if pkg.startswith("framework-%s" % framework):
return True
return False
return framework in (p.frameworks or {}).keys()
def campaign_url(url, source="platformio", medium="docs"):
@ -48,20 +58,17 @@ def campaign_url(url, source="platformio", medium="docs"):
query, data.fragment))
def generate_boards(boards, extend_debug=False, skip_columns=None):
def generate_boards_table(boards, skip_columns=None):
columns = [
("ID", "``{id}``"),
("Name", "`{name} <{url}>`_"),
("Platform", ":ref:`{platform_title} <platform_{platform}>`"),
("Name", ":ref:`board_{platform}_{id}`"),
("Platform", ":ref:`platform_{platform}`"),
("Debug", "{debug}"),
("MCU", "{mcu}"),
("Frequency", "{f_cpu:d}MHz"),
("Flash", "{rom}"),
("RAM", "{ram}"),
]
platforms = {m['name']: m['title'] for m in PLATFORM_MANIFESTS}
lines = []
lines.append("""
.. list-table::
:header-rows: 1
@ -71,36 +78,23 @@ def generate_boards(boards, extend_debug=False, skip_columns=None):
for (name, template) in columns:
if skip_columns and name in skip_columns:
continue
prefix = " * - " if name == "ID" else " - "
prefix = " * - " if name == "Name" else " - "
lines.append(prefix + name)
for data in sorted(boards, key=lambda item: item['id']):
debug = [":ref:`Yes <piodebug>`" if data['debug'] else "No"]
if extend_debug and data['debug']:
debug_onboard = []
debug_external = []
for name, options in data['debug']['tools'].items():
attrs = []
if options.get("default"):
attrs.append("default")
if options.get("onboard"):
attrs.append("on-board")
tool = ":ref:`debugging_tool_%s`" % name
if attrs:
tool = "%s (%s)" % (tool, ", ".join(attrs))
if options.get("onboard"):
debug_onboard.append(tool)
else:
debug_external.append(tool)
debug = sorted(debug_onboard) + sorted(debug_external)
for data in sorted(boards, key=lambda item: item['name']):
has_onboard_debug = (data['debug'] and any(
t.get("onboard") for (_, t) in data['debug']['tools'].items()))
debug = "No"
if has_onboard_debug:
debug = "On-board"
elif data['debug']:
debug = "External"
variables = dict(
id=data['id'],
name=data['name'],
platform=data['platform'],
platform_title=platforms[data['platform']],
debug=", ".join(debug),
url=campaign_url(data['url']),
debug=debug,
mcu=data['mcu'].upper(),
f_cpu=int(data['fcpu']) / 1000000,
ram=util.format_filesize(data['ram']),
@ -109,7 +103,7 @@ def generate_boards(boards, extend_debug=False, skip_columns=None):
for (name, template) in columns:
if skip_columns and name in skip_columns:
continue
prefix = " * - " if name == "ID" else " - "
prefix = " * - " if name == "Name" else " - "
lines.append(prefix + template.format(**variables))
if lines:
@ -118,7 +112,56 @@ def generate_boards(boards, extend_debug=False, skip_columns=None):
return lines
def generate_frameworks_contents(frameworks):
if not frameworks:
return []
lines = []
lines.append("""
Frameworks
----------
.. list-table::
:header-rows: 1
* - Name
- Description""")
known = set()
for framework in API_FRAMEWORKS:
known.add(framework['name'])
if framework['name'] not in frameworks:
continue
lines.append("""
* - :ref:`framework_{name}`
- {description}""".format(**framework))
assert known >= set(frameworks), "Unknown frameworks %s " % (
set(frameworks) - known)
return lines
def generate_platforms_contents(platforms):
if not platforms:
return []
lines = []
lines.append("""
Platforms
---------
.. list-table::
:header-rows: 1
* - Name
- Description""")
for name in sorted(platforms):
p = PlatformFactory.newPlatform(name)
lines.append("""
* - :ref:`platform_{name}`
- {description}""".format(name=p.name, description=p.description))
return lines
def generate_debug_contents(boards, skip_board_columns=None, extra_rst=None):
if not skip_board_columns:
skip_board_columns = []
skip_board_columns.append("Debug")
lines = []
onboard_debug = [
b for b in boards if b['debug'] and any(
@ -143,13 +186,13 @@ Debugging
lines.append(".. include:: %s" % extra_rst)
lines.append("""
Debug Tools
~~~~~~~~~~~
Tools & Debug Probes
~~~~~~~~~~~~~~~~~~~~
Supported debugging tools are listed in "Debug" column. For more detailed
information, please scroll table by horizontal.
You can switch between debugging :ref:`debugging_tools` using
:ref:`projectconf_debug_tool` options.
:ref:`projectconf_debug_tool` option in :ref:`projectconf`.
.. warning::
You will need to install debug tool drivers depending on your system.
@ -161,27 +204,24 @@ You can switch between debugging :ref:`debugging_tools` using
On-Board Debug Tools
^^^^^^^^^^^^^^^^^^^^
Boards listed below have on-board debug tool and **ARE READY** for debugging!
You do not need to use/buy external debug tool.
Boards listed below have on-board debug probe and **ARE READY** for debugging!
You do not need to use/buy external debug probe.
""")
lines.extend(
generate_boards(
onboard_debug,
extend_debug=True,
skip_columns=skip_board_columns))
generate_boards_table(
onboard_debug, skip_columns=skip_board_columns))
if external_debug:
lines.append("""
External Debug Tools
^^^^^^^^^^^^^^^^^^^^
Boards listed below are compatible with :ref:`piodebug` but **DEPEND ON**
external debug tool. See "Debug" column for compatible debug tools.
external debug probe. They **ARE NOT READY** for debugging.
Please click on board name for the further details.
""")
lines.extend(
generate_boards(
external_debug,
extend_debug=True,
skip_columns=skip_board_columns))
generate_boards_table(
external_debug, skip_columns=skip_board_columns))
return lines
@ -243,23 +283,12 @@ def generate_platform(name, rst_dir):
print "Processing platform: %s" % name
compatible_boards = [
board for board in BOARDS if name in board['platform']
board for board in BOARDS if name == board['platform']
]
lines = []
lines.append(
""".. Copyright (c) 2014-present PlatformIO <contact@platformio.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
""")
lines.append(RST_COPYRIGHT)
p = PlatformFactory.newPlatform(name)
assert p.repository_url.endswith(".git")
github_url = p.repository_url[:-4]
@ -269,7 +298,9 @@ def generate_platform(name, rst_dir):
lines.append(p.title)
lines.append("=" * len(p.title))
lines.append(":ref:`projectconf_env_platform` = ``%s``" % p.name)
lines.append("")
lines.append(":Configuration:")
lines.append(" :ref:`projectconf_env_platform` = ``%s``" % p.name)
lines.append("")
lines.append(p.description)
lines.append("""
@ -312,8 +343,8 @@ Examples are listed from `%s development platform repository <%s>`_:
generate_debug_contents(
compatible_boards,
skip_board_columns=["Platform"],
extra_rst="%s_debug.rst" % name
if isfile(join(rst_dir, "%s_debug.rst" % name)) else None))
extra_rst="%s_debug.rst" % name if isfile(
join(rst_dir, "%s_debug.rst" % name)) else None))
#
# Development version of dev/platform
@ -362,24 +393,11 @@ Upstream
#
# Frameworks
#
_frameworks_lines = []
compatible_frameworks = []
for framework in API_FRAMEWORKS:
if not is_compat_platform_and_framework(name, framework['name']):
continue
_frameworks_lines.append("""
* - :ref:`framework_{name}`
- {description}""".format(**framework))
if _frameworks_lines:
lines.append("""
Frameworks
----------
.. list-table::
:header-rows: 1
* - Name
- Description""")
lines.extend(_frameworks_lines)
if is_compat_platform_and_framework(name, framework['name']):
compatible_frameworks.append(framework['name'])
lines.extend(generate_frameworks_contents(compatible_frameworks))
#
# Boards
@ -405,7 +423,8 @@ Boards
for vendor, boards in sorted(vendors.items()):
lines.append(str(vendor))
lines.append("~" * len(vendor))
lines.extend(generate_boards(boards, skip_columns=["Platform"]))
lines.extend(
generate_boards_table(boards, skip_columns=["Platform"]))
return "\n".join(lines)
@ -413,8 +432,7 @@ Boards
def update_platform_docs():
for manifest in PLATFORM_MANIFESTS:
name = manifest['name']
platforms_dir = join(
dirname(realpath(__file__)), "..", "docs", "platforms")
platforms_dir = join(DOCS_ROOT_DIR, "platforms")
rst_path = join(platforms_dir, "%s.rst" % name)
with open(rst_path, "w") as f:
f.write(generate_platform(name, platforms_dir))
@ -433,25 +451,15 @@ def generate_framework(type_, data, rst_dir=None):
lines = []
lines.append(
""".. Copyright (c) 2014-present PlatformIO <contact@platformio.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
""")
lines.append(RST_COPYRIGHT)
lines.append(".. _framework_%s:" % type_)
lines.append("")
lines.append(data['title'])
lines.append("=" * len(data['title']))
lines.append(":ref:`projectconf_env_framework` = ``%s``" % type_)
lines.append("")
lines.append(":Configuration:")
lines.append(" :ref:`projectconf_env_framework` = ``%s``" % type_)
lines.append("")
lines.append(data['description'])
lines.append("""
@ -474,8 +482,8 @@ For more detailed information please visit `vendor site <%s>`_.
lines.extend(
generate_debug_contents(
compatible_boards,
extra_rst="%s_debug.rst" % type_
if isfile(join(rst_dir, "%s_debug.rst" % type_)) else None))
extra_rst="%s_debug.rst" % type_ if isfile(
join(rst_dir, "%s_debug.rst" % type_)) else None))
if compatible_platforms:
# examples
@ -492,21 +500,9 @@ Examples
"%s/tree/master/examples" % p.repository_url[:-4])))
# Platforms
lines.append("""
Platforms
---------
.. list-table::
:header-rows: 1
* - Name
- Description""")
for manifest in compatible_platforms:
p = PlatformFactory.newPlatform(manifest['name'])
lines.append("""
* - :ref:`platform_{type_}`
- {description}""".format(
type_=manifest['name'], description=p.description))
lines.extend(
generate_platforms_contents(
[manifest['name'] for manifest in compatible_platforms]))
#
# Boards
@ -529,41 +525,28 @@ Boards
for vendor, boards in sorted(vendors.items()):
lines.append(str(vendor))
lines.append("~" * len(vendor))
lines.extend(generate_boards(boards))
lines.extend(generate_boards_table(boards))
return "\n".join(lines)
def update_framework_docs():
for framework in API_FRAMEWORKS:
name = framework['name']
frameworks_dir = join(
dirname(realpath(__file__)), "..", "docs", "frameworks")
frameworks_dir = join(DOCS_ROOT_DIR, "frameworks")
rst_path = join(frameworks_dir, "%s.rst" % name)
with open(rst_path, "w") as f:
f.write(generate_framework(name, framework, frameworks_dir))
def update_embedded_boards():
def update_boards():
lines = []
lines.append(
""".. Copyright (c) 2014-present PlatformIO <contact@platformio.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
""")
lines.append(".. _embedded_boards:")
lines.append(RST_COPYRIGHT)
lines.append(".. _boards:")
lines.append("")
lines.append("Embedded Boards")
lines.append("===============")
lines.append("Boards")
lines.append("======")
lines.append("""
Rapid Embedded Development, Continuous and IDE integration in a few
@ -576,33 +559,212 @@ popular embedded boards and IDE.
* For more detailed ``board`` information please scroll tables below by horizontal.
""")
lines.append("""
.. contents:: Vendors
:local:
""")
vendors = {}
platforms = {}
for data in BOARDS:
vendor = data['vendor']
if vendor in vendors:
vendors[vendor].append(data)
platform = data['platform']
if platform in platforms:
platforms[platform].append(data)
else:
vendors[vendor] = [data]
platforms[platform] = [data]
for vendor, boards in sorted(vendors.iteritems()):
lines.append(str(vendor))
lines.append("~" * len(vendor))
lines.extend(generate_boards(boards))
for platform, boards in sorted(platforms.iteritems()):
p = PlatformFactory.newPlatform(platform)
lines.append(p.title)
lines.append("-" * len(p.title))
lines.append("""
.. toctree::
:maxdepth: 1
""")
for board in sorted(boards, key=lambda item: item['name']):
lines.append(" %s/%s" % (platform, board["id"]))
lines.append("")
emboards_rst = join(
dirname(realpath(__file__)), "..", "docs", "platforms",
"embedded_boards.rst")
emboards_rst = join(DOCS_ROOT_DIR, "boards", "index.rst")
with open(emboards_rst, "w") as f:
f.write("\n".join(lines))
# individual board page
for data in BOARDS:
# if data['id'] != "m5stack-core-esp32":
# continue
rst_path = join(DOCS_ROOT_DIR, "boards", data["platform"],
"%s.rst" % data["id"])
if not isdir(dirname(rst_path)):
os.makedirs(dirname(rst_path))
update_embedded_board(rst_path, data)
def update_embedded_board(rst_path, board):
platform = PlatformFactory.newPlatform(board['platform'])
board_config = platform.board_config(board['id'])
board_manifest_url = platform.repository_url
assert board_manifest_url
if board_manifest_url.endswith(".git"):
board_manifest_url = board_manifest_url[:-4]
board_manifest_url += "/blob/master/boards/%s.json" % board['id']
variables = dict(
id=board['id'],
name=board['name'],
platform=board['platform'],
platform_description=platform.description,
url=campaign_url(board['url']),
mcu=board_config.get("build", {}).get("mcu", ""),
mcu_upper=board['mcu'].upper(),
f_cpu=board['fcpu'],
f_cpu_mhz=int(board['fcpu']) / 1000000,
ram=util.format_filesize(board['ram']),
rom=util.format_filesize(board['rom']),
vendor=board['vendor'],
board_manifest_url=board_manifest_url,
upload_protocol=board_config.get("upload.protocol", ""))
lines = [RST_COPYRIGHT]
lines.append(".. _board_{platform}_{id}:".format(**variables))
lines.append("")
lines.append(board['name'])
lines.append("=" * len(board['name']))
lines.append("""
.. contents::
System
------
Platform :ref:`platform_{platform}`: {platform_description}
.. list-table::
* - **Microcontroller**
- {mcu_upper}
* - **Frequency**
- {f_cpu_mhz}MHz
* - **Flash**
- {rom}
* - **RAM**
- {ram}
* - **Vendor**
- `{vendor} <{url}>`__
""".format(**variables))
#
# Configuration
#
lines.append("""
Configuration
-------------
Please use ``{id}`` ID for :ref:`projectconf_env_board` option in :ref:`projectconf`:
.. code-block:: ini
[env:{id}]
platform = {platform}
board = {id}
You can override default {name} settings per build environment using
``board_***`` option, where ``***`` is a JSON object path from
board manifest `{id}.json <{board_manifest_url}>`_. For example,
``board_build.mcu``, ``board_build.f_cpu``, etc.
.. code-block:: ini
[env:{id}]
platform = {platform}
board = {id}
; change microcontroller
board_build.mcu = {mcu}
; change MCU frequency
board_build.f_cpu = {f_cpu}L
""".format(**variables))
#
# Uploading
#
upload_protocols = board_config.get("upload.protocols", [])
if len(upload_protocols) > 1:
lines.append("""
Uploading
---------
%s supports the next uploading protocols:
""" % board['name'])
for protocol in upload_protocols:
lines.append("* ``%s``" % protocol)
lines.append("""
Default protocol is ``%s``""" % variables['upload_protocol'])
lines.append("""
You can change upload protocol using :ref:`projectconf_upload_protocol` option:
.. code-block:: ini
[env:{id}]
platform = {platform}
board = {id}
upload_protocol = {upload_protocol}
""".format(**variables))
#
# Debugging
#
lines.append("Debugging")
lines.append("---------")
if not board['debug']:
lines.append(
":ref:`piodebug` currently does not support {name} board.".format(
**variables))
else:
default_debug_tool = board_config.get_debug_tool_name()
has_onboard_debug = any(
t.get("onboard") for (_, t) in board['debug']['tools'].items())
lines.append("""
:ref:`piodebug` - "1-click" solution for debugging with a zero configuration.
.. warning::
You will need to install debug tool drivers depending on your system.
Please click on compatible debug tool below for the further
instructions and configuration information.
You can switch between debugging :ref:`debugging_tools` using
:ref:`projectconf_debug_tool` option in :ref:`projectconf`.
""")
if has_onboard_debug:
lines.append(
"{name} has on-board debug probe and **IS READY** for "
"debugging. You don't need to use/buy external debug probe.".
format(**variables))
else:
lines.append(
"{name} does not have on-board debug probe and **IS NOT "
"READY** for debugging. You will need to use/buy one of "
"external probe listed below.".format(**variables))
lines.append("""
.. list-table::
:header-rows: 1
* - Compatible Tools
- On-board
- Default""")
for (tool_name, tool_data) in sorted(board['debug']['tools'].items()):
lines.append(""" * - :ref:`debugging_tool_{name}`
- {onboard}
- {default}""".format(
name=tool_name,
onboard="Yes" if tool_data.get("onboard") else "",
default="Yes" if tool_name == default_debug_tool else ""))
if board['frameworks']:
lines.extend(generate_frameworks_contents(board['frameworks']))
with open(rst_path, "w") as f:
f.write("\n".join(lines))
def update_debugging():
tools_to_platforms = {}
tool_to_platforms = {}
tool_to_boards = {}
vendors = {}
platforms = []
frameworks = []
@ -612,9 +774,12 @@ def update_debugging():
for tool in data['debug']['tools']:
tool = str(tool)
if tool not in tools_to_platforms:
tools_to_platforms[tool] = []
tools_to_platforms[tool].append(data['platform'])
if tool not in tool_to_platforms:
tool_to_platforms[tool] = []
tool_to_platforms[tool].append(data['platform'])
if tool not in tool_to_boards:
tool_to_boards[tool] = []
tool_to_boards[tool].append(data['id'])
platforms.append(data['platform'])
frameworks.extend(data['frameworks'])
@ -624,60 +789,12 @@ def update_debugging():
else:
vendors[vendor] = [data]
def _update_tool_compat_platforms(content):
begin_tpl = ".. begin_compatible_platforms_"
end_tpl = ".. end_compatible_platforms_"
for tool, platforms in tools_to_platforms.items():
begin = begin_tpl + tool
end = end_tpl + tool
begin_index = content.index(begin)
end_index = content.index(end)
chunk = ["\n\n:Compatible Platforms:\n"]
chunk.extend([
" * :ref:`platform_%s`" % str(p)
for p in sorted(set(platforms))
])
chunk.extend(["\n"])
content = content[:begin_index + len(begin)] + "\n".join(
chunk) + content[end_index:]
return content
platforms = sorted(set(platforms))
frameworks = sorted(set(frameworks))
lines = []
# Platforms
lines.append(""".. _debugging_platforms:
Platforms
---------
.. list-table::
:header-rows: 1
* - Name
- Description""")
for manifest in PLATFORM_MANIFESTS:
if manifest['name'] not in platforms:
continue
p = PlatformFactory.newPlatform(manifest['name'])
lines.append("""
* - :ref:`platform_{type_}`
- {description}""".format(
type_=manifest['name'], description=p.description))
# Frameworks
lines.append("""
Frameworks
----------
.. list-table::
:header-rows: 1
* - Name
- Description""")
for framework in API_FRAMEWORKS:
if framework['name'] not in frameworks:
continue
lines.append("""
* - :ref:`framework_{name}`
- {description}""".format(**framework))
lines = [".. _debugging_platforms:"]
lines.extend(generate_platforms_contents(platforms))
lines.extend(generate_frameworks_contents(frameworks))
# Boards
lines.append("""
@ -690,17 +807,52 @@ Boards
for vendor, boards in sorted(vendors.iteritems()):
lines.append(str(vendor))
lines.append("~" * len(vendor))
lines.extend(generate_boards(boards, extend_debug=True))
lines.extend(generate_boards_table(boards))
# save
with open(
join(util.get_source_dir(), "..", "docs", "plus", "debugging.rst"),
"r+") as fp:
content = _update_tool_compat_platforms(fp.read())
content = fp.read()
fp.seek(0)
fp.truncate()
fp.write(content[:content.index(".. _debugging_platforms:")] +
"\n".join(lines))
# Debug tools
for tool, platforms in tool_to_platforms.items():
tool_path = join(DOCS_ROOT_DIR, "plus", "debug-tools", "%s.rst" % tool)
assert isfile(tool_path)
platforms = sorted(set(platforms))
lines = [".. begin_platforms"]
lines.extend(generate_platforms_contents(platforms))
tool_frameworks = []
for platform in platforms:
for framework in frameworks:
if is_compat_platform_and_framework(platform, framework):
tool_frameworks.append(framework)
lines.extend(generate_frameworks_contents(tool_frameworks))
lines.append("""
Boards
------
.. note::
For more detailed ``board`` information please scroll tables below by horizontal.
""")
lines.extend(
generate_boards_table(
[b for b in BOARDS if b['id'] in tool_to_boards[tool]],
skip_columns=None))
with open(tool_path, "r+") as fp:
content = fp.read()
fp.seek(0)
fp.truncate()
fp.write(content[:content.index(".. begin_platforms")] +
"\n".join(lines))
def update_project_examples():
platform_readme_tpl = """
@ -709,7 +861,7 @@ def update_project_examples():
{description}
* [Home](https://platformio.org/platforms/{name}) (home page in PlatformIO Registry)
* [Documentation](http://docs.platformio.org/page/platforms/{name}.html) (advanced usage, packages, boards, frameworks, etc.)
* [Documentation](https://docs.platformio.org/page/platforms/{name}.html) (advanced usage, packages, boards, frameworks, etc.)
# Examples
@ -721,7 +873,7 @@ def update_project_examples():
{description}
* [Home](https://platformio.org/frameworks/{name}) (home page in PlatformIO Registry)
* [Documentation](http://docs.platformio.org/page/frameworks/{name}.html)
* [Documentation](https://docs.platformio.org/page/frameworks/{name}.html)
# Examples
@ -793,7 +945,7 @@ def update_project_examples():
examples="\n".join(
framework_examples_md_lines[framework['name']])))
url = campaign_url(
"http://docs.platformio.org/en/latest/frameworks/%s.html#examples"
"https://docs.platformio.org/en/latest/frameworks/%s.html#examples"
% framework['name'],
source="github",
medium="examples")
@ -826,7 +978,7 @@ def update_project_examples():
def main():
update_platform_docs()
update_framework_docs()
update_embedded_boards()
update_boards()
update_debugging()
update_project_examples()

View File

@ -15,6 +15,7 @@
import json
import subprocess
import sys
from platformio import util
def main():
@ -24,6 +25,14 @@ def main():
for platform in platforms:
if platform['forDesktop']:
continue
# RISC-V GAP does not support Windows 86
if (util.get_systype() == "windows_x86"
and platform['name'] == "riscv_gap"):
continue
# unknown issue on Linux
if ("linux" in util.get_systype()
and platform['name'] == "aceinna_imu"):
continue
subprocess.check_call(
["platformio", "platform", "install", platform['repository']])

View File

@ -37,7 +37,7 @@ setup(
license=__license__,
python_requires='>=2.7, <3',
install_requires=install_requires,
packages=find_packages(),
packages=find_packages() + ["scripts"],
package_data={
"platformio": [
"projectconftpl.ini",
@ -45,6 +45,9 @@ setup(
"ide/tpls/*/*.tpl",
"ide/tpls/*/*/*.tpl",
"ide/tpls/*/.*/*.tpl"
],
"scripts": [
"99-platformio-udev.rules"
]
},
entry_points={

View File

@ -61,7 +61,7 @@ def test_global_install_archive(clirunner, validate_cliresult,
"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",
"http://dl.platformio.org/libraries/archives/0/9540.tar.gz",
"SomeLib=http://dl.platformio.org/libraries/archives/0/9540.tar.gz",
"https://github.com/Pedroalbuquerque/ESP32WebServer/archive/master.zip"
])
validate_cliresult(result)
@ -75,7 +75,7 @@ def test_global_install_archive(clirunner, validate_cliresult,
items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()]
items2 = [
"RadioHead-1.62", "ArduinoJson", "DallasTemperature_ID54",
"RadioHead-1.62", "ArduinoJson", "SomeLib_ID54",
"OneWire_ID1", "ESP32WebServer"
]
assert set(items1) >= set(items2)
@ -158,7 +158,7 @@ def test_global_lib_list(clirunner, validate_cliresult):
items1 = [i['name'] for i in json.loads(result.output)]
items2 = [
"ESP32WebServer", "ArduinoJson", "ArduinoJson", "ArduinoJson",
"ArduinoJson", "AsyncMqttClient", "AsyncTCP", "DallasTemperature",
"ArduinoJson", "AsyncMqttClient", "AsyncTCP", "SomeLib",
"ESPAsyncTCP", "NeoPixelBus", "OneWire", "PJON", "PJON",
"PubSubClient", "RFcontrol", "RadioHead-1.62", "platformio-libmirror",
"rs485-nodeproto"
@ -202,7 +202,7 @@ def test_global_lib_update(clirunner, validate_cliresult):
# update rest libraries
result = clirunner.invoke(cmd_lib, ["-g", "update"])
validate_cliresult(result)
assert result.output.count("[Fixed]") == 6
assert result.output.count("[Detached]") == 6
assert result.output.count("[Up-to-date]") == 11
assert "Uninstalling RFcontrol @ 77d4eb3f8a" in result.output
@ -234,7 +234,7 @@ def test_global_lib_uninstall(clirunner, validate_cliresult,
items2 = [
"RadioHead-1.62", "rs485-nodeproto", "platformio-libmirror",
"PubSubClient", "ArduinoJson@src-69ebddd821f771debe7ee734d3c7fa81",
"ESPAsyncTCP_ID305", "DallasTemperature_ID54", "NeoPixelBus_ID547",
"ESPAsyncTCP_ID305", "SomeLib_ID54", "NeoPixelBus_ID547",
"PJON", "AsyncMqttClient_ID346", "ArduinoJson_ID64",
"PJON@src-79de467ebe19de18287becff0a1fb42d", "ESP32WebServer"
]

View File

@ -25,7 +25,9 @@ def test_build_flags(clirunner, validate_cliresult, tmpdir):
[env:native]
platform = native
extra_scripts = extra.py
build_flags = %s
build_flags =
; -DCOMMENTED_MACRO
%s ; inline comment
""" % " ".join([f[0] for f in build_flags]))
tmpdir.join("extra.py").write("""
@ -47,6 +49,10 @@ projenv.Append(CPPDEFINES="POST_SCRIPT_MACRO")
#error "POST_SCRIPT_MACRO"
#endif
#ifdef COMMENTED_MACRO
#error "COMMENTED_MACRO"
#endif
int main() {
}
""")

View File

@ -36,6 +36,9 @@ def pytest_generate_tests(metafunc):
p = PlatformFactory.newPlatform(manifest['__pkg_dir'])
if not p.is_embedded():
continue
# issue with "version `CXXABI_1.3.9' not found (required by sdcc)"
if "linux" in util.get_systype() and p.name == "intel_mcs51":
continue
examples_dir = join(p.get_dir(), "examples")
assert isdir(examples_dir)
examples_dirs.append(examples_dir)