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,58 @@ 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 __del__ (self ):
60
+ for f in self ._cache .values ():
61
+ f .close ()
62
+
63
+ def file_handle ( self , path , mode , reopen = False ):
64
+ """Manages the file handle cache and opening the files in the correct mode"""
65
+
66
+ if path not in self ._cache :
67
+ f = open ( path , mode )
68
+ self ._cache [path ] = f
69
+ elif reopen == True :
70
+ self ._cache [path ].close ()
71
+ f = open ( path , mode )
72
+ self ._cache [path ] = f
73
+ else :
74
+ f = self ._cache [path ]
75
+ f .seek (0 )
76
+
77
+ return f
78
+
79
+ def read (self , path , size = - 1 ):
80
+ f = self .file_handle (path , 'r' )
81
+
82
+ try :
83
+ value = f .read (size )
84
+ except IOError :
85
+ f = self .file_handle ( path , 'w+' , reopen = True )
86
+ value = f .read (size )
87
+
88
+ if size < 0 :
89
+ return value .strip ()
90
+ else :
91
+ return value
92
+
93
+ def write (self , path , value ):
94
+ f = self .file_handle ( path , 'w' )
95
+
96
+ try :
97
+ f .write ( value )
98
+ f .flush ()
99
+ except IOError :
100
+ f = self .file_handle ( path , 'w+' , reopen = True )
101
+ f .write ( value )
102
+ f .flush ()
103
+
104
+
53
105
#------------------------------------------------------------------------------
54
106
# Define the base class from which all other ev3dev classes are defined.
55
107
@@ -80,12 +132,12 @@ def __init__(self, class_name, name='*', **kwargs ):
80
132
When connected succesfully, the `connected` attribute is set to True.
81
133
"""
82
134
83
- classpath = os . path . abspath ( Device .DEVICE_ROOT_PATH + '/' + class_name )
84
- self .filehandle_cache = {}
135
+ classpath = abspath ( Device .DEVICE_ROOT_PATH + '/' + class_name )
136
+ self ._attribute_cache = FileCache ()
85
137
86
138
for file in os .listdir ( classpath ):
87
139
if fnmatch .fnmatch (file , name ):
88
- self ._path = os . path . abspath ( classpath + '/' + file )
140
+ self ._path = abspath ( classpath + '/' + file )
89
141
90
142
# See if requested attributes match:
91
143
if all ([self ._matches (k , kwargs [k ]) for k in kwargs ]):
@@ -106,44 +158,13 @@ def _matches(self, attribute, pattern):
106
158
else :
107
159
return value .find (pattern ) >= 0
108
160
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 ):
161
+ def _get_attribute ( self , attribute , size = - 1 ):
126
162
"""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 ()
163
+ return self ._attribute_cache .read (abspath (self ._path + '/' + attribute ), size )
135
164
136
165
def _set_attribute ( self , attribute , value ):
137
166
"""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 ()
167
+ self ._attribute_cache .write ( abspath (self ._path + '/' + attribute ), value )
147
168
148
169
def get_attr_int ( self , attribute ):
149
170
return int ( self ._get_attribute ( attribute ) )
@@ -1271,9 +1292,7 @@ def bin_data(self, fmt=None):
1271
1292
"float" : 4
1272
1293
}.get (self .bin_data_format , 1 ) * self .num_values
1273
1294
1274
- f = self ._attribute_file ('bin_data' , 'rb' )
1275
- f .seek (0 )
1276
- raw = bytearray (f .read (self ._bin_data_size ))
1295
+ raw = bytearray (self ._get_attribute ('bin_data' , self ._bin_data_size ))
1277
1296
1278
1297
if fmt is None : return raw
1279
1298
@@ -1822,19 +1841,14 @@ class Button(ButtonBase):
1822
1841
EVIOCGKEY = (2 << (14 + 8 + 8 ) | KEY_BUF_LEN << (8 + 8 ) | ord ('E' ) << 8 | 0x18 )
1823
1842
1824
1843
def __init__ (self ):
1825
- self .buffer_cache = {}
1826
- self .filehandle_cache = {}
1844
+ self ._file_cache = FileCache ()
1845
+ self ._buffer_cache = {}
1827
1846
for b in self ._buttons :
1828
1847
self ._button_file ( self ._buttons [b ]['name' ] )
1829
1848
self ._button_buffer ( self ._buttons [b ]['name' ] )
1830
1849
1831
1850
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
1851
+ return self ._file_cache .file_handle (name , 'r' )
1838
1852
1839
1853
def _button_buffer (self , name ):
1840
1854
if name not in self .buffer_cache :
@@ -1844,7 +1858,7 @@ def _button_buffer(self, name):
1844
1858
@property
1845
1859
def buttons_pressed (self ):
1846
1860
for b in self .buffer_cache :
1847
- fcntl .ioctl (self .filehandle_cache [ b ] , self .EVIOCGKEY , self .buffer_cache [b ])
1861
+ fcntl .ioctl (self ._button_file ( b ) , self .EVIOCGKEY , self .buffer_cache [b ])
1848
1862
1849
1863
pressed = []
1850
1864
for k ,v in self ._buttons .items ():
0 commit comments