1

the following code inside a function def seems to me to be unwieldy. Is there a better way to conditionally prefer one parameter over a dict. This came from some impedance mismatch between robotframework which does not (IMO) have a satisfactory handle on kwargs:

def get_passwd(input_dict=None, **kwargs):
    pswd = None
    if input_dict:
        if input_dict and input_dict.get('passphrase_confirm'):
            pswd = input_dict['passphrase_confirm']
        elif kwargs.get('passphrase_confirm'):
            pswd = kwargs['passphrase_confirm']
    if not pswd:
        # here because there was no password_confirm or no input_dict, we look again in kwargs
        if 'passphrase_confirm' in kwargs and kwargs['passphrase_confirm']:
            pswd = kwargs['passphrase_confirm']
        elif input_dict and 'passphrase' in input_dict and input_dict['passphrase_confirm']:
            pswd = input_dict['passphrase']
        elif 'passphrase' in kwargs and kwargs['passphrase']:
            pswd = kwargs['passphrase']
    return pswd
msudder
  • 505
  • 3
  • 14
  • It's interesting that you mention robotframework, but don't show how you are using this function from the framework. If you could show an example of this "impedence mismatch" perhaps there's a better solution than to accept either a dict or kwargs. – Bryan Oakley Jun 22 '14 at 20:42

4 Answers4

2

I think the simplest solution is to merge the two dictionaries, then just use the get method on the result. If I understand your logic correctly (and I'm not sure I do...), you want the value of "passphrase_confirm" if it exists in one of the dictionaries, and if it doesn't, you want "passphrase". Also, if it's in both, you want the one from input_dict.

I think this does what you want, and is much easier to understand than your original code:

def get_passwd(input_dict=None, **kwargs):
    kwargs = kwargs if input_dict is None else dict(kwargs.items() + input_dict.items())
    if "passphrase_confirm" in kwargs:
        return kwargs["passphrase_confirm"]
    else:
        return kwargs.get("passphrase", None)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I might even just do `return kwargs.get('passphrase_confirm') or kwargs.get('passphrase')`. It looks like the OP wants to ignore empty *or* missing `passphrase_confirm`. – nneonneo Jun 22 '14 at 21:39
1

Following msudder's suggestion, you could merge the dictionaries (the default and the kwargs), and then get the answer from the merged dictionary.

More info on merging here. The syntax looks like: merged = dict(kwargs.items() + input_dict.items()), where the "winning" dictionary comes last.

Community
  • 1
  • 1
skatenerd
  • 60
  • 7
0

So you want pwd to be (in preference order) :

  • input_dict['passphrase_confirm']
  • kwargs['passphrase_confirm']
  • input_dict['passphrase']
  • kwargs['passphrase']

where input_dict may be None

You should write :

def get_passwd(input_dict=None, **kwargs):
    if input_dict and ('passphrase_confirm' in input_dict):
        pwd = input_dict['passphrase_confirm']
    elif 'passphrase_confirm' in kwargs:
        pwd = kwargs['passphrase_confirm']
    elif input_dict and ('passphrase' in input_dict):
        pwd = input_dict['passphrase']
    elif 'passphrase' in kwargs:
        pwd = kwargs['passphrase']
    else:
        pwd = None
    return pwd

That does the same than your original code (strict respect of preference order), has less redundance (if input_dict: if input_dict and ...) and is (I hope) more pythonic

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
-1

Change signature default for input dict and then you can remove all tests on input_dict to simply use dict.get making

def get_passwd(input_dict={}, **kwargs):
    pswd = None
    if input_dict.get('passphrase_confirm'):
        pswd = input_dict['passphrase_confirm']
    elif kwargs.get('passphrase_confirm'):
        pswd = kwargs['passphrase_confirm']
    if not pswd:
        # here because there was no password_confirm so use passphrase
        if input_dict.get('passphrase'):
            pswd = input_dict['passphrase']
        elif kwargs.get('passphrase'):
            pswd = kwargs.get('passphrase')
    return pswd
msudder
  • 505
  • 3
  • 14
  • 2
    Mutable default is a common source of bugs, don't do it unless you know what you are writing. See http://docs.python-guide.org/en/latest/writing/gotchas/ – Yanshuai Cao May 30 '14 at 02:36