17
17
"Base source file parser"
18
18
19
19
import abc
20
+ import os
20
21
import os .path as p
21
22
import logging
22
23
import re
23
24
import time
25
+ from contextlib import contextmanager
24
26
25
27
from hdlcc .utils import getFileType , removeDuplicates
26
28
@@ -49,10 +51,7 @@ def __init__(self, filename, library='work', flags=None):
49
51
self ._content = None
50
52
self ._mtime = 0
51
53
self .filetype = getFileType (self .filename )
52
-
53
- self ._buffer_time = None
54
- self ._buffer_content = None
55
-
54
+ self ._prev = None
56
55
self .abspath = p .abspath (filename )
57
56
58
57
def getState (self ):
@@ -83,8 +82,7 @@ def recoverFromState(cls, state):
83
82
obj .flags = state ['flags' ]
84
83
obj ._cache = state ['_cache' ]
85
84
obj ._content = None
86
- obj ._buffer_time = None
87
- obj ._buffer_content = None
85
+ obj ._prev = None
88
86
obj ._mtime = state ['_mtime' ]
89
87
obj .filetype = state ['filetype' ]
90
88
# pylint: enable=protected-access
@@ -123,53 +121,89 @@ def _changed(self):
123
121
Checks if the file changed based on the modification time
124
122
provided by p.getmtime
125
123
"""
126
- return self .getmtime () > self ._mtime
124
+ if self .getmtime () > self ._mtime :
125
+ _logger .debug ("File '%s' has changed" , self .filename )
126
+ return True
127
+ return False
127
128
128
129
def _clearCachesIfChanged (self ):
129
130
"""
130
131
Clears all the caches if the file has changed to force updating
131
132
every parsed info
132
133
"""
133
134
if self ._changed ():
134
- self ._content = None
135
+ # Since the content was set by the caller, we can't really clear
136
+ # this unless we're handling with a proper file
137
+ if not self .hasBufferContent (): # pragma: no cover
138
+ self ._content = None
135
139
self ._cache = {}
136
140
137
141
def getmtime (self ):
138
142
"""
139
143
Gets file modification time as defined in p.getmtime
140
144
"""
141
- if self ._buffer_time is not None :
142
- return self . _buffer_time
145
+ if self .hasBufferContent () :
146
+ return 0
143
147
if not p .exists (self .filename ):
144
148
return None
145
149
return p .getmtime (self .filename )
146
150
147
- def setBufferContent (self , content ):
148
- self ._buffer_content = content
149
- self ._buffer_time = time .time ()
151
+ @contextmanager
152
+ def havingBufferContent (self , content ):
153
+ """
154
+ Context manager for handling a source file with a custom content
155
+ that is different from the file it points to. This is intended to
156
+ allow as-you-type checking
157
+ """
158
+ self ._setBufferContent (content )
159
+ yield
160
+ self ._clearBufferContent ()
161
+
162
+ def getDumpPath (self ):
163
+ """
164
+ Returns the dump path in use while inside the havingBufferContent
165
+ context
166
+ """
167
+ return p .join (p .dirname (self .filename ), '.dump_' +
168
+ p .basename (self .filename ))
150
169
151
170
def hasBufferContent (self ):
152
- return self ._buffer_content is not None
171
+ """
172
+ Returns true whenever the source is inside the havingBufferContent
173
+ context
174
+ """
175
+ return self ._prev is not None
153
176
154
- def dumpBufferContentToFile (self ):
155
- buffer_dump_path = p .join (p .dirname (self .filename ), '.dump_' +
156
- p .basename (self .filename ))
157
- open (buffer_dump_path , 'w' ).write (self ._buffer_content )
177
+ def _setBufferContent (self , content ):
178
+ """
179
+ Setup portion of the havingBufferContent context
180
+ """
181
+ _logger .debug ("Setting source content" )
182
+ self ._prev = (self ._mtime , self ._content )
183
+ self ._content = content
184
+ self ._mtime = time .time ()
185
+
186
+ buffer_dump_path = self .getDumpPath ()
187
+ _logger .debug ("Dumping buffer content to '%s'" , buffer_dump_path )
188
+ open (buffer_dump_path , 'w' ).write (self ._content )
158
189
return buffer_dump_path
159
190
160
- def clearBufferContent (self ):
161
- self ._buffer_time = None
162
- self ._buffer_content = None
191
+ def _clearBufferContent (self ):
192
+ """
193
+ Tear down portion of the havingBufferContent context
194
+ """
195
+ _logger .debug ("Clearing buffer content" )
196
+ buffer_dump_path = self .getDumpPath ()
197
+ if p .exists (buffer_dump_path ):
198
+ os .remove (buffer_dump_path )
199
+
200
+ self ._mtime , self ._content = self ._prev
201
+ self ._prev = None
163
202
164
203
def getSourceContent (self ):
165
204
"""
166
205
Cached version of the _getSourceContent method
167
206
"""
168
- if self ._buffer_content is not None :
169
- if self ._changed ():
170
- self ._cache = {}
171
- return self ._buffer_content
172
-
173
207
self ._clearCachesIfChanged ()
174
208
175
209
if self ._content is None :
@@ -185,8 +219,9 @@ def getRawSourceContent(self):
185
219
"""
186
220
self ._clearCachesIfChanged ()
187
221
188
- if self ._buffer_content is not None :
189
- return self ._buffer_content
222
+ if self .hasBufferContent ():
223
+ return self ._content
224
+
190
225
if 'raw_content' not in self ._cache or self ._changed ():
191
226
self ._cache ['raw_content' ] = \
192
227
open (self .filename , mode = 'rb' ).read ().decode (errors = 'ignore' )
0 commit comments