Move Python or Platform dependent code to "compat" module

This commit is contained in:
Ivan Kravets
2019-05-10 17:26:10 +03:00
parent ce4ed18ceb
commit 834206ff20
17 changed files with 98 additions and 67 deletions

View File

@ -14,13 +14,13 @@
import os import os
import sys import sys
from platform import system
from traceback import format_exc from traceback import format_exc
import click import click
from platformio import __version__, exception, maintenance from platformio import __version__, exception, maintenance
from platformio.commands import PlatformioCLI from platformio.commands import PlatformioCLI
from platformio.compat import CYGWIN
@click.command( @click.command(
@ -45,7 +45,7 @@ def process_result(ctx, result, force, caller): # pylint: disable=W0613
def configure(): def configure():
if "cygwin" in system().lower(): if CYGWIN:
raise exception.CygwinEnvDetected() raise exception.CygwinEnvDetected()
# https://urllib3.readthedocs.org # https://urllib3.readthedocs.org

View File

@ -25,6 +25,7 @@ from time import time
import requests import requests
from platformio import exception, lockfile, util from platformio import exception, lockfile, util
from platformio.compat import PY2, WINDOWS
def projects_dir_validate(projects_dir): def projects_dir_validate(projects_dir):
@ -173,7 +174,7 @@ class ContentCache(object):
if not arg: if not arg:
continue continue
arg = str(arg) arg = str(arg)
h.update(arg if util.PY2 else arg.encode()) h.update(arg if PY2 else arg.encode())
return h.hexdigest() return h.hexdigest()
def get(self, key): def get(self, key):
@ -361,7 +362,6 @@ def get_cid():
uid = uuid.getnode() uid = uuid.getnode()
cid = uuid.UUID(bytes=hashlib.md5(str(uid).encode()).digest()) cid = uuid.UUID(bytes=hashlib.md5(str(uid).encode()).digest())
cid = str(cid) cid = str(cid)
if ("windows" in util.get_systype() if WINDOWS or os.getuid() > 0: # yapf: disable pylint: disable=no-member
or os.getuid() > 0): # yapf: disable pylint: disable=no-member
set_state_item("cid", cid) set_state_item("cid", cid)
return cid return cid

View File

@ -33,6 +33,7 @@ from SCons.Script import DefaultEnvironment # pylint: disable=import-error
from platformio import exception, util from platformio import exception, util
from platformio.builder.tools import platformio as piotool from platformio.builder.tools import platformio as piotool
from platformio.compat import PY2, WINDOWS
from platformio.managers.lib import LibraryManager from platformio.managers.lib import LibraryManager
from platformio.managers.package import PackageManager from platformio.managers.package import PackageManager
@ -91,8 +92,6 @@ class LibBuilderFactory(object):
class LibBuilderBase(object): class LibBuilderBase(object):
IS_WINDOWS = "windows" in util.get_systype()
LDF_MODES = ["off", "chain", "deep", "chain+", "deep+"] LDF_MODES = ["off", "chain", "deep", "chain+", "deep+"]
LDF_MODE_DEFAULT = "chain" LDF_MODE_DEFAULT = "chain"
@ -135,7 +134,7 @@ class LibBuilderBase(object):
def __contains__(self, path): def __contains__(self, path):
p1 = self.path p1 = self.path
p2 = path p2 = path
if self.IS_WINDOWS: if WINDOWS:
p1 = p1.lower() p1 = p1.lower()
p2 = p2.lower() p2 = p2.lower()
return commonprefix((p1 + sep, p2)) == p1 + sep return commonprefix((p1 + sep, p2)) == p1 + sep
@ -191,7 +190,7 @@ class LibBuilderBase(object):
@property @property
def build_dir(self): def build_dir(self):
lib_hash = hashlib.sha1( 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)) return join("$BUILD_DIR", "lib%s" % lib_hash, basename(self.path))
@property @property

View File

@ -21,6 +21,7 @@ from os.path import isdir, isfile, join
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from platformio import exception, util from platformio import exception, util
from platformio.compat import WINDOWS
from platformio.managers.platform import PlatformFactory from platformio.managers.platform import PlatformFactory
# pylint: disable=too-many-branches, too-many-locals # pylint: disable=too-many-branches, too-many-locals
@ -79,7 +80,7 @@ def LoadPioPlatform(env, variables):
env.PrependENVPath( env.PrependENVPath(
"PATH", "PATH",
join(pkg_dir, "bin") if isdir(join(pkg_dir, "bin")) else pkg_dir) 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"): and type_ != "toolchain"):
env.PrependENVPath( env.PrependENVPath(
"DYLD_LIBRARY_PATH" "DYLD_LIBRARY_PATH"

View File

@ -26,6 +26,7 @@ from SCons.Script import ARGUMENTS # pylint: disable=import-error
from serial import Serial, SerialException from serial import Serial, SerialException
from platformio import exception, util from platformio import exception, util
from platformio.compat import WINDOWS
# pylint: disable=unused-argument # pylint: disable=unused-argument
@ -134,8 +135,7 @@ def AutodetectUploadPort(*args, **kwargs):
continue continue
port = item['port'] port = item['port']
if upload_protocol.startswith("blackmagic"): if upload_protocol.startswith("blackmagic"):
if "windows" in util.get_systype() and \ if WINDOWS and port.startswith("COM") and len(port) > 4:
port.startswith("COM") and len(port) > 4:
port = "\\\\.\\%s" % port port = "\\\\.\\%s" % port
if "GDB" in item['description']: if "GDB" in item['description']:
return port return port

View File

@ -18,7 +18,7 @@ from hashlib import md5
from os import makedirs from os import makedirs
from os.path import isdir, isfile, join 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 # Windows CLI has limit with command length to 8192
# Leave 2000 chars for flags and other options # Leave 2000 chars for flags and other options
@ -63,7 +63,7 @@ def _file_long_data(env, data):
makedirs(build_dir) makedirs(build_dir)
tmp_file = join( tmp_file = join(
build_dir, 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): if isfile(tmp_file):
return tmp_file return tmp_file
with open(tmp_file, "w") as fp: with open(tmp_file, "w") as fp:
@ -76,7 +76,7 @@ def exists(_):
def generate(env): def generate(env):
if "windows" not in util.get_systype(): if not WINDOWS:
return None return None
env.Replace(_long_sources_hook=long_sources_hook) env.Replace(_long_sources_hook=long_sources_hook)

View File

@ -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 Export # pylint: disable=import-error
from SCons.Script import SConscript # 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_HEADER_EXT = ["h", "hpp"]
SRC_C_EXT = ["c", "cc", "cpp"] SRC_C_EXT = ["c", "cc", "cpp"]

View File

@ -20,6 +20,7 @@ import click
import requests import requests
from platformio import VERSION, __version__, exception, util from platformio import VERSION, __version__, exception, util
from platformio.compat import WINDOWS
from platformio.managers.core import shutdown_piohome_servers from platformio.managers.core import shutdown_piohome_servers
@ -68,7 +69,7 @@ def cli(dev):
raise exception.UpgradeError("\n".join([str(cmd), str(e)])) raise exception.UpgradeError("\n".join([str(cmd), str(e)]))
permission_errors = ("permission denied", "not permitted") permission_errors = ("permission denied", "not permitted")
if (any(m in r['err'].lower() for m in permission_errors) if (any(m in r['err'].lower() for m in permission_errors)
and "windows" not in util.get_systype()): and not WINDOWS):
click.secho( click.secho(
""" """
----------------- -----------------

42
platformio/compat.py Normal file
View File

@ -0,0 +1,42 @@
# 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.
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

View File

@ -15,13 +15,14 @@
from email.utils import parsedate_tz from email.utils import parsedate_tz
from math import ceil from math import ceil
from os.path import getsize, join from os.path import getsize, join
from sys import getfilesystemencoding, version_info from sys import version_info
from time import mktime from time import mktime
import click import click
import requests import requests
from platformio import util from platformio import util
from platformio.compat import PY2, get_filesystem_encoding
from platformio.exception import (FDSHASumMismatch, FDSizeMismatch, from platformio.exception import (FDSHASumMismatch, FDSizeMismatch,
FDUnrecognizedStatusCode) FDUnrecognizedStatusCode)
@ -45,15 +46,15 @@ class FileDownloader(object):
if disposition and "filename=" in disposition: if disposition and "filename=" in disposition:
self._fname = disposition[disposition.index("filename=") + self._fname = disposition[disposition.index("filename=") +
9:].replace('"', "").replace("'", "") 9:].replace('"', "").replace("'", "")
if util.PY2: if PY2:
self._fname = self._fname.encode("utf8") self._fname = self._fname.encode("utf8")
else: else:
self._fname = [p for p in url.split("/") if p][-1] self._fname = [p for p in url.split("/") if p][-1]
self._destination = self._fname self._destination = self._fname
if dest_dir: if dest_dir:
if util.PY2: if PY2:
dest_dir = dest_dir.decode(getfilesystemencoding()) dest_dir = dest_dir.decode(get_filesystem_encoding())
self.set_destination(join(dest_dir, self._fname)) self.set_destination(join(dest_dir, self._fname))
def set_destination(self, destination): def set_destination(self, destination):

View File

@ -23,6 +23,7 @@ from click.testing import CliRunner
from platformio import exception, util from platformio import exception, util
from platformio.commands.run import cli as cmd_run from platformio.commands.run import cli as cmd_run
from platformio.compat import PY2, WINDOWS
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
from platformio.project.helpers import ( from platformio.project.helpers import (
get_projectlib_dir, get_projectlibdeps_dir, get_projectsrc_dir) get_projectlib_dir, get_projectlibdeps_dir, get_projectsrc_dir)
@ -120,7 +121,7 @@ class ProjectGenerator(object):
contents = self._render_tpl(tpl_path) contents = self._render_tpl(tpl_path)
self._merge_contents( self._merge_contents(
join(dst_dir, file_name), 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): def _render_tpl(self, tpl_path):
return bottle.template( return bottle.template(
@ -155,5 +156,4 @@ class ProjectGenerator(object):
@staticmethod @staticmethod
def _fix_os_path(path): def _fix_os_path(path):
return (re.sub(r"[\\]+", '\\' * 4, path) return (re.sub(r"[\\]+", '\\' * 4, path) if WINDOWS else path)
if "windows" in util.get_systype() else path)

View File

@ -21,6 +21,7 @@ from time import sleep
import requests import requests
from platformio import __version__, exception, util from platformio import __version__, exception, util
from platformio.compat import PY2, WINDOWS
from platformio.managers.package import PackageManager from platformio.managers.package import PackageManager
CORE_PACKAGES = { CORE_PACKAGES = {
@ -29,7 +30,7 @@ CORE_PACKAGES = {
"~2.%d%d.190418" % (sys.version_info[0], sys.version_info[1]), "~2.%d%d.190418" % (sys.version_info[0], sys.version_info[1]),
"tool-pioplus": "^2.2.0", "tool-pioplus": "^2.2.0",
"tool-unity": "~1.20403.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 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 not silent or pm.outdated(pkg_dir, requirements):
if name == "tool-pioplus" and not only_check: if name == "tool-pioplus" and not only_check:
shutdown_piohome_servers() shutdown_piohome_servers()
if "windows" in util.get_systype(): if WINDOWS:
sleep(1) sleep(1)
pm.update(name, requirements, only_check=only_check) pm.update(name, requirements, only_check=only_check)
return True return True
@ -117,7 +118,7 @@ def shutdown_piohome_servers():
def pioplus_call(args, **kwargs): 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( raise exception.PlatformioException(
"PlatformIO Core Plus v%s does not run under Python version %s.\n" "PlatformIO Core Plus v%s does not run under Python version %s.\n"
"Minimum supported version is 2.7.6, please upgrade Python.\n" "Minimum supported version is 2.7.6, please upgrade Python.\n"

View File

@ -23,6 +23,7 @@ from os.path import isdir, join
import click import click
from platformio import app, commands, exception, util from platformio import app, commands, exception, util
from platformio.compat import string_types
from platformio.managers.package import BasePkgManager from platformio.managers.package import BasePkgManager
from platformio.managers.platform import PlatformFactory, PlatformManager from platformio.managers.platform import PlatformFactory, PlatformManager
@ -120,7 +121,7 @@ class LibraryManager(BasePkgManager):
# convert listed items via comma to array # convert listed items via comma to array
for key in ("keywords", "frameworks", "platforms"): for key in ("keywords", "frameworks", "platforms"):
if key not in manifest or \ if key not in manifest or \
not isinstance(manifest[key], util.string_types): not isinstance(manifest[key], string_types):
continue continue
manifest[key] = [ manifest[key] = [
i.strip() for i in manifest[key].split(",") if i.strip() i.strip() for i in manifest[key].split(",") if i.strip()
@ -147,7 +148,7 @@ class LibraryManager(BasePkgManager):
continue continue
if item[k] == "*": if item[k] == "*":
del item[k] del item[k]
elif isinstance(item[k], util.string_types): elif isinstance(item[k], string_types):
item[k] = [ item[k] = [
i.strip() for i in item[k].split(",") if i.strip() i.strip() for i in item[k].split(",") if i.strip()
] ]

View File

@ -588,9 +588,8 @@ class PkgInstallerMixin(object):
if "__src_url" in cur_manifest: if "__src_url" in cur_manifest:
target_dirname = "%s@src-%s" % ( target_dirname = "%s@src-%s" % (
pkg_dirname, pkg_dirname,
hashlib.md5(cur_manifest['__src_url'] if util. hashlib.md5(
PY2 else cur_manifest['__src_url'].encode( cur_manifest['__src_url'].encode()).hexdigest())
)).hexdigest())
shutil.move(pkg_dir, join(self.package_dir, target_dirname)) shutil.move(pkg_dir, join(self.package_dir, target_dirname))
# fix to a version # fix to a version
elif action == 2: elif action == 2:
@ -599,9 +598,8 @@ class PkgInstallerMixin(object):
if "__src_url" in tmp_manifest: if "__src_url" in tmp_manifest:
target_dirname = "%s@src-%s" % ( target_dirname = "%s@src-%s" % (
pkg_dirname, pkg_dirname,
hashlib.md5(tmp_manifest['__src_url'] if util. hashlib.md5(
PY2 else tmp_manifest['__src_url'].encode( tmp_manifest['__src_url'].encode()).hexdigest())
)).hexdigest())
pkg_dir = join(self.package_dir, target_dirname) pkg_dir = join(self.package_dir, target_dirname)
# remove previous/not-satisfied package # remove previous/not-satisfied package

View File

@ -23,6 +23,7 @@ import click
import semantic_version import semantic_version
from platformio import __version__, app, exception, util from platformio import __version__, app, exception, util
from platformio.compat import PY2
from platformio.managers.core import get_core_package_dir from platformio.managers.core import get_core_package_dir
from platformio.managers.package import BasePkgManager, PackageManager from platformio.managers.package import BasePkgManager, PackageManager
from platformio.project.helpers import get_projectboards_dir from platformio.project.helpers import get_projectboards_dir
@ -389,7 +390,7 @@ class PlatformRunMixin(object):
# encode and append variables # encode and append variables
for key, value in variables.items(): for key, value in variables.items():
if util.PY2: if PY2:
cmd.append("%s=%s" % (key.upper(), base64.b64encode(value))) cmd.append("%s=%s" % (key.upper(), base64.b64encode(value)))
else: else:
cmd.append( cmd.append(

View File

@ -13,16 +13,14 @@
# limitations under the License. # limitations under the License.
import os import os
import sys
from hashlib import sha1 from hashlib import sha1
from os import walk from os import walk
from os.path import abspath, dirname, expanduser, isdir, isfile, join from os.path import abspath, dirname, expanduser, isdir, isfile, join
from platformio import __version__ from platformio import __version__
from platformio.compat import PY2, WINDOWS
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
PY2 = sys.version_info[0] == 2
def get_project_dir(): def get_project_dir():
return os.getcwd() return os.getcwd()
@ -132,7 +130,7 @@ def calculate_project_hash():
if path.endswith(check_suffixes): if path.endswith(check_suffixes):
chunks.append(path) chunks.append(path)
chunks_to_str = ",".join(sorted(chunks)) chunks_to_str = ",".join(sorted(chunks))
if sys.platform == "win32": if WINDOWS:
# Fix issue with useless project rebuilding for case insensitive FS. # Fix issue with useless project rebuilding for case insensitive FS.
# A case of disk drive can differ... # A case of disk drive can differ...
chunks_to_str = chunks_to_str.lower() chunks_to_str = chunks_to_str.lower()

View File

@ -32,19 +32,15 @@ import click
import requests import requests
from platformio import __apiurl__, __version__, exception 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.config import ProjectConfig
from platformio.project.helpers import ( # pylint: disable=unused-import from platformio.project.helpers import ( # pylint: disable=unused-import
get_project_dir, get_project_optional_dir, get_projectboards_dir, get_project_dir, get_project_optional_dir, get_projectboards_dir,
get_projectbuild_dir, get_projectdata_dir, get_projectlib_dir, get_projectbuild_dir, get_projectdata_dir, get_projectlib_dir,
get_projectsrc_dir, get_projecttest_dir, is_platformio_project) get_projectsrc_dir, get_projecttest_dir, is_platformio_project)
# FIXME: check platformio.project.helpers imports # FIXME: remove import of path_to_unicode
PY2 = sys.version_info[0] == 2
if PY2:
string_types = basestring # pylint: disable=undefined-variable
else:
string_types = str
class AsyncPipe(Thread): class AsyncPipe(Thread):
@ -148,12 +144,6 @@ def singleton(cls):
return get_instance 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): def load_json(file_path):
try: try:
with open(file_path, "r") as f: with open(file_path, "r") as f:
@ -180,7 +170,7 @@ def get_home_dir():
home_dir = get_project_optional_dir("home_dir", home_dir = get_project_optional_dir("home_dir",
join(expanduser("~"), ".platformio")) join(expanduser("~"), ".platformio"))
win_home_dir = None win_home_dir = None
if "windows" in get_systype(): if WINDOWS:
win_home_dir = splitdrive(home_dir)[0] + "\\.platformio" win_home_dir = splitdrive(home_dir)[0] + "\\.platformio"
if isdir(win_home_dir): if isdir(win_home_dir):
home_dir = 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) _PYTHONPATH = os.environ.get("PYTHONPATH").split(os.pathsep)
for p in os.sys.path: for p in os.sys.path:
conditions = [p not in _PYTHONPATH] conditions = [p not in _PYTHONPATH]
if "windows" not in get_systype(): if not WINDOWS:
conditions.append( conditions.append(
isdir(join(p, "click")) or isdir(join(p, "platformio"))) isdir(join(p, "click")) or isdir(join(p, "platformio")))
if all(conditions): if all(conditions):
@ -299,14 +289,12 @@ def get_serial_ports(filter_hwid=False):
for p, d, h in comports(): for p, d, h in comports():
if not p: if not p:
continue continue
if "windows" in get_systype(): if WINDOWS and PY2:
if PY2: try:
try: # pylint: disable=undefined-variable
d = unicode( # pylint: disable=undefined-variable d = unicode(d, errors="ignore")
d, except TypeError:
errors="ignore") pass
except TypeError:
pass
if not filter_hwid or "VID:PID" in h: if not filter_hwid or "VID:PID" in h:
result.append({"port": p, "description": d, "hwid": h}) result.append({"port": p, "description": d, "hwid": h})
@ -326,7 +314,7 @@ get_serialports = get_serial_ports
def get_logical_devices(): def get_logical_devices():
items = [] items = []
if "windows" in get_systype(): if WINDOWS:
try: try:
result = exec_command( result = exec_command(
["wmic", "logicaldisk", "get", "name,VolumeName"]).get( ["wmic", "logicaldisk", "get", "name,VolumeName"]).get(
@ -586,9 +574,8 @@ def where_is_program(program, envpath=None):
# try OS's built-in commands # try OS's built-in commands
try: try:
result = exec_command( result = exec_command(["where" if WINDOWS else "which", program],
["where" if "windows" in get_systype() else "which", program], env=env)
env=env)
if result['returncode'] == 0 and isfile(result['out'].strip()): if result['returncode'] == 0 and isfile(result['out'].strip()):
return result['out'].strip() return result['out'].strip()
except OSError: except OSError: