1

EDIT: I do not consider my question a duplicate (see comment below) BECAUSE that question assumes you already know "positional arguments" exist. Had I known about positional arguments - BETTER - even made a mistake in my initial comment below - had I known about keyword arguments I would not have needed to ask the question! All I could come up with is "looks like an assignment" as I would see/know of in C.

p.s. I have read the other answers - and without the answer below I would not now how to use the answers to answer my question "how to read" this code. The answer below gave me a "life-long" understanding such that I can read foo(a=b), and move on. Additionally, I have learned the term "keyword argument" - but I was also happy without knowing that :)

I also feel it is more concise - directly answering my need. I would have had to spend much more time to learn what I learned from this answer - from the 'other' answers.


The crux of the question is: considering the python call: util.find_devs_with(path=device) what is actually happening (code details/extracts below)?

  1. create the variable "path", assign the value of "device" to it
  2. pass the value just assigned to util.find_devs()
  3. so which of these two calls is made: (or something else?)

Or is it doing the following:

# blkid -t/dev/sr0 2&>/dev/null
# echo $?
4

# blkid -tpath=/dev/sr0 2&>/dev/null
# echo $?
2

Details

POSSIBLE_MOUNTS = ('sr', 'cd')
OPTICAL_DEVICES = tuple(('/dev/%s%s' % (z, i) for z in POSSIBLE_MOUNTS
                        for i in range(0, 2)))
...
def find_candidate_devs(probe_optical=True):
    """Return a list of devices that may contain the config drive.

    The returned list is sorted by search order where the first item has
    should be searched first (highest priority)

    config drive v1:
       Per documentation, this is "associated as the last available disk on the
       instance", and should be VFAT.
       Currently, we do not restrict search list to "last available disk"

    config drive v2:
       Disk should be:
        * either vfat or iso9660 formated
        * labeled with 'config-2'
    """
    if probe_optical:
        for device in OPTICAL_DEVICES:
            try:
                util.find_devs_with(path=device)
            except util.ProcessExecutionError:
                pass
...

in util.py

def find_devs_with(criteria=None, oformat='device',
                   tag=None, no_cache=False, path=None):
    """
    find devices matching given criteria (via blkid)
    criteria can be *one* of:
      TYPE=<filesystem>
      LABEL=<label>
      UUID=<uuid>
    """
    blk_id_cmd = ['blkid']
    options = []
    if criteria:
        # Search for block devices with tokens named NAME that
        # have the value 'value' and display any devices which are found.
        # Common values for NAME include  TYPE, LABEL, and UUID.
        # If there are no devices specified on the command line,
        # all block devices will be searched; otherwise,
        # only search the devices specified by the user.
        options.append("-t%s" % (criteria))
...
    cmd = blk_id_cmd + options
    # See man blkid for why 2 is added
    try:
        (out, _err) = subp(cmd, rcs=[0, 2])
    except ProcessExecutionError as e:
        if e.errno == errno.ENOENT:
            # blkid not found...
            out = ""
        else:
            raise
    entries = []
    for line in out.splitlines():
        line = line.strip()
        if line:
            entries.append(line)
    return entries

My expectation is that the command being executed is equivalent to:

blkid "-t%s" % criteria

So, what is the value "received" as criteria? aka a lesson in python argument "stacking?".

Going through all this code a second time, my guess is that the argument 'path=device' is just "somegarbage" so that blkid -tsomegarbage is called, and returns an error AFTER having filled the blkid cache.

Michael Felt
  • 484
  • 1
  • 4
  • 9
  • 3
    Possible duplicate of [Python normal arguments vs. keyword arguments](http://stackoverflow.com/questions/1419046/python-normal-arguments-vs-keyword-arguments) – Łukasz Rogalski Dec 09 '16 at 14:51
  • Yes, if you already know enough to know that "keyword arguments" exist. I was baffled by the code as I am an old dog and only know (read assumed) that is was an assignment to a variable (as can be done in a conditional in C) and the result of that assignment was passed. Had I known about the existence of "keyword arguments" I would not have needed to ask! – Michael Felt Dec 09 '16 at 16:14
  • ALSO - I see now the question was migrated. Do not know if before or after the answer below. my gut feeling is "obviously" someone who lives in SE may know this in advance - whereas for a "UNIX admin" (where the question came from) is less likely know about "positional|keyword|etc" arguments. I am 'saddened' it got moved - as I feel "more at home" at UNIX and LINUX then here (as nice and great as you guys obviously are!). Sigh. – Michael Felt Dec 09 '16 at 16:25

1 Answers1

2

In Python, arguments can be assigned with default values. Given this signature:

def find_devs_with(criteria=None, oformat='device',
                   tag=None, no_cache=False, path=None):

if you invoke it with:

util.find_devs_with(path=device)

then the the following assignments exist:

criteria = None
oformat = 'device' 
tag = None
no_cache = False
path = device   # according to the above code, /dev/sr0, ..., /dev/cd1

Since criteria is None, the -t option is not appended. The command that gets executed is simply blkid.

Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
  • Looks like I have a winner! Many thanks. So much to learn about how python adapts things. Too many years a C (not flat, but not sharp/++ either) programmer - so rather set in my ways! Again, thanks - you taught me more than I expected to learn! (Now I just need to learn to format as pretty as you :)) – Michael Felt Dec 09 '16 at 14:28