diff --git a/HISTORY.rst b/HISTORY.rst index fe6efe0f..f47b6f22 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -51,12 +51,13 @@ PlatformIO Core 5 * **Integration** - Added a new build variable (``COMPILATIONDB_INCLUDE_TOOLCHAIN``) to include toolchain paths in the compilation database (`issue #3735 `_) - - Changed default path for compilation database `compile_commands.json `__ to the root of the project + - Changed default path for compilation database `compile_commands.json `__ to the project root * **Miscellaneous** - Improved PIO Remote setup on credit-card sized computers (Raspberry Pi, BeagleBon, etc) (`issue #3865 `_) - - Better handling of the failed tests using the `Unit Testing `__ solution. + - Better handling of the failed tests using the `Unit Testing `__ solution + - Finally removed all tracks to the Python 2.7, the Python 3.6 is the minimum supported version. 5.2.5 (2022-02-10) ~~~~~~~~~~~~~~~~~~ diff --git a/docs b/docs index 7c02d91f..bde1247b 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 7c02d91f4ee1de1afbb4bbee061dbde6d6012467 +Subproject commit bde1247be3f01a63c523d1e43aeb7a949904e653 diff --git a/platformio/__main__.py b/platformio/__main__.py index 16d9352b..07816eda 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -12,15 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=import-outside-toplevel - import os import sys from traceback import format_exc import click -from platformio import __version__, exception +from platformio import __version__, exception, maintenance from platformio.commands import PlatformioCLI from platformio.compat import IS_CYGWIN, ensure_python3 @@ -55,16 +53,12 @@ def cli(ctx, force, caller, no_ansi): except: # pylint: disable=bare-except pass - from platformio import maintenance - maintenance.on_platformio_start(ctx, force, caller) @cli.result_callback() @click.pass_context def process_result(ctx, result, *_, **__): - from platformio import maintenance - maintenance.on_platformio_end(ctx, result) @@ -111,10 +105,7 @@ def main(argv=None): exit_code = int(e.code) except Exception as e: # pylint: disable=broad-except if not isinstance(e, exception.ReturnErrorCode): - if sys.version_info.major != 2: - from platformio import maintenance - - maintenance.on_platformio_exception(e) + maintenance.on_platformio_exception(e) error_str = "Error: " if isinstance(e, exception.PlatformioException): error_str += str(e) diff --git a/platformio/clients/http.py b/platformio/clients/http.py index 3cf247b4..70c9cfb8 100644 --- a/platformio/clients/http.py +++ b/platformio/clients/http.py @@ -16,6 +16,7 @@ import json import math import os import socket +from urllib.parse import urljoin import requests.adapters from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error @@ -24,11 +25,6 @@ from platformio import __check_internet_hosts__, __default_requests_timeout__, a from platformio.cache import ContentCache, cleanup_content_cache from platformio.exception import PlatformioException, UserSideException -try: - from urllib.parse import urljoin -except ImportError: - from urlparse import urljoin - class HTTPClientError(PlatformioException): def __init__(self, message, response=None): diff --git a/platformio/commands/home/rpc/handlers/piocore.py b/platformio/commands/home/rpc/handlers/piocore.py index 52a1b126..01bbf90d 100644 --- a/platformio/commands/home/rpc/handlers/piocore.py +++ b/platformio/commands/home/rpc/handlers/piocore.py @@ -14,10 +14,11 @@ from __future__ import absolute_import +import io import json import os import sys -from io import StringIO +import threading import click from ajsonrpc.core import JSONRPC20DispatchException @@ -27,27 +28,22 @@ from platformio import __main__, __version__, fs, proc from platformio.commands.home import helpers from platformio.compat import get_locale_encoding, is_bytes -try: - from thread import get_ident as thread_get_ident -except ImportError: - from threading import get_ident as thread_get_ident - class MultiThreadingStdStream(object): def __init__(self, parent_stream): - self._buffers = {thread_get_ident(): parent_stream} + self._buffers = {threading.get_ident(): parent_stream} def __getattr__(self, name): - thread_id = thread_get_ident() + thread_id = threading.get_ident() self._ensure_thread_buffer(thread_id) return getattr(self._buffers[thread_id], name) def _ensure_thread_buffer(self, thread_id): if thread_id not in self._buffers: - self._buffers[thread_id] = StringIO() + self._buffers[thread_id] = io.StringIO() def write(self, value): - thread_id = thread_get_ident() + thread_id = threading.get_ident() self._ensure_thread_buffer(thread_id) return self._buffers[thread_id].write( value.decode() if is_bytes(value) else value diff --git a/platformio/commands/lib/command.py b/platformio/commands/lib/command.py index be4fbcf6..e9f5feb2 100644 --- a/platformio/commands/lib/command.py +++ b/platformio/commands/lib/command.py @@ -18,6 +18,7 @@ import json import logging import os import time +from urllib.parse import quote import click from tabulate import tabulate @@ -32,11 +33,6 @@ from platformio.proc import is_ci from platformio.project.config import ProjectConfig from platformio.project.helpers import get_project_dir, is_platformio_project -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - CTX_META_INPUT_DIRS_KEY = __name__ + ".input_dirs" CTX_META_PROJECT_ENVIRONMENTS_KEY = __name__ + ".project_environments" CTX_META_STORAGE_DIRS_KEY = __name__ + ".storage_dirs" diff --git a/platformio/compat.py b/platformio/compat.py index f3f79ea6..04ae525f 100644 --- a/platformio/compat.py +++ b/platformio/compat.py @@ -20,16 +20,14 @@ import sys from platformio.exception import UserSideException -if sys.version_info >= (3,): - if sys.version_info >= (3, 7): - from asyncio import create_task as aio_create_task - from asyncio import get_running_loop as aio_get_running_loop - else: - from asyncio import ensure_future as aio_create_task - from asyncio import get_event_loop as aio_get_running_loop +if sys.version_info >= (3, 7): + from asyncio import create_task as aio_create_task + from asyncio import get_running_loop as aio_get_running_loop +else: + from asyncio import ensure_future as aio_create_task + from asyncio import get_event_loop as aio_get_running_loop -PY2 = sys.version_info[0] == 2 IS_CYGWIN = sys.platform.startswith("cygwin") IS_WINDOWS = WINDOWS = sys.platform.startswith("win") IS_MACOS = sys.platform.startswith("darwin") diff --git a/platformio/package/manager/_registry.py b/platformio/package/manager/_registry.py index c782135d..4c16c7b9 100644 --- a/platformio/package/manager/_registry.py +++ b/platformio/package/manager/_registry.py @@ -13,6 +13,7 @@ # limitations under the License. import time +from urllib.parse import urlparse import click @@ -22,11 +23,6 @@ from platformio.package.exception import UnknownPackageError from platformio.package.meta import PackageSpec from platformio.package.version import cast_version_to_semver -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse - class RegistryFileMirrorIterator(object): diff --git a/platformio/package/manifest/parser.py b/platformio/package/manifest/parser.py index 556339a7..a5e0f837 100644 --- a/platformio/package/manifest/parser.py +++ b/platformio/package/manifest/parser.py @@ -18,6 +18,7 @@ import json import os import re import tarfile +from urllib.parse import urlparse from platformio import util from platformio.clients.http import fetch_remote_content @@ -25,11 +26,6 @@ from platformio.compat import get_object_members, string_types from platformio.package.exception import ManifestParserError, UnknownManifestError from platformio.project.helpers import is_platformio_project -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse - class ManifestFileType(object): PLATFORM_JSON = "platform.json" diff --git a/platformio/package/manifest/schema.py b/platformio/package/manifest/schema.py index 39e57a54..6dc8764a 100644 --- a/platformio/package/manifest/schema.py +++ b/platformio/package/manifest/schema.py @@ -26,37 +26,21 @@ from platformio.clients.http import fetch_remote_content from platformio.package.exception import ManifestValidationError from platformio.util import memoized -MARSHMALLOW_2 = marshmallow.__version_info__ < (3,) +class BaseSchema(Schema): + class Meta(object): # pylint: disable=no-init + unknown = marshmallow.EXCLUDE # pylint: disable=no-member -if MARSHMALLOW_2: - - class CompatSchema(Schema): - pass - -else: - - class CompatSchema(Schema): - class Meta(object): # pylint: disable=no-init - unknown = marshmallow.EXCLUDE # pylint: disable=no-member - - def handle_error(self, error, data, **_): # pylint: disable=arguments-differ - raise ManifestValidationError( - error.messages, - data, - error.valid_data if hasattr(error, "valid_data") else error.data, - ) - - -class BaseSchema(CompatSchema): def load_manifest(self, data): - if MARSHMALLOW_2: - data, errors = self.load(data) - if errors: - raise ManifestValidationError(errors, data, data) - return data return self.load(data) + def handle_error(self, error, data, **_): # pylint: disable=arguments-differ + raise ManifestValidationError( + error.messages, + data, + error.valid_data if hasattr(error, "valid_data") else error.data, + ) + class StrictSchema(BaseSchema): def handle_error(self, error, data, **_): # pylint: disable=arguments-differ @@ -67,8 +51,6 @@ class StrictSchema(BaseSchema): ] else: error.valid_data = None - if MARSHMALLOW_2: - error.data = error.valid_data raise error diff --git a/platformio/package/vcsclient.py b/platformio/package/vcsclient.py index d7c6b94a..ca16c3f4 100644 --- a/platformio/package/vcsclient.py +++ b/platformio/package/vcsclient.py @@ -16,6 +16,7 @@ import os import re import subprocess import sys +from urllib.parse import urlparse from platformio import proc from platformio.package.exception import ( @@ -24,11 +25,6 @@ from platformio.package.exception import ( UserSideException, ) -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse - class VCSBaseException(PackageException): pass diff --git a/platformio/platform/_run.py b/platformio/platform/_run.py index 37dee069..b389b56f 100644 --- a/platformio/platform/_run.py +++ b/platformio/platform/_run.py @@ -16,6 +16,7 @@ import base64 import os import re import sys +from urllib.parse import quote import click @@ -24,11 +25,6 @@ from platformio.compat import hashlib_encode_data, is_bytes from platformio.package.manager.core import get_core_package_dir from platformio.platform.exception import BuildScriptNotFound -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - class PlatformRunMixin(object): diff --git a/platformio/project/config.py b/platformio/project/config.py index 944d565c..abce4475 100644 --- a/platformio/project/config.py +++ b/platformio/project/config.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import configparser import glob import json import os @@ -24,11 +25,6 @@ from platformio.compat import string_types from platformio.project import exception from platformio.project.options import ProjectOptions -try: - import ConfigParser as ConfigParser -except ImportError: - import configparser as ConfigParser - CONFIG_HEADER = """ ; PlatformIO Project Configuration File ; @@ -87,7 +83,7 @@ class ProjectConfigBase(object): self.expand_interpolations = expand_interpolations self.warnings = [] self._parsed = [] - self._parser = ConfigParser.ConfigParser(inline_comment_prefixes=("#", ";")) + self._parser = configparser.ConfigParser(inline_comment_prefixes=("#", ";")) if path and os.path.isfile(path): self.read(path, parse_extra) @@ -102,7 +98,7 @@ class ProjectConfigBase(object): self._parsed.append(path) try: self._parser.read(path, "utf-8") - except ConfigParser.Error as e: + except configparser.Error as e: raise exception.InvalidProjectConfError(path, str(e)) if not parse_extra: @@ -310,7 +306,7 @@ class ProjectConfigBase(object): value = None try: value = self.getraw(section, option, default) - except ConfigParser.Error as e: + except configparser.Error as e: raise exception.InvalidProjectConfError(self.path, str(e)) option_meta = ProjectOptions.get("%s.%s" % (section.split(":", 1)[0], option)) @@ -398,7 +394,7 @@ class ProjectConfig(ProjectConfigBase, ProjectConfigDirsMixin): def update(self, data, clear=False): assert isinstance(data, list) if clear: - self._parser = ConfigParser.ConfigParser() + self._parser = configparser.ConfigParser() for section, options in data: if not self._parser.has_section(section): self._parser.add_section(section) diff --git a/platformio/telemetry.py b/platformio/telemetry.py index ed2bf9b0..6b133565 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -16,6 +16,7 @@ import atexit import hashlib import json import os +import queue import re import shutil import sys @@ -32,11 +33,6 @@ from platformio.compat import hashlib_encode_data, string_types from platformio.proc import is_ci, is_container from platformio.project.helpers import is_platformio_project -try: - import queue -except ImportError: - import Queue as queue - class TelemetryBase(object): def __init__(self): diff --git a/setup.py b/setup.py index 64f28446..fe232925 100644 --- a/setup.py +++ b/setup.py @@ -24,24 +24,21 @@ from platformio import ( __url__, __version__, ) -from platformio.compat import PY2 minimal_requirements = [ "bottle==0.12.*", "click%s" % (">=8.0.3,<9" if sys.version_info >= (3, 7) else "==8.0.4"), "colorama", - "marshmallow%s" % (">=2,<3" if PY2 else ">=2,<4"), + "marshmallow==3.*", "pyelftools>=0.27,<1", "pyserial==3.*", "requests==2.*", "semantic_version==2.9.*", "tabulate==0.8.*", + "zeroconf<1", ] -if not PY2: - minimal_requirements.append("zeroconf<1") - home_requirements = [ "aiofiles==0.8.*", "ajsonrpc==1.*", @@ -59,7 +56,8 @@ setup( author_email=__email__, url=__url__, license=__license__, - install_requires=minimal_requirements + ([] if PY2 else home_requirements), + install_requires=minimal_requirements + home_requirements, + python_requires=">=3.6", packages=find_packages(exclude=["tests.*", "tests"]) + ["scripts"], package_data={ "platformio": [ diff --git a/tests/project/test_config.py b/tests/project/test_config.py index 0fada8c3..879e681a 100644 --- a/tests/project/test_config.py +++ b/tests/project/test_config.py @@ -14,13 +14,14 @@ # pylint: disable=redefined-outer-name +import configparser import os import sys import pytest from platformio import fs -from platformio.project.config import ConfigParser, ProjectConfig +from platformio.project.config import ProjectConfig from platformio.project.exception import InvalidProjectConfError, UnknownEnvNamesError BASE_CONFIG = """ @@ -154,7 +155,7 @@ def test_defaults(config): def test_sections(config): - with pytest.raises(ConfigParser.NoSectionError): + with pytest.raises(configparser.NoSectionError): config.getraw("unknown_section", "unknown_option") assert config.sections() == [ @@ -276,10 +277,10 @@ def test_sysenv_options(config): def test_getraw_value(config): # unknown option - with pytest.raises(ConfigParser.NoOptionError): + with pytest.raises(configparser.NoOptionError): config.getraw("custom", "unknown_option") # unknown option even if exists in [env] - with pytest.raises(ConfigParser.NoOptionError): + with pytest.raises(configparser.NoOptionError): config.getraw("platformio", "monitor_speed") # default diff --git a/tests/test_examples.py b/tests/test_examples.py index 0be516eb..27164fd7 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -19,7 +19,6 @@ from glob import glob import pytest from platformio import fs, proc -from platformio.compat import PY2 from platformio.package.manager.platform import PlatformPackageManager from platformio.platform.factory import PlatformFactory from platformio.project.config import ProjectConfig @@ -48,8 +47,6 @@ def pytest_generate_tests(metafunc): for root, _, files in os.walk(examples_dir): if "platformio.ini" not in files or ".skiptest" in files: continue - if "zephyr-" in root and PY2: - continue group = os.path.basename(root) if "-" in group: group = group.split("-", 1)[0]