aridity 62__tar.gz → 63__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: 62
3
+ Version: 63
4
4
  Summary: DRY config and template system, easily extensible with Python
5
5
  Home-page: https://github.com/combatopera/aridity
6
6
  Author: Andrzej Cichocki
@@ -27,6 +27,42 @@ DRY config and template system, easily extensible with Python
27
27
  * Principle of least astonishment driven design
28
28
  * Don't make users jump through hoops
29
29
 
30
+ ## Motivation
31
+ * Environment variables are too crude to configure non-trivial apps, and maybe even trivial apps in the cloud
32
+ * They do not support nested data or lists, without some encoding scheme implemented in app code or a lib
33
+ * Multiple bespoke encoding schemes in the system are an error-prone maintenance burden worth avoiding
34
+ * Testing code that queries the environment directly comes with a big risk of leaking state between tests
35
+ * Often tools/libraries must be configured using config files
36
+ * Support for config file interpolation is not enough to stay DRY, and comes with a different set of gotchas per tool
37
+ * In particular Helm/Terraform have their own ways of sharing config between envs
38
+ * aridity is a general purpose solution for all the above, also see [soak](https://github.com/combatopera/soak)
39
+
40
+ ## Config API
41
+ * Normally you pass around a Config object, and application code can get data out via attribute access e.g. config.foo.bar
42
+ * Here config.foo is also a Config object, a child scope of config named foo
43
+ * The passing around can be taken care of by a dependency injection container such as [diapyr](https://github.com/combatopera/diapyr)
44
+ * Every Config has an associated ConfigCtrl on which Python API such as processtemplate is available
45
+ * Use negation to get ConfigCtrl when you have a Config e.g. (-config).processtemplate(...)
46
+ * Use the node attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
47
+ * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
48
+
49
+ ## Guidelines
50
+ * Config files have the extension .arid and templates .aridt
51
+ * A template is simply a file-sized aridity expression
52
+ * Conventionally the template processor sets " to the appropriate quote function for the file format, e.g. jsonquote for JSON/YAML
53
+ * Instead of adding Python objects to the config in main, it's tidier to use aridity's pyref function to achieve this
54
+ * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
55
+
56
+ ## Feature switch
57
+ * Sometimes we want to deploy a change, but something in production isn't ready for that change
58
+ * A feature switch allows deployment to production in this case
59
+ * Add a boolean to the base config (conventionally root.arid) e.g. foo enabled = true
60
+ * This value should be the configuration that we eventually want in all environments
61
+ * In production config, override with foo enabled = false
62
+ * In the code, read config.foo.enabled and enable the change based on this boolean
63
+ * The above can now be deployed to all environments, and is not a blocker for other changes
64
+ * Later when production is ready for it, it's a 1 line change to remove the override from production config
65
+
30
66
  ## Install
31
67
  These are generic installation instructions.
32
68
 
@@ -16,6 +16,42 @@ DRY config and template system, easily extensible with Python
16
16
  * Principle of least astonishment driven design
17
17
  * Don't make users jump through hoops
18
18
 
19
+ ## Motivation
20
+ * Environment variables are too crude to configure non-trivial apps, and maybe even trivial apps in the cloud
21
+ * They do not support nested data or lists, without some encoding scheme implemented in app code or a lib
22
+ * Multiple bespoke encoding schemes in the system are an error-prone maintenance burden worth avoiding
23
+ * Testing code that queries the environment directly comes with a big risk of leaking state between tests
24
+ * Often tools/libraries must be configured using config files
25
+ * Support for config file interpolation is not enough to stay DRY, and comes with a different set of gotchas per tool
26
+ * In particular Helm/Terraform have their own ways of sharing config between envs
27
+ * aridity is a general purpose solution for all the above, also see [soak](https://github.com/combatopera/soak)
28
+
29
+ ## 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
32
+ * The passing around can be taken care of by a dependency injection container such as [diapyr](https://github.com/combatopera/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
36
+ * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
37
+
38
+ ## Guidelines
39
+ * Config files have the extension .arid and templates .aridt
40
+ * 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
43
+ * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
44
+
45
+ ## Feature switch
46
+ * Sometimes we want to deploy a change, but something in production isn't ready for that change
47
+ * 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
49
+ * 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
52
+ * The above can now be deployed to all environments, and is not a blocker for other changes
53
+ * Later when production is ready for it, it's a 1 line change to remove the override from production config
54
+
19
55
  ## Install
20
56
  These are generic installation instructions.
21
57
 
@@ -42,6 +42,7 @@ def _processmainfunction(mainfunction):
42
42
  appname = scriptname[:-len(dotpy)].replace('_', '-')
43
43
  else:
44
44
  attr = mainfunction.__qualname__
45
+ # FIXME: Requires metadata e.g. egg-info in projects that have not been installed:
45
46
  appname, = (ep.name for ep in entry_points(group = 'console_scripts') if ep.module == module and ep.attr == attr)
46
47
  return module, appname
47
48
 
@@ -38,7 +38,7 @@ class OpaqueKey(object):
38
38
 
39
39
  class Functions:
40
40
 
41
- from .keyring import keyring
41
+ from .keyring import gpg, keyring
42
42
 
43
43
  def screenstr(scope, resolvable):
44
44
  text = resolvable.resolve(scope).cat()
@@ -17,8 +17,11 @@
17
17
 
18
18
  from .model import Scalar
19
19
  from .util import null_exc_info
20
+ from base64 import b64decode
20
21
  from functools import partial
21
22
  from getpass import getpass
23
+ from subprocess import check_output
24
+ from tempfile import NamedTemporaryFile
22
25
  from threading import Semaphore
23
26
  import logging, os
24
27
 
@@ -51,3 +54,9 @@ def keyring(scope, serviceres, usernameres):
51
54
  username = usernameres.resolve(scope).cat()
52
55
  password = None if scope.resolved('keyring_force').scalar else get_password(service, username)
53
56
  return Scalar(Password(*[getpass(), partial(set_password, service, username)] if password is None else [password, None]))
57
+
58
+ def gpg(scope, resolvable):
59
+ with NamedTemporaryFile() as f:
60
+ f.write(b64decode(resolvable.resolve(scope).cat()))
61
+ f.flush()
62
+ return Scalar(Password(check_output(['gpg', '-d', f.name]).decode('ascii'), None))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aridity
3
- Version: 62
3
+ Version: 63
4
4
  Summary: DRY config and template system, easily extensible with Python
5
5
  Home-page: https://github.com/combatopera/aridity
6
6
  Author: Andrzej Cichocki
@@ -27,6 +27,42 @@ DRY config and template system, easily extensible with Python
27
27
  * Principle of least astonishment driven design
28
28
  * Don't make users jump through hoops
29
29
 
30
+ ## Motivation
31
+ * Environment variables are too crude to configure non-trivial apps, and maybe even trivial apps in the cloud
32
+ * They do not support nested data or lists, without some encoding scheme implemented in app code or a lib
33
+ * Multiple bespoke encoding schemes in the system are an error-prone maintenance burden worth avoiding
34
+ * Testing code that queries the environment directly comes with a big risk of leaking state between tests
35
+ * Often tools/libraries must be configured using config files
36
+ * Support for config file interpolation is not enough to stay DRY, and comes with a different set of gotchas per tool
37
+ * In particular Helm/Terraform have their own ways of sharing config between envs
38
+ * aridity is a general purpose solution for all the above, also see [soak](https://github.com/combatopera/soak)
39
+
40
+ ## Config API
41
+ * Normally you pass around a Config object, and application code can get data out via attribute access e.g. config.foo.bar
42
+ * Here config.foo is also a Config object, a child scope of config named foo
43
+ * The passing around can be taken care of by a dependency injection container such as [diapyr](https://github.com/combatopera/diapyr)
44
+ * Every Config has an associated ConfigCtrl on which Python API such as processtemplate is available
45
+ * Use negation to get ConfigCtrl when you have a Config e.g. (-config).processtemplate(...)
46
+ * Use the node attribute to get Config when you have a ConfigCtrl, this is a rare situation in practice
47
+ * When unit testing a class or function that expects a Config object, you can use SimpleNamespace to mock one
48
+
49
+ ## Guidelines
50
+ * Config files have the extension .arid and templates .aridt
51
+ * A template is simply a file-sized aridity expression
52
+ * Conventionally the template processor sets " to the appropriate quote function for the file format, e.g. jsonquote for JSON/YAML
53
+ * Instead of adding Python objects to the config in main, it's tidier to use aridity's pyref function to achieve this
54
+ * When some value needs to be constructed using concatenation, consider whether it would be more tasteful to do this in the config
55
+
56
+ ## Feature switch
57
+ * Sometimes we want to deploy a change, but something in production isn't ready for that change
58
+ * A feature switch allows deployment to production in this case
59
+ * Add a boolean to the base config (conventionally root.arid) e.g. foo enabled = true
60
+ * This value should be the configuration that we eventually want in all environments
61
+ * In production config, override with foo enabled = false
62
+ * In the code, read config.foo.enabled and enable the change based on this boolean
63
+ * The above can now be deployed to all environments, and is not a blocker for other changes
64
+ * Later when production is ready for it, it's a 1 line change to remove the override from production config
65
+
30
66
  ## Install
31
67
  These are generic installation instructions.
32
68
 
@@ -136,7 +136,7 @@ def ext_modules():
136
136
  sourceinfo = SourceInfo('.')
137
137
  setuptools.setup(
138
138
  name = 'aridity',
139
- version = '62',
139
+ version = '63',
140
140
  description = 'DRY config and template system, easily extensible with Python',
141
141
  long_description = long_description(),
142
142
  long_description_content_type = 'text/markdown',
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