Merge branch 'release/v6.1.5'

This commit is contained in:
Ivan Kravets
2022-11-01 20:28:49 +02:00
20 changed files with 133 additions and 126 deletions

View File

@ -21,7 +21,7 @@ jobs:
- smartknob: - smartknob:
repository: "scottbez1/smartknob" repository: "scottbez1/smartknob"
folder: "smartknob" folder: "smartknob"
config_dir: "smartknob/firmware" config_dir: "smartknob"
env_name: "view" env_name: "view"
- espurna: - espurna:
repository: "xoseperez/espurna" repository: "xoseperez/espurna"

View File

@ -13,6 +13,15 @@ PlatformIO Core 6
**A professional collaborative platform for declarative, safety-critical, and test-driven embedded development.** **A professional collaborative platform for declarative, safety-critical, and test-driven embedded development.**
6.1.5 (2022-11-01)
~~~~~~~~~~~~~~~~~~
* Added a new `enable_proxy_strict_ssl <https://docs.platformio.org/en/latest/core/userguide/cmd_settings.html>`__ setting to disable the proxy server certificate verification (`issue #4432 <https://github.com/platformio/platformio-core/issues/4432>`_)
* Documented `PlatformIO Core Proxy Configuration <https://docs.platformio.org/en/latest/core/installation/proxy-configuration.html>`__
* Speeded up device port finder by avoiding loading board HWIDs from development platforms
* Improved caching of build metadata in debug mode
* Fixed an issue when `pio pkg install --storage-dir <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html>`__ command requires PlatformIO project (`issue #4410 <https://github.com/platformio/platformio-core/issues/4410>`_)
6.1.4 (2022-08-12) 6.1.4 (2022-08-12)
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~

2
docs

Submodule docs updated: b38923e39b...f82e7f4266

View File

@ -14,7 +14,7 @@
import sys import sys
VERSION = (6, 1, 4) VERSION = (6, 1, 5)
__version__ = ".".join([str(s) for s in VERSION]) __version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio" __title__ = "platformio"
@ -44,8 +44,6 @@ __registry_mirror_hosts__ = [
] ]
__pioremote_endpoint__ = "ssl:host=remote.platformio.org:port=4413" __pioremote_endpoint__ = "ssl:host=remote.platformio.org:port=4413"
__default_requests_timeout__ = (10, None) # (connect, read)
__core_packages__ = { __core_packages__ = {
"contrib-piohome": "~3.4.2", "contrib-piohome": "~3.4.2",
"contrib-pysite": "~2.%d%d.0" % (sys.version_info.major, sys.version_info.minor), "contrib-pysite": "~2.%d%d.0" % (sys.version_info.major, sys.version_info.minor),

View File

@ -58,6 +58,10 @@ DEFAULT_SETTINGS = {
"value": get_default_projects_dir(), "value": get_default_projects_dir(),
"validator": projects_dir_validate, "validator": projects_dir_validate,
}, },
"enable_proxy_strict_ssl": {
"description": "Verify the proxy server certificate against the list of supplied CAs",
"value": True,
},
} }
SESSION_VARS = { SESSION_VARS = {

View File

@ -24,7 +24,7 @@ from platformio.proc import exec_command, where_is_program
def IsIntegrationDump(_): def IsIntegrationDump(_):
return set(["_idedata", "idedata"]) & set(COMMAND_LINE_TARGETS) return set(["__idedata", "idedata"]) & set(COMMAND_LINE_TARGETS)
def DumpIntegrationIncludes(env): def DumpIntegrationIncludes(env):
@ -147,6 +147,7 @@ def _subst_cmd(env, cmd):
def DumpIntegrationData(*args): def DumpIntegrationData(*args):
projenv, globalenv = args[0:2] # pylint: disable=unbalanced-tuple-unpacking projenv, globalenv = args[0:2] # pylint: disable=unbalanced-tuple-unpacking
data = { data = {
"build_type": globalenv.GetBuildType(),
"env_name": globalenv["PIOENV"], "env_name": globalenv["PIOENV"],
"libsource_dirs": [ "libsource_dirs": [
globalenv.subst(item) for item in globalenv.GetLibSourceDirs() globalenv.subst(item) for item in globalenv.GetLibSourceDirs()

View File

@ -145,7 +145,7 @@ class DebugConfigBase: # pylint: disable=too-many-instance-attributes
) )
def _load_build_data(self): def _load_build_data(self):
data = load_build_metadata(os.getcwd(), self.env_name, cache=True) data = load_build_metadata(os.getcwd(), self.env_name, cache=True, debug=True)
if data: if data:
return data return data
raise DebugInvalidOptionsError("Could not load a build configuration") raise DebugInvalidOptionsError("Could not load a build configuration")

View File

@ -14,6 +14,7 @@
import os import os
from fnmatch import fnmatch from fnmatch import fnmatch
from functools import lru_cache
import click import click
import serial import serial
@ -119,6 +120,8 @@ class SerialPortFinder:
@staticmethod @staticmethod
def match_device_hwid(patterns): def match_device_hwid(patterns):
if not patterns:
return None
for item in list_serial_ports(as_objects=True): for item in list_serial_ports(as_objects=True):
if not item.vid or not item.pid: if not item.vid or not item.pid:
continue continue
@ -143,10 +146,10 @@ class SerialPortFinder:
if not device: if not device:
device = self._find_known_device() device = self._find_known_device()
if device: if device:
port = self._reveal_device_port(device) return self._reveal_device_port(device)
# pick the best PID:VID USB device # pick the best PID:VID USB device
best_port = None port = best_port = None
for item in list_serial_ports(): for item in list_serial_ports():
if self.ensure_ready and not is_serial_port_ready(item["port"]): if self.ensure_ready and not is_serial_port_ready(item["port"]):
continue continue
@ -215,20 +218,26 @@ class SerialPortFinder:
if os.path.isfile(udev_rules_path): if os.path.isfile(udev_rules_path):
hwids.extend(parse_udev_rules_hwids(udev_rules_path)) hwids.extend(parse_udev_rules_hwids(udev_rules_path))
# load from installed dev-platforms @lru_cache(maxsize=1)
for platform in PlatformPackageManager().get_installed(): def _fetch_hwids_from_platforms():
p = PlatformFactory.new(platform) """load from installed dev-platforms"""
for board_config in p.get_boards().values(): result = []
for board_hwid in board_config.get("build.hwids", []): for platform in PlatformPackageManager().get_installed():
board_hwid = self.normalize_board_hwid(board_hwid) p = PlatformFactory.new(platform)
if board_hwid not in hwids: for board_config in p.get_boards().values():
hwids.append(board_hwid) for board_hwid in board_config.get("build.hwids", []):
board_hwid = self.normalize_board_hwid(board_hwid)
if board_hwid not in result:
result.append(board_hwid)
return result
try: try:
@retry(timeout=self.timeout) @retry(timeout=self.timeout)
def wrapper(): def wrapper():
device = self.match_device_hwid(hwids) device = self.match_device_hwid(hwids)
if not device:
device = self.match_device_hwid(_fetch_hwids_from_platforms())
if device: if device:
return device return device
raise retry.RetryNextException() raise retry.RetryNextException()

View File

@ -14,15 +14,15 @@
import socket import socket
import requests
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
from platformio import util from platformio import util
from platformio.compat import IS_WINDOWS from platformio.compat import IS_WINDOWS
from platformio.http import HTTPSession
from platformio.proc import where_is_program from platformio.proc import where_is_program
class AsyncSession(requests.Session): class AsyncSession(HTTPSession):
async def request( # pylint: disable=signature-differs,invalid-overridden-method async def request( # pylint: disable=signature-differs,invalid-overridden-method
self, *args, **kwargs self, *args, **kwargs
): ):

View File

@ -20,7 +20,7 @@ from functools import cmp_to_key
import click import click
from platformio import __default_requests_timeout__, fs from platformio import fs
from platformio.cache import ContentCache from platformio.cache import ContentCache
from platformio.device.list.util import list_logical_devices from platformio.device.list.util import list_logical_devices
from platformio.home import helpers from platformio.home import helpers
@ -50,13 +50,9 @@ class OSRPC:
session = helpers.requests_session() session = helpers.requests_session()
if data: if data:
r = await session.post( r = await session.post(uri, data=data, headers=headers)
uri, data=data, headers=headers, timeout=__default_requests_timeout__
)
else: else:
r = await session.get( r = await session.get(uri, headers=headers)
uri, headers=headers, timeout=__default_requests_timeout__
)
r.raise_for_status() r.raise_for_status()
result = r.text result = r.text

View File

@ -20,10 +20,12 @@ from urllib.parse import urljoin
import requests.adapters import requests.adapters
from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error
from platformio import __check_internet_hosts__, __default_requests_timeout__, app, util from platformio import __check_internet_hosts__, app, util
from platformio.cache import ContentCache, cleanup_content_cache from platformio.cache import ContentCache, cleanup_content_cache
from platformio.exception import PlatformioException, UserSideException from platformio.exception import PlatformioException, UserSideException
__default_requests_timeout__ = (10, None) # (connect, read)
class HTTPClientError(PlatformioException): class HTTPClientError(PlatformioException):
def __init__(self, message, response=None): def __init__(self, message, response=None):
@ -44,19 +46,30 @@ class InternetIsOffline(UserSideException):
) )
class EndpointSession(requests.Session): class HTTPSession(requests.Session):
def __init__(self, base_url, *args, **kwargs): def __init__(self, *args, **kwargs):
self._x_base_url = kwargs.pop("x_base_url") if "x_base_url" in kwargs else None
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.base_url = base_url self.headers.update({"User-Agent": app.get_user_agent()})
self.verify = app.get_setting("enable_proxy_strict_ssl")
def request( # pylint: disable=signature-differs,arguments-differ def request( # pylint: disable=signature-differs,arguments-differ
self, method, url, *args, **kwargs self, method, url, *args, **kwargs
): ):
# print(self.base_url, method, url, args, kwargs) # print("HTTPSession::request", self._x_base_url, method, url, args, kwargs)
return super().request(method, urljoin(self.base_url, url), *args, **kwargs) if "timeout" not in kwargs:
kwargs["timeout"] = __default_requests_timeout__
return super().request(
method,
url
if url.startswith("http") or not self._x_base_url
else urljoin(self._x_base_url, url),
*args,
**kwargs
)
class EndpointSessionIterator: class HTTPSessionIterator:
def __init__(self, endpoints): def __init__(self, endpoints):
if not isinstance(endpoints, list): if not isinstance(endpoints, list):
endpoints = [endpoints] endpoints = [endpoints]
@ -75,8 +88,7 @@ class EndpointSessionIterator:
def __next__(self): def __next__(self):
base_url = next(self.endpoints_iter) base_url = next(self.endpoints_iter)
session = EndpointSession(base_url) session = HTTPSession(x_base_url=base_url)
session.headers.update({"User-Agent": app.get_user_agent()})
adapter = requests.adapters.HTTPAdapter(max_retries=self.retry) adapter = requests.adapters.HTTPAdapter(max_retries=self.retry)
session.mount(base_url, adapter) session.mount(base_url, adapter)
return session return session
@ -84,7 +96,7 @@ class EndpointSessionIterator:
class HTTPClient: class HTTPClient:
def __init__(self, endpoints): def __init__(self, endpoints):
self._session_iter = EndpointSessionIterator(endpoints) self._session_iter = HTTPSessionIterator(endpoints)
self._session = None self._session = None
self._next_session() self._next_session()
@ -122,10 +134,6 @@ class HTTPClient:
) )
kwargs["headers"] = headers kwargs["headers"] = headers
# set default timeout
if "timeout" not in kwargs:
kwargs["timeout"] = __default_requests_timeout__
while True: while True:
try: try:
return getattr(self._session, method)(path, **kwargs) return getattr(self._session, method)(path, **kwargs)
@ -201,13 +209,8 @@ def ensure_internet_on(raise_exception=False):
def fetch_remote_content(*args, **kwargs): def fetch_remote_content(*args, **kwargs):
kwargs["headers"] = kwargs.get("headers", {}) with HTTPSession() as s:
if "User-Agent" not in kwargs["headers"]: r = s.get(*args, **kwargs)
kwargs["headers"]["User-Agent"] = app.get_user_agent() r.raise_for_status()
r.close()
if "timeout" not in kwargs: return r.text
kwargs["timeout"] = __default_requests_timeout__
r = requests.get(*args, **kwargs)
r.raise_for_status()
return r.text

View File

@ -61,7 +61,7 @@ from platformio.test.runners.factory import TestRunnerFactory
@click.option("-f", "--force", is_flag=True, help="Reinstall package if it exists") @click.option("-f", "--force", is_flag=True, help="Reinstall package if it exists")
@click.option("-s", "--silent", is_flag=True, help="Suppress progress reporting") @click.option("-s", "--silent", is_flag=True, help="Suppress progress reporting")
def package_install_cmd(**options): def package_install_cmd(**options):
if options.get("global"): if options.get("global") or options.get("storage_dir"):
install_global_dependencies(options) install_global_dependencies(options)
else: else:
install_project_dependencies(options) install_project_dependencies(options)

View File

@ -18,31 +18,30 @@ from os.path import getsize, join
from time import mktime from time import mktime
import click import click
import requests
from platformio import __default_requests_timeout__, app, fs from platformio import fs
from platformio.compat import is_terminal from platformio.compat import is_terminal
from platformio.http import HTTPSession
from platformio.package.exception import PackageException from platformio.package.exception import PackageException
class FileDownloader: class FileDownloader:
def __init__(self, url, dest_dir=None): def __init__(self, url, dest_dir=None):
self._request = None self._http_session = HTTPSession()
self._http_response = None
# make connection # make connection
self._request = requests.get( self._http_response = self._http_session.get(
url, url,
stream=True, stream=True,
headers={"User-Agent": app.get_user_agent()},
timeout=__default_requests_timeout__,
) )
if self._request.status_code != 200: if self._http_response.status_code != 200:
raise PackageException( raise PackageException(
"Got the unrecognized status code '{0}' when downloaded {1}".format( "Got the unrecognized status code '{0}' when downloaded {1}".format(
self._request.status_code, url self._http_response.status_code, url
) )
) )
disposition = self._request.headers.get("content-disposition") disposition = self._http_response.headers.get("content-disposition")
if disposition and "filename=" in disposition: if disposition and "filename=" in disposition:
self._fname = ( self._fname = (
disposition[disposition.index("filename=") + 9 :] disposition[disposition.index("filename=") + 9 :]
@ -63,17 +62,17 @@ class FileDownloader:
return self._destination return self._destination
def get_lmtime(self): def get_lmtime(self):
return self._request.headers.get("last-modified") return self._http_response.headers.get("last-modified")
def get_size(self): def get_size(self):
if "content-length" not in self._request.headers: if "content-length" not in self._http_response.headers:
return -1 return -1
return int(self._request.headers["content-length"]) return int(self._http_response.headers["content-length"])
def start(self, with_progress=True, silent=False): def start(self, with_progress=True, silent=False):
label = "Downloading" label = "Downloading"
file_size = self.get_size() file_size = self.get_size()
itercontent = self._request.iter_content(chunk_size=io.DEFAULT_BUFFER_SIZE) itercontent = self._http_response.iter_content(chunk_size=io.DEFAULT_BUFFER_SIZE)
try: try:
with open(self._destination, "wb") as fp: with open(self._destination, "wb") as fp:
if file_size == -1 or not with_progress or silent: if file_size == -1 or not with_progress or silent:
@ -110,7 +109,8 @@ class FileDownloader:
pb.update(len(chunk)) pb.update(len(chunk))
fp.write(chunk) fp.write(chunk)
finally: finally:
self._request.close() self._http_response.close()
self._http_session.close()
if self.get_lmtime(): if self.get_lmtime():
self._preserve_filemtime(self.get_lmtime()) self._preserve_filemtime(self.get_lmtime())
@ -158,5 +158,6 @@ class FileDownloader:
fs.change_filemtime(self._destination, lmtime) fs.change_filemtime(self._destination, lmtime)
def __del__(self): def __del__(self):
if self._request: self._http_session.close()
self._request.close() if self._http_response:
self._http_response.close()

View File

@ -121,7 +121,7 @@ def compute_project_checksum(config):
return checksum.hexdigest() return checksum.hexdigest()
def load_build_metadata(project_dir, env_or_envs, cache=False): def load_build_metadata(project_dir, env_or_envs, cache=False, debug=False):
assert env_or_envs assert env_or_envs
env_names = env_or_envs env_names = env_or_envs
if not isinstance(env_names, list): if not isinstance(env_names, list):
@ -129,9 +129,19 @@ def load_build_metadata(project_dir, env_or_envs, cache=False):
with fs.cd(project_dir): with fs.cd(project_dir):
result = _get_cached_build_metadata(project_dir, env_names) if cache else {} result = _get_cached_build_metadata(project_dir, env_names) if cache else {}
# incompatible build-type data
for name in list(result.keys()):
build_type = result[name].get("build_type", "")
outdated_conds = [
not build_type,
debug and "debug" not in build_type,
not debug and "debug" in build_type,
]
if any(outdated_conds):
del result[name]
missed_env_names = set(env_names) - set(result.keys()) missed_env_names = set(env_names) - set(result.keys())
if missed_env_names: if missed_env_names:
result.update(_load_build_metadata(project_dir, missed_env_names)) result.update(_load_build_metadata(project_dir, missed_env_names, debug))
if not isinstance(env_or_envs, list) and env_or_envs in result: if not isinstance(env_or_envs, list) and env_or_envs in result:
return result[env_or_envs] return result[env_or_envs]
@ -142,11 +152,13 @@ def load_build_metadata(project_dir, env_or_envs, cache=False):
load_project_ide_data = load_build_metadata load_project_ide_data = load_build_metadata
def _load_build_metadata(project_dir, env_names): def _load_build_metadata(project_dir, env_names, debug=False):
# pylint: disable=import-outside-toplevel # pylint: disable=import-outside-toplevel
from platformio.run.cli import cli as cmd_run from platformio.run.cli import cli as cmd_run
args = ["--project-dir", project_dir, "--target", "_idedata"] args = ["--project-dir", project_dir, "--target", "__idedata"]
if debug:
args.extend(["--target", "__debug"])
for name in env_names: for name in env_names:
args.extend(["-e", name]) args.extend(["-e", name])
result = CliRunner().invoke(cmd_run, args) result = CliRunner().invoke(cmd_run, args)

View File

@ -30,7 +30,7 @@ class ShellType(Enum):
def get_bash_version(): def get_bash_version():
result = subprocess.run(["bash", "--version"], capture_output=True, check=True) result = subprocess.run(["bash", "--version"], capture_output=True, check=True)
match = re.search(r"version\s+(\d+)\.(\d+)", result.stdout.decode()) match = re.search(r"version\s+(\d+)\.(\d+)", result.stdout.decode(), re.IGNORECASE)
if match: if match:
return (int(match.group(1)), int(match.group(2))) return (int(match.group(1)), int(match.group(2)))
return (0, 0) return (0, 0)

View File

@ -30,6 +30,7 @@ import requests
from platformio import __version__, app, exception, util from platformio import __version__, app, exception, util
from platformio.cli import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.compat import hashlib_encode_data, string_types from platformio.compat import hashlib_encode_data, string_types
from platformio.http import HTTPSession
from platformio.proc import is_ci, is_container from platformio.proc import is_ci, is_container
from platformio.project.helpers import is_platformio_project from platformio.project.helpers import is_platformio_project
@ -146,6 +147,7 @@ class MeasurementProtocol(TelemetryBase):
"device", "device",
"org", "org",
"package", "package",
"pkg",
"platform", "platform",
"project", "project",
"settings", "settings",
@ -183,7 +185,7 @@ class MeasurementProtocol(TelemetryBase):
def _ignore_hit(self): def _ignore_hit(self):
if not app.get_setting("enable_telemetry"): if not app.get_setting("enable_telemetry"):
return True return True
if self["ea"] in ("Idedata", "_Idedata"): if self["ea"] in ("Idedata", "__Idedata"):
return True return True
return False return False
@ -205,7 +207,7 @@ class MPDataPusher:
def __init__(self): def __init__(self):
self._queue = queue.LifoQueue() self._queue = queue.LifoQueue()
self._failedque = deque() self._failedque = deque()
self._http_session = requests.Session() self._http_session = HTTPSession()
self._http_offline = False self._http_offline = False
self._workers = [] self._workers = []
@ -269,7 +271,6 @@ class MPDataPusher:
r = self._http_session.post( r = self._http_session.post(
"https://ssl.google-analytics.com/collect", "https://ssl.google-analytics.com/collect",
data=data, data=data,
headers={"User-Agent": app.get_user_agent()},
timeout=1, timeout=1,
) )
r.raise_for_status() r.raise_for_status()

View File

@ -19,7 +19,6 @@ from pathlib import Path
import click import click
from platformio.package.manager.library import LibraryPackageManager
from platformio.test.exception import UnitTestSuiteError from platformio.test.exception import UnitTestSuiteError
from platformio.test.result import TestCase, TestCaseSource, TestStatus from platformio.test.result import TestCase, TestCaseSource, TestStatus
from platformio.test.runners.base import TestRunnerBase from platformio.test.runners.base import TestRunnerBase
@ -188,20 +187,6 @@ void unityOutputComplete(void) { unittest_uart_end(); }
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Delete when Unity > 2.5.2 is released""" """Delete when Unity > 2.5.2 is released"""
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._tmp_pre_upgrade()
def _tmp_pre_upgrade(self):
"""Delete when Unity > 2.5.2 is released"""
lm = LibraryPackageManager(
os.path.join(
self.project_config.get("platformio", "libdeps_dir"),
self.test_suite.env_name,
),
)
pkg = lm.get_package(self.EXTRA_LIB_DEPS[0])
if not pkg or os.path.isfile(os.path.join(pkg.path, "platformio-build.py")):
return
lm.uninstall(pkg)
def get_unity_framework_config(self): def get_unity_framework_config(self):
if not self.platform.is_embedded(): if not self.platform.is_embedded():

View File

@ -76,6 +76,13 @@ ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="0189", MODE="0666", ENV{ID_MM_DEVICE
# FireBeetle-ESP32 # FireBeetle-ESP32
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7522", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7522", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
#Wio Terminal
ATTRS{idVendor}=="2886", ATTRS{idProduct}=="[08]02d", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Raspberry Pi Pico
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="[01]*", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# #
# Debuggers # Debuggers
# #
@ -87,44 +94,29 @@ SUBSYSTEM=="tty", ATTRS{interface}=="Black Magic UART Port", MODE="0666", ENV{ID
# opendous and estick # opendous and estick
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Original FT232/FT245 VID:PID # Original FT232/FT245/FT2232/FT232H/FT4232
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="60[01][104]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Original FT2232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Original FT4232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Original FT232H VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# DISTORTEC JTAG-lock-pick Tiny 2 # DISTORTEC JTAG-lock-pick Tiny 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# TUMPA, TUMPA Lite # TUMPA, TUMPA Lite
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a9[89]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# XDS100v2 # XDS100v2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) # Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca[01]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# TI/Luminary Stellaris Evaluation Board FTDI (several) # TI/Luminary Stellaris Evaluation Board FTDI (several)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd[9a]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# egnite Turtelizer 2 # egnite Turtelizer 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Section5 ICEbear # Section5 ICEbear
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c14[01]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Amontec JTAGkey and JTAGkey-tiny # Amontec JTAGkey and JTAGkey-tiny
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
@ -176,6 +168,3 @@ ATTRS{product}=="*CMSIS-DAP*", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID
# Atmel AVR Dragon # Atmel AVR Dragon
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2107", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2107", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
# Raspberry Pi Pico
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="[01]*", MODE:="0666"

View File

@ -25,27 +25,29 @@ from platformio import (
__version__, __version__,
) )
PY36 = sys.version_info < (3, 7)
minimal_requirements = [ minimal_requirements = [
"bottle==0.12.*", "bottle==0.12.*",
"click%s" % (">=8.0.4,<9" if sys.version_info >= (3, 7) else "==8.0.4"), "click%s" % ("==8.0.4" if PY36 else ">=8.0.4,<9"),
"colorama", "colorama",
"marshmallow==%s" % ("3.*" if sys.version_info >= (3, 7) else "3.14.1"), "marshmallow==%s" % ("3.14.1" if PY36 else "3.*"),
"pyelftools>=0.27,<1", "pyelftools>=0.27,<1",
"pyserial==3.5.*", # keep in sync "device/monitor/terminal.py" "pyserial==3.5.*", # keep in sync "device/monitor/terminal.py"
"requests==2.*", "requests==2.*",
"requests==%s" % ("2.*" if sys.version_info >= (3, 7) else "2.27.1"), "requests==%s" % ("2.27.1" if PY36 else "2.*"),
"semantic_version==2.10.*", "semantic_version==2.10.*",
"tabulate==0.8.*", "tabulate==%s" % ("0.8.10" if PY36 else "0.9.*"),
"zeroconf<1", "zeroconf<1",
] ]
home_requirements = [ home_requirements = [
"aiofiles==0.8.*", "aiofiles==%s" % ("0.8.0" if PY36 else "22.1.*"),
"ajsonrpc==1.*", "ajsonrpc==1.*",
"starlette==%s" % ("0.20.*" if sys.version_info >= (3, 7) else "0.19.1"), "starlette==%s" % ("0.19.1" if PY36 else "0.21.*"),
"uvicorn==%s" % ("0.18.*" if sys.version_info >= (3, 7) else "0.16.0"), "uvicorn==%s" % ("0.16.0" if PY36 else "0.19.*"),
"wsproto==%s" % ("1.1.*" if sys.version_info >= (3, 7) else "1.0.0"), "wsproto==%s" % ("1.0.0" if PY36 else "1.2.*"),
] ]
setup( setup(

View File

@ -12,9 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
[tox]
envlist = py36,py37,py38,py39
[isort] [isort]
profile = black profile = black
known_third_party=OpenSSL, SCons, jsonrpc, twisted, zope known_third_party=OpenSSL, SCons, jsonrpc, twisted, zope
@ -29,7 +26,7 @@ filterwarnings =
passenv = * passenv = *
usedevelop = True usedevelop = True
deps = deps =
py36,py37,py38,py39: black black
isort isort
pylint pylint
pytest pytest