aridity 77__tar.gz → 79__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: 77
3
+ Version: 79
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
@@ -8,11 +8,46 @@ Author-email: shrovis@foyono.com
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: importlib-metadata>=2.1.3
10
10
  Requires-Dist: importlib-resources>=3.3.1
11
- Requires-Dist: pyparsing==2.4.7
11
+ Requires-Dist: pyparsing>=3.0.2
12
12
 
13
13
  # aridity
14
14
  DRY config and template system, easily extensible with Python
15
15
 
16
+ ## Typical usage
17
+ Main module of dbtool app:
18
+ ```
19
+ from aridity.config import ConfigCtrl
20
+
21
+ def main():
22
+ # Deduce app name from main function and create scope of that name, load dbtool.arid into that scope, load .settings.arid into the root scope, and return app scope:
23
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
24
+ print(config.dbhost)
25
+ ```
26
+ Sibling dbtool.arid of main module, self-documenting that `dbhost` should be configured:
27
+ ```
28
+ dbhost = $(void)
29
+ ```
30
+ Shared config file `.settings.arid` in home directory:
31
+ ```
32
+ dbtool dbhost = anaximander.local
33
+ ```
34
+
35
+ ### Integration with argparse
36
+ App config file:
37
+ ```
38
+ cli v = $(void)
39
+ verbose = $(cli v)
40
+ ```
41
+ Main function:
42
+ ```
43
+ def main():
44
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
45
+ parser = ArgumentParser()
46
+ parser.add_argument('-v', action = 'store_true')
47
+ parser.parse_args(namespace = config.cli)
48
+ print(config.verbose)
49
+ ```
50
+
16
51
  ## The Arid Manifesto
17
52
  * Keys are paths to avoid concatenation
18
53
  * It's never necessary to repeat a value
@@ -23,7 +58,7 @@ DRY config and template system, easily extensible with Python
23
58
  * Templating using same syntax as expressions
24
59
  * Easy to correctly quote/escape values in templates
25
60
  * Extensibility via user-defined functions
26
- * Easy tasks are easy, hard tasks are possible
61
+ * Common tasks are easy, rare tasks are possible
27
62
  * Many applications can share one user config
28
63
  * Principle of least astonishment driven design
29
64
  * Don't make users jump through hoops
@@ -39,28 +74,28 @@ DRY config and template system, easily extensible with Python
39
74
  * aridity is a general purpose solution for all the above, also see [soak](https://pypi.org/project/soak/)
40
75
 
41
76
  ## Config API
42
- * Normally you pass around a Config object, and application code can get data out via attribute access e.g. config.foo.bar
43
- * Here config.foo is also a Config object, a child scope of config named foo
77
+ * Normally you pass around a `Config` object, and application code can get data out via attribute access e.g. `config.foo.bar`
78
+ * Here `config.foo` is also a Config object, a child scope of `config` named foo
44
79
  * The passing around can be taken care of by a dependency injection container such as [diapyr](https://pypi.org/project/diapyr/)
45
- * Every Config has an associated ConfigCtrl on which Python API such as processtemplate is available
46
- * Use negation to get ConfigCtrl when you have a Config e.g. (-config).processtemplate(...)
47
- * Use the node attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
80
+ * Every Config has an associated ConfigCtrl on which Python API such as `processtemplate` is available
81
+ * Use negation to get ConfigCtrl when you have a Config e.g. `(-config).processtemplate(...)`
82
+ * Use the `node` attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
48
83
  * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
49
84
 
50
85
  ## Guidelines
51
- * Config files have the extension .arid and templates .aridt
86
+ * Config files have the extension `.arid` and templates `.aridt`
52
87
  * A template is simply a file-sized aridity expression
53
- * Conventionally the template processor sets " to the appropriate quote function for the file format, e.g. jsonquote for JSON/YAML
54
- * Instead of adding Python objects to the config in main, it's tidier to use aridity's pyref function to achieve this
88
+ * Conventionally the template processor sets `"` to the appropriate quote function for the file format, e.g. `jsonquote` for JSON/YAML
89
+ * Instead of adding Python objects to the config in `main`, it's tidier to use aridity's `pyref` function to achieve this
55
90
  * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
56
91
 
57
92
  ## Feature switch
58
93
  * Sometimes we want to deploy a change, but something in production isn't ready for that change
59
94
  * A feature switch allows deployment to production in this case
60
- * Add a boolean to the base config (conventionally root.arid) e.g. foo enabled = true
95
+ * Add a boolean to the base config (conventionally root.arid) e.g. `foo enabled = true`
61
96
  * This value should be the configuration that we eventually want in all environments
62
- * In production config, override with foo enabled = false
63
- * In the code, read config.foo.enabled and enable the change based on this boolean
97
+ * In production config, override with `foo enabled = false`
98
+ * In the code, read `config.foo.enabled` and enable the change based on this boolean
64
99
  * The above can now be deployed to all environments, and is not a blocker for other changes
65
100
  * Later when production is ready for it, it's a 1 line change to remove the override from production config
66
101
 
@@ -604,7 +639,7 @@ Python object in given module with given qualified name. Module may be relative
604
639
  ###### pyres
605
640
 
606
641
  ```python
607
- def pyres(scope, packageresolvable, nameresolvable)
642
+ def pyres(scope, packageresolvable, nameresolvable, encoding=Text('ascii'))
608
643
  ```
609
644
 
610
645
  Python resource for inclusion with `.` directive.
@@ -1,18 +1,41 @@
1
- Metadata-Version: 2.1
2
- Name: aridity
3
- Version: 77
4
- Summary: DRY config and template system, easily extensible with Python
5
- Home-page: https://pypi.org/project/aridity/
6
- Author: foyono
7
- Author-email: shrovis@foyono.com
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: importlib-metadata>=2.1.3
10
- Requires-Dist: importlib-resources>=3.3.1
11
- Requires-Dist: pyparsing==2.4.7
12
-
13
1
  # aridity
14
2
  DRY config and template system, easily extensible with Python
15
3
 
4
+ ## Typical usage
5
+ Main module of dbtool app:
6
+ ```
7
+ from aridity.config import ConfigCtrl
8
+
9
+ def main():
10
+ # Deduce app name from main function and create scope of that name, load dbtool.arid into that scope, load .settings.arid into the root scope, and return app scope:
11
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
12
+ print(config.dbhost)
13
+ ```
14
+ Sibling dbtool.arid of main module, self-documenting that `dbhost` should be configured:
15
+ ```
16
+ dbhost = $(void)
17
+ ```
18
+ Shared config file `.settings.arid` in home directory:
19
+ ```
20
+ dbtool dbhost = anaximander.local
21
+ ```
22
+
23
+ ### Integration with argparse
24
+ App config file:
25
+ ```
26
+ cli v = $(void)
27
+ verbose = $(cli v)
28
+ ```
29
+ Main function:
30
+ ```
31
+ def main():
32
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
33
+ parser = ArgumentParser()
34
+ parser.add_argument('-v', action = 'store_true')
35
+ parser.parse_args(namespace = config.cli)
36
+ print(config.verbose)
37
+ ```
38
+
16
39
  ## The Arid Manifesto
17
40
  * Keys are paths to avoid concatenation
18
41
  * It's never necessary to repeat a value
@@ -23,7 +46,7 @@ DRY config and template system, easily extensible with Python
23
46
  * Templating using same syntax as expressions
24
47
  * Easy to correctly quote/escape values in templates
25
48
  * Extensibility via user-defined functions
26
- * Easy tasks are easy, hard tasks are possible
49
+ * Common tasks are easy, rare tasks are possible
27
50
  * Many applications can share one user config
28
51
  * Principle of least astonishment driven design
29
52
  * Don't make users jump through hoops
@@ -39,28 +62,28 @@ DRY config and template system, easily extensible with Python
39
62
  * aridity is a general purpose solution for all the above, also see [soak](https://pypi.org/project/soak/)
40
63
 
41
64
  ## Config API
42
- * Normally you pass around a Config object, and application code can get data out via attribute access e.g. config.foo.bar
43
- * Here config.foo is also a Config object, a child scope of config named foo
65
+ * Normally you pass around a `Config` object, and application code can get data out via attribute access e.g. `config.foo.bar`
66
+ * Here `config.foo` is also a Config object, a child scope of `config` named foo
44
67
  * The passing around can be taken care of by a dependency injection container such as [diapyr](https://pypi.org/project/diapyr/)
45
- * Every Config has an associated ConfigCtrl on which Python API such as processtemplate is available
46
- * Use negation to get ConfigCtrl when you have a Config e.g. (-config).processtemplate(...)
47
- * Use the node attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
68
+ * Every Config has an associated ConfigCtrl on which Python API such as `processtemplate` is available
69
+ * Use negation to get ConfigCtrl when you have a Config e.g. `(-config).processtemplate(...)`
70
+ * Use the `node` attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
48
71
  * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
49
72
 
50
73
  ## Guidelines
51
- * Config files have the extension .arid and templates .aridt
74
+ * Config files have the extension `.arid` and templates `.aridt`
52
75
  * A template is simply a file-sized aridity expression
53
- * Conventionally the template processor sets " to the appropriate quote function for the file format, e.g. jsonquote for JSON/YAML
54
- * Instead of adding Python objects to the config in main, it's tidier to use aridity's pyref function to achieve this
76
+ * Conventionally the template processor sets `"` to the appropriate quote function for the file format, e.g. `jsonquote` for JSON/YAML
77
+ * Instead of adding Python objects to the config in `main`, it's tidier to use aridity's `pyref` function to achieve this
55
78
  * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
56
79
 
57
80
  ## Feature switch
58
81
  * Sometimes we want to deploy a change, but something in production isn't ready for that change
59
82
  * A feature switch allows deployment to production in this case
60
- * Add a boolean to the base config (conventionally root.arid) e.g. foo enabled = true
83
+ * Add a boolean to the base config (conventionally root.arid) e.g. `foo enabled = true`
61
84
  * This value should be the configuration that we eventually want in all environments
62
- * In production config, override with foo enabled = false
63
- * In the code, read config.foo.enabled and enable the change based on this boolean
85
+ * In production config, override with `foo enabled = false`
86
+ * In the code, read `config.foo.enabled` and enable the change based on this boolean
64
87
  * The above can now be deployed to all environments, and is not a blocker for other changes
65
88
  * Later when production is ready for it, it's a 1 line change to remove the override from production config
66
89
 
@@ -604,7 +627,7 @@ Python object in given module with given qualified name. Module may be relative
604
627
  ###### pyres
605
628
 
606
629
  ```python
607
- def pyres(scope, packageresolvable, nameresolvable)
630
+ def pyres(scope, packageresolvable, nameresolvable, encoding=Text('ascii'))
608
631
  ```
609
632
 
610
633
  Python resource for inclusion with `.` directive.
@@ -221,9 +221,9 @@ class Functions:
221
221
  pyobj = getattr(pyobj, name)
222
222
  return wrap(pyobj)
223
223
 
224
- def pyres(scope, packageresolvable, nameresolvable):
224
+ def pyres(scope, packageresolvable, nameresolvable, encoding = Text('ascii')):
225
225
  'Python resource for inclusion with `.` directive.'
226
- return Resource(packageresolvable.resolve(scope).cat(), nameresolvable.resolve(scope).cat())
226
+ return Resource(packageresolvable.resolve(scope).cat(), nameresolvable.resolve(scope).cat(), encoding.resolve(scope).cat())
227
227
 
228
228
  @realname('\N{NOT SIGN}')
229
229
  def not_(scope, resolvable):
@@ -3,7 +3,7 @@ from .util import null_exc_info
3
3
  from base64 import b64decode
4
4
  from functools import partial
5
5
  from getpass import getpass
6
- from subprocess import check_output
6
+ from subprocess import CalledProcessError, check_output
7
7
  from tempfile import NamedTemporaryFile
8
8
  from threading import Semaphore
9
9
  import logging, os
@@ -38,9 +38,14 @@ def keyring(scope, serviceres, usernameres):
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
 
41
+ class DecryptionFailedException(Exception): pass
42
+
41
43
  def gpg(scope, resolvable):
42
44
  'Use gpg to decrypt the given base64-encoded blob.'
43
45
  with NamedTemporaryFile() as f:
44
46
  f.write(b64decode(resolvable.resolve(scope).cat()))
45
47
  f.flush()
46
- return Scalar(Password(check_output(['gpg', '-d', f.name]).decode('ascii'), None))
48
+ try:
49
+ return Scalar(Password(check_output(['gpg', '-d', f.name]).decode('ascii'), None))
50
+ except CalledProcessError:
51
+ raise DecryptionFailedException
@@ -1,6 +1,53 @@
1
+ Metadata-Version: 2.1
2
+ Name: aridity
3
+ Version: 79
4
+ Summary: DRY config and template system, easily extensible with Python
5
+ Home-page: https://pypi.org/project/aridity/
6
+ Author: foyono
7
+ Author-email: shrovis@foyono.com
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: importlib-metadata>=2.1.3
10
+ Requires-Dist: importlib-resources>=3.3.1
11
+ Requires-Dist: pyparsing>=3.0.2
12
+
1
13
  # aridity
2
14
  DRY config and template system, easily extensible with Python
3
15
 
16
+ ## Typical usage
17
+ Main module of dbtool app:
18
+ ```
19
+ from aridity.config import ConfigCtrl
20
+
21
+ def main():
22
+ # Deduce app name from main function and create scope of that name, load dbtool.arid into that scope, load .settings.arid into the root scope, and return app scope:
23
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
24
+ print(config.dbhost)
25
+ ```
26
+ Sibling dbtool.arid of main module, self-documenting that `dbhost` should be configured:
27
+ ```
28
+ dbhost = $(void)
29
+ ```
30
+ Shared config file `.settings.arid` in home directory:
31
+ ```
32
+ dbtool dbhost = anaximander.local
33
+ ```
34
+
35
+ ### Integration with argparse
36
+ App config file:
37
+ ```
38
+ cli v = $(void)
39
+ verbose = $(cli v)
40
+ ```
41
+ Main function:
42
+ ```
43
+ def main():
44
+ config = ConfigCtrl().loadappconfig(main, 'dbtool.arid')
45
+ parser = ArgumentParser()
46
+ parser.add_argument('-v', action = 'store_true')
47
+ parser.parse_args(namespace = config.cli)
48
+ print(config.verbose)
49
+ ```
50
+
4
51
  ## The Arid Manifesto
5
52
  * Keys are paths to avoid concatenation
6
53
  * It's never necessary to repeat a value
@@ -11,7 +58,7 @@ DRY config and template system, easily extensible with Python
11
58
  * Templating using same syntax as expressions
12
59
  * Easy to correctly quote/escape values in templates
13
60
  * Extensibility via user-defined functions
14
- * Easy tasks are easy, hard tasks are possible
61
+ * Common tasks are easy, rare tasks are possible
15
62
  * Many applications can share one user config
16
63
  * Principle of least astonishment driven design
17
64
  * Don't make users jump through hoops
@@ -27,28 +74,28 @@ DRY config and template system, easily extensible with Python
27
74
  * aridity is a general purpose solution for all the above, also see [soak](https://pypi.org/project/soak/)
28
75
 
29
76
  ## Config API
30
- * Normally you pass around a Config object, and application code can get data out via attribute access e.g. config.foo.bar
31
- * Here config.foo is also a Config object, a child scope of config named foo
77
+ * Normally you pass around a `Config` object, and application code can get data out via attribute access e.g. `config.foo.bar`
78
+ * Here `config.foo` is also a Config object, a child scope of `config` named foo
32
79
  * The passing around can be taken care of by a dependency injection container such as [diapyr](https://pypi.org/project/diapyr/)
33
- * Every Config has an associated ConfigCtrl on which Python API such as processtemplate is available
34
- * Use negation to get ConfigCtrl when you have a Config e.g. (-config).processtemplate(...)
35
- * Use the node attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
80
+ * Every Config has an associated ConfigCtrl on which Python API such as `processtemplate` is available
81
+ * Use negation to get ConfigCtrl when you have a Config e.g. `(-config).processtemplate(...)`
82
+ * Use the `node` attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
36
83
  * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
37
84
 
38
85
  ## Guidelines
39
- * Config files have the extension .arid and templates .aridt
86
+ * Config files have the extension `.arid` and templates `.aridt`
40
87
  * A template is simply a file-sized aridity expression
41
- * Conventionally the template processor sets " to the appropriate quote function for the file format, e.g. jsonquote for JSON/YAML
42
- * Instead of adding Python objects to the config in main, it's tidier to use aridity's pyref function to achieve this
88
+ * Conventionally the template processor sets `"` to the appropriate quote function for the file format, e.g. `jsonquote` for JSON/YAML
89
+ * Instead of adding Python objects to the config in `main`, it's tidier to use aridity's `pyref` function to achieve this
43
90
  * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
44
91
 
45
92
  ## Feature switch
46
93
  * Sometimes we want to deploy a change, but something in production isn't ready for that change
47
94
  * A feature switch allows deployment to production in this case
48
- * Add a boolean to the base config (conventionally root.arid) e.g. foo enabled = true
95
+ * Add a boolean to the base config (conventionally root.arid) e.g. `foo enabled = true`
49
96
  * This value should be the configuration that we eventually want in all environments
50
- * In production config, override with foo enabled = false
51
- * In the code, read config.foo.enabled and enable the change based on this boolean
97
+ * In production config, override with `foo enabled = false`
98
+ * In the code, read `config.foo.enabled` and enable the change based on this boolean
52
99
  * The above can now be deployed to all environments, and is not a blocker for other changes
53
100
  * Later when production is ready for it, it's a 1 line change to remove the override from production config
54
101
 
@@ -592,7 +639,7 @@ Python object in given module with given qualified name. Module may be relative
592
639
  ###### pyres
593
640
 
594
641
  ```python
595
- def pyres(scope, packageresolvable, nameresolvable)
642
+ def pyres(scope, packageresolvable, nameresolvable, encoding=Text('ascii'))
596
643
  ```
597
644
 
598
645
  Python resource for inclusion with `.` directive.
@@ -1,3 +1,3 @@
1
1
  importlib-metadata>=2.1.3
2
2
  importlib-resources>=3.3.1
3
- pyparsing==2.4.7
3
+ pyparsing>=3.0.2
@@ -1,5 +1,5 @@
1
1
  [bdist_wheel]
2
- universal = 1
2
+ universal = 0
3
3
 
4
4
  [egg_info]
5
5
  tag_build =
aridity-79/setup.py ADDED
@@ -0,0 +1,62 @@
1
+ from setuptools import setup
2
+ try:
3
+ from Cython.Build import cythonize
4
+ except ModuleNotFoundError:
5
+ pass
6
+ from pathlib import Path
7
+ from setuptools import find_packages
8
+ import os
9
+
10
+ class SourceInfo:
11
+
12
+ class PYXPath:
13
+
14
+ def __init__(self, module, path):
15
+ self.module = module
16
+ self.path = path
17
+
18
+ def make_ext(self):
19
+ g = {}
20
+ with open(f"{self.path}bld") as f: # Assume project root.
21
+ exec(f.read(), g)
22
+ return g['make_ext'](self.module, self.path)
23
+
24
+ def __init__(self, rootdir):
25
+ def addextpaths(dirpath, moduleprefix, suffix = '.pyx'):
26
+ for name in sorted(os.listdir(os.path.join(rootdir, dirpath))):
27
+ if name.endswith(suffix):
28
+ module = f"{moduleprefix}{name[:-len(suffix)]}"
29
+ if module not in extpaths:
30
+ extpaths[module] = self.PYXPath(module, os.path.join(dirpath, name))
31
+ self.packages = find_packages(rootdir)
32
+ extpaths = {}
33
+ addextpaths('.', '')
34
+ for package in self.packages:
35
+ addextpaths(package.replace('.', os.sep), f"{package}.")
36
+ self.extpaths = extpaths.values()
37
+
38
+ def setup_kwargs(self):
39
+ kwargs = dict(packages = self.packages)
40
+ try:
41
+ kwargs['long_description'] = Path('README.md').read_text()
42
+ kwargs['long_description_content_type'] = 'text/markdown'
43
+ except FileNotFoundError:
44
+ pass
45
+ if self.extpaths:
46
+ kwargs['ext_modules'] = cythonize([path.make_ext() for path in self.extpaths])
47
+ return kwargs
48
+
49
+ sourceinfo = SourceInfo('.')
50
+ setup(
51
+ name = 'aridity',
52
+ version = '79',
53
+ description = 'DRY config and template system, easily extensible with Python',
54
+ url = 'https://pypi.org/project/aridity/',
55
+ author = 'foyono',
56
+ author_email = 'shrovis@foyono.com',
57
+ py_modules = ['parabject'],
58
+ install_requires = ['importlib-metadata>=2.1.3', 'importlib-resources>=3.3.1', 'pyparsing>=3.0.2'],
59
+ package_data = {'': ['*.pxd', '*.pyx', '*.pyxbld', '*.arid', '*.aridt']},
60
+ entry_points = {'console_scripts': ['aridity=aridity.__init__:main', 'arid-config=aridity.arid_config:main', 'processtemplate=aridity.processtemplate:main']},
61
+ **sourceinfo.setup_kwargs(),
62
+ )
aridity-77/setup.py DELETED
@@ -1,21 +0,0 @@
1
- from setuptools import find_packages, setup
2
-
3
- def long_description():
4
- with open('README.md') as f:
5
- return f.read()
6
-
7
- setup(
8
- name = 'aridity',
9
- version = '77',
10
- description = 'DRY config and template system, easily extensible with Python',
11
- long_description = long_description(),
12
- long_description_content_type = 'text/markdown',
13
- url = 'https://pypi.org/project/aridity/',
14
- author = 'foyono',
15
- author_email = 'shrovis@foyono.com',
16
- packages = find_packages(),
17
- py_modules = ['parabject'],
18
- install_requires = ['importlib-metadata>=2.1.3', 'importlib-resources>=3.3.1', 'pyparsing==2.4.7'],
19
- package_data = {'': ['*.pxd', '*.pyx', '*.pyxbld', '*.arid', '*.aridt']},
20
- entry_points = {'console_scripts': ['aridity=aridity.__init__:main', 'arid-config=aridity.arid_config:main', 'processtemplate=aridity.processtemplate:main']},
21
- )
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