28
28
#~autogen
29
29
30
30
import os
31
- import os .path
32
31
import fnmatch
33
32
import numbers
34
33
import platform
35
34
import fcntl
36
35
import array
37
36
import mmap
38
37
import ctypes
38
+ from os .path import abspath
39
39
from PIL import Image , ImageDraw
40
40
from struct import pack , unpack
41
41
@@ -50,6 +50,54 @@ def current_platform():
50
50
else :
51
51
return 'unsupported'
52
52
53
+ #------------------------------------------------------------------------------
54
+ # Attribute reader/writer with cached file access
55
+ class FileCache (object ):
56
+ def __init__ (self ):
57
+ self ._cache = {}
58
+
59
+ def file_handle ( self , path , mode , reopen = False ):
60
+ """Manages the file handle cache and opening the files in the correct mode"""
61
+
62
+ if path not in self ._cache :
63
+ f = open ( path , mode )
64
+ self ._cache [path ] = f
65
+ elif reopen == True :
66
+ self ._cache [path ].close ()
67
+ f = open ( path , mode )
68
+ self ._cache [path ] = f
69
+ else :
70
+ f = self ._cache [path ]
71
+ f .seek (0 )
72
+
73
+ return f
74
+
75
+ def read (self , path , size = None ):
76
+ f = self .file_handle (path , 'r' )
77
+
78
+ try :
79
+ value = f .read (size )
80
+ except IOError :
81
+ f = self .file_handle ( path , 'w+' , reopen = True )
82
+ value = f .read (size )
83
+
84
+ if size is None :
85
+ return value .strip ()
86
+ else :
87
+ return value
88
+
89
+ def write (self , path , value ):
90
+ f = self .file_handle ( path , 'w' )
91
+
92
+ try :
93
+ f .write ( value )
94
+ f .flush ()
95
+ except IOError :
96
+ f = self .file_handle ( path , 'w+' , reopen = True )
97
+ f .write ( value )
98
+ f .flush ()
99
+
100
+
53
101
#------------------------------------------------------------------------------
54
102
# Define the base class from which all other ev3dev classes are defined.
55
103
@@ -80,12 +128,12 @@ def __init__(self, class_name, name='*', **kwargs ):
80
128
When connected succesfully, the `connected` attribute is set to True.
81
129
"""
82
130
83
- classpath = os . path . abspath ( Device .DEVICE_ROOT_PATH + '/' + class_name )
84
- self .filehandle_cache = {}
131
+ classpath = abspath ( Device .DEVICE_ROOT_PATH + '/' + class_name )
132
+ self ._attribute_cache = FileCache ()
85
133
86
134
for file in os .listdir ( classpath ):
87
135
if fnmatch .fnmatch (file , name ):
88
- self ._path = os . path . abspath ( classpath + '/' + file )
136
+ self ._path = abspath ( classpath + '/' + file )
89
137
90
138
# See if requested attributes match:
91
139
if all ([self ._matches (k , kwargs [k ]) for k in kwargs ]):
@@ -106,44 +154,13 @@ def _matches(self, attribute, pattern):
106
154
else :
107
155
return value .find (pattern ) >= 0
108
156
109
- def _attribute_file ( self , attribute , mode , reopen = False ):
110
- """Manages the file handle cache and opening the files in the correct mode"""
111
-
112
- attribute_name = os .path .abspath ( self ._path + '/' + attribute )
113
-
114
- if attribute_name not in self .filehandle_cache :
115
- f = open ( attribute_name , mode )
116
- self .filehandle_cache [attribute_name ] = f
117
- elif reopen == True :
118
- self .filehandle_cache [attribute_name ].close ()
119
- f = open ( attribute_name , mode )
120
- self .filehandle_cache [attribute_name ] = f
121
- else :
122
- f = self .filehandle_cache [attribute_name ]
123
- return f
124
-
125
- def _get_attribute ( self , attribute ):
157
+ def _get_attribute ( self , attribute , size = None ):
126
158
"""Device attribute getter"""
127
- f = self ._attribute_file ( attribute , 'r' )
128
- try :
129
- f .seek (0 )
130
- value = f .read ()
131
- except IOError :
132
- f = self ._attribute_file ( attribute , 'w+' , True )
133
- value = f .read ()
134
- return value .strip ()
159
+ return self ._attribute_cache .read (abspath (self ._path + '/' + attribute ), size )
135
160
136
161
def _set_attribute ( self , attribute , value ):
137
162
"""Device attribute setter"""
138
- f = self ._attribute_file ( attribute , 'w' )
139
- try :
140
- f .seek (0 )
141
- f .write ( value )
142
- f .flush ()
143
- except IOError :
144
- f = self ._attribute_file ( attribute , 'w+' , True )
145
- f .write ( value )
146
- f .flush ()
163
+ self ._attribute_cache .write ( abspath (self ._path + '/' + attribute ), value )
147
164
148
165
def get_attr_int ( self , attribute ):
149
166
return int ( self ._get_attribute ( attribute ) )
@@ -1271,9 +1288,7 @@ def bin_data(self, fmt=None):
1271
1288
"float" : 4
1272
1289
}.get (self .bin_data_format , 1 ) * self .num_values
1273
1290
1274
- f = self ._attribute_file ('bin_data' , 'rb' )
1275
- f .seek (0 )
1276
- raw = bytearray (f .read (self ._bin_data_size ))
1291
+ raw = bytearray (self ._get_attribute ('bin_data' , self ._bin_data_size ))
1277
1292
1278
1293
if fmt is None : return raw
1279
1294
@@ -1822,19 +1837,14 @@ class Button(ButtonBase):
1822
1837
EVIOCGKEY = (2 << (14 + 8 + 8 ) | KEY_BUF_LEN << (8 + 8 ) | ord ('E' ) << 8 | 0x18 )
1823
1838
1824
1839
def __init__ (self ):
1825
- self .buffer_cache = {}
1826
- self .filehandle_cache = {}
1840
+ self ._file_cache = FileCache ()
1841
+ self ._buffer_cache = {}
1827
1842
for b in self ._buttons :
1828
1843
self ._button_file ( self ._buttons [b ]['name' ] )
1829
1844
self ._button_buffer ( self ._buttons [b ]['name' ] )
1830
1845
1831
1846
def _button_file (self , name ):
1832
- if name not in self .filehandle_cache :
1833
- f = open ( name , 'r' )
1834
- self .filehandle_cache [name ] = f
1835
- else :
1836
- f = self .filehandle_cache [name ]
1837
- return f
1847
+ return self ._file_cache .file_handle (name , 'r' )
1838
1848
1839
1849
def _button_buffer (self , name ):
1840
1850
if name not in self .buffer_cache :
@@ -1844,7 +1854,7 @@ def _button_buffer(self, name):
1844
1854
@property
1845
1855
def buttons_pressed (self ):
1846
1856
for b in self .buffer_cache :
1847
- fcntl .ioctl (self .filehandle_cache [ b ] , self .EVIOCGKEY , self .buffer_cache [b ])
1857
+ fcntl .ioctl (self ._button_file ( b ) , self .EVIOCGKEY , self .buffer_cache [b ])
1848
1858
1849
1859
pressed = []
1850
1860
for k ,v in self ._buttons .items ():
0 commit comments