envstack 0.6.2__tar.gz → 0.6.3__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.6.2/lib/envstack.egg-info → envstack-0.6.3}/PKG-INFO +21 -6
- {envstack-0.6.2 → envstack-0.6.3}/README.md +20 -5
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/__init__.py +2 -2
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/config.py +4 -5
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/env.py +67 -8
- envstack-0.6.3/lib/envstack/util.py +81 -0
- {envstack-0.6.2 → envstack-0.6.3/lib/envstack.egg-info}/PKG-INFO +21 -6
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/SOURCES.txt +1 -0
- {envstack-0.6.2 → envstack-0.6.3}/setup.py +1 -1
- {envstack-0.6.2 → envstack-0.6.3}/LICENSE +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/dev.env +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/dist.json +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/cli.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/exceptions.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/logger.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/path.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack/wrapper.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/dependency_links.txt +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/entry_points.txt +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/not-zip-safe +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/requires.txt +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/lib/envstack.egg-info/top_level.txt +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/setup.cfg +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/stack.env +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/tests/test_env.py +0 -0
- {envstack-0.6.2 → envstack-0.6.3}/tests/test_path.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: envstack
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Stacked environment variable management system
|
|
5
5
|
Home-page: http://github.com/rsgalloway/envstack
|
|
6
6
|
Author: Ryan Galloway
|
|
@@ -184,19 +184,34 @@ $ envstack [STACK] --sources
|
|
|
184
184
|
|
|
185
185
|
## Python API
|
|
186
186
|
|
|
187
|
-
To
|
|
187
|
+
To initialize the environment stack in Python, use the `init` function:
|
|
188
188
|
|
|
189
189
|
```python
|
|
190
|
-
>>> envstack.init(
|
|
191
|
-
>>> os.getenv("
|
|
192
|
-
'
|
|
190
|
+
>>> envstack.init()
|
|
191
|
+
>>> os.getenv("HELLO")
|
|
192
|
+
'world'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
To initialize the "dev" stack:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
>>> envstack.init("dev")
|
|
199
|
+
>>> os.getenv("ENV")
|
|
200
|
+
'dev'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
To revert the original environment:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
>>> envstack.revert()
|
|
207
|
+
>>> os.getenv("HELLO")
|
|
208
|
+
>>>
|
|
193
209
|
```
|
|
194
210
|
|
|
195
211
|
Alternatively, `envstack.getenv` can be a drop-in replacement for `os.getenv`
|
|
196
212
|
for the default environment stack:
|
|
197
213
|
|
|
198
214
|
```python
|
|
199
|
-
>>> import envstack
|
|
200
215
|
>>> envstack.getenv("HELLO")
|
|
201
216
|
'world'
|
|
202
217
|
```
|
|
@@ -161,19 +161,34 @@ $ envstack [STACK] --sources
|
|
|
161
161
|
|
|
162
162
|
## Python API
|
|
163
163
|
|
|
164
|
-
To
|
|
164
|
+
To initialize the environment stack in Python, use the `init` function:
|
|
165
165
|
|
|
166
166
|
```python
|
|
167
|
-
>>> envstack.init(
|
|
168
|
-
>>> os.getenv("
|
|
169
|
-
'
|
|
167
|
+
>>> envstack.init()
|
|
168
|
+
>>> os.getenv("HELLO")
|
|
169
|
+
'world'
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
To initialize the "dev" stack:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
>>> envstack.init("dev")
|
|
176
|
+
>>> os.getenv("ENV")
|
|
177
|
+
'dev'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
To revert the original environment:
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
>>> envstack.revert()
|
|
184
|
+
>>> os.getenv("HELLO")
|
|
185
|
+
>>>
|
|
170
186
|
```
|
|
171
187
|
|
|
172
188
|
Alternatively, `envstack.getenv` can be a drop-in replacement for `os.getenv`
|
|
173
189
|
for the default environment stack:
|
|
174
190
|
|
|
175
191
|
```python
|
|
176
|
-
>>> import envstack
|
|
177
192
|
>>> envstack.getenv("HELLO")
|
|
178
193
|
'world'
|
|
179
194
|
```
|
|
@@ -34,6 +34,6 @@ Stacked environment variable management system.
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
__prog__ = "envstack"
|
|
37
|
-
__version__ = "0.6.
|
|
37
|
+
__version__ = "0.6.3"
|
|
38
38
|
|
|
39
|
-
from envstack.env import Env, getenv, init, load_file
|
|
39
|
+
from envstack.env import Env, getenv, init, load_file, revert, save
|
|
@@ -76,14 +76,13 @@ DEFAULT_ENV = {
|
|
|
76
76
|
"USER": USERNAME,
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
# default location of
|
|
80
|
-
# NOTE: the siteconf sitecustomize.py module may override this
|
|
79
|
+
# default location of env stack .env files
|
|
81
80
|
DEFAULT_ENV_DIR = os.getenv(
|
|
82
81
|
"DEFAULT_ENV_DIR",
|
|
83
82
|
{
|
|
84
|
-
"darwin": "{HOME}/Library/Application Support/
|
|
85
|
-
"linux": "{HOME}/.local/
|
|
86
|
-
"windows": "C:\\ProgramData\\
|
|
83
|
+
"darwin": "{HOME}/Library/Application Support/pipe/{ENV}/env",
|
|
84
|
+
"linux": "{HOME}/.local/pipe/{ENV}/env",
|
|
85
|
+
"windows": "C:\\ProgramData\\pipe\\{ENV}\\env",
|
|
87
86
|
}
|
|
88
87
|
.get(PLATFORM)
|
|
89
88
|
.format(**DEFAULT_ENV),
|
|
@@ -36,8 +36,9 @@ Contains functions and classes for processing scoped .env files.
|
|
|
36
36
|
import os
|
|
37
37
|
import re
|
|
38
38
|
import string
|
|
39
|
+
import sys
|
|
39
40
|
|
|
40
|
-
from envstack import config, logger, path
|
|
41
|
+
from envstack import config, logger, path, util
|
|
41
42
|
from envstack.exceptions import *
|
|
42
43
|
|
|
43
44
|
# value delimiter pattern (splits values by colons or semicolons)
|
|
@@ -49,6 +50,9 @@ load_file_cache = {}
|
|
|
49
50
|
# value for unresolvable variables
|
|
50
51
|
null = ""
|
|
51
52
|
|
|
53
|
+
# stores the original environment
|
|
54
|
+
SAVED_ENVIRONMENT = None
|
|
55
|
+
|
|
52
56
|
|
|
53
57
|
class EnvVar(string.Template, str):
|
|
54
58
|
"""A string class for supporting $-substitutions, e.g.: ::
|
|
@@ -529,7 +533,7 @@ def expandvars(var, env=None, recursive=False):
|
|
|
529
533
|
return EnvVar(var).expand(env, recursive=recursive)
|
|
530
534
|
|
|
531
535
|
|
|
532
|
-
def export(name, shell=
|
|
536
|
+
def export(name, shell=config.SHELL, resolve=False, scope=None, clear=False):
|
|
533
537
|
"""Returns environment commands that can be sourced.
|
|
534
538
|
|
|
535
539
|
$ source <(envstack --export)
|
|
@@ -542,7 +546,7 @@ def export(name, shell="bash", resolve=False, scope=None, clear=False):
|
|
|
542
546
|
(see output of config.detect_shell()).
|
|
543
547
|
|
|
544
548
|
:param name: stack namespace.
|
|
545
|
-
:param shell: name of shell (default:
|
|
549
|
+
:param shell: name of shell (default: current shell).
|
|
546
550
|
:param resolve: resolve values (default: True).
|
|
547
551
|
:param scope: environment scope (default: cwd).
|
|
548
552
|
:param clear: clear existing values (default: False).
|
|
@@ -580,14 +584,66 @@ def export(name, shell="bash", resolve=False, scope=None, clear=False):
|
|
|
580
584
|
return exp
|
|
581
585
|
|
|
582
586
|
|
|
587
|
+
def save():
|
|
588
|
+
"""Saves the current environment."""
|
|
589
|
+
global SAVED_ENVIRONMENT
|
|
590
|
+
if not SAVED_ENVIRONMENT:
|
|
591
|
+
SAVED_ENVIRONMENT = dict(os.environ.copy())
|
|
592
|
+
return SAVED_ENVIRONMENT
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def revert():
|
|
596
|
+
"""Reverts the environment to the saved environment."""
|
|
597
|
+
global SAVED_ENVIRONMENT
|
|
598
|
+
if SAVED_ENVIRONMENT is None:
|
|
599
|
+
return
|
|
600
|
+
os.environ.clear()
|
|
601
|
+
os.environ.update(SAVED_ENVIRONMENT)
|
|
602
|
+
|
|
603
|
+
|
|
583
604
|
def init(name=config.DEFAULT_NAMESPACE):
|
|
584
|
-
"""Initializes the environment for a given namespace.
|
|
605
|
+
"""Initializes the environment for a given namespace. Modifies sys.path
|
|
606
|
+
from PYTHONPATH.
|
|
585
607
|
|
|
586
|
-
|
|
608
|
+
# initialize the default environemnt
|
|
609
|
+
>>> envstack.init()
|
|
610
|
+
|
|
611
|
+
# initialize the dev environment
|
|
612
|
+
>>> envstack.init('dev')
|
|
613
|
+
|
|
614
|
+
# revert to the original environment
|
|
615
|
+
>>> envstack.revert()
|
|
616
|
+
|
|
617
|
+
:param name: stack namespace (default stack).
|
|
587
618
|
"""
|
|
619
|
+
logger.log.debug("initializing env stack: %s", name)
|
|
620
|
+
|
|
621
|
+
# save the current environment
|
|
622
|
+
save()
|
|
623
|
+
|
|
624
|
+
# clear old sys.path values
|
|
625
|
+
for path in util.get_paths_from_var("PYTHONPATH"):
|
|
626
|
+
if path and path in sys.path:
|
|
627
|
+
sys.path.remove(path)
|
|
628
|
+
|
|
629
|
+
# clear vars from stack namespace
|
|
630
|
+
env = load_environ(name, environ=None)
|
|
631
|
+
for key in env.keys():
|
|
632
|
+
if key in os.environ:
|
|
633
|
+
del os.environ[key]
|
|
634
|
+
|
|
635
|
+
# store the name of the environment stack (e.g. for $PS1)
|
|
636
|
+
os.environ["ENVSTACK"] = name
|
|
637
|
+
|
|
638
|
+
# load the new environment
|
|
588
639
|
env = load_environ(name)
|
|
589
640
|
os.environ.update(encode(env))
|
|
590
641
|
|
|
642
|
+
# update sys.path from PYTHONPATH
|
|
643
|
+
for path in util.get_paths_from_var("PYTHONPATH"):
|
|
644
|
+
if path and path not in sys.path:
|
|
645
|
+
sys.path.insert(0, path)
|
|
646
|
+
|
|
591
647
|
|
|
592
648
|
def load_environ(
|
|
593
649
|
name=config.DEFAULT_NAMESPACE,
|
|
@@ -688,9 +744,11 @@ def merge(env, other, strict=False, platform=config.PLATFORM):
|
|
|
688
744
|
"""
|
|
689
745
|
merged = env.copy()
|
|
690
746
|
for key, value in merged.items():
|
|
691
|
-
|
|
747
|
+
varstr = "${%s}" % key
|
|
748
|
+
# replace variables in other with values from env
|
|
692
749
|
if key in other:
|
|
693
|
-
|
|
750
|
+
# replace variables in value with values from other
|
|
751
|
+
if varstr in str(value):
|
|
694
752
|
value = re.sub(
|
|
695
753
|
r"\${(\w+)}",
|
|
696
754
|
lambda match: other.get(match.group(1), match.group(0)),
|
|
@@ -699,7 +757,8 @@ def merge(env, other, strict=False, platform=config.PLATFORM):
|
|
|
699
757
|
elif not strict:
|
|
700
758
|
value = other.get(key)
|
|
701
759
|
else:
|
|
702
|
-
value = str(value).replace(
|
|
760
|
+
value = str(value).replace(varstr, "")
|
|
761
|
+
# replace colons with semicolons on windows
|
|
703
762
|
if platform == "windows":
|
|
704
763
|
result = re.sub(r"(?<!\b[A-Za-z]):", ";", str(value))
|
|
705
764
|
value = result.rstrip(";")
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2024, Ryan Galloway (ryan@rsgalloway.com)
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
|
7
|
+
#
|
|
8
|
+
# - Redistributions of source code must retain the above copyright notice,
|
|
9
|
+
# this list of conditions and the following disclaimer.
|
|
10
|
+
#
|
|
11
|
+
# - Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
# and/or other materials provided with the distribution.
|
|
14
|
+
#
|
|
15
|
+
# - Neither the name of the software nor the names of its contributors
|
|
16
|
+
# may be used to endorse or promote products derived from this software
|
|
17
|
+
# without specific prior written permission.
|
|
18
|
+
#
|
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
__doc__ = """
|
|
33
|
+
Contains common utility functions and classes.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import os
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def dict_diff(dict1, dict2):
|
|
40
|
+
"""
|
|
41
|
+
Compare two dictionaries and return their differences.
|
|
42
|
+
|
|
43
|
+
:param dict1: First dictionary.
|
|
44
|
+
:param dict2: Second dictionary.
|
|
45
|
+
:returns: diff dict: 'added', 'removed', 'changed', and 'unchanged'.
|
|
46
|
+
"""
|
|
47
|
+
added = {k: dict2[k] for k in dict2 if k not in dict1}
|
|
48
|
+
removed = {k: dict1[k] for k in dict1 if k not in dict2}
|
|
49
|
+
changed = {
|
|
50
|
+
k: (dict1[k], dict2[k]) for k in dict1 if k in dict2 and dict1[k] != dict2[k]
|
|
51
|
+
}
|
|
52
|
+
unchanged = {k: dict1[k] for k in dict1 if k in dict2 and dict1[k] == dict2[k]}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"added": added,
|
|
56
|
+
"removed": removed,
|
|
57
|
+
"changed": changed,
|
|
58
|
+
"unchanged": unchanged,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_paths_from_var(var="PYTHONPATH", pathsep=os.pathsep, reverse=True):
|
|
63
|
+
"""Returns a list of paths from a given pathsep separated environment
|
|
64
|
+
variable.
|
|
65
|
+
|
|
66
|
+
:param var: The environment variable to get paths from.
|
|
67
|
+
:param pathsep: The path separator to use.
|
|
68
|
+
:param reverse: Reverse the order of the paths.
|
|
69
|
+
:returns: A list of paths.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
paths = []
|
|
73
|
+
value = os.environ.get(var)
|
|
74
|
+
|
|
75
|
+
if value:
|
|
76
|
+
paths = value.split(pathsep)
|
|
77
|
+
|
|
78
|
+
if reverse:
|
|
79
|
+
paths.reverse()
|
|
80
|
+
|
|
81
|
+
return paths
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: envstack
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Stacked environment variable management system
|
|
5
5
|
Home-page: http://github.com/rsgalloway/envstack
|
|
6
6
|
Author: Ryan Galloway
|
|
@@ -184,19 +184,34 @@ $ envstack [STACK] --sources
|
|
|
184
184
|
|
|
185
185
|
## Python API
|
|
186
186
|
|
|
187
|
-
To
|
|
187
|
+
To initialize the environment stack in Python, use the `init` function:
|
|
188
188
|
|
|
189
189
|
```python
|
|
190
|
-
>>> envstack.init(
|
|
191
|
-
>>> os.getenv("
|
|
192
|
-
'
|
|
190
|
+
>>> envstack.init()
|
|
191
|
+
>>> os.getenv("HELLO")
|
|
192
|
+
'world'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
To initialize the "dev" stack:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
>>> envstack.init("dev")
|
|
199
|
+
>>> os.getenv("ENV")
|
|
200
|
+
'dev'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
To revert the original environment:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
>>> envstack.revert()
|
|
207
|
+
>>> os.getenv("HELLO")
|
|
208
|
+
>>>
|
|
193
209
|
```
|
|
194
210
|
|
|
195
211
|
Alternatively, `envstack.getenv` can be a drop-in replacement for `os.getenv`
|
|
196
212
|
for the default environment stack:
|
|
197
213
|
|
|
198
214
|
```python
|
|
199
|
-
>>> import envstack
|
|
200
215
|
>>> envstack.getenv("HELLO")
|
|
201
216
|
'world'
|
|
202
217
|
```
|
|
@@ -74,7 +74,7 @@ class PostInstallCommand(install):
|
|
|
74
74
|
|
|
75
75
|
setup(
|
|
76
76
|
name="envstack",
|
|
77
|
-
version="0.6.
|
|
77
|
+
version="0.6.3",
|
|
78
78
|
description="Stacked environment variable management system",
|
|
79
79
|
long_description=long_description,
|
|
80
80
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|