1 # -*- coding: utf-8 -*- |
1 # -*- coding: utf-8 -*- |
2 |
2 |
3 # Copyright (c) 2013 Tobias Rzepka <tobias.rzepka@gmail.com> |
3 # Copyright (c) 2013 - 2013 Tobias Rzepka <tobias.rzepka@gmail.com> |
4 # |
4 # |
5 |
5 |
6 """ |
6 """ |
7 Module implementing the open behavior of Python3 for use with Eric5. |
7 Module implementing the open behavior of Python3 for use with Eric5. |
8 The from Eric5 used features are emulated only. The not emulated features |
8 The Eric5 used features are emulated only. The not emulated features |
9 should throw a NotImplementedError exception. |
9 should throw a NotImplementedError exception. |
10 """ |
10 """ |
11 |
11 |
12 from __future__ import unicode_literals # __IGNORE_WARNING__ |
12 from __future__ import unicode_literals # __IGNORE_WARNING__ |
13 |
13 |
14 import __builtin__ |
14 import __builtin__ |
15 import codecs |
15 import codecs |
16 |
16 |
17 |
17 |
18 def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): |
18 def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): |
|
19 """ |
|
20 Replacement for the build in open function. |
|
21 |
|
22 @param file filename or file descriptor (string) |
|
23 @keyparam mode access mode (string) |
|
24 @keyparam buffering size of the read buffer (string) |
|
25 @keyparam encoding character encoding for reading/ writing (string) |
|
26 @keyparam errors behavior for the character encoding ('strict', 'explicit', ...) (string) |
|
27 @keyparam newline controls how universal newlines works (string) |
|
28 @keyparam closefd close underlying file descriptor if given as file parameter (boolean) |
|
29 """ |
19 return File(file, mode, buffering, encoding, errors, newline, closefd) |
30 return File(file, mode, buffering, encoding, errors, newline, closefd) |
20 |
31 |
21 |
32 |
22 class File(file): |
33 class File(file): #__IGNORE_WARNING__ |
|
34 """ |
|
35 Facade for the original file class. |
|
36 """ |
23 def __init__(self, filein, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): |
37 def __init__(self, filein, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): |
|
38 """ |
|
39 Constructor, checks for unimplemented parameters. |
|
40 |
|
41 @param filein filename or file descriptor (string) |
|
42 @keyparam mode access mode (string) |
|
43 @keyparam buffering size of the read buffer (string) |
|
44 @keyparam encoding character encoding for reading/ writing (string) |
|
45 @keyparam errors behavior for the character encoding ('strict', 'explicit', ...) (string) |
|
46 @keyparam newline controls how universal newlines works (string) |
|
47 @keyparam closefd close underlying file descriptor if given as file parameter (boolean) |
|
48 """ |
24 self.__encoding = encoding |
49 self.__encoding = encoding |
25 self.__newline = newline |
50 self.__newline = newline |
26 self.__closefd = closefd |
51 self.__closefd = closefd |
27 if newline is not None: |
52 if newline is not None: |
28 if 'r' in mode: |
53 if 'r' in mode: |
29 raise NotImplementedError |
54 raise NotImplementedError |
30 else: |
55 else: |
31 mode = mode.replace('t', 'b') |
56 mode = mode.replace('t', 'b') |
|
57 if 'b' not in mode: |
|
58 mode = mode + 'b' |
32 |
59 |
33 if closefd == False: |
60 if closefd == False: |
34 raise NotImplementedError |
61 raise NotImplementedError |
35 |
62 |
36 if errors is None: |
63 if errors is None: |
37 self.__errors = 'strict' |
64 self.__errors = 'strict' |
38 else: |
65 else: |
39 self.__errors = errors |
66 self.__errors = errors |
40 |
67 |
41 file.__init__(self, filein, mode, buffering) |
68 file.__init__(self, filein, mode, buffering) |
42 |
69 |
43 def read(self, n=-1): |
70 def read(self, n=-1): |
|
71 """ |
|
72 Read n bytes or all if n=-1 from file. |
|
73 |
|
74 @keyparam n bytecount or all if n=-1 (int) |
|
75 @return decoded bytes read |
|
76 """ |
44 txt = super(File, self).read(n) |
77 txt = super(File, self).read(n) |
45 if self.__encoding is None: |
78 if self.__encoding is None: |
46 return txt |
79 return txt |
47 else: |
80 else: |
48 return codecs.decode(txt, self.__encoding) |
81 return codecs.decode(txt, self.__encoding) |
49 |
82 |
50 def readline(self, limit=-1): |
83 def readline(self, limit=-1): |
|
84 """ |
|
85 Read one line from file. |
|
86 |
|
87 @keyparam limit maximum bytes to read or all if limit=-1 (int) |
|
88 @return decoded line read |
|
89 """ |
51 txt = super(File, self).readline(limit) |
90 txt = super(File, self).readline(limit) |
52 if self.__encoding is None: |
91 if self.__encoding is None: |
53 return txt |
92 return txt |
54 else: |
93 else: |
55 return codecs.decode(txt, self.__encoding) |
94 return codecs.decode(txt, self.__encoding) |
56 |
95 |
57 def readlines(self, hint=-1): |
96 def readlines(self, hint=-1): |
|
97 """ |
|
98 Read all lines from file. |
|
99 |
|
100 @keyparam hint maximum bytes to read or all if hint=-1 (int) |
|
101 @return decoded lines read |
|
102 """ |
58 if self.__encoding is None: |
103 if self.__encoding is None: |
59 return super(File, self).readlines(hint) |
104 return super(File, self).readlines(hint) |
60 else: |
105 else: |
61 return [codecs.decode(txt, self.__encoding) for txt in super(File, self).readlines(hint)] |
106 return [codecs.decode(txt, self.__encoding) for txt in super(File, self).readlines(hint)] |
62 |
107 |
63 def write(self, txt): |
108 def write(self, txt): |
|
109 """ |
|
110 Write given data to file. Encode if needed. |
|
111 |
|
112 @param txt data to write. (str, bytes) |
|
113 """ |
64 if self.__encoding is not None: |
114 if self.__encoding is not None: |
65 txt = codecs.encode(txt, self.__encoding, self.__errors) |
115 txt = codecs.encode(txt, self.__encoding, self.__errors) |
66 |
116 |
67 if self.__newline in ['\r\n', '\r']: |
117 if self.__newline in ['\r\n', '\r']: |
68 txt = txt.replace('\n', self.__newline) |
118 txt = txt.replace('\n', self.__newline) |
|
119 |
|
120 super(File, self).write(txt) |
|
121 |
|
122 def next(self): |
|
123 """ |
|
124 Method if used in a iterator. |
69 |
125 |
70 super(File, self).write(txt) |
126 @return decoded data read |
71 |
127 """ |
72 def next(self): |
|
73 txt = super(File, self).next() |
128 txt = super(File, self).next() |
74 if self.__encoding is None: |
129 if self.__encoding is None: |
75 return txt |
130 return txt |
76 else: |
131 else: |
77 return codecs.decode(txt, self.__encoding) |
132 return codecs.decode(txt, self.__encoding) |
78 |
133 |
79 |
134 # Inject into the __builtin__ dictionary |
80 __builtin__.open = open |
135 __builtin__.open = open |
81 |
136 |
82 if __name__ == '__main__': |
137 if __name__ == '__main__': |
83 fp = open('compatibility_fixes.py', encoding='latin1') |
138 fp = open('compatibility_fixes.py', encoding='latin1') |
84 print(fp.read()) |
139 print(fp.read()) |
85 fp.close() |
140 fp.close() |
86 |
141 |
87 with open('compatibility_fixes.py', encoding='UTF-8') as fp: |
142 with open('compatibility_fixes.py', encoding='UTF-8') as fp: |
88 rlines = fp.readlines() |
143 rlines = fp.readlines() |
89 print(rlines[-1]) |
144 print(rlines[-1]) |