envstack 0.6.3__tar.gz → 0.6.4__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.
Files changed (27) hide show
  1. {envstack-0.6.3/lib/envstack.egg-info → envstack-0.6.4}/PKG-INFO +5 -17
  2. {envstack-0.6.3 → envstack-0.6.4}/README.md +3 -15
  3. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/__init__.py +2 -2
  4. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/cli.py +9 -2
  5. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/env.py +137 -60
  6. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/util.py +25 -0
  7. {envstack-0.6.3 → envstack-0.6.4/lib/envstack.egg-info}/PKG-INFO +5 -17
  8. envstack-0.6.4/lib/envstack.egg-info/requires.txt +1 -0
  9. {envstack-0.6.3 → envstack-0.6.4}/setup.py +2 -2
  10. envstack-0.6.3/lib/envstack.egg-info/requires.txt +0 -1
  11. {envstack-0.6.3 → envstack-0.6.4}/LICENSE +0 -0
  12. {envstack-0.6.3 → envstack-0.6.4}/dev.env +0 -0
  13. {envstack-0.6.3 → envstack-0.6.4}/dist.json +0 -0
  14. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/config.py +0 -0
  15. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/exceptions.py +0 -0
  16. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/logger.py +0 -0
  17. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/path.py +0 -0
  18. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack/wrapper.py +0 -0
  19. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack.egg-info/SOURCES.txt +0 -0
  20. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack.egg-info/dependency_links.txt +0 -0
  21. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack.egg-info/entry_points.txt +0 -0
  22. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack.egg-info/not-zip-safe +0 -0
  23. {envstack-0.6.3 → envstack-0.6.4}/lib/envstack.egg-info/top_level.txt +0 -0
  24. {envstack-0.6.3 → envstack-0.6.4}/setup.cfg +0 -0
  25. {envstack-0.6.3 → envstack-0.6.4}/stack.env +0 -0
  26. {envstack-0.6.3 → envstack-0.6.4}/tests/test_env.py +0 -0
  27. {envstack-0.6.3 → envstack-0.6.4}/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
3
+ Version: 0.6.4
4
4
  Summary: Stacked environment variable management system
5
5
  Home-page: http://github.com/rsgalloway/envstack
6
6
  Author: Ryan Galloway
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Requires-Python: >=3.6
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: PyYAML>=5.1.2
22
+ Requires-Dist: PyYAML==5.1.2
23
23
 
24
24
  envstack
25
25
  ========
@@ -303,7 +303,7 @@ the output of the `--export` command:
303
303
 
304
304
  #### bash
305
305
  ```bash
306
- alias envstack-set='source <(envstack "$1" --export)';
306
+ alias envstack-init='source <(envstack --export)';
307
307
  ```
308
308
 
309
309
  #### cmd
@@ -311,13 +311,13 @@ alias envstack-set='source <(envstack "$1" --export)';
311
311
  doskey envstack-set=for /f "usebackq" %i in (`envstack --export $*`) do %%i
312
312
  ```
313
313
 
314
- Then you can set the environment stack in your shell with the `envstack-set`
314
+ Then you can set the environment stack in your shell with the `envstack-init`
315
315
  command. To clear the environment in your current shell, create an alias that
316
316
  sources the output of the `--clear` command:
317
317
 
318
318
  #### bash
319
319
  ```bash
320
- alias envstack-clear='source <(envstack "$1" --clear)';
320
+ alias envstack-clear='source <(envstack --clear)';
321
321
  ```
322
322
 
323
323
  #### cmd
@@ -325,18 +325,6 @@ alias envstack-clear='source <(envstack "$1" --clear)';
325
325
  doskey envstack-clear=for /f "usebackq" %i in (`envstack --clear $*`) do %%i
326
326
  ```
327
327
 
328
- Create a function for convenience that does both in one command:
329
-
330
- #### bash
331
- ```bash
332
- envstack-init() { envstack-clear "$1"; envstack-set "$1"; }
333
- ```
334
-
335
- #### cmd
336
- ```cmd
337
- doskey envstack-init=envstack-clear $* & envstack-set $*
338
- ```
339
-
340
328
  ## Config
341
329
 
342
330
  Default config settings are in the config.py module. The following environment
@@ -280,7 +280,7 @@ the output of the `--export` command:
280
280
 
281
281
  #### bash
282
282
  ```bash
283
- alias envstack-set='source <(envstack "$1" --export)';
283
+ alias envstack-init='source <(envstack --export)';
284
284
  ```
285
285
 
286
286
  #### cmd
@@ -288,13 +288,13 @@ alias envstack-set='source <(envstack "$1" --export)';
288
288
  doskey envstack-set=for /f "usebackq" %i in (`envstack --export $*`) do %%i
289
289
  ```
290
290
 
291
- Then you can set the environment stack in your shell with the `envstack-set`
291
+ Then you can set the environment stack in your shell with the `envstack-init`
292
292
  command. To clear the environment in your current shell, create an alias that
293
293
  sources the output of the `--clear` command:
294
294
 
295
295
  #### bash
296
296
  ```bash
297
- alias envstack-clear='source <(envstack "$1" --clear)';
297
+ alias envstack-clear='source <(envstack --clear)';
298
298
  ```
299
299
 
300
300
  #### cmd
@@ -302,18 +302,6 @@ alias envstack-clear='source <(envstack "$1" --clear)';
302
302
  doskey envstack-clear=for /f "usebackq" %i in (`envstack --clear $*`) do %%i
303
303
  ```
304
304
 
305
- Create a function for convenience that does both in one command:
306
-
307
- #### bash
308
- ```bash
309
- envstack-init() { envstack-clear "$1"; envstack-set "$1"; }
310
- ```
311
-
312
- #### cmd
313
- ```cmd
314
- doskey envstack-init=envstack-clear $* & envstack-set $*
315
- ```
316
-
317
305
  ## Config
318
306
 
319
307
  Default config settings are in the config.py module. The following environment
@@ -34,6 +34,6 @@ Stacked environment variable management system.
34
34
  """
35
35
 
36
36
  __prog__ = "envstack"
37
- __version__ = "0.6.3"
37
+ __version__ = "0.6.4"
38
38
 
39
- from envstack.env import Env, getenv, init, load_file, revert, save
39
+ from envstack.env import Env, clear, getenv, init, load_file, revert, save
@@ -38,7 +38,14 @@ import sys
38
38
  import traceback
39
39
 
40
40
  from envstack import __version__, config
41
- from envstack.env import build_sources, expandvars, export, load_environ, trace_var
41
+ from envstack.env import (
42
+ build_sources,
43
+ expandvars,
44
+ clear,
45
+ export,
46
+ load_environ,
47
+ trace_var,
48
+ )
42
49
  from envstack.wrapper import run_command
43
50
 
44
51
 
@@ -139,7 +146,7 @@ def main():
139
146
  for source in sources:
140
147
  print(source)
141
148
  elif args.clear:
142
- print(export(args.namespace, config.SHELL, clear=True))
149
+ print(clear(args.namespace, config.SHELL))
143
150
  elif args.export:
144
151
  print(export(args.namespace, config.SHELL))
145
152
  elif command:
@@ -533,59 +533,128 @@ def expandvars(var, env=None, recursive=False):
533
533
  return EnvVar(var).expand(env, recursive=recursive)
534
534
 
535
535
 
536
- def export(name, shell=config.SHELL, resolve=False, scope=None, clear=False):
537
- """Returns environment commands that can be sourced.
536
+ def clear(
537
+ name=config.DEFAULT_NAMESPACE,
538
+ shell=config.SHELL,
539
+ scope=None,
540
+ ):
541
+ """Returns shell commands that can be sourced to unset or restore env stack
542
+ environment variables. Should only be run after a previous export:
538
543
 
539
- $ source <(envstack --export)
544
+ $ source <(envstack --export)
545
+ $ source <(envstack --clear)
540
546
 
541
- or to clear existing values:
547
+ List of shell names: bash, sh, tcsh, cmd, pwsh
548
+ (see output of config.detect_shell()).
542
549
 
543
- $ source <(envstack --clear)
550
+ :param name: stack namespace.
551
+ :param shell: name of shell (default: current shell).
552
+ :param scope: environment scope (default: cwd).
553
+ :returns: shell commands as string.
554
+ """
555
+ if "ENVSTACK" not in os.environ:
556
+ logger.log.info("Environment is already clear")
557
+ return ""
558
+
559
+ env = load_environ(name, environ=None, scope=scope)
560
+ export_vars = dict(env.items())
561
+ export_list = list()
562
+
563
+ # vars that should never be unset
564
+ restricted_vars = ["PATH", "PS1", "PWD", "PROMPT", "DEFAULT_ENV_DIR"]
565
+
566
+ for key in export_vars:
567
+ if key not in os.environ:
568
+ continue
569
+ old_key = f"_ES_OLD_{key}"
570
+ old_val = os.environ.get(old_key)
571
+ if shell in ["bash", "sh", "zsh"]:
572
+ if old_val:
573
+ export_list.append("export %s=%s" % (key, old_val))
574
+ export_list.append("unset %s" % (old_key))
575
+ elif key not in restricted_vars:
576
+ export_list.append(f"unset {key}")
577
+ elif shell == "tcsh":
578
+ if old_val:
579
+ export_list.append(f"setenv {key} {old_val}")
580
+ export_list.append(f"unsetenv {old_key}")
581
+ elif key not in restricted_vars:
582
+ export_list.append(f"unsetenv {key}")
583
+ elif shell == "cmd":
584
+ if old_val:
585
+ export_list.append(f"set {key}={old_val}")
586
+ export_list.append(f"set {old_key}=")
587
+ elif key not in restricted_vars:
588
+ export_list.append(f"set {key}=")
589
+ elif shell == "pwsh":
590
+ if old_val:
591
+ export_list.append(f"$env:{key}='{old_val}'")
592
+ export_list.append(f"Remove-Item Env:{old_key}")
593
+ elif key not in restricted_vars:
594
+ export_list.append(f"Remove-Item Env:{key}")
595
+ elif shell == "unknown":
596
+ raise Exception("unknown shell")
597
+
598
+ export_list.sort()
599
+ exp = "\n".join(export_list)
600
+
601
+ return exp
602
+
603
+
604
+ def export(
605
+ name=config.DEFAULT_NAMESPACE,
606
+ shell=config.SHELL,
607
+ scope=None,
608
+ ):
609
+ """Returns shell set env commands that can be sourced to set env stack
610
+ environment variables.
544
611
 
545
612
  List of shell names: bash, sh, tcsh, cmd, pwsh
546
613
  (see output of config.detect_shell()).
547
614
 
548
615
  :param name: stack namespace.
549
616
  :param shell: name of shell (default: current shell).
550
- :param resolve: resolve values (default: True).
551
617
  :param scope: environment scope (default: cwd).
552
- :param clear: clear existing values (default: False).
553
618
  :returns: shell commands as string.
554
619
  """
555
620
  env = load_environ(name, scope=scope)
556
- expList = list()
557
- for k, v in env.items():
558
- if resolve:
559
- v = expandvars(v, env, recursive=False)
621
+ export_vars = dict(env.items())
622
+ export_list = list()
623
+
624
+ for key, val in export_vars.items():
625
+ val = expandvars(val, env, recursive=False)
626
+ old_key = f"_ES_OLD_{key}"
627
+ old_val = os.environ.get(key)
628
+ if key == "PATH" and not val:
629
+ logger.log.warning("PATH is empty")
630
+ continue
560
631
  if shell in ["bash", "sh", "zsh"]:
561
- if clear:
562
- expList.append(f"unset {k}")
563
- else:
564
- expList.append(f'export {k}="{v}"')
632
+ export_list.append(f"export {key}={val}")
633
+ if old_val:
634
+ export_list.append(f"export {old_key}={old_val}")
565
635
  elif shell == "tcsh":
566
- if clear:
567
- expList.append(f"unsetenv {k}")
568
- else:
569
- expList.append(f'setenv {k}:"{v}"')
636
+ export_list.append(f'setenv {key}:"{val}"')
637
+ if old_val:
638
+ export_list.append(f'setenv {old_key}:"{old_val}"')
570
639
  elif shell == "cmd":
571
- if clear:
572
- expList.append(f"set {k}=")
573
- else:
574
- expList.append(f'set {k}="{v}"')
640
+ export_list.append(f'set {key}="{val}"')
641
+ if old_val:
642
+ export_list.append(f'set {old_key}="{old_val}"')
575
643
  elif shell == "pwsh":
576
- if clear:
577
- expList.append(f"Remove-Item Env:{k}")
578
- else:
579
- expList.append(f'$env:{k}="{v}"')
644
+ export_list.append(f'$env:{key}="{val}"')
645
+ if old_val:
646
+ export_list.append(f'$env:{old_key}="{old_val}"')
580
647
  elif shell == "unknown":
581
648
  raise Exception("unknown shell")
582
- expList.sort()
583
- exp = "\n".join(expList)
649
+
650
+ export_list.sort()
651
+ exp = "\n".join(export_list)
652
+
584
653
  return exp
585
654
 
586
655
 
587
656
  def save():
588
- """Saves the current environment."""
657
+ """Saves the current environment for later restoration."""
589
658
  global SAVED_ENVIRONMENT
590
659
  if not SAVED_ENVIRONMENT:
591
660
  SAVED_ENVIRONMENT = dict(os.environ.copy())
@@ -593,56 +662,62 @@ def save():
593
662
 
594
663
 
595
664
  def revert():
596
- """Reverts the environment to the saved environment."""
665
+ """Reverts the environment to the saved environment. Updates sys.path using
666
+ paths found in PYTHONPATH.
667
+
668
+ Initialize the default environment stack:
669
+ >>> envstack.init()
670
+
671
+ Revert to the previous environment:
672
+ >>> envstack.revert()
673
+ """
597
674
  global SAVED_ENVIRONMENT
598
675
  if SAVED_ENVIRONMENT is None:
599
676
  return
677
+
678
+ # clear current sys.path values
679
+ util.clear_sys_path()
680
+
681
+ # restore the original environment
600
682
  os.environ.clear()
601
683
  os.environ.update(SAVED_ENVIRONMENT)
602
684
 
685
+ # restore sys.path from PYTHONPATH
686
+ util.load_sys_path()
687
+
688
+ SAVED_ENVIRONMENT = None
689
+
603
690
 
604
691
  def init(name=config.DEFAULT_NAMESPACE):
605
- """Initializes the environment for a given namespace. Modifies sys.path
606
- from PYTHONPATH.
692
+ """Initializes the environment from a given stack namespace. Environments
693
+ propogate downwards with subsequent calls to init().
607
694
 
608
- # initialize the default environemnt
609
- >>> envstack.init()
695
+ Updates sys.path using paths found in PYTHONPATH.
610
696
 
611
- # initialize the dev environment
612
- >>> envstack.init('dev')
697
+ Initialize the default environment stack:
698
+ >>> envstack.init()
613
699
 
614
- # revert to the original environment
615
- >>> envstack.revert()
700
+ Initialize the dev environment stack (inherits from previous call):
701
+ >>> envstack.init('dev')
616
702
 
617
- :param name: stack namespace (default stack).
618
- """
619
- logger.log.debug("initializing env stack: %s", name)
703
+ Revert to the original environment:
704
+ >>> envstack.revert()
620
705
 
621
- # save the current environment
706
+ :param name: stack namespace (default: 'stack').
707
+ :param reset: clear existing values first (default: False).
708
+ """
709
+ # save environment to restore later using envstack.revert()
622
710
  save()
623
711
 
624
712
  # 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]
713
+ util.clear_sys_path()
634
714
 
635
- # store the name of the environment stack (e.g. for $PS1)
636
- os.environ["ENVSTACK"] = name
637
-
638
- # load the new environment
715
+ # load the stack and update the environment
639
716
  env = load_environ(name)
640
717
  os.environ.update(encode(env))
641
718
 
642
719
  # 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)
720
+ util.load_sys_path()
646
721
 
647
722
 
648
723
  def load_environ(
@@ -672,7 +747,6 @@ def load_environ(
672
747
  :param includes: merge included namespaces.
673
748
  :returns: dict of environment variables.
674
749
  """
675
-
676
750
  # build list of sources from namespace(s) and scope
677
751
  if not sources:
678
752
  sources = build_sources(name, scope=scope, includes=includes)
@@ -687,6 +761,9 @@ def load_environ(
687
761
  for source in sources:
688
762
  env.update(source.load(platform=platform))
689
763
 
764
+ # store the name of the environment stack
765
+ env["ENVSTACK"] = env.get("ENVSTACK", "|".join(name))
766
+
690
767
  # merge values from given environment
691
768
  if environ:
692
769
  return merge(env, environ, platform=platform)
@@ -34,6 +34,31 @@ Contains common utility functions and classes.
34
34
  """
35
35
 
36
36
  import os
37
+ import sys
38
+
39
+
40
+ def clear_sys_path(var="PYTHONPATH"):
41
+ """
42
+ Remove paths from sys.path that are in the given environment variable.
43
+
44
+ :param var: The environment variable to remove paths from.
45
+ """
46
+ for path in get_paths_from_var(var):
47
+ if path and path in sys.path:
48
+ sys.path.remove(path)
49
+
50
+
51
+ def load_sys_path(var="PYTHONPATH", pathsep=os.pathsep, reverse=True):
52
+ """
53
+ Add paths from the given environment variable to sys.path.
54
+
55
+ :param var: The environment variable to add paths from.
56
+ :param pathsep: The path separator to use.
57
+ :param reverse: Reverse the order of the paths.
58
+ """
59
+ for path in get_paths_from_var(var, pathsep, reverse):
60
+ if path and path not in sys.path:
61
+ sys.path.insert(0, path)
37
62
 
38
63
 
39
64
  def dict_diff(dict1, dict2):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: envstack
3
- Version: 0.6.3
3
+ Version: 0.6.4
4
4
  Summary: Stacked environment variable management system
5
5
  Home-page: http://github.com/rsgalloway/envstack
6
6
  Author: Ryan Galloway
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Requires-Python: >=3.6
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: PyYAML>=5.1.2
22
+ Requires-Dist: PyYAML==5.1.2
23
23
 
24
24
  envstack
25
25
  ========
@@ -303,7 +303,7 @@ the output of the `--export` command:
303
303
 
304
304
  #### bash
305
305
  ```bash
306
- alias envstack-set='source <(envstack "$1" --export)';
306
+ alias envstack-init='source <(envstack --export)';
307
307
  ```
308
308
 
309
309
  #### cmd
@@ -311,13 +311,13 @@ alias envstack-set='source <(envstack "$1" --export)';
311
311
  doskey envstack-set=for /f "usebackq" %i in (`envstack --export $*`) do %%i
312
312
  ```
313
313
 
314
- Then you can set the environment stack in your shell with the `envstack-set`
314
+ Then you can set the environment stack in your shell with the `envstack-init`
315
315
  command. To clear the environment in your current shell, create an alias that
316
316
  sources the output of the `--clear` command:
317
317
 
318
318
  #### bash
319
319
  ```bash
320
- alias envstack-clear='source <(envstack "$1" --clear)';
320
+ alias envstack-clear='source <(envstack --clear)';
321
321
  ```
322
322
 
323
323
  #### cmd
@@ -325,18 +325,6 @@ alias envstack-clear='source <(envstack "$1" --clear)';
325
325
  doskey envstack-clear=for /f "usebackq" %i in (`envstack --clear $*`) do %%i
326
326
  ```
327
327
 
328
- Create a function for convenience that does both in one command:
329
-
330
- #### bash
331
- ```bash
332
- envstack-init() { envstack-clear "$1"; envstack-set "$1"; }
333
- ```
334
-
335
- #### cmd
336
- ```cmd
337
- doskey envstack-init=envstack-clear $* & envstack-set $*
338
- ```
339
-
340
328
  ## Config
341
329
 
342
330
  Default config settings are in the config.py module. The following environment
@@ -0,0 +1 @@
1
+ PyYAML==5.1.2
@@ -74,7 +74,7 @@ class PostInstallCommand(install):
74
74
 
75
75
  setup(
76
76
  name="envstack",
77
- version="0.6.3",
77
+ version="0.6.4",
78
78
  description="Stacked environment variable management system",
79
79
  long_description=long_description,
80
80
  long_description_content_type="text/markdown",
@@ -106,7 +106,7 @@ setup(
106
106
  ],
107
107
  },
108
108
  install_requires=[
109
- "PyYAML>=5.1.2",
109
+ "PyYAML==5.1.2",
110
110
  ],
111
111
  python_requires=">=3.6",
112
112
  data_files=[(".", ["stack.env", "dev.env", "dist.json"])],
@@ -1 +0,0 @@
1
- PyYAML>=5.1.2
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes