aridity 83__tar.gz → 84__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aridity
3
- Version: 83
3
+ Version: 84
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
@@ -558,7 +558,7 @@ If given 3 args, the first two are variable names for scope key and scope respec
558
558
  ###### join
559
559
 
560
560
  ```python
561
- def join(scope, resolvables, *args)
561
+ def join(scope, partsresolvable, sepresolvable=None)
562
562
  ```
563
563
 
564
564
  Concatenate the given list, using optional separator. Frequently used with `map`.
@@ -548,7 +548,7 @@ If given 3 args, the first two are variable names for scope key and scope respec
548
548
  ###### join
549
549
 
550
550
  ```python
551
- def join(scope, resolvables, *args)
551
+ def join(scope, partsresolvable, sepresolvable=None)
552
552
  ```
553
553
 
554
554
  Concatenate the given list, using optional separator. Frequently used with `map`.
@@ -148,7 +148,7 @@ class ConfigCtrl:
148
148
  s = self.scope()
149
149
  obj = _wrappathorstream(frompathorstream).processtemplate(s)
150
150
  if getattr(topathorstream, 'writable', lambda: False)():
151
- topathorstream.write(obj.cat() if hasattr(topathorstream, 'encoding') else obj.binaryvalue)
151
+ topathorstream.write(obj.textvalue if hasattr(topathorstream, 'encoding') else obj.binaryvalue)
152
152
  else:
153
153
  obj.writeout(topathorstream)
154
154
 
@@ -36,7 +36,7 @@ class Redirect:
36
36
  class Write:
37
37
  name = '!write'
38
38
  def __call__(self, prefix, suffix, scope):
39
- scope.resolved('stdout').flush(suffix.tophrase().resolve(scope).cat())
39
+ scope.resolved('stdout').flush(suffix.tophrase().resolve(scope).textvalue)
40
40
 
41
41
  @_directive
42
42
  class Source:
@@ -94,4 +94,4 @@ class Cat:
94
94
  name = '<'
95
95
  def __call__(self, prefix, suffix, scope):
96
96
  scope = scope.getorcreatesubscope(prefix.topath(scope))
97
- scope.resolved('stdout').flush(suffix.tophrase().resolve(scope).openable(scope).processtemplate(scope).cat())
97
+ scope.resolved('stdout').flush(suffix.tophrase().resolve(scope).openable(scope).processtemplate(scope).textvalue)
@@ -1,4 +1,4 @@
1
- from .model import Boolean, Hole, Number, Resource, Text, wrap
1
+ from .model import Boolean, Hole, Indeterminate, Number, Resource, Text, wrap
2
2
  from .util import allfunctions, dotpy, NoSuchPathException, realname
3
3
  from importlib import import_module
4
4
  from itertools import chain
@@ -25,19 +25,19 @@ class Functions:
25
25
 
26
26
  def screenstr(scope, resolvable):
27
27
  'GNU Screen string literal.'
28
- return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).cat())))
28
+ return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).textvalue)))
29
29
 
30
30
  def scstr(scope, resolvable):
31
31
  'SuperCollider string literal.'
32
- return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).cat())))
32
+ return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).textvalue)))
33
33
 
34
34
  def hclstr(scope, resolvable):
35
35
  'HashiCorp configuration language string literal.'
36
- return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).cat())))
36
+ return Text('"{}"'.format(re.sub(r'[\\\n"]', r'\\\g<0>', resolvable.resolve(scope).textvalue)))
37
37
 
38
38
  def groovystr(scope, resolvable):
39
39
  'Groovy string literal.'
40
- return Text("'{}'".format(re.sub(r"[\\\n']", r'\\\g<0>', resolvable.resolve(scope).cat())))
40
+ return Text("'{}'".format(re.sub(r"[\\\n']", r'\\\g<0>', resolvable.resolve(scope).textvalue)))
41
41
 
42
42
  def pystr(scope, resolvable):
43
43
  'Python literal.'
@@ -45,7 +45,7 @@ class Functions:
45
45
 
46
46
  def shstr(scope, resolvable):
47
47
  'Shell string literal.'
48
- return Text(shlex.quote(resolvable.resolve(scope).cat()))
48
+ return Text(shlex.quote(resolvable.resolve(scope).textvalue))
49
49
 
50
50
  def jsonquote(scope, resolvable):
51
51
  'JSON literal, also suitable for YAML.'
@@ -54,21 +54,21 @@ class Functions:
54
54
  def xmlattr(scope, resolvable):
55
55
  'XML attribute literal (including quotes).'
56
56
  from xml.sax.saxutils import quoteattr
57
- return Text(quoteattr(resolvable.resolve(scope).cat())) # TODO: Support booleans.
57
+ return Text(quoteattr(resolvable.resolve(scope).textvalue)) # TODO: Support booleans.
58
58
 
59
59
  def xmltext(scope, resolvable):
60
60
  'XML content, suggest assigning this to & with xmlattr assigned to " as is convention.'
61
61
  from xml.sax.saxutils import escape
62
- return Text(escape(resolvable.resolve(scope).cat(), xmlentities))
62
+ return Text(escape(resolvable.resolve(scope).textvalue, xmlentities))
63
63
 
64
64
  def tomlquote(scope, resolvable):
65
65
  'TOML string literal.'
66
- return Text(_tomlquote(resolvable.resolve(scope).cat()))
66
+ return Text(_tomlquote(resolvable.resolve(scope).textvalue))
67
67
 
68
68
  def urlquote(scope, resolvable):
69
69
  'Percent-encode all reserved characters.'
70
70
  from urllib.parse import quote
71
- return Text(quote(resolvable.resolve(scope).cat(), safe = ''))
71
+ return Text(quote(resolvable.resolve(scope).textvalue, safe = ''))
72
72
 
73
73
  def map(scope, objsresolvable, *args):
74
74
  '''If given 1 arg, evaluate it against every scope in `objsresolvable` and return that list.
@@ -96,7 +96,7 @@ class Functions:
96
96
  s[vname,] = v
97
97
  return s
98
98
  vname, resolvable = args
99
- vname = vname.resolve(scope).cat()
99
+ vname = vname.resolve(scope).textvalue
100
100
  else:
101
101
  def context(k, v):
102
102
  s = Scope(parents)
@@ -104,8 +104,8 @@ class Functions:
104
104
  s[vname,] = v
105
105
  return s
106
106
  kname, vname, resolvable = args
107
- kname = kname.resolve(scope).cat()
108
- vname = vname.resolve(scope).cat()
107
+ kname = kname.resolve(scope).textvalue
108
+ vname = vname.resolve(scope).textvalue
109
109
  result = Scope(islist = True) # XXX: Really no parent?
110
110
  for k, v in objs.resolveditems():
111
111
  result.resolvables.put(k, resolvable.resolve(context(k, v)))
@@ -122,19 +122,13 @@ class Functions:
122
122
  def label(scope):
123
123
  return scope.label
124
124
 
125
- def join(scope, resolvables, *args):
125
+ def join(scope, partsresolvable, sepresolvable = None):
126
126
  'Concatenate the given list, using optional separator. Frequently used with `map`.'
127
- if args:
128
- r, = args
129
- separator = r.resolve(scope).cat()
130
- else:
131
- separator = ''
132
- s = resolvables.resolve(scope)
133
- return Text(separator.join(o.cat() for _, o in s.resolveditems()))
127
+ return Join(scope, partsresolvable).execute(sepresolvable)
134
128
 
135
129
  @realname(',') # XXX: Oh yeah?
136
130
  def aslist(scope, *resolvables):
137
- return scope.resolved(*(r.resolve(scope).cat() for r in resolvables), **{'aslist': True})
131
+ return scope.resolved(*(r.resolve(scope).textvalue for r in resolvables), **{'aslist': True})
138
132
 
139
133
  def str(scope, resolvable):
140
134
  'Coerce to string.'
@@ -178,7 +172,7 @@ class Functions:
178
172
  @realname('./')
179
173
  def hereslash(scope, *resolvables):
180
174
  'Join the given path components with the directory of the current resource.'
181
- return scope.resolved('here').slash((r.resolve(scope).cat() for r in resolvables), False)
175
+ return scope.resolved('here').slash((r.resolve(scope).textvalue for r in resolvables), False)
182
176
 
183
177
  def readfile(scope, resolvable):
184
178
  'Include the content of the given path.'
@@ -190,12 +184,12 @@ class Functions:
190
184
  return resolvable.resolve(scope).openable(scope).processtemplate(scope)
191
185
 
192
186
  def lower(scope, resolvable):
193
- return Text(resolvable.resolve(scope).cat().lower())
187
+ return Text(resolvable.resolve(scope).textvalue.lower())
194
188
 
195
189
  def pyref(scope, moduleresolvable, qualnameresolvable):
196
190
  'Python object in given module with given qualified name. Module may be relative to current resource, in which case assignment with `:=` is normally necessary. Typically used to import functions.'
197
191
  def moduleobj():
198
- moduleref = moduleresolvable.resolve(scope).cat()
192
+ moduleref = moduleresolvable.resolve(scope).textvalue
199
193
  leadingdots = len(zeroormoredots.match(moduleref).group())
200
194
  if not leadingdots:
201
195
  return import_module(moduleref)
@@ -212,23 +206,23 @@ class Functions:
212
206
  exec(f.read(), g)
213
207
  return M()
214
208
  pyobj = moduleobj()
215
- for name in qualnameresolvable.resolve(scope).cat().split('.'):
209
+ for name in qualnameresolvable.resolve(scope).textvalue.split('.'):
216
210
  pyobj = getattr(pyobj, name)
217
211
  return wrap(pyobj)
218
212
 
219
213
  def pyres(scope, packageresolvable, nameresolvable, encoding = Text('ascii')):
220
214
  'Python resource for inclusion with `.` directive.'
221
- return Resource(packageresolvable.resolve(scope).cat(), nameresolvable.resolve(scope).cat(), encoding.resolve(scope).cat())
215
+ return Resource(packageresolvable.resolve(scope).textvalue, nameresolvable.resolve(scope).textvalue, encoding.resolve(scope).textvalue)
222
216
 
223
217
  @realname('\N{NOT SIGN}')
224
218
  def not_(scope, resolvable):
225
219
  return Boolean(not resolvable.resolve(scope).truth())
226
220
 
227
221
  def getfrom(scope, scoperesolvable, *resolvables):
228
- return scoperesolvable.resolve(scope).resolved(*(r.resolve(scope).cat() for r in resolvables))
222
+ return scoperesolvable.resolve(scope).resolved(*(r.resolve(scope).textvalue for r in resolvables))
229
223
 
230
224
  def rmeol(scope, resolvable):
231
- text = resolvable.resolve(scope).cat()
225
+ text = resolvable.resolve(scope).textvalue
232
226
  if text.endswith('\r\n'):
233
227
  n = 2
234
228
  elif text.endswith(('\r', '\n')):
@@ -238,15 +232,40 @@ class Functions:
238
232
  return Text(text[:-n])
239
233
 
240
234
  def indentmorelines(scope, resolvable):
241
- indent = scope.resolved('indent').cat()
242
- lines = resolvable.resolve(scope).cat().splitlines(True)
235
+ indent = scope.resolved('indent').textvalue
236
+ lines = resolvable.resolve(scope).textvalue.splitlines(True)
243
237
  return Text(''.join(chain(lines[:1], (indent + line for line in lines[1:]))))
244
238
 
245
239
  def hole(scope, resolvable):
246
- return Hole(Text(''), resolvable.resolve(scope).cat())
240
+ return Hole(Text(''), resolvable.resolve(scope).textvalue)
241
+
242
+ class Join:
243
+
244
+ def __init__(self, scope, partsresolvable):
245
+ self.i = (o for _, o in partsresolvable.resolve(scope).resolveditems())
246
+ self.scope = scope
247
+
248
+ def _load(self):
249
+ try:
250
+ self.obj = next(self.i)
251
+ return True
252
+ except StopIteration:
253
+ pass
254
+
255
+ def execute(self, sepresolvable):
256
+ resobj = Indeterminate
257
+ if self._load():
258
+ resobj = resobj.plus(self.obj)
259
+ if self._load():
260
+ sepobj = Indeterminate if sepresolvable is None else sepresolvable.resolve(self.scope)
261
+ while True:
262
+ resobj = resobj.plus(sepobj).plus(self.obj)
263
+ if not self._load():
264
+ break
265
+ return resobj
247
266
 
248
267
  def getimpl(scope, *resolvables, **kwargs):
249
- return scope.resolved(*(r.resolve(scope).cat() for r in resolvables), **kwargs)
268
+ return scope.resolved(*(r.resolve(scope).textvalue for r in resolvables), **kwargs)
250
269
 
251
270
  def getfunctions():
252
271
  return allfunctions(Functions)
@@ -33,8 +33,8 @@ def keyring(scope, serviceres, usernameres):
33
33
  log.debug("Set %s to: %s", key, value)
34
34
  os.environ[key] = value
35
35
  from keyring import get_password, set_password
36
- service = serviceres.resolve(scope).cat()
37
- username = usernameres.resolve(scope).cat()
36
+ service = serviceres.resolve(scope).textvalue
37
+ username = usernameres.resolve(scope).textvalue
38
38
  password = None if scope.resolved('keyring_force').scalar else get_password(service, username)
39
39
  return Scalar(Password(*[getpass(), partial(set_password, service, username)] if password is None else [password, None]))
40
40
 
@@ -43,7 +43,7 @@ class DecryptionFailedException(Exception): pass
43
43
  def gpg(scope, resolvable):
44
44
  'Use gpg to decrypt the given base64-encoded blob.'
45
45
  with NamedTemporaryFile() as f:
46
- f.write(b64decode(resolvable.resolve(scope).cat()))
46
+ f.write(b64decode(resolvable.resolve(scope).textvalue))
47
47
  f.flush()
48
48
  try:
49
49
  return Scalar(Password(check_output(['gpg', '-d', f.name]).decode('ascii'), None))
@@ -52,7 +52,7 @@ class NegBuffer:
52
52
  def annihilate(self, obj):
53
53
  if not self.text:
54
54
  return obj
55
- text = obj.cat()
55
+ text = obj.textvalue
56
56
  if not text:
57
57
  return obj
58
58
  k = min(len(self.text), len(text))
@@ -63,7 +63,7 @@ class NegBuffer:
63
63
  def propagate(self, obj):
64
64
  return Hole(obj, self.text) if self.text else obj
65
65
 
66
- class Concat(Resolvable):
66
+ class Concat(Resolvable): # TODO: Ban in path components.
67
67
 
68
68
  ignorable = False
69
69
 
@@ -95,17 +95,14 @@ class Concat(Resolvable):
95
95
  obj = negbuffer.annihilate(obj)
96
96
  result = result.plus(obj)
97
97
  try:
98
- text = obj.cat()
99
- except CatNotSupportedException:
98
+ text = obj.textvalue
99
+ except AttributeError:
100
100
  pass
101
101
  else:
102
102
  self.monitor(text)
103
103
  negbuffer.insert(negtext)
104
104
  return negbuffer.propagate(result)
105
105
 
106
- # TODO: Always throw when concatenation within a path component is attempted.
107
- class CatNotSupportedException(Exception): pass
108
-
109
106
  class BaseSimpleValue(Resolved):
110
107
 
111
108
  @classmethod
@@ -113,35 +110,28 @@ class BaseSimpleValue(Resolved):
113
110
  value, = t
114
111
  return cls(value)
115
112
 
116
- def cat(self):
117
- raise CatNotSupportedException(self)
118
-
119
113
  def unravel(self):
120
114
  return self.scalar
121
115
 
122
- class SimpleValue(BaseSimpleValue):
123
-
124
- def __init__(self, scalar):
125
- self.scalar = scalar
126
-
127
- class Cat:
128
-
129
- def cat(self):
130
- return self.scalar
131
-
132
- class Blank(Cat, SimpleValue):
116
+ class Blank(BaseSimpleValue):
133
117
 
134
118
  ignorable = True
135
119
  boundary = False
136
120
 
121
+ def __init__(self, textvalue):
122
+ self.textvalue = textvalue
123
+
137
124
  def plus(self, that):
138
- return Text(self.scalar + that.cat())
125
+ return Text(self.textvalue + that.textvalue)
139
126
 
140
- class Boundary(SimpleValue):
127
+ class Boundary(BaseSimpleValue):
141
128
 
142
129
  ignorable = True
143
130
  boundary = True
144
131
 
132
+ def __init__(self, scalar):
133
+ self.scalar = scalar
134
+
145
135
  class BaseScalar(BaseSimpleValue):
146
136
 
147
137
  ignorable = False
@@ -159,7 +149,7 @@ class Scalar(BaseScalar):
159
149
  def __init__(self, scalar):
160
150
  self.scalar = scalar
161
151
 
162
- class Text(Cat, BaseScalar):
152
+ class Text(BaseScalar):
163
153
 
164
154
  @classmethod
165
155
  def joinpa(cls, s, l, t):
@@ -203,12 +193,12 @@ class Text(Cat, BaseScalar):
203
193
  return Locator(s)
204
194
 
205
195
  def plus(self, that):
206
- return self._of(self.textvalue + that.cat())
196
+ return self._of(self.textvalue + that.textvalue)
207
197
 
208
- class Indeterminate:
198
+ class Indeterminate(BaseSimpleValue): # XXX: Base class needed?
209
199
 
210
- def cat(self):
211
- return ''
200
+ binaryvalue = b''
201
+ textvalue = ''
212
202
 
213
203
  def plus(self, that):
214
204
  return that
@@ -218,11 +208,13 @@ class Indeterminate:
218
208
 
219
209
  Indeterminate = Indeterminate()
220
210
 
211
+ class ResidualHoleException(Exception): pass
212
+
221
213
  class Hole(BaseScalar):
222
214
 
223
215
  @property
224
216
  def scalar(self):
225
- raise CatNotSupportedException
217
+ raise ResidualHoleException
226
218
 
227
219
  def __init__(self, prefix, holevalue):
228
220
  self.prefix = prefix
@@ -341,14 +333,8 @@ class Number(BaseScalar):
341
333
  text = str(self.numbervalue) # TODO: Test this.
342
334
  return Text(text)
343
335
 
344
- def cat(self):
345
- try:
346
- return self.textvalue
347
- except AttributeError:
348
- raise CatNotSupportedException
349
-
350
336
  def plus(self, that):
351
- return Text(self.textvalue + that.cat())
337
+ return Text(self.textvalue + that.textvalue)
352
338
 
353
339
  class Boolean(BaseScalar):
354
340
 
@@ -472,7 +458,7 @@ class Entry(Struct):
472
458
  return [r for r in self.resolvables if not r.ignorable]
473
459
 
474
460
  def topath(self, scope):
475
- return tuple((None if self.wildcard == r else r.resolve(scope).totext().cat()) for r in self.resolvables if not r.ignorable)
461
+ return tuple((None if self.wildcard == r else r.resolve(scope).totext().textvalue) for r in self.resolvables if not r.ignorable)
476
462
 
477
463
  def subentry(self, i, j):
478
464
  v = list(self.resolvables)
@@ -501,7 +487,7 @@ class Entry(Struct):
501
487
  if not r.ignorable or r.boundary:
502
488
  break
503
489
  indent.append(r) # XXX: Can we simply grab its value?
504
- return Concat.unlesssingleton(indent).resolve(None).cat()
490
+ return Concat.unlesssingleton(indent).resolve(None).textvalue
505
491
 
506
492
  def wrap(value):
507
493
  'Attempt to wrap the given value in a model object of the most specific type.'
@@ -1,7 +1,7 @@
1
1
  from . import directives
2
2
  from .directives import Precedence
3
3
  from .functions import getfunctions, getimpl, OpaqueKey
4
- from .model import CatNotSupportedException, Directive, Function, Hole, Resolvable, Scalar, star, Stream, Text
4
+ from .model import Directive, Function, Hole, Resolvable, Scalar, star, Stream, Text
5
5
  from .resolve import AnchorResolveContext
6
6
  from .search import Query
7
7
  from .stacks import IndentStack, SimpleStack, ThreadLocalResolvable
@@ -160,7 +160,7 @@ class AbstractScope(Resolvable): # TODO LATER: Some methods should probably be m
160
160
  precedence = Precedence.void
161
161
  for i, wordobj in enumerate(entry.words()):
162
162
  try:
163
- word = wordobj.cat()
163
+ word = wordobj.textvalue
164
164
  if not word:
165
165
  continue
166
166
  initialcategory = _categoryornone(word[0])
@@ -172,7 +172,7 @@ class AbstractScope(Resolvable): # TODO LATER: Some methods should probably be m
172
172
  del directives[:]
173
173
  precedence = p
174
174
  directives.append((d, i))
175
- except (AttributeError, CatNotSupportedException, NoSuchPathException):
175
+ except (AttributeError, NoSuchPathException):
176
176
  pass
177
177
  if directives:
178
178
  d, i = directives[0] # XXX: Always use first?
@@ -216,7 +216,7 @@ class StaticScope(AbstractScope):
216
216
  def __init__(self):
217
217
  super(StaticScope, self).__init__(())
218
218
  for word, d in directives.lookup.items():
219
- self[word.cat(),] = Directive(d)
219
+ self[word.textvalue,] = Directive(d)
220
220
  for name, f in getfunctions():
221
221
  self[name,] = Function(f)
222
222
  self['',] = Function(getimpl) # TODO: Refer to the other one.
@@ -253,7 +253,7 @@ class Slash(Text, Function):
253
253
  def slashfunction(scope, *resolvables):
254
254
  path = None
255
255
  for r in reversed(resolvables):
256
- component = r.resolve(scope).cat()
256
+ component = r.resolve(scope).textvalue
257
257
  path = component if path is None else os.path.join(component, path)
258
258
  if os.path.isabs(path):
259
259
  break
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aridity
3
- Version: 83
3
+ Version: 84
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
@@ -558,7 +558,7 @@ If given 3 args, the first two are variable names for scope key and scope respec
558
558
  ###### join
559
559
 
560
560
  ```python
561
- def join(scope, resolvables, *args)
561
+ def join(scope, partsresolvable, sepresolvable=None)
562
562
  ```
563
563
 
564
564
  Concatenate the given list, using optional separator. Frequently used with `map`.
@@ -49,7 +49,7 @@ class SourceInfo:
49
49
  sourceinfo = SourceInfo('.')
50
50
  setup(
51
51
  name = 'aridity',
52
- version = '83',
52
+ version = '84',
53
53
  description = 'DRY config and template system, easily extensible with Python',
54
54
  url = 'https://pypi.org/project/aridity/',
55
55
  author = 'foyono',
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