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.
Files changed (29) hide show
  1. {aridity-86 → aridity-88}/PKG-INFO +1 -1
  2. aridity-88/aridity/__init__.py +19 -0
  3. {aridity-86 → aridity-88}/aridity/config.py +4 -5
  4. {aridity-86 → aridity-88}/aridity/functions.py +2 -0
  5. {aridity-86 → aridity-88}/aridity/model.py +26 -7
  6. aridity-88/aridity/processtemplate.py +15 -0
  7. aridity-88/aridity/repl.py +74 -0
  8. {aridity-86 → aridity-88}/aridity/scope.py +0 -2
  9. {aridity-86 → aridity-88}/aridity.egg-info/PKG-INFO +1 -1
  10. {aridity-86 → aridity-88}/setup.py +1 -1
  11. aridity-86/aridity/__init__.py +0 -18
  12. aridity-86/aridity/processtemplate.py +0 -13
  13. aridity-86/aridity/repl.py +0 -81
  14. {aridity-86 → aridity-88}/README.md +0 -0
  15. {aridity-86 → aridity-88}/aridity/arid_config.py +0 -0
  16. {aridity-86 → aridity-88}/aridity/directives.py +0 -0
  17. {aridity-86 → aridity-88}/aridity/grammar.py +0 -0
  18. {aridity-86 → aridity-88}/aridity/keyring.py +0 -0
  19. {aridity-86 → aridity-88}/aridity/resolve.py +0 -0
  20. {aridity-86 → aridity-88}/aridity/search.py +0 -0
  21. {aridity-86 → aridity-88}/aridity/stacks.py +0 -0
  22. {aridity-86 → aridity-88}/aridity/util.py +0 -0
  23. {aridity-86 → aridity-88}/aridity.egg-info/SOURCES.txt +0 -0
  24. {aridity-86 → aridity-88}/aridity.egg-info/dependency_links.txt +0 -0
  25. {aridity-86 → aridity-88}/aridity.egg-info/entry_points.txt +0 -0
  26. {aridity-86 → aridity-88}/aridity.egg-info/requires.txt +0 -0
  27. {aridity-86 → aridity-88}/aridity.egg-info/top_level.txt +0 -0
  28. {aridity-86 → aridity-88}/parabject.py +0 -0
  29. {aridity-86 → aridity-88}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aridity
3
- Version: 86
3
+ Version: 88
4
4
  Summary: DRY config and template system, easily extensible with Python
5
5
  Home-page: https://pypi.org/project/aridity/
6
6
  Author: foyono
@@ -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
- settingsopenable = Locator(Path.home() / '.settings.arid')
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
- with Repl(self.scope) as repl:
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):
@@ -286,3 +286,5 @@ def corefunctions():
286
286
  yield 'getfrom', _getfrom
287
287
  yield 'indentmorelines', _indentmorelines
288
288
  yield 'hole', _hole
289
+ yield '', getimpl # TODO: Refer to the other one.
290
+ yield 'get', getimpl
@@ -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 numbers, os
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 Repl
433
- with Repl(scope, rootprefix = prefix) as repl:
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) # XXX: Can we simply grab its value?
494
- return Concat.unlesssingleton(indent).resolve(None).textvalue
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('~'))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aridity
3
- Version: 86
3
+ Version: 88
4
4
  Summary: DRY config and template system, easily extensible with Python
5
5
  Home-page: https://pypi.org/project/aridity/
6
6
  Author: foyono
@@ -49,7 +49,7 @@ class SourceInfo:
49
49
  sourceinfo = SourceInfo('.')
50
50
  setup(
51
51
  name = 'aridity',
52
- version = '86',
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',
@@ -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()
@@ -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