Hello community,

here is the log from the commit of package python-knack for openSUSE:Factory 
checked in at 2019-05-06 13:25:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-knack (Old)
 and      /work/SRC/openSUSE:Factory/.python-knack.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-knack"

Mon May  6 13:25:08 2019 rev:6 rq:694216 version:0.5.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-knack/python-knack.changes        
2019-03-28 22:50:17.931035821 +0100
+++ /work/SRC/openSUSE:Factory/.python-knack.new.5148/python-knack.changes      
2019-05-06 13:25:09.841020349 +0200
@@ -1,0 +2,9 @@
+Fri Apr 12 12:24:44 UTC 2019 - pgaj...@suse.com
+
+- version update to 0.5.4
+  * Allows the loading of text files using @filename syntax.
+  * Adds the argument kwarg configured_default to support setting
+    argument defaults via the config file's [defaults] section or
+    an environment variable.
+
+-------------------------------------------------------------------

Old:
----
  v0.5.3.tar.gz

New:
----
  v0.5.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-knack.spec ++++++
--- /var/tmp/diff_new_pack.iamgMo/_old  2019-05-06 13:25:11.125022974 +0200
+++ /var/tmp/diff_new_pack.iamgMo/_new  2019-05-06 13:25:11.125022974 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-knack
-Version:        0.5.3
+Version:        0.5.4
 Release:        0
 Summary:        A Command-Line Interface framework
 License:        MIT

++++++ v0.5.3.tar.gz -> v0.5.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/cli.py new/knack-0.5.4/knack/cli.py
--- old/knack-0.5.3/knack/cli.py        2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/knack/cli.py        2019-03-29 20:11:28.000000000 +0100
@@ -81,7 +81,7 @@
         self._event_handlers = defaultdict(lambda: [])
         # Data that's typically backed to persistent storage
         self.config = config_cls(
-            config_dir=config_dir or os.path.join('~', '.{}'.format(cli_name)),
+            config_dir=config_dir or os.path.expanduser(os.path.join('~', 
'.{}'.format(cli_name))),
             config_env_var_prefix=config_env_var_prefix or cli_name.upper()
         )
         # In memory collection of key-value data for this current cli. This 
persists between invocations.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/commands.py 
new/knack-0.5.4/knack/commands.py
--- old/knack-0.5.3/knack/commands.py   2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/knack/commands.py   2019-03-29 20:11:28.000000000 +0100
@@ -17,6 +17,7 @@
 from .events import (EVENT_CMDLOADER_LOAD_COMMAND_TABLE, 
EVENT_CMDLOADER_LOAD_ARGUMENTS,
                      EVENT_COMMAND_CANCELLED)
 from .log import get_logger
+from .validators import DefaultInt, DefaultStr
 
 logger = get_logger(__name__)
 
@@ -71,6 +72,18 @@
     def should_load_description(self):
         return not self.cli_ctx.data['completer_active']
 
+    def _resolve_default_value_from_config_file(self, arg, overrides):
+        default_key = overrides.settings.get('configured_default', None)
+        if not default_key:
+            return
+
+        defaults_section = self.cli_ctx.config.defaults_section_name
+        config_value = self.cli_ctx.config.get(defaults_section, default_key, 
None)
+        if config_value:
+            logger.info("Configured default '%s' for arg %s", config_value, 
arg.name)
+            overrides.settings['default'] = DefaultStr(config_value)
+            overrides.settings['required'] = False
+
     def load_arguments(self):
         if self.arguments_loader:
             cmd_args = self.arguments_loader()
@@ -87,7 +100,20 @@
 
     def update_argument(self, param_name, argtype):
         arg = self.arguments[param_name]
+        # resolve defaults from either environment variable or config file
+        self._resolve_default_value_from_config_file(arg, argtype)
         arg.type.update(other=argtype)
+        arg_default = arg.type.settings.get('default', None)
+        # apply DefaultStr and DefaultInt to allow distinguishing between
+        # when a default was applied or when the user specified a value
+        # that coincides with the default
+        if isinstance(arg_default, str):
+            arg_default = DefaultStr(arg_default)
+        elif isinstance(arg_default, int):
+            arg_default = DefaultInt(arg_default)
+        # update the default
+        if arg_default:
+            arg.type.settings['default'] = arg_default
 
     def execute(self, **kwargs):
         return self(**kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/config.py 
new/knack-0.5.4/knack/config.py
--- old/knack-0.5.3/knack/config.py     2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/knack/config.py     2019-03-29 20:11:28.000000000 +0100
@@ -23,6 +23,7 @@
     _DEFAULT_CONFIG_ENV_VAR_PREFIX = 'CLI'
     _DEFAULT_CONFIG_DIR = os.path.join('~', '.{}'.format('cli'))
     _DEFAULT_CONFIG_FILE_NAME = 'config'
+    _CONFIG_DEFAULTS_SECTION = 'defaults'
 
     def __init__(self, config_dir=None, config_env_var_prefix=None, 
config_file_name=None):
         """ Manages configuration options available in the CLI
@@ -44,6 +45,7 @@
         configuration_file_name = config_file_name or 
CLIConfig._DEFAULT_CONFIG_FILE_NAME
         self.config_path = os.path.join(self.config_dir, 
configuration_file_name)
         self._env_var_format = '{}{}'.format(env_var_prefix, 
'{section}_{option}')
+        self.defaults_section_name = CLIConfig._CONFIG_DEFAULTS_SECTION
         self.config_parser.read(self.config_path)
 
     def env_var_name(self, section, option):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/parser.py 
new/knack-0.5.4/knack/parser.py
--- old/knack-0.5.3/knack/parser.py     2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/knack/parser.py     2019-03-29 20:11:28.000000000 +0100
@@ -7,8 +7,10 @@
 
 from .deprecation import Deprecated
 from .events import EVENT_PARSER_GLOBAL_CREATE
+from .log import get_logger
 from .util import CtxTypeError
 
+logger = get_logger(__name__)
 
 # List of keyword arguments supported in argparse
 # from https://github.com/python/cpython/blob/master/Lib/argparse.py#L748
@@ -66,6 +68,25 @@
             argparse_options['metavar'] = 
'<{}>'.format(argparse_options['dest'].upper())
         return obj.add_argument(**argparse_options)
 
+    @staticmethod
+    def _expand_prefixed_files(args):
+        """ Load arguments prefixed with '@' from file as string
+
+        :param args: Arguments passed from command line
+        :type args: list
+        """
+        for arg, _ in enumerate(args):
+            if args[arg].startswith('@'):
+                try:
+                    logger.debug('Attempting to read file %s', args[arg][1:])
+                    with open(args[arg][1:], 'r') as f:
+                        content = f.read()
+                    args[arg] = content
+                except IOError:
+                    # Leave arg unmodified
+                    logger.debug('File Error: Failed to open %s, assume not a 
file', args[arg][1:])
+        return args
+
     def __init__(self, cli_ctx=None, cli_help=None, **kwargs):
         """ Create the argument parser
 
@@ -224,3 +245,12 @@
                                 self._actions[-1] if is_group else self,
                                 is_group)
         self.exit()
+
+    def parse_args(self, args=None, namespace=None):
+        """ Overrides argparse.ArgumentParser.parse_args
+
+        Enables '@'-prefixed files to be expanded before arguments are 
processed
+        by ArgumentParser.parse_args as usual
+        """
+        self._expand_prefixed_files(args)
+        return super(CLICommandParser, self).parse_args(args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/testsdk/patches.py 
new/knack-0.5.4/knack/testsdk/patches.py
--- old/knack-0.5.3/knack/testsdk/patches.py    2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/knack/testsdk/patches.py    2019-03-29 20:11:28.000000000 
+0100
@@ -4,7 +4,10 @@
 # 
--------------------------------------------------------------------------------------------
 
 import unittest
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 from .exceptions import CliTestError
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/knack/validators.py 
new/knack-0.5.4/knack/validators.py
--- old/knack-0.5.3/knack/validators.py 1970-01-01 01:00:00.000000000 +0100
+++ new/knack-0.5.4/knack/validators.py 2019-03-29 20:11:28.000000000 +0100
@@ -0,0 +1,20 @@
+# 
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for 
license information.
+# 
--------------------------------------------------------------------------------------------
+
+
+class DefaultStr(str):
+
+    def __new__(cls, *args, **kwargs):
+        instance = str.__new__(cls, *args, **kwargs)
+        instance.is_default = True
+        return instance
+
+
+class DefaultInt(int):
+
+    def __new__(cls, *args, **kwargs):
+        instance = int.__new__(cls, *args, **kwargs)
+        instance.is_default = True
+        return instance
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/setup.py new/knack-0.5.4/setup.py
--- old/knack-0.5.3/setup.py    2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/setup.py    2019-03-29 20:11:28.000000000 +0100
@@ -9,7 +9,7 @@
 from codecs import open
 from setuptools import setup, find_packages
 
-VERSION = '0.5.3'
+VERSION = '0.5.4'
 
 DEPENDENCIES = [
     'argcomplete',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_cli_scenarios.py 
new/knack-0.5.4/tests/test_cli_scenarios.py
--- old/knack-0.5.3/tests/test_cli_scenarios.py 2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_cli_scenarios.py 2019-03-29 20:11:28.000000000 
+0100
@@ -5,6 +5,10 @@
 
 import os
 import unittest
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 import mock
 
 from collections import OrderedDict
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/knack-0.5.3/tests/test_command_with_configured_defaults.py 
new/knack-0.5.4/tests/test_command_with_configured_defaults.py
--- old/knack-0.5.3/tests/test_command_with_configured_defaults.py      
1970-01-01 01:00:00.000000000 +0100
+++ new/knack-0.5.4/tests/test_command_with_configured_defaults.py      
2019-03-29 20:11:28.000000000 +0100
@@ -0,0 +1,90 @@
+# 
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for 
license information.
+# 
--------------------------------------------------------------------------------------------
+from __future__ import print_function
+import os
+import logging
+import unittest
+try:
+    import mock
+except ImportError:
+    from unittest import mock
+from six import StringIO
+import sys
+
+from knack.arguments import ArgumentsContext
+from knack.commands import CLICommandsLoader, CLICommand, CommandGroup
+from knack.config import CLIConfig
+from tests.util import DummyCLI, redirect_io
+
+
+# a dummy callback for arg-parse
+def load_params(_):
+    pass
+
+
+def list_foo(my_param):
+    print(str(my_param), end='')
+
+
+class TestCommandWithConfiguredDefaults(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        # Ensure initialization has occurred correctly
+        logging.basicConfig(level=logging.DEBUG)
+
+    @classmethod
+    def tearDownClass(cls):
+        logging.shutdown()
+
+    def _set_up_command_table(self, required):
+
+        class TestCommandsLoader(CLICommandsLoader):
+
+            def load_command_table(self, args):
+                super(TestCommandsLoader, self).load_command_table(args)
+                with CommandGroup(self, 'foo', '{}#{{}}'.format(__name__)) as 
g:
+                    g.command('list', 'list_foo')
+                return self.command_table
+
+            def load_arguments(self, command):
+                with ArgumentsContext(self, 'foo') as c:
+                    c.argument('my_param', options_list='--my-param',
+                               configured_default='param', required=required)
+                super(TestCommandsLoader, self).load_arguments(command)
+        self.cli_ctx = DummyCLI(commands_loader_cls=TestCommandsLoader)
+
+    @mock.patch.dict(os.environ, {'CLI_DEFAULTS_PARAM': 'myVal'})
+    @redirect_io
+    def test_apply_configured_defaults_on_required_arg(self):
+        self._set_up_command_table(required=True)
+        self.cli_ctx.invoke('foo list'.split())
+        actual = self.io.getvalue()
+        expected = 'myVal'
+        self.assertEqual(expected, actual)
+
+    @redirect_io
+    def test_no_configured_default_on_required_arg(self):
+        self._set_up_command_table(required=True)
+        with self.assertRaises(SystemExit):
+            self.cli_ctx.invoke('foo list'.split())
+        actual = self.io.getvalue()
+        expected = 'required: --my-param'
+        if sys.version_info[0] == 2:
+            expected = 'argument --my-param is required'
+        self.assertEqual(expected in actual, True)
+
+    @mock.patch.dict(os.environ, {'CLI_DEFAULTS_PARAM': 'myVal'})
+    @redirect_io
+    def test_apply_configured_defaults_on_optional_arg(self):
+        self._set_up_command_table(required=False)
+        self.cli_ctx.invoke('foo list'.split())
+        actual = self.io.getvalue()
+        expected = 'myVal'
+        self.assertEqual(expected, actual)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_completion.py 
new/knack-0.5.4/tests/test_completion.py
--- old/knack-0.5.3/tests/test_completion.py    2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_completion.py    2019-03-29 20:11:28.000000000 
+0100
@@ -5,7 +5,10 @@
 
 import os
 import unittest
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 
 from knack.completion import CLICompletion, CaseInsensitiveChoicesCompleter, 
ARGCOMPLETE_ENV_NAME
 from tests.util import MockContext
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_config.py 
new/knack-0.5.4/tests/test_config.py
--- old/knack-0.5.3/tests/test_config.py        2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_config.py        2019-03-29 20:11:28.000000000 
+0100
@@ -7,7 +7,10 @@
 import stat
 import unittest
 import tempfile
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 from six.moves import configparser
 
 from knack.config import CLIConfig, get_config_parser
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_deprecation.py 
new/knack-0.5.4/tests/test_deprecation.py
--- old/knack-0.5.3/tests/test_deprecation.py   2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_deprecation.py   2019-03-29 20:11:28.000000000 
+0100
@@ -5,16 +5,17 @@
 
 from __future__ import unicode_literals
 
-import sys
 import unittest
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 from threading import Lock
-from six import StringIO
 
 from knack.arguments import ArgumentsContext
 from knack.commands import CLICommand, CLICommandsLoader, CommandGroup
 
-from tests.util import DummyCLI
+from tests.util import DummyCLI, redirect_io
 
 
 def example_handler(arg1, arg2=None, arg3=None):
@@ -27,20 +28,6 @@
     pass
 
 
-original_stdout = sys.stdout
-original_stderr = sys.stderr
-
-
-def redirect_io(func):
-    def wrapper(self):
-        sys.stdout = sys.stderr = self.io = StringIO()
-        func(self)
-        self.io.close()
-        sys.stdout = original_stderr
-        sys.stderr = original_stderr
-    return wrapper
-
-
 class TestCommandDeprecation(unittest.TestCase):
 
     def setUp(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_log.py 
new/knack-0.5.4/tests/test_log.py
--- old/knack-0.5.3/tests/test_log.py   2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/tests/test_log.py   2019-03-29 20:11:28.000000000 +0100
@@ -4,7 +4,10 @@
 # 
--------------------------------------------------------------------------------------------
 
 import unittest
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 import logging
 import colorama
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_parser.py 
new/knack-0.5.4/tests/test_parser.py
--- old/knack-0.5.3/tests/test_parser.py        2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_parser.py        2019-03-29 20:11:28.000000000 
+0100
@@ -133,6 +133,34 @@
         parser = CLICommandParser()
         parser.load_command_table(self.mock_ctx.commands_loader)
 
+    def test_prefix_file_expansion(self):
+        import json, os
+
+        def test_handler():
+            pass
+
+        def create_test_file(file, contents):
+            with open(file, 'w') as f:
+                f.write(contents)
+
+        def remove_test_file(file):
+            os.remove(file)
+
+        json_test_data = json.dumps({'one': 1, 'two': 2, 'three': 3})
+        create_test_file('test.json', json_test_data)
+
+        command = CLICommand(self.mock_ctx, 'test command', test_handler)
+        command.add_argument('json_data', '--param')
+        cmd_table = {'test command': command}
+        self.mock_ctx.commands_loader.command_table = cmd_table
+        parser = CLICommandParser()
+        parser.load_command_table(self.mock_ctx.commands_loader)
+
+        args = parser.parse_args('test command --param @test.json'.split())
+        self.assertEqual(json_test_data, args.json_data)
+
+        remove_test_file('test.json')
+
 
 class VerifyError(object):  # pylint: disable=too-few-public-methods
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/test_prompting.py 
new/knack-0.5.4/tests/test_prompting.py
--- old/knack-0.5.3/tests/test_prompting.py     2019-03-06 00:03:37.000000000 
+0100
+++ new/knack-0.5.4/tests/test_prompting.py     2019-03-29 20:11:28.000000000 
+0100
@@ -5,7 +5,10 @@
 
 import sys
 import unittest
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
 from six import StringIO
 
 from knack.prompting import (verify_is_a_tty, NoTTYException, 
_INVALID_PASSWORD_MSG, prompt,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/knack-0.5.3/tests/util.py 
new/knack-0.5.4/tests/util.py
--- old/knack-0.5.3/tests/util.py       2019-03-06 00:03:37.000000000 +0100
+++ new/knack-0.5.4/tests/util.py       2019-03-29 20:11:28.000000000 +0100
@@ -3,11 +3,29 @@
 # Licensed under the MIT License. See License.txt in the project root for 
license information.
 # 
--------------------------------------------------------------------------------------------
 
-import mock
+try:
+    import mock
+except ImportError:
+    from unittest import mock
+import sys
 import tempfile
+from six import StringIO
 
 from knack.cli import CLI, CLICommandsLoader, CommandInvoker
 
+def redirect_io(func):
+
+    original_stderr = sys.stderr
+    original_stdout = sys.stdout
+
+    def wrapper(self):
+        sys.stdout = sys.stderr = self.io = StringIO()
+        func(self)
+        self.io.close()
+        sys.stdout = original_stderr
+        sys.stderr = original_stderr
+    return wrapper
+
 
 class MockContext(CLI):
 


Reply via email to