From 981413268c610c611a872941a01962d3265d9f91 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 20 Dec 2019 14:41:04 +0800 Subject: [PATCH] Minimal change to support python3 --- .travis.yml | 8 ++++---- moulinette/actionsmap.py | 8 ++++---- moulinette/authenticators/__init__.py | 4 ++-- moulinette/core.py | 9 +++------ moulinette/interfaces/__init__.py | 2 +- moulinette/interfaces/cli.py | 10 +++++----- moulinette/utils/filesystem.py | 16 ++++++++-------- moulinette/utils/network.py | 2 +- moulinette/utils/stream.py | 2 +- moulinette/utils/text.py | 4 ++-- setup.py | 2 +- test/conftest.py | 4 ++-- test/test_filesystem.py | 6 +++--- test/test_text.py | 2 +- tox.ini | 4 ++-- 15 files changed, 40 insertions(+), 43 deletions(-) diff --git a/.travis.yml b/.travis.yml index fde3108c..a322499c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,13 +8,13 @@ addons: matrix: include: - - python: 2.7 - env: TOXENV=py27 - - python: 2.7 + - python: 3.5 + env: TOXENV=py35 + - python: 3.5 env: TOXENV=lint - python: 3.6 env: TOXENV=format-check - - python: 2.7 + - python: 3.5 env: TOXENV=docs install: diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 11f7e2be..46d86465 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -4,7 +4,7 @@ import os import re import logging import yaml -import cPickle as pickle +import pickle as pickle from time import time from collections import OrderedDict from importlib import import_module @@ -188,7 +188,7 @@ class PatternParameter(_ExtraParameter): # Use temporarly utf-8 encoded value try: - v = unicode(arg_value, "utf-8") + v = str(arg_value, "utf-8") except: v = arg_value @@ -442,7 +442,7 @@ class ActionsMap(object): if use_cache and os.path.exists(actionsmap_pkl): try: # Attempt to load cache - with open(actionsmap_pkl) as f: + with open(actionsmap_pkl, "rb") as f: actionsmaps[n] = pickle.load(f) # TODO: Switch to python3 and catch proper exception except (IOError, EOFError): @@ -647,7 +647,7 @@ class ActionsMap(object): pkl = "%s-%d-%d.pkl" % (n, am_file_stat.st_size, am_file_stat.st_mtime) - with open_cachefile(pkl, "w", subdir="actionsmap") as f: + with open_cachefile(pkl, "wb", subdir="actionsmap") as f: pickle.dump(actionsmaps[n], f) return actionsmaps diff --git a/moulinette/authenticators/__init__.py b/moulinette/authenticators/__init__.py index 3a78b7e6..a6e51fe2 100644 --- a/moulinette/authenticators/__init__.py +++ b/moulinette/authenticators/__init__.py @@ -163,7 +163,7 @@ class BaseAuthenticator(object): """Store a session to be able to use it later to reauthenticate""" # We store a hash of the session_id and the session_token (the token is assumed to be secret) - to_hash = "{id}:{token}".format(id=session_id, token=session_token) + to_hash = "{id}:{token}".format(id=session_id, token=session_token).encode() hash_ = hashlib.sha256(to_hash).hexdigest() with self._open_sessionfile(session_id, "w") as f: f.write(hash_) @@ -196,7 +196,7 @@ class BaseAuthenticator(object): # re-hash the {id}:{token} and compare it to the previously stored hash for this session_id ... # It it matches, then the user is authenticated. Otherwise, the token is invalid. # - to_hash = "{id}:{token}".format(id=session_id, token=session_token) + to_hash = "{id}:{token}".format(id=session_id, token=session_token).encode() hash_ = hashlib.sha256(to_hash).hexdigest() if not hmac.compare_digest(hash_, stored_hash): diff --git a/moulinette/core.py b/moulinette/core.py index d3a2299c..dd53ed60 100644 --- a/moulinette/core.py +++ b/moulinette/core.py @@ -100,13 +100,10 @@ class Translator(object): try: return ( self._translations[self.locale][key] - .encode("utf-8") .format(*args, **kwargs) ) except KeyError as e: - unformatted_string = self._translations[self.locale][key].encode( - "utf-8" - ) + unformatted_string = self._translations[self.locale][key] error_message = ( "Failed to format translated string '%s': '%s' with arguments '%s' and '%s, raising error: %s(%s) (don't panic this is just a warning)" % (key, unformatted_string, args, kwargs, e.__class__.__name__, e) @@ -176,8 +173,8 @@ class Translator(object): return True try: - with open("%s/%s.json" % (self.locale_dir, locale), "r") as f: - j = json.load(f, "utf-8") + with open("%s/%s.json" % (self.locale_dir, locale), "r", encoding='utf-8') as f: + j = json.load(f) except IOError: return False else: diff --git a/moulinette/interfaces/__init__.py b/moulinette/interfaces/__init__.py index 4f2e33dd..2fbfe84a 100644 --- a/moulinette/interfaces/__init__.py +++ b/moulinette/interfaces/__init__.py @@ -475,7 +475,7 @@ class ExtendedArgumentParser(argparse.ArgumentParser): def dequeue_callbacks(self, namespace): queue = self._get_callbacks_queue(namespace, False) - for _i in xrange(len(queue)): + for _i in range(len(queue)): c, v = queue.popleft() # FIXME: break dequeue if callback returns c.execute(namespace, v) diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 804028bc..d83270d0 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -91,7 +91,7 @@ def plain_print_dict(d, depth=0): print("{}{}".format("#" * (depth + 1), k)) plain_print_dict(v, depth + 1) else: - if isinstance(d, unicode): + if isinstance(d, str): d = d.encode("utf-8") print(d) @@ -155,13 +155,13 @@ def pretty_print_dict(d, depth=0): elif isinstance(value, dict): pretty_print_dict({key: value}, depth + 1) else: - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode("utf-8") elif isinstance(v, date): v = pretty_date(v) print("{:s}- {}".format(" " * (depth + 1), value)) else: - if isinstance(v, unicode): + if isinstance(v, str): v = v.encode("utf-8") elif isinstance(v, date): v = pretty_date(v) @@ -507,7 +507,7 @@ class Interface(BaseInterface): if is_password: prompt = lambda m: getpass.getpass(colorize(m18n.g("colon", m), color)) else: - prompt = lambda m: raw_input(colorize(m18n.g("colon", m), color)) + prompt = lambda m: input(colorize(m18n.g("colon", m), color)) value = prompt(message) if confirm: @@ -523,7 +523,7 @@ class Interface(BaseInterface): Handle the core.MoulinetteSignals.display signal. """ - if isinstance(message, unicode): + if isinstance(message, str): message = message.encode("utf-8") if style == "success": print("{} {}".format(colorize(m18n.g("success"), "green"), message)) diff --git a/moulinette/utils/filesystem.py b/moulinette/utils/filesystem.py index b7580b2c..f453e7b6 100644 --- a/moulinette/utils/filesystem.py +++ b/moulinette/utils/filesystem.py @@ -22,7 +22,7 @@ def read_file(file_path): Keyword argument: file_path -- Path to the text file """ - assert isinstance(file_path, basestring), ( + assert isinstance(file_path, str), ( "Error: file_path '%s' should be a string but is of type '%s' instead" % (file_path, type(file_path)) ) @@ -151,7 +151,7 @@ def write_to_file(file_path, data, file_mode="w"): file_mode -- Mode used when writing the file. Option meant to be used by append_to_file to avoid duplicating the code of this function. """ - assert isinstance(data, basestring) or isinstance(data, list), ( + assert isinstance(data, str) or isinstance(data, list), ( "Error: data '%s' should be either a string or a list but is of type '%s'" % (data, type(data)) ) @@ -164,9 +164,9 @@ def write_to_file(file_path, data, file_mode="w"): ) # If data is a list, check elements are strings and build a single string - if not isinstance(data, basestring): + if not isinstance(data, str): for element in data: - assert isinstance(element, basestring), ( + assert isinstance(element, str), ( "Error: element '%s' should be a string but is of type '%s' instead" % (element, type(element)) ) @@ -203,7 +203,7 @@ def write_to_json(file_path, data): """ # Assumptions - assert isinstance(file_path, basestring), ( + assert isinstance(file_path, str), ( "Error: file_path '%s' should be a string but is of type '%s' instead" % (file_path, type(file_path)) ) @@ -238,7 +238,7 @@ def write_to_yaml(file_path, data): data -- The data to write (must be a dict or a list) """ # Assumptions - assert isinstance(file_path, basestring) + assert isinstance(file_path, str) assert isinstance(data, dict) or isinstance(data, list) assert not os.path.isdir(file_path) assert os.path.isdir(os.path.dirname(file_path)) @@ -313,14 +313,14 @@ def chown(path, uid=None, gid=None, recursive=False): raise ValueError("either uid or gid argument is required") # Retrieve uid/gid - if isinstance(uid, basestring): + if isinstance(uid, str): try: uid = getpwnam(uid).pw_uid except KeyError: raise MoulinetteError("unknown_user", user=uid) elif uid is None: uid = -1 - if isinstance(gid, basestring): + if isinstance(gid, str): try: gid = grp.getgrnam(gid).gr_gid except KeyError: diff --git a/moulinette/utils/network.py b/moulinette/utils/network.py index bddad986..8f6e60f0 100644 --- a/moulinette/utils/network.py +++ b/moulinette/utils/network.py @@ -59,6 +59,6 @@ def download_json(url, timeout=30, expected_status_code=200): try: loaded_json = json.loads(text) except ValueError as e: - raise MoulinetteError("corrupted_json", ressource=url, error=e) + raise MoulinetteError("corrupted_json", ressource=url, error=str(e)) return loaded_json diff --git a/moulinette/utils/stream.py b/moulinette/utils/stream.py index b7fb3eb8..652565ac 100644 --- a/moulinette/utils/stream.py +++ b/moulinette/utils/stream.py @@ -1,7 +1,7 @@ import os import time -from multiprocessing.process import Process +from multiprocessing.process import BaseProcess as Process from multiprocessing.queues import SimpleQueue diff --git a/moulinette/utils/text.py b/moulinette/utils/text.py index e2b2936f..77aba762 100644 --- a/moulinette/utils/text.py +++ b/moulinette/utils/text.py @@ -47,9 +47,9 @@ def searchf(pattern, path, count=0, flags=re.MULTILINE): content by using the search function. """ - with open(path, "r+") as f: + with open(path, "rb+") as f: data = mmap.mmap(f.fileno(), 0) - match = search(pattern, data, count, flags) + match = search(pattern, data.read().decode(), count, flags) data.close() return match diff --git a/setup.py b/setup.py index b8d8024f..99611e3f 100755 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ setup(name='Moulinette', license='AGPL', packages=find_packages(exclude=['test']), data_files=[(LOCALES_DIR, locale_files)], - python_requires='==2.7.*', + python_requires='>=3.5', install_requires=[ 'argcomplete', 'psutil', diff --git a/test/conftest.py b/test/conftest.py index 6df66806..3d1079fe 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -165,7 +165,7 @@ def moulinette_cli(moulinette, mocker): def test_file(tmp_path): test_text = "foo\nbar\n" test_file = tmp_path / "test.txt" - test_file.write_bytes(test_text) + test_file.write_bytes(test_text.encode()) return test_file @@ -173,7 +173,7 @@ def test_file(tmp_path): def test_json(tmp_path): test_json = json.dumps({"foo": "bar"}) test_file = tmp_path / "test.json" - test_file.write_bytes(test_json) + test_file.write_bytes(test_json.encode()) return test_file diff --git a/test/test_filesystem.py b/test/test_filesystem.py index fcfa832b..0974e837 100644 --- a/test/test_filesystem.py +++ b/test/test_filesystem.py @@ -42,7 +42,7 @@ def test_read_file_missing_file(): def test_read_file_cannot_read_ioerror(test_file, mocker): error = "foobar" - mocker.patch("__builtin__.open", side_effect=IOError(error)) + mocker.patch("builtins.open", side_effect=IOError(error)) with pytest.raises(MoulinetteError) as exception: read_file(str(test_file)) @@ -174,7 +174,7 @@ def test_write_to_new_file(tmp_path): def test_write_to_existing_file_bad_perms(test_file, mocker): error = "foobar" - mocker.patch("__builtin__.open", side_effect=IOError(error)) + mocker.patch("builtins.open", side_effect=IOError(error)) with pytest.raises(MoulinetteError) as exception: write_to_file(str(test_file), "yolo\nswag") @@ -279,7 +279,7 @@ def text_write_list_to_json(tmp_path): def test_write_to_json_bad_perms(test_json, mocker): error = "foobar" - mocker.patch("__builtin__.open", side_effect=IOError(error)) + mocker.patch("builtins.open", side_effect=IOError(error)) with pytest.raises(MoulinetteError) as exception: write_to_json(str(test_json), {"a": 1}) diff --git a/test/test_text.py b/test/test_text.py index a734b9cf..1bf1f896 100644 --- a/test/test_text.py +++ b/test/test_text.py @@ -19,4 +19,4 @@ def test_prependlines(): def test_random_ascii(): - assert isinstance(random_ascii(length=2), unicode) + assert isinstance(random_ascii(length=2), str) diff --git a/tox.ini b/tox.ini index d71b31b5..aceb7a25 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] -envlist = - py27 +envlist = + py35 lint docs skipdist = True