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 59848c3115
commit d2449762c2
17 changed files with 98 additions and 67 deletions

View File

@ -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

View File

@ -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

View File

@ -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

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 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"

View File

@ -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

View File

@ -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)

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 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"]

View File

@ -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(
"""
-----------------

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 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):

View File

@ -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)

View File

@ -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
@ -126,7 +127,7 @@ def inject_contrib_pysite():
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"

View File

@ -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()
]

View File

@ -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

View File

@ -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(

View File

@ -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()

View File

@ -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(
@ -583,9 +571,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: