eric6/Globals/compatibility_fixes.py

changeset 6942
2602857055c5
parent 5587
ea526b78ee6c
diff -r f99d60d6b59b -r 2602857055c5 eric6/Globals/compatibility_fixes.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Globals/compatibility_fixes.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,289 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013 - 2015 Tobias Rzepka <tobias.rzepka@gmail.com>
+#
+
+"""
+Module implementing some workarounds to let eric6 run under Python 2.
+"""
+
+
+import __builtin__      # __IGNORE_EXCEPTION__
+import codecs
+import imp
+import locale
+import os
+import sys
+
+# convert all command line arguments to unicode
+sys.argv = [arg.decode(locale.getpreferredencoding()) for arg in sys.argv]
+
+"""
+Improvement for the os.path.join function because the original join doesn't
+use the correct encoding.
+"""
+# Save original function for use in joinAsUnicode
+__join = os.path.join
+# Flag to disable unicode conversion of join function
+os.path.join_unicode = True
+
+
+def joinAsUnicode(*args):
+    """
+    Convert none unicode parameter of the os.path.join into unicode.
+    
+    @param args paths which should be joined (str, unicode)
+    @return unicode str of the path (unicode)
+    """
+    if os.path.join_unicode:
+        convArgs = []
+        for arg in args:
+            if isinstance(arg, str):
+                arg = arg.decode(locale.getpreferredencoding(), 'replace')
+            convArgs.append(arg)
+        return __join(*convArgs)
+    else:
+        return __join(*args)
+
+# Replace os.path.join with unicode aware version
+os.path.join = joinAsUnicode
+
+"""
+Improvement for the imp.load_source and imp.find_module functions because the
+originals doesn't use the correct encoding.
+"""
+# Save original function for use in load_sourceAsStr and find_moduleAsStr
+__load_source = imp.load_source
+__find_module = imp.find_module
+
+
+def load_sourceAsStr(*args):
+    """
+    Convert none str parameter of the imp.load_source into str.
+    
+    @param args  (str, unicode)
+    @return list of args converted to str (list)
+    """
+    convArgs = []
+    for arg in args:
+        if isinstance(arg, unicode):
+            arg = arg.encode(sys.getfilesystemencoding(), 'strict')
+        convArgs.append(arg)
+    return __load_source(*convArgs)
+
+
+def find_moduleAsStr(*args):
+    """
+    Convert none str parameter of the imp.find_module into str.
+    
+    @param args  (str, unicode)
+    @return list of args converted to str (list)
+    """
+    convArgs = []
+    for arg in args:
+        if isinstance(arg, unicode):
+            arg = arg.encode(sys.getfilesystemencoding(), 'strict')
+        convArgs.append(arg)
+    return __find_module(*convArgs)
+    
+# Replace imp.load_source and imp.find_module with unicode aware version
+imp.load_source = load_sourceAsStr
+imp.find_module = find_moduleAsStr
+
+"""
+Improvement for the sys.path list because some other functions doesn't expect
+unicode in the sys.path list.
+"""
+
+
+class PlainStrList(list):
+    """
+    Keep track that all added paths to sys.path are str.
+    """
+    def __init__(self, *args):
+        """
+        Constructor
+        
+        @param args list of paths to start with (list)
+        """
+        super(PlainStrList, self).__init__()
+        self.extend(list(args))
+
+    def __convert(self, element):
+        """
+        Private method to convert unicode to file system encoding.
+        
+        @param element to convert from unicode to file system encoding (any)
+        @return converted element
+        """
+        if isinstance(element, unicode):
+            # Throw exception if it can't be converted, otherwise exception
+            # could occur somewhere else
+            element = element.encode(sys.getfilesystemencoding(), 'strict')
+        return element
+
+    def __setitem__(self, idx, value):
+        """
+        Special method to overwrite a specific list item.
+        
+        @param idx index of the item (int)
+        @param value the new value (any)
+        """
+        super(PlainStrList, self).__setitem__(idx, self.__convert(value))
+
+    def insert(self, idx, value):
+        """
+        Public method to insert a specific list item.
+        
+        @param idx index of the item (int)
+        @param value the new value (any)
+        """
+        super(PlainStrList, self).insert(idx, self.__convert(value))
+
+
+# insert a conversion function from unicode to str at sys.path access
+sys.path = PlainStrList(*sys.path)
+
+"""
+The open function and File class simulates the open behaviour of Python3.
+
+The Eric6 used features are emulated only. The not emulated features
+should throw a NotImplementedError exception.
+"""
+
+
+def open(filein, mode='r', buffering=-1, encoding=None,
+         errors=None, newline=None, closefd=True):
+    """
+    Replacement for the build in open function.
+    
+    @param filein filename or file descriptor (string)
+    @keyparam mode access mode (string)
+    @keyparam buffering size of the read buffer (string)
+    @keyparam encoding character encoding for reading/ writing (string)
+    @keyparam errors behavior for the character encoding ('strict',
+        'explicit', ...) (string)
+    @keyparam newline controls how universal newlines works (string)
+    @keyparam closefd close underlying file descriptor if given as file
+        parameter (boolean)
+    @return Returns the new file object
+    """
+    return File(filein, mode, buffering, encoding, errors, newline, closefd)
+
+
+class File(file):   # __IGNORE_WARNING__
+    """
+    Facade for the original file class.
+    """
+    def __init__(self, filein, mode='r', buffering=-1,
+                 encoding=None, errors=None, newline=None, closefd=True):
+        """
+        Constructor
+        
+        It checks for unimplemented parameters.
+        
+        @param filein filename or file descriptor (string)
+        @keyparam mode access mode (string)
+        @keyparam buffering size of the read buffer (string)
+        @keyparam encoding character encoding for reading/ writing (string)
+        @keyparam errors behavior for the character encoding ('strict',
+            'explicit', ...) (string)
+        @keyparam newline controls how universal newlines works (string)
+        @keyparam closefd close underlying file descriptor if given as file
+            parameter (boolean)
+        @exception NotImplementedError for not implemented method parameters
+        """
+        self.__encoding = encoding
+        self.__newline = str(newline)
+        self.__closefd = closefd
+        if newline is not None:
+            if 'r' in mode:
+                raise NotImplementedError
+            else:
+                mode = mode.replace('t', 'b')
+                if 'b' not in mode:
+                    mode = mode + 'b'
+
+        if closefd is False:
+            raise NotImplementedError
+
+        if errors is None:
+            self.__errors = 'strict'
+        else:
+            self.__errors = errors
+
+        file.__init__(self, filein, mode, buffering)    # __IGNORE_WARNING__
+
+    def read(self, n=-1):
+        """
+        Public method to read n bytes or all if n=-1 from file.
+        
+        @keyparam n bytecount or all if n=-1 (int)
+        @return decoded bytes read
+        """
+        txt = super(File, self).read(n)
+        if self.__encoding is None:
+            return txt
+        else:
+            return codecs.decode(txt, self.__encoding)
+
+    def readline(self, limit=-1):
+        """
+        Public method to read one line from file.
+        
+        @keyparam limit maximum bytes to read or all if limit=-1 (int)
+        @return decoded line read
+        """
+        txt = super(File, self).readline(limit)
+        if self.__encoding is None:
+            return txt
+        else:
+            return codecs.decode(txt, self.__encoding)
+
+    def readlines(self, hint=-1):
+        """
+        Public method to read all lines from file.
+        
+        @keyparam hint maximum bytes to read or all if hint=-1 (int)
+        @return decoded lines read
+        """
+        if self.__encoding is None:
+            return super(File, self).readlines(hint)
+        else:
+            return [codecs.decode(txt, self.__encoding)
+                    for txt in super(File, self).readlines(hint)]
+
+    def write(self, txt):
+        """
+        Public method to write given data to file and encode if needed.
+        
+        @param txt data to write. (str, bytes)
+        """
+        if self.__encoding is not None:
+            txt = codecs.encode(txt, self.__encoding, self.__errors)
+        elif isinstance(txt, unicode):
+            txt = codecs.encode(txt, 'utf-8', self.__errors)
+
+        if self.__newline in ['\r\n', '\r']:
+            txt = txt.replace('\n', self.__newline)
+
+        super(File, self).write(txt)
+
+    def next(self):
+        """
+        Public method used in an iterator.
+        
+        @return decoded data read
+        """
+        txt = super(File, self).next()
+        if self.__encoding is None:
+            return txt
+        else:
+            return codecs.decode(txt, self.__encoding)
+
+# Inject into the __builtin__ dictionary
+__builtin__.open = open
+
+#
+# eflag: FileType = Python2
+# eflag: noqa = M702

eric ide

mercurial