envstack 0.4.2__tar.gz → 0.5.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.
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: envstack
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: Stacked environment variable management system.
5
5
  Home-page: http://github.com/rsgalloway/envstack
6
6
  Author: Ryan Galloway
7
7
  Author-email: ryan@rsgalloway.com
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: PyYAML>=5.1.2
10
- Requires-Dist: siteconf>=0.1.7
11
10
 
12
11
  envstack
13
12
  ========
@@ -16,11 +15,9 @@ Stacked environment variable management system. The lightweight, easy to use
16
15
  "rez" alternative for production pipelines.
17
16
 
18
17
  Environment variables are declared in namespaced .env files using yaml syntax.
19
- The default stack is `stack` and variables are declared in `stack.env`
20
- files. You can create any new stack by creating new `.env` files, e.g. creating
21
- a new `test` stack just create `test.env` files.
22
-
23
- > **Note:** envstack works best combined with [siteconf](https://github.com/rsgalloway/siteconf).
18
+ The default stack declares env variables in `stack.env` files. You can create any
19
+ new stack by creating new `.env` files, e.g. to create a new `thing` stack just
20
+ create `thing.env` files in any given context.
24
21
 
25
22
  ## Installation
26
23
 
@@ -30,47 +27,66 @@ The easiest way to install:
30
27
  $ pip install envstack
31
28
  ```
32
29
 
33
- ## Quickstart
30
+ Alternatively,
31
+
32
+ ```bash
33
+ $ git clone https://github.com/rsgalloway/envstack
34
+ $ cd envstack
35
+ $ python setup.py install
36
+ ```
34
37
 
35
- Copy the default stack file
36
- [`stack.env`](https://github.com/rsgalloway/envstack/blob/master/stack.env)
37
- to your current working directory, the root of your project or $DEFAULT_ENV_DIR if defined (defaults: /etc/envstack on posix platforms and C:/ProgramData/envstack on Windows).
38
+ The install process will automatically attempt to install the default `stack.env` file to the
39
+ default env file directory defined `$DEFAULT_ENV_DIR`. **Note:** The [siteconf](https://github.com/rsgalloway/siteconf) sitecustomize.py module may override `$DEFAULT_ENV_DIR`.
38
40
 
41
+ If installing from source, you can use [distman](https://github.com/rsgalloway/distman) to
42
+ install envstack and the default `stack.env` file using the provided `dist.json` file:
39
43
 
40
- ```bach
41
- $ cp stack.env $DEFAULT_ENV_DIR
44
+ ```bash
45
+ $ distman
42
46
  ```
43
47
 
48
+ ## Quickstart
49
+
44
50
  The `stack` namespace is the default environment stack. Running the `envstack` command
45
- should show you the resolved environment for your platform:
51
+ should show you the default environment stack:
46
52
 
47
53
  ```bash
48
54
  $ envstack
49
- ENV 'prod'
50
- HELLO 'world'
51
- FOO 'bar'
52
- PYVERSION 3.11
53
- LIB 'lib/python3.11'
54
- LOG_LEVEL 20
55
- ROOT '/mnt/tools/lib/python3.11'
55
+ ENV=prod
56
+ HELLO=world
57
+ LOG_LEVEL=INFO
58
+ DEFAULT_ENV_DIR=${DEPLOY_ROOT}/env
59
+ DEPLOY_ROOT=${ROOT}/${ENV}
60
+ ROOT=${HOME}/.local/envstack
56
61
  ```
57
62
 
58
- Modify the environment stack by updating `stack.env` or by creating new contextual
59
- `stack.env` files up and down the project hierarchy.
63
+ Modify the environment stack by editing `stack.env` or by creating new contextual
64
+ `stack.env` files up on the filesystem.
60
65
 
61
66
  You can execute any command inside the default stacked environment like this:
62
67
 
63
68
  ```bash
64
- $ envstack -- <command>
69
+ $ envstack -- [COMMAND]
65
70
  ```
66
71
 
67
- For example:
72
+ For example, use the `echo` command to see the resolved value of `$HELLO` (note: we
73
+ have to escape it first to it's not pre-expanded in the shell):
74
+
75
+ ```bash
76
+ $ envstack -- echo \$HELLO
77
+ world
78
+ ```
79
+
80
+ Any command can be run in an envstack environment by preceeding the command
81
+ with `--`:
68
82
 
69
83
  ```bash
70
84
  $ envstack -- python -c "import os; print(os.environ['HELLO'])"
71
85
  world
72
86
  ```
73
87
 
88
+ ## Creating Stacks
89
+
74
90
  To create a new environment stack, create a new namespaced .env file.
75
91
  For example `thing.env` (the stack namespace is "thing"):
76
92
 
@@ -86,16 +102,6 @@ $ envstack thing
86
102
  FOO 'bar'
87
103
  ```
88
104
 
89
- Environment stacks are hierarchical, so values for `$FOO` defined in .env files lower
90
- in the filesystem (lower in scope) override those defined higher up (higher in scope):
91
-
92
- ```
93
- /show/thing.env
94
- /show/seq/thing.env
95
- /show/seq/shot/thing.env
96
- /show/seq/shot/task/thing.env
97
- ```
98
-
99
105
  Variables can reference other variables defined elsewhere (but cannot be circular):
100
106
 
101
107
  ```yaml
@@ -117,71 +123,76 @@ Environment files can include other namespaced environments (all stacks inherit
117
123
  include: ['other']
118
124
  ```
119
125
 
120
- ## Usage
126
+ ## Context
121
127
 
122
- To see the default resolved environment for any given scope (directory):
128
+ Environment stacks are hierarchical, so values for `$FOO` defined in .env files lower
129
+ in the filesystem (lower in scope) override those defined higher up (higher in scope):
123
130
 
124
- ```bash
125
- $ envstack
131
+ ```
132
+ ${DEFAULT_ENV_DIR}
133
+ /stack.env
134
+ /show/stack.env
135
+ /show/seq/stack.env
136
+ /show/seq/shot/stack.env
137
+ /show/seq/shot/task/stack.env
126
138
  ```
127
139
 
128
- To see the resolved environment for a given namespace.
140
+ If you are working in the task directory, those envstack $VARs will override the
141
+ $VARs defined in the shot, seq, show and root directories.
142
+
143
+
144
+ ## Usage
145
+
146
+ To see the default environment for any given stack:
129
147
 
130
148
  ```bash
131
- $ envstack <stack> [OPTIONS]
149
+ $ envstack [STACK]
132
150
  ```
133
151
 
134
- To resolve a `$VAR` declaration for a given environment stack:
152
+ To resolve one or more environment vars for a given stack:
135
153
 
136
154
  ```bash
137
- $ envstack <stack> -r <VAR>
155
+ $ envstack [STACK] -r [VAR [VAR ...]]
138
156
  ```
139
157
 
140
- To trace where a `$VAR` declaration is being set:
158
+ To trace where one or more environment vars is being set:
141
159
 
142
160
  ```bash
143
- $ envstack <stack> -t <VAR>
161
+ $ envstack [STACK] -t [VAR [VAR ...]]
144
162
  ```
145
163
 
146
- To see an environment stack on another platform:
164
+ To get the list of source files for a given stack:
147
165
 
148
166
  ```bash
149
- $ envstack <stack> -p <platform>
167
+ $ envstack [STACK] --sources
150
168
  ```
151
169
 
152
170
  ## Python API
153
171
 
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:
172
+ To init the environment stack, use the `init` function:
164
173
 
165
174
  ```python
166
175
  >>> envstack.init("thing")
167
- >>> envstack.getenv("FOO")
176
+ >>> os.getenv("FOO")
168
177
  'bar'
169
178
  ```
170
179
 
171
- The `init` function also updates the current environment for code that is not using envstack:
180
+ Alternatively, `envstack.getenv` uses the default environment stack `stack` and can be
181
+ a drop-in replacement for `os.getenv`
172
182
 
173
183
  ```python
174
- >>> os.getenv("FOO")
175
- 'bar'
184
+ >>> import envstack
185
+ >>> envstack.getenv("HELLO")
186
+ 'world'
176
187
  ```
177
188
 
178
189
  ## Running Commands
179
190
 
180
- To run any command line executable inside of an environment stack, where `<command>`
191
+ To run any command line executable inside of an environment stack, where `[COMMAND]`
181
192
  is the command to run:
182
193
 
183
194
  ```bash
184
- $ envstack <stack> -- <command>
195
+ $ envstack [STACK] -- [COMMAND]
185
196
  ```
186
197
 
187
198
  For example, running python in the default stack (reading from the default `stack.env` file):
@@ -5,11 +5,9 @@ Stacked environment variable management system. The lightweight, easy to use
5
5
  "rez" alternative for production pipelines.
6
6
 
7
7
  Environment variables are declared in namespaced .env files using yaml syntax.
8
- The default stack is `stack` and variables are declared in `stack.env`
9
- files. You can create any new stack by creating new `.env` files, e.g. creating
10
- a new `test` stack just create `test.env` files.
11
-
12
- > **Note:** envstack works best combined with [siteconf](https://github.com/rsgalloway/siteconf).
8
+ The default stack declares env variables in `stack.env` files. You can create any
9
+ new stack by creating new `.env` files, e.g. to create a new `thing` stack just
10
+ create `thing.env` files in any given context.
13
11
 
14
12
  ## Installation
15
13
 
@@ -19,47 +17,66 @@ The easiest way to install:
19
17
  $ pip install envstack
20
18
  ```
21
19
 
22
- ## Quickstart
20
+ Alternatively,
21
+
22
+ ```bash
23
+ $ git clone https://github.com/rsgalloway/envstack
24
+ $ cd envstack
25
+ $ python setup.py install
26
+ ```
23
27
 
24
- Copy the default stack file
25
- [`stack.env`](https://github.com/rsgalloway/envstack/blob/master/stack.env)
26
- to your current working directory, the root of your project or $DEFAULT_ENV_DIR if defined (defaults: /etc/envstack on posix platforms and C:/ProgramData/envstack on Windows).
28
+ The install process will automatically attempt to install the default `stack.env` file to the
29
+ default env file directory defined `$DEFAULT_ENV_DIR`. **Note:** The [siteconf](https://github.com/rsgalloway/siteconf) sitecustomize.py module may override `$DEFAULT_ENV_DIR`.
27
30
 
31
+ If installing from source, you can use [distman](https://github.com/rsgalloway/distman) to
32
+ install envstack and the default `stack.env` file using the provided `dist.json` file:
28
33
 
29
- ```bach
30
- $ cp stack.env $DEFAULT_ENV_DIR
34
+ ```bash
35
+ $ distman
31
36
  ```
32
37
 
38
+ ## Quickstart
39
+
33
40
  The `stack` namespace is the default environment stack. Running the `envstack` command
34
- should show you the resolved environment for your platform:
41
+ should show you the default environment stack:
35
42
 
36
43
  ```bash
37
44
  $ envstack
38
- ENV 'prod'
39
- HELLO 'world'
40
- FOO 'bar'
41
- PYVERSION 3.11
42
- LIB 'lib/python3.11'
43
- LOG_LEVEL 20
44
- ROOT '/mnt/tools/lib/python3.11'
45
+ ENV=prod
46
+ HELLO=world
47
+ LOG_LEVEL=INFO
48
+ DEFAULT_ENV_DIR=${DEPLOY_ROOT}/env
49
+ DEPLOY_ROOT=${ROOT}/${ENV}
50
+ ROOT=${HOME}/.local/envstack
45
51
  ```
46
52
 
47
- Modify the environment stack by updating `stack.env` or by creating new contextual
48
- `stack.env` files up and down the project hierarchy.
53
+ Modify the environment stack by editing `stack.env` or by creating new contextual
54
+ `stack.env` files up on the filesystem.
49
55
 
50
56
  You can execute any command inside the default stacked environment like this:
51
57
 
52
58
  ```bash
53
- $ envstack -- <command>
59
+ $ envstack -- [COMMAND]
54
60
  ```
55
61
 
56
- For example:
62
+ For example, use the `echo` command to see the resolved value of `$HELLO` (note: we
63
+ have to escape it first to it's not pre-expanded in the shell):
64
+
65
+ ```bash
66
+ $ envstack -- echo \$HELLO
67
+ world
68
+ ```
69
+
70
+ Any command can be run in an envstack environment by preceeding the command
71
+ with `--`:
57
72
 
58
73
  ```bash
59
74
  $ envstack -- python -c "import os; print(os.environ['HELLO'])"
60
75
  world
61
76
  ```
62
77
 
78
+ ## Creating Stacks
79
+
63
80
  To create a new environment stack, create a new namespaced .env file.
64
81
  For example `thing.env` (the stack namespace is "thing"):
65
82
 
@@ -75,16 +92,6 @@ $ envstack thing
75
92
  FOO 'bar'
76
93
  ```
77
94
 
78
- Environment stacks are hierarchical, so values for `$FOO` defined in .env files lower
79
- in the filesystem (lower in scope) override those defined higher up (higher in scope):
80
-
81
- ```
82
- /show/thing.env
83
- /show/seq/thing.env
84
- /show/seq/shot/thing.env
85
- /show/seq/shot/task/thing.env
86
- ```
87
-
88
95
  Variables can reference other variables defined elsewhere (but cannot be circular):
89
96
 
90
97
  ```yaml
@@ -106,71 +113,76 @@ Environment files can include other namespaced environments (all stacks inherit
106
113
  include: ['other']
107
114
  ```
108
115
 
109
- ## Usage
116
+ ## Context
110
117
 
111
- To see the default resolved environment for any given scope (directory):
118
+ Environment stacks are hierarchical, so values for `$FOO` defined in .env files lower
119
+ in the filesystem (lower in scope) override those defined higher up (higher in scope):
112
120
 
113
- ```bash
114
- $ envstack
121
+ ```
122
+ ${DEFAULT_ENV_DIR}
123
+ /stack.env
124
+ /show/stack.env
125
+ /show/seq/stack.env
126
+ /show/seq/shot/stack.env
127
+ /show/seq/shot/task/stack.env
115
128
  ```
116
129
 
117
- To see the resolved environment for a given namespace.
130
+ If you are working in the task directory, those envstack $VARs will override the
131
+ $VARs defined in the shot, seq, show and root directories.
132
+
133
+
134
+ ## Usage
135
+
136
+ To see the default environment for any given stack:
118
137
 
119
138
  ```bash
120
- $ envstack <stack> [OPTIONS]
139
+ $ envstack [STACK]
121
140
  ```
122
141
 
123
- To resolve a `$VAR` declaration for a given environment stack:
142
+ To resolve one or more environment vars for a given stack:
124
143
 
125
144
  ```bash
126
- $ envstack <stack> -r <VAR>
145
+ $ envstack [STACK] -r [VAR [VAR ...]]
127
146
  ```
128
147
 
129
- To trace where a `$VAR` declaration is being set:
148
+ To trace where one or more environment vars is being set:
130
149
 
131
150
  ```bash
132
- $ envstack <stack> -t <VAR>
151
+ $ envstack [STACK] -t [VAR [VAR ...]]
133
152
  ```
134
153
 
135
- To see an environment stack on another platform:
154
+ To get the list of source files for a given stack:
136
155
 
137
156
  ```bash
138
- $ envstack <stack> -p <platform>
157
+ $ envstack [STACK] --sources
139
158
  ```
140
159
 
141
160
  ## Python API
142
161
 
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:
162
+ To init the environment stack, use the `init` function:
153
163
 
154
164
  ```python
155
165
  >>> envstack.init("thing")
156
- >>> envstack.getenv("FOO")
166
+ >>> os.getenv("FOO")
157
167
  'bar'
158
168
  ```
159
169
 
160
- The `init` function also updates the current environment for code that is not using envstack:
170
+ Alternatively, `envstack.getenv` uses the default environment stack `stack` and can be
171
+ a drop-in replacement for `os.getenv`
161
172
 
162
173
  ```python
163
- >>> os.getenv("FOO")
164
- 'bar'
174
+ >>> import envstack
175
+ >>> envstack.getenv("HELLO")
176
+ 'world'
165
177
  ```
166
178
 
167
179
  ## Running Commands
168
180
 
169
- To run any command line executable inside of an environment stack, where `<command>`
181
+ To run any command line executable inside of an environment stack, where `[COMMAND]`
170
182
  is the command to run:
171
183
 
172
184
  ```bash
173
- $ envstack <stack> -- <command>
185
+ $ envstack [STACK] -- [COMMAND]
174
186
  ```
175
187
 
176
188
  For example, running python in the default stack (reading from the default `stack.env` file):
@@ -34,6 +34,7 @@ Stacked environment variable management system.
34
34
  """
35
35
 
36
36
  __prog__ = "envstack"
37
- __version__ = "0.4.2"
37
+ __version__ = "0.5.0"
38
38
 
39
- from envstack.env import getenv, init
39
+ from envstack.env import Env
40
+ from envstack.env import getenv, init, load_file
@@ -30,12 +30,10 @@
30
30
  #
31
31
 
32
32
  __doc__ = """
33
- Contains command line interface for envstack.
33
+ Command line interface for envstack: stacked environment variable management.
34
34
  """
35
35
 
36
36
  import argparse
37
- import os
38
- import pprint
39
37
  import sys
40
38
  import traceback
41
39
 
@@ -85,24 +83,26 @@ def parse_args():
85
83
  "--platform",
86
84
  default=config.PLATFORM,
87
85
  metavar="PLATFORM",
88
- help="specify the platform to resolve variables for",
86
+ help="platform to resolve variables for (linux, darwin, windows)",
89
87
  )
90
88
  parser.add_argument(
91
89
  "-r",
92
90
  "--resolve",
91
+ nargs="*",
93
92
  metavar="VAR",
94
- help="resolve an environment variable",
95
- )
96
- parser.add_argument(
97
- "--sources",
98
- action="store_true",
99
- help="list the sources for a stack",
93
+ help="resolve environment variables",
100
94
  )
101
95
  parser.add_argument(
102
96
  "-t",
103
97
  "--trace",
98
+ nargs="*",
104
99
  metavar="VAR",
105
- help="trace where a variable is getting set",
100
+ help="trace where environment variables are being set",
101
+ )
102
+ parser.add_argument(
103
+ "--sources",
104
+ action="store_true",
105
+ help="list the sources for a stack",
106
106
  )
107
107
 
108
108
  args = parser.parse_args(args_before_dash)
@@ -115,15 +115,20 @@ def main():
115
115
  args, command = parse_args()
116
116
 
117
117
  try:
118
- if args.resolve:
119
- env = load_environ(
120
- args.namespace, environ=os.environ, platform=args.platform
121
- )
122
- var = env.get(args.resolve)
123
- print(pprint.pformat(expandvars(var, env, recursive=True)))
124
- elif args.trace:
125
- path = trace_var(args.namespace, args.trace)
126
- print("{0}: {1}".format(args.trace, path))
118
+ if args.resolve is not None:
119
+ if len(args.resolve) == 0:
120
+ args.resolve = load_environ(args.namespace).keys()
121
+ env = load_environ(args.namespace, platform=args.platform)
122
+ for resolve in args.resolve:
123
+ var = env.get(resolve)
124
+ val = expandvars(var, env, recursive=True)
125
+ print(f"{resolve}={val}")
126
+ elif args.trace is not None:
127
+ if len(args.trace) == 0:
128
+ args.trace = load_environ(args.namespace).keys()
129
+ for trace in args.trace:
130
+ path = trace_var(args.namespace, trace)
131
+ print("{0}: {1}".format(trace, path))
127
132
  elif args.sources:
128
133
  sources = build_sources(args.namespace)
129
134
  for source in sources:
@@ -135,7 +140,7 @@ def main():
135
140
  else:
136
141
  env = load_environ(args.namespace, platform=args.platform, includes=True)
137
142
  for k, v in env.items():
138
- print(f"{k} {pprint.pformat(v)}")
143
+ print(f"{k}={v}")
139
144
 
140
145
  except KeyboardInterrupt:
141
146
  print("Stopping...")
@@ -59,20 +59,30 @@ def detect_shell():
59
59
 
60
60
  DEBUG = os.getenv("DEBUG")
61
61
  DEFAULT_NAMESPACE = os.getenv("DEFAULT_ENV_STACK", "stack")
62
- LOG_LEVEL = int(os.environ.get("LOG_LEVEL", 20))
62
+ ENV = os.getenv("ENV", "prod")
63
+ HOME = os.getenv("HOME")
64
+ LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO")
63
65
  ON_POSIX = "posix" in sys.builtin_module_names
64
66
  PLATFORM = platform.system().lower()
65
67
  PYTHON_VERSION = sys.version_info[0]
66
68
  SHELL = detect_shell()
67
69
  USERNAME = os.getenv("USERNAME", os.getenv("USER"))
68
70
 
69
- # default location of the global env stacks
70
- # set in sitecustomize.py using siteconf>=0.1.7
71
+ # set some default environment variables
72
+ DEFAULT_ENV = {
73
+ "ENV": ENV,
74
+ "HOME": HOME,
75
+ "PLATFORM": PLATFORM,
76
+ "USER": USERNAME,
77
+ }
78
+
79
+ # default location of envstack files
80
+ # NOTE: the siteconf sitecustomize.py module may override this
71
81
  DEFAULT_ENV_DIR = os.getenv(
72
82
  "DEFAULT_ENV_DIR",
73
83
  {
74
- "darwin": "/etc/envstack",
75
- "linux": "/etc/envstack",
76
- "windows": "C:/ProgramData/envstack",
77
- }.get(PLATFORM),
84
+ "darwin": "{HOME}/Library/Application Support/envstack",
85
+ "linux": "{HOME}/.local/envstack",
86
+ "windows": "C:\\ProgramData\\envstack",
87
+ }.get(PLATFORM).format(**DEFAULT_ENV),
78
88
  )
@@ -260,18 +260,22 @@ class Env(dict):
260
260
  """Returns raw, unexpanded value of key, or None."""
261
261
  return self.get(key, resolved=False).template
262
262
 
263
- def items(self):
264
- """Returns list of (key, value) pairs, as 2-tuples."""
265
- return [(k, EnvVar(self[k]).value()) for k in self]
266
-
267
263
  def merge(self, env):
268
- """Merges another environ into this one, i.e.
269
- env[k] will replace self[k].
264
+ """Merges another environ `env` into this one.
270
265
 
271
266
  :param env: env to merge into this one
272
267
  """
273
- for k, v in env.items():
274
- self[k] = v
268
+ merged = env.copy()
269
+ for key, value in self.items():
270
+ if isinstance(value, str):
271
+ # replace ${KEY} vars with values from env
272
+ value = re.sub(
273
+ r"\${(\w+)}",
274
+ lambda match: env.get(match.group(1), match.group(0)),
275
+ value,
276
+ )
277
+ merged[key] = value
278
+ return merged
275
279
 
276
280
  def set_namespace(self, name):
277
281
  """Stores the namespace for this environment.
@@ -538,7 +542,7 @@ def init(name=config.DEFAULT_NAMESPACE):
538
542
  def load_environ(
539
543
  name=config.DEFAULT_NAMESPACE,
540
544
  sources=None,
541
- environ=None,
545
+ environ=os.environ,
542
546
  platform=config.PLATFORM,
543
547
  scope=None,
544
548
  includes=True,
@@ -577,7 +581,7 @@ def load_environ(
577
581
  for source in sources:
578
582
  env.update(source.load(platform=platform))
579
583
 
580
- # load values from local environment
584
+ # merge values from given environment
581
585
  if environ:
582
586
  env.merge(environ)
583
587
 
@@ -650,7 +654,7 @@ def trace_var(name, var, scope=None):
650
654
  :returns: source path
651
655
  """
652
656
  if var in os.environ:
653
- return "local environment (unset to clear)"
657
+ return "local environment"
654
658
  sources = build_sources(name, scope=scope)
655
659
  sources.reverse()
656
660
  for source in sources:
@@ -660,6 +664,7 @@ def trace_var(name, var, scope=None):
660
664
  return source.path
661
665
 
662
666
 
667
+ # default stack environment
663
668
  environ = load_environ(environ=os.environ)
664
669
 
665
670
 
@@ -33,7 +33,17 @@ import logging
33
33
 
34
34
  from envstack.config import LOG_LEVEL
35
35
 
36
- log = logging.Logger("envstack")
36
+
37
+ class Logger(logging.Logger):
38
+ """Custom logger class."""
39
+
40
+ def setLevel(self, level):
41
+ if isinstance(level, str):
42
+ level = getattr(logging, level.upper(), logging.NOTSET)
43
+ super().setLevel(level)
44
+
45
+
46
+ log = Logger("envstack")
37
47
  log.setLevel(LOG_LEVEL)
38
48
  log.addHandler(logging.NullHandler())
39
49