diff --git a/platformio/__main__.py b/platformio/__main__.py index 9138fe3c..0dc0cca1 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -14,13 +14,13 @@ import os import sys -from platform import system from traceback import format_exc import click from platformio import __version__, exception, maintenance from platformio.commands import PlatformioCLI +from platformio.compat import CYGWIN @click.command( @@ -45,7 +45,7 @@ def process_result(ctx, result, force, caller): # pylint: disable=W0613 def configure(): - if "cygwin" in system().lower(): + if CYGWIN: raise exception.CygwinEnvDetected() # https://urllib3.readthedocs.org diff --git a/platformio/app.py b/platformio/app.py index 247fb65c..c8a071fc 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -25,6 +25,7 @@ from time import time import requests from platformio import exception, lockfile, util +from platformio.compat import PY2, WINDOWS def projects_dir_validate(projects_dir): @@ -173,7 +174,7 @@ class ContentCache(object): if not arg: continue arg = str(arg) - h.update(arg if util.PY2 else arg.encode()) + h.update(arg if PY2 else arg.encode()) return h.hexdigest() def get(self, key): @@ -361,7 +362,6 @@ def get_cid(): uid = uuid.getnode() cid = uuid.UUID(bytes=hashlib.md5(str(uid).encode()).digest()) cid = str(cid) - if ("windows" in util.get_systype() - or os.getuid() > 0): # yapf: disable pylint: disable=no-member + if WINDOWS or os.getuid() > 0: # yapf: disable pylint: disable=no-member set_state_item("cid", cid) return cid diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index e1a0b50b..270f3f21 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -33,6 +33,7 @@ from SCons.Script import DefaultEnvironment # pylint: disable=import-error from platformio import exception, util from platformio.builder.tools import platformio as piotool +from platformio.compat import PY2, WINDOWS from platformio.managers.lib import LibraryManager from platformio.managers.package import PackageManager @@ -91,8 +92,6 @@ class LibBuilderFactory(object): class LibBuilderBase(object): - IS_WINDOWS = "windows" in util.get_systype() - LDF_MODES = ["off", "chain", "deep", "chain+", "deep+"] LDF_MODE_DEFAULT = "chain" @@ -135,7 +134,7 @@ class LibBuilderBase(object): def __contains__(self, path): p1 = self.path p2 = path - if self.IS_WINDOWS: + if WINDOWS: p1 = p1.lower() p2 = p2.lower() return commonprefix((p1 + sep, p2)) == p1 + sep @@ -191,7 +190,7 @@ class LibBuilderBase(object): @property def build_dir(self): lib_hash = hashlib.sha1( - self.path if util.PY2 else self.path.encode()).hexdigest()[:3] + self.path if PY2 else self.path.encode()).hexdigest()[:3] return join("$BUILD_DIR", "lib%s" % lib_hash, basename(self.path)) @property diff --git a/platformio/builder/tools/pioplatform.py b/platformio/builder/tools/pioplatform.py index 6427b33c..cc61a709 100644 --- a/platformio/builder/tools/pioplatform.py +++ b/platformio/builder/tools/pioplatform.py @@ -21,6 +21,7 @@ from os.path import isdir, isfile, join from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error from platformio import exception, util +from platformio.compat import WINDOWS from platformio.managers.platform import PlatformFactory # pylint: disable=too-many-branches, too-many-locals @@ -79,7 +80,7 @@ def LoadPioPlatform(env, variables): env.PrependENVPath( "PATH", join(pkg_dir, "bin") if isdir(join(pkg_dir, "bin")) else pkg_dir) - if ("windows" not in systype and isdir(join(pkg_dir, "lib")) + if (not WINDOWS and isdir(join(pkg_dir, "lib")) and type_ != "toolchain"): env.PrependENVPath( "DYLD_LIBRARY_PATH" diff --git a/platformio/builder/tools/pioupload.py b/platformio/builder/tools/pioupload.py index 0d5a55ea..a7b2685d 100644 --- a/platformio/builder/tools/pioupload.py +++ b/platformio/builder/tools/pioupload.py @@ -26,6 +26,7 @@ from SCons.Script import ARGUMENTS # pylint: disable=import-error from serial import Serial, SerialException from platformio import exception, util +from platformio.compat import WINDOWS # pylint: disable=unused-argument @@ -134,8 +135,7 @@ def AutodetectUploadPort(*args, **kwargs): continue port = item['port'] if upload_protocol.startswith("blackmagic"): - if "windows" in util.get_systype() and \ - port.startswith("COM") and len(port) > 4: + if WINDOWS and port.startswith("COM") and len(port) > 4: port = "\\\\.\\%s" % port if "GDB" in item['description']: return port diff --git a/platformio/builder/tools/piowinhooks.py b/platformio/builder/tools/piowinhooks.py index c893ffd5..1105091f 100644 --- a/platformio/builder/tools/piowinhooks.py +++ b/platformio/builder/tools/piowinhooks.py @@ -18,7 +18,7 @@ from hashlib import md5 from os import makedirs from os.path import isdir, isfile, join -from platformio import util +from platformio.compat import PY2, WINDOWS # Windows CLI has limit with command length to 8192 # Leave 2000 chars for flags and other options @@ -63,7 +63,7 @@ def _file_long_data(env, data): makedirs(build_dir) tmp_file = join( build_dir, - "longcmd-%s" % md5(data if util.PY2 else data.encode()).hexdigest()) + "longcmd-%s" % md5(data if PY2 else data.encode()).hexdigest()) if isfile(tmp_file): return tmp_file with open(tmp_file, "w") as fp: @@ -76,7 +76,7 @@ def exists(_): def generate(env): - if "windows" not in util.get_systype(): + if not WINDOWS: return None env.Replace(_long_sources_hook=long_sources_hook) diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 41f32700..a8272b83 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -27,7 +27,8 @@ from SCons.Script import DefaultEnvironment # pylint: disable=import-error from SCons.Script import Export # pylint: disable=import-error from SCons.Script import SConscript # pylint: disable=import-error -from platformio.util import glob_escape, pioversion_to_intstr, string_types +from platformio.compat import string_types +from platformio.util import glob_escape, pioversion_to_intstr SRC_HEADER_EXT = ["h", "hpp"] SRC_C_EXT = ["c", "cc", "cpp"] diff --git a/platformio/commands/upgrade.py b/platformio/commands/upgrade.py index c47ff8dc..6acb83ae 100644 --- a/platformio/commands/upgrade.py +++ b/platformio/commands/upgrade.py @@ -20,6 +20,7 @@ import click import requests from platformio import VERSION, __version__, exception, util +from platformio.compat import WINDOWS from platformio.managers.core import shutdown_piohome_servers @@ -68,7 +69,7 @@ def cli(dev): raise exception.UpgradeError("\n".join([str(cmd), str(e)])) permission_errors = ("permission denied", "not permitted") if (any(m in r['err'].lower() for m in permission_errors) - and "windows" not in util.get_systype()): + and not WINDOWS): click.secho( """ ----------------- diff --git a/platformio/compat.py b/platformio/compat.py new file mode 100644 index 00000000..cd50d905 --- /dev/null +++ b/platformio/compat.py @@ -0,0 +1,42 @@ +# Copyright (c) 2014-present PlatformIO +# +# 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. + +import sys + +PY2 = sys.version_info[0] == 2 +CYGWIN = sys.platform.startswith('cygwin') +WINDOWS = sys.platform.startswith('win') + + +def get_filesystem_encoding(): + return sys.getfilesystemencoding() or sys.getdefaultencoding() + + +if PY2: + # pylint: disable=undefined-variable + string_types = (str, unicode) + + def is_bytes(x): + return isinstance(x, (buffer, bytearray)) + + def path_to_unicode(path): + return path.decode(get_filesystem_encoding()).encode("utf-8") +else: + string_types = (str, ) + + def is_bytes(x): + return isinstance(x, (bytes, memoryview, bytearray)) + + def path_to_unicode(path): + return path diff --git a/platformio/downloader.py b/platformio/downloader.py index 0b0ef5df..f86b723d 100644 --- a/platformio/downloader.py +++ b/platformio/downloader.py @@ -15,13 +15,14 @@ from email.utils import parsedate_tz from math import ceil from os.path import getsize, join -from sys import getfilesystemencoding, version_info +from sys import version_info from time import mktime import click import requests from platformio import util +from platformio.compat import PY2, get_filesystem_encoding from platformio.exception import (FDSHASumMismatch, FDSizeMismatch, FDUnrecognizedStatusCode) @@ -45,15 +46,15 @@ class FileDownloader(object): if disposition and "filename=" in disposition: self._fname = disposition[disposition.index("filename=") + 9:].replace('"', "").replace("'", "") - if util.PY2: + if PY2: self._fname = self._fname.encode("utf8") else: self._fname = [p for p in url.split("/") if p][-1] self._destination = self._fname if dest_dir: - if util.PY2: - dest_dir = dest_dir.decode(getfilesystemencoding()) + if PY2: + dest_dir = dest_dir.decode(get_filesystem_encoding()) self.set_destination(join(dest_dir, self._fname)) def set_destination(self, destination): diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index 9cbf3028..1216aaee 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -23,6 +23,7 @@ from click.testing import CliRunner from platformio import exception, util from platformio.commands.run import cli as cmd_run +from platformio.compat import PY2, WINDOWS from platformio.project.config import ProjectConfig from platformio.project.helpers import ( get_projectlib_dir, get_projectlibdeps_dir, get_projectsrc_dir) @@ -120,7 +121,7 @@ class ProjectGenerator(object): contents = self._render_tpl(tpl_path) self._merge_contents( join(dst_dir, file_name), - contents.encode("utf8") if util.PY2 else contents) + contents.encode("utf8") if PY2 else contents) def _render_tpl(self, tpl_path): return bottle.template( @@ -155,5 +156,4 @@ class ProjectGenerator(object): @staticmethod def _fix_os_path(path): - return (re.sub(r"[\\]+", '\\' * 4, path) - if "windows" in util.get_systype() else path) + return (re.sub(r"[\\]+", '\\' * 4, path) if WINDOWS else path) diff --git a/platformio/managers/core.py b/platformio/managers/core.py index 0dd84552..62492bcf 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -21,6 +21,7 @@ from time import sleep import requests from platformio import __version__, exception, util +from platformio.compat import PY2, WINDOWS from platformio.managers.package import PackageManager CORE_PACKAGES = { @@ -29,7 +30,7 @@ CORE_PACKAGES = { "~2.%d%d.190418" % (sys.version_info[0], sys.version_info[1]), "tool-pioplus": "^2.2.0", "tool-unity": "~1.20403.0", - "tool-scons": "~2.20501.7" if util.PY2 else "~3.30005.0" + "tool-scons": "~2.20501.7" if PY2 else "~3.30005.0" } PIOPLUS_AUTO_UPDATES_MAX = 100 @@ -99,7 +100,7 @@ def update_core_packages(only_check=False, silent=False): 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(): + if WINDOWS: sleep(1) pm.update(name, requirements, only_check=only_check) return True @@ -117,7 +118,7 @@ def shutdown_piohome_servers(): def pioplus_call(args, **kwargs): - if "windows" in util.get_systype() and sys.version_info < (2, 7, 6): + if WINDOWS and sys.version_info < (2, 7, 6): raise exception.PlatformioException( "PlatformIO Core Plus v%s does not run under Python version %s.\n" "Minimum supported version is 2.7.6, please upgrade Python.\n" diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 4cbb34a7..b478f49c 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -23,6 +23,7 @@ from os.path import isdir, join import click from platformio import app, commands, exception, util +from platformio.compat import string_types from platformio.managers.package import BasePkgManager from platformio.managers.platform import PlatformFactory, PlatformManager @@ -120,7 +121,7 @@ class LibraryManager(BasePkgManager): # convert listed items via comma to array for key in ("keywords", "frameworks", "platforms"): if key not in manifest or \ - not isinstance(manifest[key], util.string_types): + not isinstance(manifest[key], string_types): continue manifest[key] = [ i.strip() for i in manifest[key].split(",") if i.strip() @@ -147,7 +148,7 @@ class LibraryManager(BasePkgManager): continue if item[k] == "*": del item[k] - elif isinstance(item[k], util.string_types): + elif isinstance(item[k], string_types): item[k] = [ i.strip() for i in item[k].split(",") if i.strip() ] diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 516a951c..4d637716 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -588,9 +588,8 @@ class PkgInstallerMixin(object): if "__src_url" in cur_manifest: target_dirname = "%s@src-%s" % ( pkg_dirname, - hashlib.md5(cur_manifest['__src_url'] if util. - PY2 else cur_manifest['__src_url'].encode( - )).hexdigest()) + hashlib.md5( + cur_manifest['__src_url'].encode()).hexdigest()) shutil.move(pkg_dir, join(self.package_dir, target_dirname)) # fix to a version elif action == 2: @@ -599,9 +598,8 @@ class PkgInstallerMixin(object): if "__src_url" in tmp_manifest: target_dirname = "%s@src-%s" % ( pkg_dirname, - hashlib.md5(tmp_manifest['__src_url'] if util. - PY2 else tmp_manifest['__src_url'].encode( - )).hexdigest()) + hashlib.md5( + tmp_manifest['__src_url'].encode()).hexdigest()) pkg_dir = join(self.package_dir, target_dirname) # remove previous/not-satisfied package diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index bfcda3f2..8c0b7de9 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -23,6 +23,7 @@ import click import semantic_version from platformio import __version__, app, exception, util +from platformio.compat import PY2 from platformio.managers.core import get_core_package_dir from platformio.managers.package import BasePkgManager, PackageManager from platformio.project.helpers import get_projectboards_dir @@ -389,7 +390,7 @@ class PlatformRunMixin(object): # encode and append variables for key, value in variables.items(): - if util.PY2: + if PY2: cmd.append("%s=%s" % (key.upper(), base64.b64encode(value))) else: cmd.append( diff --git a/platformio/project/helpers.py b/platformio/project/helpers.py index d7c19595..66a9c39b 100644 --- a/platformio/project/helpers.py +++ b/platformio/project/helpers.py @@ -13,16 +13,14 @@ # limitations under the License. import os -import sys from hashlib import sha1 from os import walk from os.path import abspath, dirname, expanduser, isdir, isfile, join from platformio import __version__ +from platformio.compat import PY2, WINDOWS from platformio.project.config import ProjectConfig -PY2 = sys.version_info[0] == 2 - def get_project_dir(): return os.getcwd() @@ -132,7 +130,7 @@ def calculate_project_hash(): if path.endswith(check_suffixes): chunks.append(path) chunks_to_str = ",".join(sorted(chunks)) - if sys.platform == "win32": + if WINDOWS: # Fix issue with useless project rebuilding for case insensitive FS. # A case of disk drive can differ... chunks_to_str = chunks_to_str.lower() diff --git a/platformio/util.py b/platformio/util.py index 8055cc4d..6e5db848 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -32,19 +32,15 @@ import click import requests from platformio import __apiurl__, __version__, exception +from platformio.compat import path_to_unicode # pylint: disable=unused-import +from platformio.compat import PY2, WINDOWS, string_types from platformio.project.config import ProjectConfig from platformio.project.helpers import ( # pylint: disable=unused-import get_project_dir, get_project_optional_dir, get_projectboards_dir, get_projectbuild_dir, get_projectdata_dir, get_projectlib_dir, get_projectsrc_dir, get_projecttest_dir, is_platformio_project) -# FIXME: check platformio.project.helpers imports - -PY2 = sys.version_info[0] == 2 -if PY2: - string_types = basestring # pylint: disable=undefined-variable -else: - string_types = str +# FIXME: remove import of path_to_unicode class AsyncPipe(Thread): @@ -148,12 +144,6 @@ def singleton(cls): return get_instance -def path_to_unicode(path): - if not PY2: - return path - return path.decode(sys.getfilesystemencoding()).encode("utf-8") - - def load_json(file_path): try: with open(file_path, "r") as f: @@ -180,7 +170,7 @@ def get_home_dir(): home_dir = get_project_optional_dir("home_dir", join(expanduser("~"), ".platformio")) win_home_dir = None - if "windows" in get_systype(): + if WINDOWS: win_home_dir = splitdrive(home_dir)[0] + "\\.platformio" if isdir(win_home_dir): home_dir = win_home_dir @@ -281,7 +271,7 @@ def copy_pythonpath_to_osenv(): _PYTHONPATH = os.environ.get("PYTHONPATH").split(os.pathsep) for p in os.sys.path: conditions = [p not in _PYTHONPATH] - if "windows" not in get_systype(): + if not WINDOWS: conditions.append( isdir(join(p, "click")) or isdir(join(p, "platformio"))) if all(conditions): @@ -299,14 +289,12 @@ def get_serial_ports(filter_hwid=False): for p, d, h in comports(): if not p: continue - if "windows" in get_systype(): - if PY2: - try: - d = unicode( # pylint: disable=undefined-variable - d, - errors="ignore") - except TypeError: - pass + if WINDOWS and PY2: + try: + # pylint: disable=undefined-variable + d = unicode(d, errors="ignore") + except TypeError: + pass if not filter_hwid or "VID:PID" in h: result.append({"port": p, "description": d, "hwid": h}) @@ -326,7 +314,7 @@ get_serialports = get_serial_ports def get_logical_devices(): items = [] - if "windows" in get_systype(): + if WINDOWS: try: result = exec_command( ["wmic", "logicaldisk", "get", "name,VolumeName"]).get( @@ -586,9 +574,8 @@ def where_is_program(program, envpath=None): # try OS's built-in commands try: - result = exec_command( - ["where" if "windows" in get_systype() else "which", program], - env=env) + result = exec_command(["where" if WINDOWS else "which", program], + env=env) if result['returncode'] == 0 and isfile(result['out'].strip()): return result['out'].strip() except OSError: