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