envstack 0.2.6__tar.gz → 0.4.0__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.
- {envstack-0.2.6 → envstack-0.4.0}/PKG-INFO +66 -12
- {envstack-0.2.6 → envstack-0.4.0}/README.md +65 -11
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/__init__.py +3 -1
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/cli.py +8 -1
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/config.py +26 -5
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/env.py +101 -22
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/wrapper.py +1 -41
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/PKG-INFO +66 -12
- {envstack-0.2.6 → envstack-0.4.0}/setup.py +18 -10
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/exceptions.py +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/logger.py +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack/path.py +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/SOURCES.txt +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/dependency_links.txt +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/entry_points.txt +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/not-zip-safe +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/requires.txt +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/lib/envstack.egg-info/top_level.txt +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/setup.cfg +0 -0
- {envstack-0.2.6 → envstack-0.4.0}/stack.env +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: envstack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Stacked environment variable management system.
|
|
5
5
|
Home-page: http://github.com/rsgalloway/envstack
|
|
6
6
|
Author: Ryan Galloway
|
|
@@ -20,10 +20,9 @@ The default stack is `stack` and variables are declared in `stack.env`
|
|
|
20
20
|
files. You can create any new stack by creating new `.env` files, e.g. creating
|
|
21
21
|
a new `test` stack just create `test.env` files.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
> **Note:** envstack works best combined with [siteconf](https://github.com/rsgalloway/siteconf).
|
|
24
24
|
|
|
25
|
-
Installation
|
|
26
|
-
------------
|
|
25
|
+
## Installation
|
|
27
26
|
|
|
28
27
|
The easiest way to install:
|
|
29
28
|
|
|
@@ -35,9 +34,15 @@ $ pip install envstack
|
|
|
35
34
|
|
|
36
35
|
Copy the default stack file
|
|
37
36
|
[`stack.env`](https://github.com/rsgalloway/envstack/blob/master/stack.env)
|
|
38
|
-
to your current working directory,
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
to your current working directory, the root of your project or `/etc/envstack` (the default location for envstack files, or `C:/ProgramData/envstack` on Windows).
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
```bach
|
|
41
|
+
cp stack.env /etc/envstack
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The `stack` namespace is the default environment stack. Running the `envstack` command
|
|
45
|
+
should show you the resolved environment for your platform:
|
|
41
46
|
|
|
42
47
|
```bash
|
|
43
48
|
$ envstack
|
|
@@ -56,7 +61,7 @@ Modify the environment stack by updating `stack.env` or by creating new contextu
|
|
|
56
61
|
You can execute any command inside the default stacked environment like this:
|
|
57
62
|
|
|
58
63
|
```bash
|
|
59
|
-
$
|
|
64
|
+
$ envstack -- <command>
|
|
60
65
|
```
|
|
61
66
|
|
|
62
67
|
For example:
|
|
@@ -106,7 +111,8 @@ linux:
|
|
|
106
111
|
HELLO: world
|
|
107
112
|
```
|
|
108
113
|
|
|
109
|
-
Environment files can include other namespaced environments
|
|
114
|
+
Environment files can include other namespaced environments (all stacks inherit the default stack.env automatically).
|
|
115
|
+
|
|
110
116
|
```yaml
|
|
111
117
|
include: ['other']
|
|
112
118
|
```
|
|
@@ -143,14 +149,39 @@ To see an environment stack on another platform:
|
|
|
143
149
|
$ envstack <stack> -p <platform>
|
|
144
150
|
```
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
## Python API
|
|
153
|
+
|
|
154
|
+
By default, `envstack.getenv` uses the resolved default env stack `stack` and can be
|
|
155
|
+
a drop-in replacement for `os.getenv`
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
>>> import envstack
|
|
159
|
+
>>> envstack.getenv("HELLO")
|
|
160
|
+
'world'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
To use a different stack, use the `init` function:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
>>> envstack.init("thing")
|
|
167
|
+
>>> envstack.getenv("FOO")
|
|
168
|
+
'bar'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The `init` function also updates the current environment for code that is not using envstack:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
>>> os.getenv("FOO")
|
|
175
|
+
'bar'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Running Commands
|
|
148
179
|
|
|
149
180
|
To run any command line executable inside of an environment stack, where `<command>`
|
|
150
181
|
is the command to run:
|
|
151
182
|
|
|
152
183
|
```bash
|
|
153
|
-
$
|
|
184
|
+
$ envstack <stack> -- <command>
|
|
154
185
|
```
|
|
155
186
|
|
|
156
187
|
For example, running python in the default stack (reading from the default `stack.env` file):
|
|
@@ -166,3 +197,26 @@ Same command but using the "thing" stack"
|
|
|
166
197
|
$ envstack thing -- python -c "import os; print(os.environ['FOO'])"
|
|
167
198
|
bar
|
|
168
199
|
```
|
|
200
|
+
|
|
201
|
+
To source the environment in your current shell, source the output of --export (and create
|
|
202
|
+
an alias for convenience):
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
$ source <(envstack --export)
|
|
206
|
+
$ alias esinit='source <(envstack $ARG --export)'
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
In Windows command prompt:
|
|
210
|
+
|
|
211
|
+
```cmd
|
|
212
|
+
for /f "usebackq" %i in (`envstack --export`) do %i
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Config
|
|
216
|
+
|
|
217
|
+
Default config settings are in the config.py module. The following environment variables are supported:
|
|
218
|
+
|
|
219
|
+
| Variable | Description |
|
|
220
|
+
|---------------------|-------------|
|
|
221
|
+
| $DEFAULT_ENV_DIR | the folder containing the default env stack files |
|
|
222
|
+
| $DEFAULT_ENV_STACK | the name of the default env stack namespace (default "stack") |
|
|
@@ -9,10 +9,9 @@ The default stack is `stack` and variables are declared in `stack.env`
|
|
|
9
9
|
files. You can create any new stack by creating new `.env` files, e.g. creating
|
|
10
10
|
a new `test` stack just create `test.env` files.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
> **Note:** envstack works best combined with [siteconf](https://github.com/rsgalloway/siteconf).
|
|
13
13
|
|
|
14
|
-
Installation
|
|
15
|
-
------------
|
|
14
|
+
## Installation
|
|
16
15
|
|
|
17
16
|
The easiest way to install:
|
|
18
17
|
|
|
@@ -24,9 +23,15 @@ $ pip install envstack
|
|
|
24
23
|
|
|
25
24
|
Copy the default stack file
|
|
26
25
|
[`stack.env`](https://github.com/rsgalloway/envstack/blob/master/stack.env)
|
|
27
|
-
to your current working directory,
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
to your current working directory, the root of your project or `/etc/envstack` (the default location for envstack files, or `C:/ProgramData/envstack` on Windows).
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
```bach
|
|
30
|
+
cp stack.env /etc/envstack
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The `stack` namespace is the default environment stack. Running the `envstack` command
|
|
34
|
+
should show you the resolved environment for your platform:
|
|
30
35
|
|
|
31
36
|
```bash
|
|
32
37
|
$ envstack
|
|
@@ -45,7 +50,7 @@ Modify the environment stack by updating `stack.env` or by creating new contextu
|
|
|
45
50
|
You can execute any command inside the default stacked environment like this:
|
|
46
51
|
|
|
47
52
|
```bash
|
|
48
|
-
$
|
|
53
|
+
$ envstack -- <command>
|
|
49
54
|
```
|
|
50
55
|
|
|
51
56
|
For example:
|
|
@@ -95,7 +100,8 @@ linux:
|
|
|
95
100
|
HELLO: world
|
|
96
101
|
```
|
|
97
102
|
|
|
98
|
-
Environment files can include other namespaced environments
|
|
103
|
+
Environment files can include other namespaced environments (all stacks inherit the default stack.env automatically).
|
|
104
|
+
|
|
99
105
|
```yaml
|
|
100
106
|
include: ['other']
|
|
101
107
|
```
|
|
@@ -132,14 +138,39 @@ To see an environment stack on another platform:
|
|
|
132
138
|
$ envstack <stack> -p <platform>
|
|
133
139
|
```
|
|
134
140
|
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
## Python API
|
|
142
|
+
|
|
143
|
+
By default, `envstack.getenv` uses the resolved default env stack `stack` and can be
|
|
144
|
+
a drop-in replacement for `os.getenv`
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
>>> import envstack
|
|
148
|
+
>>> envstack.getenv("HELLO")
|
|
149
|
+
'world'
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
To use a different stack, use the `init` function:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
>>> envstack.init("thing")
|
|
156
|
+
>>> envstack.getenv("FOO")
|
|
157
|
+
'bar'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The `init` function also updates the current environment for code that is not using envstack:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
>>> os.getenv("FOO")
|
|
164
|
+
'bar'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Running Commands
|
|
137
168
|
|
|
138
169
|
To run any command line executable inside of an environment stack, where `<command>`
|
|
139
170
|
is the command to run:
|
|
140
171
|
|
|
141
172
|
```bash
|
|
142
|
-
$
|
|
173
|
+
$ envstack <stack> -- <command>
|
|
143
174
|
```
|
|
144
175
|
|
|
145
176
|
For example, running python in the default stack (reading from the default `stack.env` file):
|
|
@@ -155,3 +186,26 @@ Same command but using the "thing" stack"
|
|
|
155
186
|
$ envstack thing -- python -c "import os; print(os.environ['FOO'])"
|
|
156
187
|
bar
|
|
157
188
|
```
|
|
189
|
+
|
|
190
|
+
To source the environment in your current shell, source the output of --export (and create
|
|
191
|
+
an alias for convenience):
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
$ source <(envstack --export)
|
|
195
|
+
$ alias esinit='source <(envstack $ARG --export)'
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
In Windows command prompt:
|
|
199
|
+
|
|
200
|
+
```cmd
|
|
201
|
+
for /f "usebackq" %i in (`envstack --export`) do %i
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Config
|
|
205
|
+
|
|
206
|
+
Default config settings are in the config.py module. The following environment variables are supported:
|
|
207
|
+
|
|
208
|
+
| Variable | Description |
|
|
209
|
+
|---------------------|-------------|
|
|
210
|
+
| $DEFAULT_ENV_DIR | the folder containing the default env stack files |
|
|
211
|
+
| $DEFAULT_ENV_STACK | the name of the default env stack namespace (default "stack") |
|
|
@@ -40,7 +40,7 @@ import sys
|
|
|
40
40
|
import traceback
|
|
41
41
|
|
|
42
42
|
from envstack import __version__, config
|
|
43
|
-
from envstack.env import build_sources, expandvars, load_environ, trace_var
|
|
43
|
+
from envstack.env import build_sources, expandvars, export, load_environ, trace_var
|
|
44
44
|
from envstack.wrapper import run_command
|
|
45
45
|
|
|
46
46
|
|
|
@@ -75,6 +75,11 @@ def parse_args():
|
|
|
75
75
|
default=config.DEFAULT_NAMESPACE,
|
|
76
76
|
help="the environment stack to use (default '%s')" % config.DEFAULT_NAMESPACE,
|
|
77
77
|
)
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--export",
|
|
80
|
+
action="store_true",
|
|
81
|
+
help="generate export commands for the current shell",
|
|
82
|
+
)
|
|
78
83
|
parser.add_argument(
|
|
79
84
|
"-p",
|
|
80
85
|
"--platform",
|
|
@@ -123,6 +128,8 @@ def main():
|
|
|
123
128
|
sources = build_sources(args.namespace)
|
|
124
129
|
for source in sources:
|
|
125
130
|
print(source)
|
|
131
|
+
elif args.export:
|
|
132
|
+
print(export(args.namespace, config.SHELL))
|
|
126
133
|
elif command:
|
|
127
134
|
return run_command(args.namespace, command)
|
|
128
135
|
else:
|
|
@@ -37,20 +37,41 @@ import os
|
|
|
37
37
|
import platform
|
|
38
38
|
import sys
|
|
39
39
|
|
|
40
|
+
|
|
41
|
+
def detect_shell():
|
|
42
|
+
"""Detect the current shell."""
|
|
43
|
+
if PLATFORM == "windows":
|
|
44
|
+
comspec = os.environ.get("ComSpec")
|
|
45
|
+
if comspec:
|
|
46
|
+
if "cmd.exe" in comspec:
|
|
47
|
+
return "cmd"
|
|
48
|
+
elif "powershell.exe" in comspec:
|
|
49
|
+
return "pwsh"
|
|
50
|
+
else:
|
|
51
|
+
return "unknown"
|
|
52
|
+
else:
|
|
53
|
+
shell = os.environ.get("SHELL")
|
|
54
|
+
if shell:
|
|
55
|
+
return shell.split("/")[-1]
|
|
56
|
+
else:
|
|
57
|
+
return "unknown"
|
|
58
|
+
|
|
59
|
+
|
|
40
60
|
DEBUG = os.getenv("DEBUG")
|
|
41
|
-
DEFAULT_NAMESPACE = "stack"
|
|
61
|
+
DEFAULT_NAMESPACE = os.getenv("DEFAULT_ENV_STACK", "stack")
|
|
42
62
|
LOG_LEVEL = int(os.environ.get("LOG_LEVEL", 20))
|
|
43
63
|
ON_POSIX = "posix" in sys.builtin_module_names
|
|
44
64
|
PLATFORM = platform.system().lower()
|
|
45
65
|
PYTHON_VERSION = sys.version_info[0]
|
|
66
|
+
SHELL = detect_shell()
|
|
46
67
|
USERNAME = os.getenv("USERNAME", os.getenv("USER"))
|
|
47
68
|
|
|
48
|
-
# default location of the global
|
|
69
|
+
# default location of the global env stacks
|
|
49
70
|
DEFAULT_ENV_DIR = os.getenv(
|
|
50
71
|
"DEFAULT_ENV_DIR",
|
|
51
72
|
{
|
|
52
|
-
"darwin":
|
|
53
|
-
"linux":
|
|
54
|
-
"windows":
|
|
73
|
+
"darwin": "/etc/envstack",
|
|
74
|
+
"linux": "/etc/envstack",
|
|
75
|
+
"windows": "C:/ProgramData/envstack",
|
|
55
76
|
}.get(PLATFORM),
|
|
56
77
|
)
|
|
@@ -356,31 +356,44 @@ def clear_file_cache():
|
|
|
356
356
|
load_file_cache = {}
|
|
357
357
|
|
|
358
358
|
|
|
359
|
-
def
|
|
360
|
-
"""Returns
|
|
361
|
-
Useful for preserving nested values in wrappers.
|
|
362
|
-
"""
|
|
359
|
+
def decode_value(value):
|
|
360
|
+
"""Returns a decoded value that's been encoded by a wrapper.
|
|
363
361
|
|
|
364
|
-
|
|
362
|
+
Decoding encoded environments can be tricky. For example, it must account for path
|
|
363
|
+
templates that include curly braces, e.g. path templates string like this must be
|
|
364
|
+
preserved:
|
|
365
365
|
|
|
366
|
-
|
|
367
|
-
from ast import literal_eval
|
|
366
|
+
'/path/with/{variable}'
|
|
368
367
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
368
|
+
:param value: wrapper encoded env value
|
|
369
|
+
:returns: decoded value
|
|
370
|
+
"""
|
|
371
|
+
# TODO: find a better way to encode/decode wrapper envs
|
|
372
|
+
return (
|
|
373
|
+
str(value)
|
|
374
|
+
.replace("'[", "[")
|
|
375
|
+
.replace("]'", "]")
|
|
376
|
+
.replace('"[', "[")
|
|
377
|
+
.replace(']"', "]")
|
|
378
|
+
.replace('"{"', "{'")
|
|
379
|
+
.replace('"}"', "'}")
|
|
380
|
+
.replace("'{'", "{'")
|
|
381
|
+
.replace("'}'", "'}")
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def encode(env, resolved=True):
|
|
386
|
+
"""Returns environment as a dict with str encoded key/values for passing to
|
|
387
|
+
wrapper subprocesses.
|
|
388
|
+
|
|
389
|
+
:param env: `Env` instance or os.environ.
|
|
390
|
+
:param resolved: fully resolve values (default=True).
|
|
391
|
+
:returns: dict with bytestring key/values.
|
|
392
|
+
"""
|
|
393
|
+
c = lambda v: str(v)
|
|
394
|
+
if resolved:
|
|
395
|
+
return dict((c(k), c(expandvars(v, env))) for k, v in env.items())
|
|
396
|
+
return dict((c(k), c(v)) for k, v in env.items())
|
|
384
397
|
|
|
385
398
|
|
|
386
399
|
def build_sources(
|
|
@@ -481,6 +494,47 @@ def expandvars(var, env=None, recursive=False):
|
|
|
481
494
|
return EnvVar(var).expand(env, recursive=recursive)
|
|
482
495
|
|
|
483
496
|
|
|
497
|
+
def export(name, shell="bash", resolve=False, scope=None):
|
|
498
|
+
"""Returns environment commands that can be sourced.
|
|
499
|
+
|
|
500
|
+
$ source <(envstack --export)
|
|
501
|
+
|
|
502
|
+
List of shell names: bash, tcsh, cmd, pwsh
|
|
503
|
+
(see output of config.detect_shell()).
|
|
504
|
+
|
|
505
|
+
:param name: stack namespace
|
|
506
|
+
:param shell: name of shell (default: bash)
|
|
507
|
+
:param resolve: resolve values (default: True)
|
|
508
|
+
:param scope: environment scope (default: cwd)
|
|
509
|
+
:returns: shell commands as string
|
|
510
|
+
"""
|
|
511
|
+
env = load_environ(name, scope=scope)
|
|
512
|
+
expList = list()
|
|
513
|
+
for k, v in env.items():
|
|
514
|
+
if resolve:
|
|
515
|
+
v = expandvars(v, env, recursive=False)
|
|
516
|
+
if shell == "bash":
|
|
517
|
+
expList.append('export {0}="{1}"'.format(k, v))
|
|
518
|
+
elif shell == "tcsh":
|
|
519
|
+
expList.append('setenv {0}:"{1}"'.format(k, v))
|
|
520
|
+
elif shell == "cmd":
|
|
521
|
+
expList.append('set {0}="{1}"'.format(k, v))
|
|
522
|
+
elif shell == "pwsh":
|
|
523
|
+
expList.append('$env:{0}="{1}"'.format(k, v))
|
|
524
|
+
expList.sort()
|
|
525
|
+
exp = "\n".join(expList)
|
|
526
|
+
return exp
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def init(name=config.DEFAULT_NAMESPACE):
|
|
530
|
+
"""Initializes the environment for a given namespace.
|
|
531
|
+
|
|
532
|
+
:param name: namespace (basename of env files).
|
|
533
|
+
"""
|
|
534
|
+
env = load_environ(name)
|
|
535
|
+
os.environ.update(encode(env))
|
|
536
|
+
|
|
537
|
+
|
|
484
538
|
def load_environ(
|
|
485
539
|
name=config.DEFAULT_NAMESPACE,
|
|
486
540
|
sources=None,
|
|
@@ -562,6 +616,31 @@ def load_file(path):
|
|
|
562
616
|
return data
|
|
563
617
|
|
|
564
618
|
|
|
619
|
+
def safe_eval(value):
|
|
620
|
+
"""Returns template value preserving original class.
|
|
621
|
+
Useful for preserving nested values in wrappers.
|
|
622
|
+
"""
|
|
623
|
+
|
|
624
|
+
try:
|
|
625
|
+
from ast import literal_eval
|
|
626
|
+
|
|
627
|
+
eval_func = literal_eval
|
|
628
|
+
except ImportError:
|
|
629
|
+
# warning: security issue
|
|
630
|
+
eval_func = eval
|
|
631
|
+
|
|
632
|
+
if type(value) == str:
|
|
633
|
+
try:
|
|
634
|
+
return eval_func(value)
|
|
635
|
+
except Exception:
|
|
636
|
+
try:
|
|
637
|
+
return eval_func(decode_value(value))
|
|
638
|
+
except Exception:
|
|
639
|
+
return value
|
|
640
|
+
|
|
641
|
+
return value
|
|
642
|
+
|
|
643
|
+
|
|
565
644
|
def trace_var(name, var, scope=None):
|
|
566
645
|
"""Traces where a var is getting set for a given name.
|
|
567
646
|
|
|
@@ -38,47 +38,7 @@ import subprocess
|
|
|
38
38
|
import traceback
|
|
39
39
|
|
|
40
40
|
from envstack import logger
|
|
41
|
-
from envstack.env import expandvars, load_environ
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def decode_value(value):
|
|
45
|
-
"""Returns a decoded value that's been encoded by a wrapper.
|
|
46
|
-
|
|
47
|
-
Decoding encoded environments can be tricky. For example, it must account for path
|
|
48
|
-
templates that include curly braces, e.g. path templates string like this must be
|
|
49
|
-
preserved:
|
|
50
|
-
|
|
51
|
-
'/path/with/{variable}'
|
|
52
|
-
|
|
53
|
-
:param value: wrapper encoded env value
|
|
54
|
-
:returns: decoded value
|
|
55
|
-
"""
|
|
56
|
-
# TODO: find a better way to encode/decode wrapper envs
|
|
57
|
-
return (
|
|
58
|
-
str(value)
|
|
59
|
-
.replace("'[", "[")
|
|
60
|
-
.replace("]'", "]")
|
|
61
|
-
.replace('"[', "[")
|
|
62
|
-
.replace(']"', "]")
|
|
63
|
-
.replace('"{"', "{'")
|
|
64
|
-
.replace('"}"', "'}")
|
|
65
|
-
.replace("'{'", "{'")
|
|
66
|
-
.replace("'}'", "'}")
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def encode(env, resolved=True):
|
|
71
|
-
"""Returns environment as a dict with str encoded key/values for passing to
|
|
72
|
-
wrapper subprocesses.
|
|
73
|
-
|
|
74
|
-
:param env: `Env` instance or os.environ.
|
|
75
|
-
:param resolved: fully resolve values (default=True).
|
|
76
|
-
:returns: dict with bytestring key/values.
|
|
77
|
-
"""
|
|
78
|
-
c = lambda v: str(v)
|
|
79
|
-
if resolved:
|
|
80
|
-
return dict((c(k), c(expandvars(v, env))) for k, v in env.items())
|
|
81
|
-
return dict((c(k), c(v)) for k, v in env.items())
|
|
41
|
+
from envstack.env import encode, expandvars, load_environ
|
|
82
42
|
|
|
83
43
|
|
|
84
44
|
def to_args(cmd):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: envstack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Stacked environment variable management system.
|
|
5
5
|
Home-page: http://github.com/rsgalloway/envstack
|
|
6
6
|
Author: Ryan Galloway
|
|
@@ -20,10 +20,9 @@ The default stack is `stack` and variables are declared in `stack.env`
|
|
|
20
20
|
files. You can create any new stack by creating new `.env` files, e.g. creating
|
|
21
21
|
a new `test` stack just create `test.env` files.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
> **Note:** envstack works best combined with [siteconf](https://github.com/rsgalloway/siteconf).
|
|
24
24
|
|
|
25
|
-
Installation
|
|
26
|
-
------------
|
|
25
|
+
## Installation
|
|
27
26
|
|
|
28
27
|
The easiest way to install:
|
|
29
28
|
|
|
@@ -35,9 +34,15 @@ $ pip install envstack
|
|
|
35
34
|
|
|
36
35
|
Copy the default stack file
|
|
37
36
|
[`stack.env`](https://github.com/rsgalloway/envstack/blob/master/stack.env)
|
|
38
|
-
to your current working directory,
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
to your current working directory, the root of your project or `/etc/envstack` (the default location for envstack files, or `C:/ProgramData/envstack` on Windows).
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
```bach
|
|
41
|
+
cp stack.env /etc/envstack
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The `stack` namespace is the default environment stack. Running the `envstack` command
|
|
45
|
+
should show you the resolved environment for your platform:
|
|
41
46
|
|
|
42
47
|
```bash
|
|
43
48
|
$ envstack
|
|
@@ -56,7 +61,7 @@ Modify the environment stack by updating `stack.env` or by creating new contextu
|
|
|
56
61
|
You can execute any command inside the default stacked environment like this:
|
|
57
62
|
|
|
58
63
|
```bash
|
|
59
|
-
$
|
|
64
|
+
$ envstack -- <command>
|
|
60
65
|
```
|
|
61
66
|
|
|
62
67
|
For example:
|
|
@@ -106,7 +111,8 @@ linux:
|
|
|
106
111
|
HELLO: world
|
|
107
112
|
```
|
|
108
113
|
|
|
109
|
-
Environment files can include other namespaced environments
|
|
114
|
+
Environment files can include other namespaced environments (all stacks inherit the default stack.env automatically).
|
|
115
|
+
|
|
110
116
|
```yaml
|
|
111
117
|
include: ['other']
|
|
112
118
|
```
|
|
@@ -143,14 +149,39 @@ To see an environment stack on another platform:
|
|
|
143
149
|
$ envstack <stack> -p <platform>
|
|
144
150
|
```
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
## Python API
|
|
153
|
+
|
|
154
|
+
By default, `envstack.getenv` uses the resolved default env stack `stack` and can be
|
|
155
|
+
a drop-in replacement for `os.getenv`
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
>>> import envstack
|
|
159
|
+
>>> envstack.getenv("HELLO")
|
|
160
|
+
'world'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
To use a different stack, use the `init` function:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
>>> envstack.init("thing")
|
|
167
|
+
>>> envstack.getenv("FOO")
|
|
168
|
+
'bar'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The `init` function also updates the current environment for code that is not using envstack:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
>>> os.getenv("FOO")
|
|
175
|
+
'bar'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Running Commands
|
|
148
179
|
|
|
149
180
|
To run any command line executable inside of an environment stack, where `<command>`
|
|
150
181
|
is the command to run:
|
|
151
182
|
|
|
152
183
|
```bash
|
|
153
|
-
$
|
|
184
|
+
$ envstack <stack> -- <command>
|
|
154
185
|
```
|
|
155
186
|
|
|
156
187
|
For example, running python in the default stack (reading from the default `stack.env` file):
|
|
@@ -166,3 +197,26 @@ Same command but using the "thing" stack"
|
|
|
166
197
|
$ envstack thing -- python -c "import os; print(os.environ['FOO'])"
|
|
167
198
|
bar
|
|
168
199
|
```
|
|
200
|
+
|
|
201
|
+
To source the environment in your current shell, source the output of --export (and create
|
|
202
|
+
an alias for convenience):
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
$ source <(envstack --export)
|
|
206
|
+
$ alias esinit='source <(envstack $ARG --export)'
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
In Windows command prompt:
|
|
210
|
+
|
|
211
|
+
```cmd
|
|
212
|
+
for /f "usebackq" %i in (`envstack --export`) do %i
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Config
|
|
216
|
+
|
|
217
|
+
Default config settings are in the config.py module. The following environment variables are supported:
|
|
218
|
+
|
|
219
|
+
| Variable | Description |
|
|
220
|
+
|---------------------|-------------|
|
|
221
|
+
| $DEFAULT_ENV_DIR | the folder containing the default env stack files |
|
|
222
|
+
| $DEFAULT_ENV_STACK | the name of the default env stack namespace (default "stack") |
|
|
@@ -43,27 +43,35 @@ with open(os.path.join(here, "README.md")) as f:
|
|
|
43
43
|
class PostInstallCommand(install):
|
|
44
44
|
"""Custom post-installation for copying stack.env."""
|
|
45
45
|
|
|
46
|
-
def
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
def install_default_stack(self):
|
|
47
|
+
"""Copy the default stack.env file to the default location."""
|
|
48
|
+
from envstack.config import DEFAULT_ENV_DIR
|
|
49
49
|
|
|
50
|
-
if not
|
|
51
|
-
|
|
52
|
-
return
|
|
50
|
+
if not os.path.isdir(DEFAULT_ENV_DIR):
|
|
51
|
+
os.makedirs(DEFAULT_ENV_DIR)
|
|
53
52
|
|
|
54
53
|
source = os.path.join(os.path.dirname(__file__), "stack.env")
|
|
55
|
-
destination = os.path.join(
|
|
54
|
+
destination = os.path.join(DEFAULT_ENV_DIR, "stack.env")
|
|
56
55
|
|
|
57
56
|
if os.path.exists(source):
|
|
57
|
+
print(f"Copying {source} to {destination}")
|
|
58
58
|
shutil.copy(source, destination)
|
|
59
|
-
print(f"Copied {source} to {destination}")
|
|
60
59
|
else:
|
|
61
|
-
print(f"{source} not found")
|
|
60
|
+
print(f"{source} not found)")
|
|
61
|
+
|
|
62
|
+
def run(self):
|
|
63
|
+
"""Run the default install and copy the default stack.env file."""
|
|
64
|
+
install.run(self)
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
self.install_default_stack()
|
|
68
|
+
except Exception as e:
|
|
69
|
+
print(f"Error copying stack.env: {e}")
|
|
62
70
|
|
|
63
71
|
|
|
64
72
|
setup(
|
|
65
73
|
name="envstack",
|
|
66
|
-
version="0.
|
|
74
|
+
version="0.4.0",
|
|
67
75
|
description="Stacked environment variable management system.",
|
|
68
76
|
long_description=long_description,
|
|
69
77
|
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
|