|
1 | 1 | from abc import ABC, abstractmethod
|
| 2 | +import getpass |
2 | 3 | import sys, os, pickle, hashlib
|
3 | 4 | import tempfile
|
4 | 5 | import types
|
@@ -308,28 +309,38 @@ def __init__(self, grammar: 'Union[Grammar, str, IO[str]]', **options) -> None:
|
308 | 309 | if self.options.cache is not True:
|
309 | 310 | raise ConfigurationError("cache argument must be bool or str")
|
310 | 311 |
|
311 |
| - cache_fn = tempfile.gettempdir() + '/.lark_cache_%s_%s_%s.tmp' % (cache_md5, *sys.version_info[:2]) |
312 |
| - |
313 |
| - if FS.exists(cache_fn): |
314 |
| - logger.debug('Loading grammar from cache: %s', cache_fn) |
315 |
| - # Remove options that aren't relevant for loading from cache |
316 |
| - for name in (set(options) - _LOAD_ALLOWED_OPTIONS): |
317 |
| - del options[name] |
| 312 | + try: |
| 313 | + username = getpass.getuser() |
| 314 | + except Exception: |
| 315 | + # The exception raised may be ImportError or OSError in |
| 316 | + # the future. For the cache, we don't care about the |
| 317 | + # specific reason - we just want a username. |
| 318 | + username = "unknown" |
| 319 | + |
| 320 | + cache_fn = tempfile.gettempdir() + "/.lark_cache_%s_%s_%s_%s.tmp" % (username, cache_md5, *sys.version_info[:2]) |
| 321 | + |
| 322 | + old_options = self.options |
| 323 | + try: |
318 | 324 | with FS.open(cache_fn, 'rb') as f:
|
319 |
| - old_options = self.options |
320 |
| - try: |
321 |
| - file_md5 = f.readline().rstrip(b'\n') |
322 |
| - cached_used_files = pickle.load(f) |
323 |
| - if file_md5 == cache_md5.encode('utf8') and verify_used_files(cached_used_files): |
324 |
| - cached_parser_data = pickle.load(f) |
325 |
| - self._load(cached_parser_data, **options) |
326 |
| - return |
327 |
| - except Exception: # We should probably narrow done which errors we catch here. |
328 |
| - logger.exception("Failed to load Lark from cache: %r. We will try to carry on." % cache_fn) |
329 |
| - |
330 |
| - # In theory, the Lark instance might have been messed up by the call to `_load`. |
331 |
| - # In practice the only relevant thing that might have been overriden should be `options` |
332 |
| - self.options = old_options |
| 325 | + logger.debug('Loading grammar from cache: %s', cache_fn) |
| 326 | + # Remove options that aren't relevant for loading from cache |
| 327 | + for name in (set(options) - _LOAD_ALLOWED_OPTIONS): |
| 328 | + del options[name] |
| 329 | + file_md5 = f.readline().rstrip(b'\n') |
| 330 | + cached_used_files = pickle.load(f) |
| 331 | + if file_md5 == cache_md5.encode('utf8') and verify_used_files(cached_used_files): |
| 332 | + cached_parser_data = pickle.load(f) |
| 333 | + self._load(cached_parser_data, **options) |
| 334 | + return |
| 335 | + except FileNotFoundError: |
| 336 | + # The cache file doesn't exist; parse and compose the grammar as normal |
| 337 | + pass |
| 338 | + except Exception: # We should probably narrow done which errors we catch here. |
| 339 | + logger.exception("Failed to load Lark from cache: %r. We will try to carry on.", cache_fn) |
| 340 | + |
| 341 | + # In theory, the Lark instance might have been messed up by the call to `_load`. |
| 342 | + # In practice the only relevant thing that might have been overwritten should be `options` |
| 343 | + self.options = old_options |
333 | 344 |
|
334 | 345 |
|
335 | 346 | # Parse the grammar file and compose the grammars
|
@@ -421,11 +432,14 @@ def __init__(self, grammar: 'Union[Grammar, str, IO[str]]', **options) -> None:
|
421 | 432 |
|
422 | 433 | if cache_fn:
|
423 | 434 | logger.debug('Saving grammar to cache: %s', cache_fn)
|
424 |
| - with FS.open(cache_fn, 'wb') as f: |
425 |
| - assert cache_md5 is not None |
426 |
| - f.write(cache_md5.encode('utf8') + b'\n') |
427 |
| - pickle.dump(used_files, f) |
428 |
| - self.save(f, _LOAD_ALLOWED_OPTIONS) |
| 435 | + try: |
| 436 | + with FS.open(cache_fn, 'wb') as f: |
| 437 | + assert cache_md5 is not None |
| 438 | + f.write(cache_md5.encode('utf8') + b'\n') |
| 439 | + pickle.dump(used_files, f) |
| 440 | + self.save(f, _LOAD_ALLOWED_OPTIONS) |
| 441 | + except IOError as e: |
| 442 | + logger.exception("Failed to save Lark to cache: %r.", cache_fn, e) |
429 | 443 |
|
430 | 444 | if __doc__:
|
431 | 445 | __doc__ += "\n\n" + LarkOptions.OPTIONS_DOC
|
|
0 commit comments