aridity 86__tar.gz → 88__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aridity-86 → aridity-88}/PKG-INFO +1 -1
- aridity-88/aridity/__init__.py +19 -0
- {aridity-86 → aridity-88}/aridity/config.py +4 -5
- {aridity-86 → aridity-88}/aridity/functions.py +2 -0
- {aridity-86 → aridity-88}/aridity/model.py +26 -7
- aridity-88/aridity/processtemplate.py +15 -0
- aridity-88/aridity/repl.py +74 -0
- {aridity-86 → aridity-88}/aridity/scope.py +0 -2
- {aridity-86 → aridity-88}/aridity.egg-info/PKG-INFO +1 -1
- {aridity-86 → aridity-88}/setup.py +1 -1
- aridity-86/aridity/__init__.py +0 -18
- aridity-86/aridity/processtemplate.py +0 -13
- aridity-86/aridity/repl.py +0 -81
- {aridity-86 → aridity-88}/README.md +0 -0
- {aridity-86 → aridity-88}/aridity/arid_config.py +0 -0
- {aridity-86 → aridity-88}/aridity/directives.py +0 -0
- {aridity-86 → aridity-88}/aridity/grammar.py +0 -0
- {aridity-86 → aridity-88}/aridity/keyring.py +0 -0
- {aridity-86 → aridity-88}/aridity/resolve.py +0 -0
- {aridity-86 → aridity-88}/aridity/search.py +0 -0
- {aridity-86 → aridity-88}/aridity/stacks.py +0 -0
- {aridity-86 → aridity-88}/aridity/util.py +0 -0
- {aridity-86 → aridity-88}/aridity.egg-info/SOURCES.txt +0 -0
- {aridity-86 → aridity-88}/aridity.egg-info/dependency_links.txt +0 -0
- {aridity-86 → aridity-88}/aridity.egg-info/entry_points.txt +0 -0
- {aridity-86 → aridity-88}/aridity.egg-info/requires.txt +0 -0
- {aridity-86 → aridity-88}/aridity.egg-info/top_level.txt +0 -0
- {aridity-86 → aridity-88}/parabject.py +0 -0
- {aridity-86 → aridity-88}/setup.cfg +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'Interactive REPL.'
|
|
2
|
+
from .repl import CommandReader
|
|
3
|
+
from .scope import Scope
|
|
4
|
+
from .util import NoSuchPathException
|
|
5
|
+
from traceback import print_exc
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
assert NoSuchPathException
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
scope = Scope()
|
|
12
|
+
for command in CommandReader(sys.stdin):
|
|
13
|
+
try:
|
|
14
|
+
scope.execute(command)
|
|
15
|
+
except:
|
|
16
|
+
print_exc(0)
|
|
17
|
+
|
|
18
|
+
if '__main__' == __name__:
|
|
19
|
+
main()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from .functions import OpaqueKey
|
|
2
2
|
from .model import Entry, Locator, Resource, Stream, Text, wrap
|
|
3
|
-
from .repl import Repl
|
|
4
3
|
from .scope import Scope
|
|
5
4
|
from .search import resolvedscopeornone
|
|
6
5
|
from .util import dotpy, NoSuchPathException, qualname, selectentrypoints, solo
|
|
6
|
+
from io import StringIO
|
|
7
7
|
from parabject import Parabject, register
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
import errno, logging, os, sys
|
|
@@ -34,7 +34,8 @@ def _wrappathorstream(pathorstream):
|
|
|
34
34
|
class ConfigCtrl:
|
|
35
35
|
'High level scope API.'
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
if 'HOME' in os.environ:
|
|
38
|
+
settingsopenable = Locator(Path.home() / '.settings.arid')
|
|
38
39
|
|
|
39
40
|
@classmethod
|
|
40
41
|
def _of(cls, *args, **kwargs):
|
|
@@ -99,9 +100,7 @@ class ConfigCtrl:
|
|
|
99
100
|
|
|
100
101
|
def execute(self, text):
|
|
101
102
|
'Execute given config text.'
|
|
102
|
-
|
|
103
|
-
for line in text.splitlines(True):
|
|
104
|
-
repl(line)
|
|
103
|
+
self.load(StringIO(text))
|
|
105
104
|
|
|
106
105
|
@property
|
|
107
106
|
def scope(self):
|
|
@@ -5,7 +5,8 @@ from importlib.resources import files
|
|
|
5
5
|
from io import TextIOWrapper
|
|
6
6
|
from itertools import chain, islice
|
|
7
7
|
from parabject import dereference, UnknownParabjectException
|
|
8
|
-
import
|
|
8
|
+
from pathlib import PurePath
|
|
9
|
+
import numbers, os, re
|
|
9
10
|
|
|
10
11
|
class Struct:
|
|
11
12
|
|
|
@@ -429,10 +430,8 @@ class Stream(Resolved):
|
|
|
429
430
|
self.streamvalue.flush()
|
|
430
431
|
|
|
431
432
|
def source(self, scope, prefix):
|
|
432
|
-
from .repl import
|
|
433
|
-
|
|
434
|
-
for line in self.streamvalue:
|
|
435
|
-
repl(line)
|
|
433
|
+
from .repl import CommandReader
|
|
434
|
+
CommandReader(self.streamvalue, prefix).pipeto(scope)
|
|
436
435
|
|
|
437
436
|
def processtemplate(self, scope):
|
|
438
437
|
from .grammar import templateparser
|
|
@@ -445,6 +444,10 @@ class Entry(Struct):
|
|
|
445
444
|
def pa(cls, s, l, t):
|
|
446
445
|
return cls(t.asList())
|
|
447
446
|
|
|
447
|
+
@classmethod
|
|
448
|
+
def _of(cls, *args):
|
|
449
|
+
return cls(*args)
|
|
450
|
+
|
|
448
451
|
def __init__(self, resolvables):
|
|
449
452
|
self.resolvables = resolvables
|
|
450
453
|
|
|
@@ -490,8 +493,11 @@ class Entry(Struct):
|
|
|
490
493
|
for r in self.resolvables:
|
|
491
494
|
if not r.ignorable or r.boundary:
|
|
492
495
|
break
|
|
493
|
-
indent.append(r)
|
|
494
|
-
return
|
|
496
|
+
indent.append(r.textvalue)
|
|
497
|
+
return ''.join(indent)
|
|
498
|
+
|
|
499
|
+
def plus(self, that):
|
|
500
|
+
return self._of([*self.resolvables, *that.resolvables])
|
|
495
501
|
|
|
496
502
|
def wrap(value):
|
|
497
503
|
'Attempt to wrap the given value in a model object of the most specific type.'
|
|
@@ -511,3 +517,16 @@ def wrap(value):
|
|
|
511
517
|
if hasattr(value, 'encode'):
|
|
512
518
|
return Text(value)
|
|
513
519
|
return Scalar(value) # XXX: Interpret mappings and sequences?
|
|
520
|
+
|
|
521
|
+
quotablebysquare = re.compile('[$()]+')
|
|
522
|
+
|
|
523
|
+
def quote(obj): # TODO: Duplicates some wrap logic.
|
|
524
|
+
for b in map(bool, range(2)):
|
|
525
|
+
if obj is b:
|
|
526
|
+
return str(b).lower()
|
|
527
|
+
if isinstance(obj, PurePath):
|
|
528
|
+
obj = str(obj)
|
|
529
|
+
try:
|
|
530
|
+
return f"""$.({quotablebysquare.sub(lambda m: f"$'[{m.group()}]", obj)})"""
|
|
531
|
+
except TypeError:
|
|
532
|
+
return obj
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'Process the given template to stdout using config from stdin.'
|
|
2
|
+
from .config import ConfigCtrl
|
|
3
|
+
from argparse import ArgumentParser
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
parser = ArgumentParser()
|
|
8
|
+
parser.add_argument('templatepath')
|
|
9
|
+
args = parser.parse_args()
|
|
10
|
+
cc = ConfigCtrl()
|
|
11
|
+
cc.load(sys.stdin)
|
|
12
|
+
cc.processtemplate(args.templatepath, sys.stdout)
|
|
13
|
+
|
|
14
|
+
if '__main__' == __name__:
|
|
15
|
+
main()
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from .grammar import commandparser
|
|
2
|
+
from .model import Entry
|
|
3
|
+
from pyparsing import ParseException
|
|
4
|
+
|
|
5
|
+
class DanglingStackException(Exception): pass
|
|
6
|
+
|
|
7
|
+
class NoSuchIndentException(Exception): pass
|
|
8
|
+
|
|
9
|
+
class MalformedEntryException(Exception): pass
|
|
10
|
+
|
|
11
|
+
class Suffix:
|
|
12
|
+
|
|
13
|
+
def __init__(self, entry):
|
|
14
|
+
self.indent = entry.indent()
|
|
15
|
+
self.entry = entry
|
|
16
|
+
|
|
17
|
+
def closing(self, contextindent):
|
|
18
|
+
if any(x != y for x, y in zip(self.indent, contextindent)):
|
|
19
|
+
raise MalformedEntryException(self.entry)
|
|
20
|
+
return len(self.indent) <= len(contextindent)
|
|
21
|
+
|
|
22
|
+
class Command:
|
|
23
|
+
|
|
24
|
+
def __init__(self, entry):
|
|
25
|
+
self.size = entry.size()
|
|
26
|
+
self.entry = entry
|
|
27
|
+
|
|
28
|
+
emptyentry = Entry([])
|
|
29
|
+
emptysuffix = Suffix(emptyentry)
|
|
30
|
+
|
|
31
|
+
class CommandReader:
|
|
32
|
+
|
|
33
|
+
def __init__(self, stream, rootprefix = emptyentry):
|
|
34
|
+
self.stack = []
|
|
35
|
+
self.partials = {'': emptyentry}
|
|
36
|
+
self.stream = stream
|
|
37
|
+
self.rootprefix = rootprefix
|
|
38
|
+
for _ in self._update(False, emptysuffix):
|
|
39
|
+
assert False
|
|
40
|
+
|
|
41
|
+
def _readcommands(self, line):
|
|
42
|
+
try:
|
|
43
|
+
suffix = Suffix(commandparser(''.join([*self.stack, line])))
|
|
44
|
+
del self.stack[:]
|
|
45
|
+
except ParseException:
|
|
46
|
+
self.stack.append(line)
|
|
47
|
+
return
|
|
48
|
+
fire = suffix.closing(self.indent)
|
|
49
|
+
if not fire:
|
|
50
|
+
self.partials[suffix.indent] = self.command.entry
|
|
51
|
+
elif suffix.indent not in self.partials:
|
|
52
|
+
raise NoSuchIndentException(suffix.entry)
|
|
53
|
+
for i in list(self.partials):
|
|
54
|
+
if len(suffix.indent) < len(i):
|
|
55
|
+
del self.partials[i]
|
|
56
|
+
yield from self._update(fire, suffix)
|
|
57
|
+
|
|
58
|
+
def _update(self, fire, suffix):
|
|
59
|
+
command = self.rootprefix.plus(self.command.entry) if fire and self.command.size else None
|
|
60
|
+
self.command = Command(self.partials[suffix.indent].plus(suffix.entry))
|
|
61
|
+
self.indent = suffix.indent
|
|
62
|
+
if command is not None:
|
|
63
|
+
yield command
|
|
64
|
+
|
|
65
|
+
def __iter__(self):
|
|
66
|
+
for line in self.stream:
|
|
67
|
+
yield from self._readcommands(line)
|
|
68
|
+
if self.stack:
|
|
69
|
+
raise DanglingStackException(self.stack)
|
|
70
|
+
yield from self._update(True, emptysuffix)
|
|
71
|
+
|
|
72
|
+
def pipeto(self, scope):
|
|
73
|
+
for command in self:
|
|
74
|
+
scope.execute(command)
|
|
@@ -214,8 +214,6 @@ class StaticScope(AbstractScope):
|
|
|
214
214
|
self[word,] = Directive(d)
|
|
215
215
|
for name, f in corefunctions():
|
|
216
216
|
self[name,] = Function(f)
|
|
217
|
-
self['',] = Function(getimpl) # TODO: Refer to the other one.
|
|
218
|
-
self['get',] = Function(getimpl)
|
|
219
217
|
self['keyring_cron',] = Scalar(False)
|
|
220
218
|
self['keyring_force',] = Scalar(False)
|
|
221
219
|
self['~',] = Text(os.path.expanduser('~'))
|
|
@@ -49,7 +49,7 @@ class SourceInfo:
|
|
|
49
49
|
sourceinfo = SourceInfo('.')
|
|
50
50
|
setup(
|
|
51
51
|
name = 'aridity',
|
|
52
|
-
version = '
|
|
52
|
+
version = '88',
|
|
53
53
|
description = 'DRY config and template system, easily extensible with Python',
|
|
54
54
|
url = 'https://pypi.org/project/aridity/',
|
|
55
55
|
author = 'foyono',
|
aridity-86/aridity/__init__.py
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
'Interactive REPL.'
|
|
2
|
-
from .model import Stream
|
|
3
|
-
from .repl import Repl
|
|
4
|
-
from .scope import Scope
|
|
5
|
-
from .util import NoSuchPathException
|
|
6
|
-
import sys
|
|
7
|
-
|
|
8
|
-
assert NoSuchPathException
|
|
9
|
-
|
|
10
|
-
def main():
|
|
11
|
-
scope = Scope()
|
|
12
|
-
scope['stdout',] = Stream(sys.stdout)
|
|
13
|
-
with Repl(scope, True) as repl:
|
|
14
|
-
for line in sys.stdin:
|
|
15
|
-
repl(line)
|
|
16
|
-
|
|
17
|
-
if '__main__' == __name__:
|
|
18
|
-
main()
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'Process the given template to stdout using config from stdin.'
|
|
2
|
-
from .repl import Repl
|
|
3
|
-
import os, sys
|
|
4
|
-
|
|
5
|
-
def main():
|
|
6
|
-
templatepath, = sys.argv[1:]
|
|
7
|
-
with Repl() as repl:
|
|
8
|
-
for line in sys.stdin:
|
|
9
|
-
repl(line)
|
|
10
|
-
repl.printf("< %s", os.path.abspath(templatepath))
|
|
11
|
-
|
|
12
|
-
if '__main__' == __name__:
|
|
13
|
-
main()
|
aridity-86/aridity/repl.py
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
from .grammar import commandparser
|
|
2
|
-
from .model import Entry, Text
|
|
3
|
-
from .scope import Scope
|
|
4
|
-
from pathlib import PurePath
|
|
5
|
-
import pyparsing, re, traceback
|
|
6
|
-
|
|
7
|
-
class DanglingStackException(Exception): pass
|
|
8
|
-
|
|
9
|
-
class NoSuchIndentException(Exception): pass
|
|
10
|
-
|
|
11
|
-
class MalformedEntryException(Exception): pass
|
|
12
|
-
|
|
13
|
-
class Repl:
|
|
14
|
-
|
|
15
|
-
quotablebysquare = re.compile('[$()]+')
|
|
16
|
-
|
|
17
|
-
@classmethod
|
|
18
|
-
def _quote(cls, obj): # TODO: Duplicates some wrap logic.
|
|
19
|
-
for b in map(bool, range(2)):
|
|
20
|
-
if obj is b:
|
|
21
|
-
return str(b).lower()
|
|
22
|
-
if isinstance(obj, PurePath):
|
|
23
|
-
obj = str(obj)
|
|
24
|
-
try:
|
|
25
|
-
return f"""$.({cls.quotablebysquare.sub(lambda m: f"$'[{m.group()}]", obj)})"""
|
|
26
|
-
except TypeError:
|
|
27
|
-
return obj
|
|
28
|
-
|
|
29
|
-
def __init__(self, scope = None, interactive = False, rootprefix = Entry([])):
|
|
30
|
-
self.stack = []
|
|
31
|
-
self.indent = ''
|
|
32
|
-
self.command = Entry([Text(':')])
|
|
33
|
-
self.commandsize = self.command.size()
|
|
34
|
-
self.partials = {'': rootprefix}
|
|
35
|
-
self.scope = Scope() if scope is None else scope
|
|
36
|
-
self.interactive = interactive
|
|
37
|
-
|
|
38
|
-
def __enter__(self):
|
|
39
|
-
return self
|
|
40
|
-
|
|
41
|
-
def printf(self, template, *args): # TODO: Replace with methods corresponding to directives.
|
|
42
|
-
self(template % tuple(self._quote(a) for a in args))
|
|
43
|
-
|
|
44
|
-
def __call__(self, line):
|
|
45
|
-
try:
|
|
46
|
-
suffix = commandparser(''.join(self.stack + [line]))
|
|
47
|
-
del self.stack[:]
|
|
48
|
-
except pyparsing.ParseException:
|
|
49
|
-
self.stack.append(line)
|
|
50
|
-
return
|
|
51
|
-
indent = suffix.indent()
|
|
52
|
-
common = min(len(self.indent), len(indent))
|
|
53
|
-
if indent[:common] != self.indent[:common]:
|
|
54
|
-
raise MalformedEntryException(suffix)
|
|
55
|
-
if len(indent) <= len(self.indent):
|
|
56
|
-
self.fire()
|
|
57
|
-
if indent not in self.partials:
|
|
58
|
-
raise NoSuchIndentException(suffix)
|
|
59
|
-
else:
|
|
60
|
-
self.partials[indent] = self.command
|
|
61
|
-
for i in list(self.partials):
|
|
62
|
-
if len(indent) < len(i):
|
|
63
|
-
del self.partials[i]
|
|
64
|
-
self.command = Entry(self.partials[indent].resolvables + suffix.resolvables)
|
|
65
|
-
self.commandsize = Entry(suffix.resolvables).size()
|
|
66
|
-
self.indent = indent
|
|
67
|
-
|
|
68
|
-
def fire(self):
|
|
69
|
-
if self.commandsize:
|
|
70
|
-
try:
|
|
71
|
-
self.scope.execute(self.command)
|
|
72
|
-
except:
|
|
73
|
-
if not self.interactive:
|
|
74
|
-
raise
|
|
75
|
-
traceback.print_exc(0)
|
|
76
|
-
|
|
77
|
-
def __exit__(self, exc_type, *args):
|
|
78
|
-
if exc_type is None:
|
|
79
|
-
if self.stack:
|
|
80
|
-
raise DanglingStackException(self.stack)
|
|
81
|
-
self.fire()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|