Browse Source

Added support for atomicwrites

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.11.3
MegaIng1 4 years ago
parent
commit
704e7552bd
4 changed files with 34 additions and 6 deletions
  1. +2
    -0
      lark-stubs/lark.pyi
  2. +18
    -4
      lark/lark.py
  3. +12
    -1
      lark/utils.py
  4. +2
    -1
      setup.py

+ 2
- 0
lark-stubs/lark.pyi View File

@@ -38,6 +38,7 @@ class LarkOptions:
use_bytes: bool use_bytes: bool
import_paths: List[Union[str, Callable[[Union[None, str, PackageResource], str], Tuple[str, str]]]] import_paths: List[Union[str, Callable[[Union[None, str, PackageResource], str], Tuple[str, str]]]]
source_path: Optional[str] source_path: Optional[str]
safe_cache: Literal[False, True, "atomic"]




class PackageResource(object): class PackageResource(object):
@@ -81,6 +82,7 @@ class Lark:
use_bytes: bool = False, use_bytes: bool = False,
import_paths: List[Union[str, Callable[[Union[None, str, PackageResource], str], Tuple[str, str]]]] = ..., import_paths: List[Union[str, Callable[[Union[None, str, PackageResource], str], Tuple[str, str]]]] = ...,
source_path: Optional[str]=None, source_path: Optional[str]=None,
safe_cache: Literal[False, True, "atomic"]=True,
): ):
... ...




+ 18
- 4
lark/lark.py View File

@@ -23,6 +23,11 @@ try:
import regex import regex
except ImportError: except ImportError:
regex = None regex = None
try:
import atomicwrites
except ImportError:
atomicwrites = None



###{standalone ###{standalone


@@ -100,7 +105,11 @@ class LarkOptions(Serialize):
A List of either paths or loader functions to specify from where grammars are imported A List of either paths or loader functions to specify from where grammars are imported
source_path source_path
Override the source of from where the grammar was loaded. Useful for relative imports and unconventional grammar loading Override the source of from where the grammar was loaded. Useful for relative imports and unconventional grammar loading

safe_cache
Controls how exactly the cache is saved & verified
- False: simple read/write, no extend file checking
- True: use atomicwrites if available and check if any of the imported files were modified
- "atomic": same as True, but require atomicwrites to be installed
**=== End Options ===** **=== End Options ===**
""" """
if __doc__: if __doc__:
@@ -136,6 +145,7 @@ class LarkOptions(Serialize):
'use_bytes': False, 'use_bytes': False,
'import_paths': [], 'import_paths': [],
'source_path': None, 'source_path': None,
'safe_cache': True,
} }


def __init__(self, options_dict): def __init__(self, options_dict):
@@ -145,7 +155,7 @@ class LarkOptions(Serialize):
for name, default in self._defaults.items(): for name, default in self._defaults.items():
if name in o: if name in o:
value = o.pop(name) value = o.pop(name)
if isinstance(default, bool) and name not in ('cache', 'use_bytes'):
if isinstance(default, bool) and name not in ('cache', 'use_bytes', 'safe_cache'):
value = bool(value) value = bool(value)
else: else:
value = default value = default
@@ -258,11 +268,15 @@ class Lark(Serialize):
if self.options.cache: if self.options.cache:
if self.options.parser != 'lalr': if self.options.parser != 'lalr':
raise ConfigurationError("cache only works with parser='lalr' for now") raise ConfigurationError("cache only works with parser='lalr' for now")
if self.options.safe_cache == "atomic":
if not atomicwrites:
raise ConfigurationError("safe_cache='atomic' requires atomicwrites to be installed")


unhashable = ('transformer', 'postlex', 'lexer_callbacks', 'edit_terminals') unhashable = ('transformer', 'postlex', 'lexer_callbacks', 'edit_terminals')
options_str = ''.join(k+str(v) for k, v in options.items() if k not in unhashable) options_str = ''.join(k+str(v) for k, v in options.items() if k not in unhashable)
from . import __version__ from . import __version__
s = grammar + options_str + __version__
s = grammar + options_str + __version__ + str(sys.version_info[:2])
cache_md5 = hashlib.md5(s.encode()).hexdigest() cache_md5 = hashlib.md5(s.encode()).hexdigest()


if isinstance(self.options.cache, STRING_TYPE): if isinstance(self.options.cache, STRING_TYPE):
@@ -270,7 +284,7 @@ class Lark(Serialize):
else: else:
if self.options.cache is not True: if self.options.cache is not True:
raise ConfigurationError("cache argument must be bool or str") raise ConfigurationError("cache argument must be bool or str")
cache_fn = tempfile.gettempdir() + '/.lark_cache_%s.tmp' % cache_md5
cache_fn = tempfile.gettempdir() + '/.lark_cache_%s_%s_%s.tmp' % (cache_md5, *sys.version_info[:2])


if FS.exists(cache_fn): if FS.exists(cache_fn):
logger.debug('Loading grammar from cache: %s', cache_fn) logger.debug('Loading grammar from cache: %s', cache_fn)


+ 12
- 1
lark/utils.py View File

@@ -281,9 +281,20 @@ def combine_alternatives(lists):
return reduce(lambda a,b: [i+[j] for i in a for j in b], lists[1:], init) return reduce(lambda a,b: [i+[j] for i in a for j in b], lists[1:], init)




try:
import atomicwrites
except ImportError:
atomicwrites = None

class FS: class FS:
open = open
exists = os.path.exists exists = os.path.exists
@staticmethod
def open(name, mode="r", **kwargs):
if atomicwrites and "w" in mode:
return atomicwrites.atomic_write(name, mode=mode, override=True, **kwargs)
else:
return open(name, mode, **kwargs)




def isascii(s): def isascii(s):


+ 2
- 1
setup.py View File

@@ -16,7 +16,8 @@ setup(


extras_require = { extras_require = {
"regex": ["regex"], "regex": ["regex"],
"nearley": ["js2py"]
"nearley": ["js2py"],
"atomicwrites": ["atomicwrites"],
}, },


package_data = {'': ['*.md', '*.lark'], 'lark-stubs': ['*.pyi']}, package_data = {'': ['*.md', '*.lark'], 'lark-stubs': ['*.pyi']},


Loading…
Cancel
Save