From 94876b648e865555f1d1b3c2212209b0f97eb79c Mon Sep 17 00:00:00 2001 From: Erik Cederstrand Date: Fri, 4 Jun 2021 09:53:50 +0200 Subject: [PATCH 1/3] Let Command know about baked call args when wrapping the module --- sh.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sh.py b/sh.py index 1baa6bf3..3c2c3492 100644 --- a/sh.py +++ b/sh.py @@ -3523,6 +3523,9 @@ def __call__(self, **kwargs): baked_args = self.__env.baked_args.copy() baked_args.update(kwargs) new_mod = self.__class__(self.__self_module, baked_args) + # Update baked call args on the new Command class + call_args, _ = new_mod.Command._extract_call_args(baked_args) + new_mod.Command._call_args.update(call_args) # inspect the line in the parent frame that calls and assigns the new sh # variable, and get the name of the new variable we're assigning to. From 53af01d17a512578f5fc0e3111d4eec29c49b9ca Mon Sep 17 00:00:00 2001 From: Erik Cederstrand Date: Fri, 4 Jun 2021 21:01:41 +0200 Subject: [PATCH 2/3] When wrapping th module, also copy the Command class. Make it aware of baked args --- sh.py | 16 ++++++++++++---- test.py | 7 +++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/sh.py b/sh.py index 3c2c3492..830d9fea 100644 --- a/sh.py +++ b/sh.py @@ -3512,7 +3512,18 @@ def __init__(self, self_module, baked_args=None): # if we set this to None. and 3.3 needs a value for __path__ self.__path__ = [] self.__self_module = self_module - self.__env = Environment(globals(), baked_args=baked_args) + + # Copy the Command class and add any baked call kwargs to it + cls_attrs = Command.__dict__.copy() + if baked_args: + call_args, _ = Command._extract_call_args(baked_args) + cls_attrs['_call_args'] = cls_attrs['_call_args'].copy() + cls_attrs['_call_args'].update(call_args) + command_cls = type(Command.__name__, Command.__bases__, cls_attrs) + globs = globals().copy() + globs[Command.__name__] = command_cls + + self.__env = Environment(globs, baked_args=baked_args) def __getattr__(self, name): return self.__env[name] @@ -3523,9 +3534,6 @@ def __call__(self, **kwargs): baked_args = self.__env.baked_args.copy() baked_args.update(kwargs) new_mod = self.__class__(self.__self_module, baked_args) - # Update baked call args on the new Command class - call_args, _ = new_mod.Command._extract_call_args(baked_args) - new_mod.Command._call_args.update(call_args) # inspect the line in the parent frame that calls and assigns the new sh # variable, and get the name of the new variable we're assigning to. diff --git a/test.py b/test.py index d9cc1dac..4e9e8e03 100644 --- a/test.py +++ b/test.py @@ -3138,6 +3138,13 @@ def test_reimport_no_interfere(self): _sh.echo("-n", "TEST") self.assertEqual("TEST", out.getvalue()) + def test_command_with_baked_call_args(self): + # Test that sh.Command() knows about baked call args + import sh + _sh = sh(_ok_code=1) + self.assertEqual(sh.Command._call_args['ok_code'], 0) + self.assertEqual(_sh.Command._call_args['ok_code'], 1) + def test_importer_detects_module_name(self): import sh _sh = sh() From 06eaa91f9b1fb889eabb30755b7a68ae096e6870 Mon Sep 17 00:00:00 2001 From: Erik Cederstrand Date: Sun, 6 Jun 2021 09:01:48 +0200 Subject: [PATCH 3/3] Add Changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab69be2a..3a7afb92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # Changelog +## 1.14.3 +* bugfix where `Command` was not aware of default call args when wrapping the module [#559](https://github.com/amoffat/sh/pull/573) + ## 1.14.1 - 10/24/20 * bugfix where setting `_ok_code` to not include 0, but 0 was the exit code [#545](https://github.com/amoffat/sh/pull/545)