Improve compatibility with hashlib Py2/Py3

This commit is contained in:
Ivan Kravets
2019-06-03 13:30:35 +03:00
parent ac3236693f
commit e269c91d26
11 changed files with 68 additions and 45 deletions

View File

@ -25,7 +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 from platformio.compat import WINDOWS, hashlib_encode_data
from platformio.proc import is_ci from platformio.proc import is_ci
from platformio.project.helpers import (get_project_cache_dir, from platformio.project.helpers import (get_project_cache_dir,
get_project_core_dir) get_project_core_dir)
@ -174,10 +174,8 @@ class ContentCache(object):
def key_from_args(*args): def key_from_args(*args):
h = hashlib.md5() h = hashlib.md5()
for arg in args: for arg in args:
if not arg: if arg:
continue h.update(hashlib_encode_data(arg))
arg = str(arg)
h.update(arg if PY2 else arg.encode())
return h.hexdigest() return h.hexdigest()
def get(self, key): def get(self, key):
@ -363,7 +361,7 @@ def get_cid():
pass pass
if not uid: if not uid:
uid = uuid.getnode() uid = uuid.getnode()
cid = uuid.UUID(bytes=hashlib.md5(str(uid).encode()).digest()) cid = uuid.UUID(bytes=hashlib.md5(hashlib_encode_data(uid)).digest())
cid = str(cid) cid = str(cid)
if WINDOWS 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) set_state_item("cid", cid)

View File

@ -12,7 +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.
import base64
import json import json
import sys import sys
from os import environ from os import environ
@ -31,6 +30,7 @@ from SCons.Script import Variables # pylint: disable=import-error
from platformio import util from platformio import util
from platformio.compat import PY2, path_to_unicode from platformio.compat import PY2, path_to_unicode
from platformio.managers.platform import PlatformBase
from platformio.proc import get_pythonexe_path from platformio.proc import get_pythonexe_path
from platformio.project import helpers as project_helpers from platformio.project import helpers as project_helpers
@ -91,11 +91,11 @@ if not int(ARGUMENTS.get("PIOVERBOSE", 0)):
env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS) env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS)
# Load variables from CLI # Load variables from CLI
for key in list(clivars.keys()): env.Replace(
if key in env: **{
env[key] = base64.b64decode(env[key]) key: PlatformBase.decode_scons_arg(env[key])
if isinstance(env[key], bytes): for key in list(clivars.keys()) if key in env
env[key] = env[key].decode() })
if env.GetOption('clean'): if env.GetOption('clean'):
env.PioClean(env.subst("$BUILD_DIR")) env.PioClean(env.subst("$BUILD_DIR"))

View File

@ -32,7 +32,8 @@ 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, get_file_contents, string_types from platformio.compat import (WINDOWS, get_file_contents, hashlib_encode_data,
string_types)
from platformio.managers.lib import LibraryManager from platformio.managers.lib import LibraryManager
@ -181,8 +182,7 @@ class LibBuilderBase(object):
@property @property
def build_dir(self): def build_dir(self):
lib_hash = hashlib.sha1( lib_hash = hashlib.sha1(hashlib_encode_data(self.path)).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

@ -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.compat import PY2, WINDOWS from platformio.compat import WINDOWS, hashlib_encode_data
# 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
@ -61,9 +61,8 @@ def _file_long_data(env, data):
build_dir = env.subst("$BUILD_DIR") build_dir = env.subst("$BUILD_DIR")
if not isdir(build_dir): if not isdir(build_dir):
makedirs(build_dir) makedirs(build_dir)
tmp_file = join( tmp_file = join(build_dir,
build_dir, "longcmd-%s" % md5(hashlib_encode_data(data)).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:

View File

@ -29,7 +29,7 @@ from platformio import app, exception, util
from platformio.commands.debug import helpers, initcfgs from platformio.commands.debug import helpers, initcfgs
from platformio.commands.debug.process import BaseProcess from platformio.commands.debug.process import BaseProcess
from platformio.commands.debug.server import DebugServer from platformio.commands.debug.server import DebugServer
from platformio.compat import PY2 from platformio.compat import hashlib_encode_data
from platformio.project.helpers import get_project_cache_dir from platformio.project.helpers import get_project_cache_dir
from platformio.telemetry import MeasurementProtocol from platformio.telemetry import MeasurementProtocol
@ -61,8 +61,7 @@ class GDBClient(BaseProcess): # pylint: disable=too-many-instance-attributes
def spawn(self, gdb_path, prog_path): def spawn(self, gdb_path, prog_path):
session_hash = gdb_path + prog_path session_hash = gdb_path + prog_path
self._session_id = sha1( self._session_id = sha1(hashlib_encode_data(session_hash)).hexdigest()
session_hash if PY2 else session_hash.encode()).hexdigest()
self._kill_previous_session() self._kill_previous_session()
patterns = { patterns = {

View File

@ -35,12 +35,21 @@ if PY2:
return isinstance(x, (buffer, bytearray)) return isinstance(x, (buffer, bytearray))
def path_to_unicode(path): def path_to_unicode(path):
if isinstance(path, unicode):
return path
return path.decode(get_filesystem_encoding()).encode("utf-8") return path.decode(get_filesystem_encoding()).encode("utf-8")
def get_file_contents(path): def get_file_contents(path):
with open(path) as f: with open(path) as f:
return f.read() return f.read()
def hashlib_encode_data(data):
if is_bytes(data):
return data
if not isinstance(data, string_types):
data = str(data)
return data
_magic_check = re.compile('([*?[])') _magic_check = re.compile('([*?[])')
_magic_check_bytes = re.compile(b'([*?[])') _magic_check_bytes = re.compile(b'([*?[])')
@ -74,3 +83,10 @@ else:
except UnicodeDecodeError: except UnicodeDecodeError:
with open(path, encoding="latin-1") as f: with open(path, encoding="latin-1") as f:
return f.read() return f.read()
def hashlib_encode_data(data):
if is_bytes(data):
return data
if not isinstance(data, string_types):
data = str(data)
return data.encode()

View File

@ -26,7 +26,7 @@ import requests
import semantic_version import semantic_version
from platformio import __version__, app, exception, telemetry, util from platformio import __version__, app, exception, telemetry, util
from platformio.compat import path_to_unicode from platformio.compat import hashlib_encode_data, path_to_unicode
from platformio.downloader import FileDownloader from platformio.downloader import FileDownloader
from platformio.lockfile import LockFile from platformio.lockfile import LockFile
from platformio.unpacker import FileUnpacker from platformio.unpacker import FileUnpacker
@ -173,7 +173,7 @@ class PkgInstallerMixin(object):
cache_key_data = app.ContentCache.key_from_args(url, "data") cache_key_data = app.ContentCache.key_from_args(url, "data")
if self.FILE_CACHE_VALID: if self.FILE_CACHE_VALID:
with app.ContentCache() as cc: with app.ContentCache() as cc:
fname = cc.get(cache_key_fname) fname = str(cc.get(cache_key_fname))
cache_path = cc.get_cache_path(cache_key_data) cache_path = cc.get_cache_path(cache_key_data)
if fname and isfile(cache_path): if fname and isfile(cache_path):
dst_path = join(dest_dir, fname) dst_path = join(dest_dir, fname)
@ -591,7 +591,8 @@ class PkgInstallerMixin(object):
target_dirname = "%s@src-%s" % ( target_dirname = "%s@src-%s" % (
pkg_dirname, pkg_dirname,
hashlib.md5( hashlib.md5(
cur_manifest['__src_url'].encode()).hexdigest()) hashlib_encode_data(
cur_manifest['__src_url'])).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:
@ -601,7 +602,8 @@ class PkgInstallerMixin(object):
target_dirname = "%s@src-%s" % ( target_dirname = "%s@src-%s" % (
pkg_dirname, pkg_dirname,
hashlib.md5( hashlib.md5(
tmp_manifest['__src_url'].encode()).hexdigest()) hashlib_encode_data(
tmp_manifest['__src_url'])).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

@ -24,7 +24,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.compat import get_filesystem_encoding, string_types
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.proc import (BuildAsyncPipe, copy_pythonpath_to_osenv, from platformio.proc import (BuildAsyncPipe, copy_pythonpath_to_osenv,
@ -359,6 +359,17 @@ class PlatformRunMixin(object):
LINE_ERROR_RE = re.compile(r"(^|\s+)error:?\s+", re.I) LINE_ERROR_RE = re.compile(r"(^|\s+)error:?\s+", re.I)
@staticmethod
def encode_scons_arg(value):
if isinstance(value, string_types):
value = value.encode(get_filesystem_encoding())
return base64.urlsafe_b64encode(value).decode()
@staticmethod
def decode_scons_arg(value):
return base64.urlsafe_b64decode(value).decode(
get_filesystem_encoding())
def run(self, variables, targets, silent, verbose): def run(self, variables, targets, silent, verbose):
assert isinstance(variables, dict) assert isinstance(variables, dict)
assert isinstance(targets, list) assert isinstance(targets, list)
@ -402,12 +413,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 PY2: cmd.append("%s=%s" % (key.upper(), self.encode_scons_arg(value)))
cmd.append("%s=%s" % (key.upper(), base64.b64encode(value)))
else:
cmd.append(
"%s=%s" %
(key.upper(), base64.b64encode(value.encode()).decode()))
def _write_and_flush(stream, data): def _write_and_flush(stream, data):
stream.write(data) stream.write(data)

View File

@ -19,7 +19,7 @@ from os.path import isdir, isfile, join, normpath
from threading import Thread from threading import Thread
from platformio import exception from platformio import exception
from platformio.compat import PY2, WINDOWS, string_types from platformio.compat import WINDOWS, get_filesystem_encoding, string_types
class AsyncPipeBase(object): class AsyncPipeBase(object):
@ -123,8 +123,8 @@ def exec_command(*args, **kwargs):
result[s[3:]] = kwargs[s].get_buffer() result[s[3:]] = kwargs[s].get_buffer()
for k, v in result.items(): for k, v in result.items():
if not PY2 and isinstance(result[k], bytes): if isinstance(result[k], bytes):
result[k] = result[k].decode() result[k] = result[k].decode(get_filesystem_encoding())
if v and isinstance(v, string_types): if v and isinstance(v, string_types):
result[k] = result[k].strip() result[k] = result[k].strip()

View File

@ -19,7 +19,7 @@ from os.path import (basename, dirname, expanduser, isdir, isfile, join,
realpath, splitdrive) realpath, splitdrive)
from platformio import __version__ from platformio import __version__
from platformio.compat import PY2, WINDOWS from platformio.compat import WINDOWS, hashlib_encode_data
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
@ -54,9 +54,8 @@ def get_project_optional_dir(name, default=None):
if "$PROJECT_HASH" in optional_dir: if "$PROJECT_HASH" in optional_dir:
optional_dir = optional_dir.replace( optional_dir = optional_dir.replace(
"$PROJECT_HASH", "%s-%s" % "$PROJECT_HASH", "%s-%s" %
(basename(project_dir), (basename(project_dir), sha1(
sha1(project_dir if PY2 else project_dir.encode()).hexdigest() hashlib_encode_data(project_dir)).hexdigest()[:10]))
[:10]))
if optional_dir.startswith("~"): if optional_dir.startswith("~"):
optional_dir = expanduser(optional_dir) optional_dir = expanduser(optional_dir)
@ -179,4 +178,4 @@ def calculate_project_hash():
# 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()
return sha1(chunks_to_str if PY2 else chunks_to_str.encode()).hexdigest() return sha1(hashlib_encode_data(chunks_to_str)).hexdigest()

View File

@ -28,6 +28,7 @@ import requests
from platformio import __version__, app, exception, util from platformio import __version__, app, exception, util
from platformio.commands import PlatformioCLI from platformio.commands import PlatformioCLI
from platformio.compat import string_types
from platformio.proc import is_ci, is_container from platformio.proc import is_ci, is_container
try: try:
@ -135,12 +136,15 @@ class MeasurementProtocol(TelemetryBase):
return _arg return _arg
return None return None
args = [ args = []
str(arg).lower() for arg in PlatformioCLI.leftover_args for arg in PlatformioCLI.leftover_args:
if not str(arg).startswith("-") if not isinstance(arg, string_types):
] arg = str(arg)
if not arg.startswith("-"):
args.append(arg.lower())
if not args: if not args:
return return
cmd_path = args[:1] cmd_path = args[:1]
if args[0] in ("platform", "platforms", "serialports", "device", if args[0] in ("platform", "platforms", "serialports", "device",
"settings", "account"): "settings", "account"):