Instruction:
Can you generate the documentation for the following Python 3 function
def start(self, measurementId, durationInSeconds=None):
        logger.info(">> measurement " + measurementId +
                    ((" for " + str(durationInSeconds)) if durationInSeconds is not None else " until break"))
        self.failureCode = None
        self.measurementOverflowed = False
        self.dataHandler.start(measurementId)
        self.breakRead = False
        self.startTime = time.time()
        self.doInit()
        # this must follow doInit because doInit sets status to INITIALISED
        self.status = RecordingDeviceStatus.RECORDING
        elapsedTime = 0
        try:
            self._sampleIdx = 0
            while True:
                logger.debug(measurementId + " provideData ")
                self.dataHandler.handle(self.provideData())
                elapsedTime = time.time() - self.startTime
                if self.breakRead or durationInSeconds is not None and elapsedTime > durationInSeconds:
                    logger.debug(measurementId + " breaking provideData")
                    self.startTime = 0
                    break
        except:
            self.status = RecordingDeviceStatus.FAILED
            self.failureCode = str(sys.exc_info())
            logger.exception(measurementId + " failed")
        finally:
            expectedSamples = self.fs * (durationInSeconds if durationInSeconds is not None else elapsedTime)
            if self._sampleIdx < expectedSamples:
                self.status = RecordingDeviceStatus.FAILED
                self.failureCode = "Insufficient samples " + str(self._sampleIdx) + " for " + \
                                   str(elapsedTime) + " second long run, expected " + str(expectedSamples)
            self._sampleIdx = 0
            if self.measurementOverflowed:
                self.status = RecordingDeviceStatus.FAILED
                self.failureCode = "Measurement overflow detected"
            if self.status == RecordingDeviceStatus.FAILED:
                logger.error("<< measurement " + measurementId + " - FAILED - " + self.failureCode)
            else:
                self.status = RecordingDeviceStatus.INITIALISED
                logger.info("<< measurement " + measurementId + " - " + self.status.name)
            self.dataHandler.stop(measurementId, self.failureCode)
            if self.status == RecordingDeviceStatus.FAILED:
                logger.warning("Reinitialising device after measurement failure")
                self.doInit()

Response: Start recording the specified measurement.


Instruction:
How would you code a function in Python 3 to
yield the analysed wav data.

Response:
def get(self, targetId):
        """
        Yields the analysed wav data.
        :param targetId:
        :return:
        """
        result = self._targetController.analyse(targetId)
        if result:
            if len(result) == 2:
                if result[1] == 404:
                    return result
                else:
                    return {'name': targetId, 'data': self._jsonify(result)}, 200
            else:
                return None, 404
        else:
            return None, 500


Instruction:
Write a Python 3 script to
store a new target.

Response:
def put(self, targetId):
        """
        stores a new target.
        :param targetId: the target to store.
        :return:
        """
        json = request.get_json()
        if 'hinge' in json:
            logger.info('Storing target ' + targetId)
            if self._targetController.storeFromHinge(targetId, json['hinge']):
                logger.info('Stored target ' + targetId)
                return None, 200
            else:
                return None, 500
        else:
            return None, 400


Instruction:
Write a Python 3 function that can
return a datetime for the input floating point Julian Day Count

Response:
def to_datetime(jdc):
    '''Return a datetime for the input floating point Julian Day Count'''
    year, month, day = gregorian.from_jd(jdc)

    # in jdc: 0.0 = noon, 0.5 = midnight
    # the 0.5 changes it to 0.0 = midnight, 0.5 = noon
    frac = (jdc + 0.5) % 1

    hours = int(24 * frac)

    mfrac = frac * 24 - hours
    mins = int(60 * round(mfrac, 6))

    sfrac = mfrac * 60 - mins
    secs = int(60 * round(sfrac, 6))

    msfrac = sfrac * 60 - secs

    # down to ms, which are 1/1000 of a second
    ms = int(1000 * round(msfrac, 6))

    return datetime(year, month, day, int(hours), int(mins), int(secs), int(ms), tzinfo=utc)


Instruction:
Can you generate the documentation for the following Python 3 function
def dict_from_qs(qs):
    ''' Slightly introverted parser for lists of dot-notation nested fields
        i.e. "period.di,period.fhr" => {"period": {"di": {}, "fhr": {}}}
    '''
    entries = qs.split(',') if qs.strip() else []
    entries = [entry.strip() for entry in entries]

    def _dict_from_qs(line, d):
        if '.' in line:
            key, value = line.split('.', 1)
            d.setdefault(key, {})
            return _dict_from_qs(value, d[key])
        else:
            d[line] = {}

    def _default():
        return defaultdict(_default)

    d = defaultdict(_default)
    for line in entries:
        _dict_from_qs(line, d)
    return d

Response:
Slightly introverted parser for lists of dot - notation nested fields
AttributeNames = > dict


Instruction:
Can you generate the documentation for the following Python 3 function
def qs_from_dict(qsdict, prefix=""):
    ''' Same as dict_from_qs, but in reverse
        i.e. {"period": {"di": {}, "fhr": {}}} => "period.di,period.fhr"
    '''
    prefix = prefix + '.' if prefix else ""

    def descend(qsd):
        for key, val in sorted(qsd.items()):
            if val:
                yield qs_from_dict(val, prefix + key)
            else:
                yield prefix + key
    return ",".join(descend(qsdict))

Response: Returns a string that is a list of all the items in the dictionary.


Instruction:
Given the following Python 3 function, write the documentation
def dbcon(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        self = args[0]
        if self.dbcon is None:
            # set up connection
            self.dbcon = sqlite3.connect(self.db)
            self.dbcur = self.dbcon.cursor()
            self.dbcur.execute(SQL_SENSOR_TABLE)
            self.dbcur.execute(SQL_TMPO_TABLE)

            # execute function
            try:
                result = func(*args, **kwargs)
            except Exception as e:
                # on exception, first close connection and then raise
                self.dbcon.rollback()
                self.dbcon.commit()
                self.dbcon.close()
                self.dbcon = None
                self.dbcur = None
                raise e
            else:
                # commit everything and close connection
                self.dbcon.commit()
                self.dbcon.close()
                self.dbcon = None
                self.dbcur = None
        else:
            result = func(*args, **kwargs)
        return result
    return wrapper

Response: Set up connection before executing function commit and close connection after executing function. Unless a connection already has been created a new one is created.


Instruction:
Can you implement a function in Python 3 that
adds new sensor to the database

Response:
def add(self, sid, token):
        """
        Add new sensor to the database

        Parameters
        ----------
        sid : str
            SensorId
        token : str
        """
        try:
            self.dbcur.execute(SQL_SENSOR_INS, (sid, token))
        except sqlite3.IntegrityError:  # sensor entry exists
            pass


Instruction:
Write a Python 3 script for
removing a specific sensor from the database.

Response:
def remove(self, sid):
        """
        Remove sensor from the database

        Parameters
        ----------
        sid : str
            SensorID
        """
        self.dbcur.execute(SQL_SENSOR_DEL, (sid,))
        self.dbcur.execute(SQL_TMPO_DEL, (sid,))


Instruction:
Here you have a function in Python 3, explain what it does
def sync(self, *sids):
        if sids == ():
            sids = [sid for (sid,) in self.dbcur.execute(SQL_SENSOR_ALL)]
        for sid in sids:
            self.dbcur.execute(SQL_TMPO_LAST, (sid,))
            last = self.dbcur.fetchone()
            if last:
                rid, lvl, bid, ext = last
                self._clean(sid, rid, lvl, bid)
                # prevent needless polling
                if time.time() < bid + 256:
                    return
            else:
                rid, lvl, bid = 0, 0, 0
            self._req_sync(sid, rid, lvl, bid)

Response: Synchronise data with the specified sensors.


Instruction:
Make a summary of the following Python 3 code
def list(self, *sids):
        if sids == ():
            sids = [sid for (sid,) in self.dbcur.execute(SQL_SENSOR_ALL)]
        slist = []
        for sid in sids:
            tlist = []
            for tmpo in self.dbcur.execute(SQL_TMPO_ALL, (sid,)):
                tlist.append(tmpo)
                sid, rid, lvl, bid, ext, ctd, blk = tmpo
                self._dprintf(DBG_TMPO_WRITE, ctd, sid, rid, lvl, bid, len(blk))
            slist.append(tlist)
        return slist

Response: List all tmpo - blocks in the database.


Instruction:
Write a Python 3 function for
creating data Series from a record.

Response:
def series(self, sid, recycle_id=None, head=None, tail=None,
               datetime=True):
        """
        Create data Series

        Parameters
        ----------
        sid : str
        recycle_id : optional
        head : int | pandas.Timestamp, optional
            Start of the interval
            default earliest available
        tail : int | pandas.Timestamp, optional
            End of the interval
            default max epoch
        datetime : bool
            convert index to datetime
            default True

        Returns
        -------
        pandas.Series
        """
        if head is None:
            head = 0
        else:
            head = self._2epochs(head)

        if tail is None:
            tail = EPOCHS_MAX
        else:
            tail = self._2epochs(tail)

        if recycle_id is None:
            self.dbcur.execute(SQL_TMPO_RID_MAX, (sid,))
            recycle_id = self.dbcur.fetchone()[0]
        tlist = self.list(sid)[0]
        srlist = []
        for _sid, rid, lvl, bid, ext, ctd, blk in tlist:
            if (recycle_id == rid
            and head < self._blocktail(lvl, bid)
            and tail >= bid):
                srlist.append(self._blk2series(ext, blk, head, tail))
        if len(srlist) > 0:
            ts = pd.concat(srlist)
            ts.name = sid
            if datetime is True:
                ts.index = pd.to_datetime(ts.index, unit="s", utc=True)
            return ts
        else:
            return pd.Series([], name=sid)


Instruction:
Create a Python 3 function to
create data frame for a set of sids.

Response:
def dataframe(self, sids, head=0, tail=EPOCHS_MAX, datetime=True):
        """
        Create data frame

        Parameters
        ----------
        sids : list[str]
        head : int | pandas.Timestamp, optional
            Start of the interval
            default earliest available
        tail : int | pandas.Timestamp, optional
            End of the interval
            default max epoch
        datetime : bool
            convert index to datetime
            default True

        Returns
        -------
        pandas.DataFrame
        """
        if head is None:
            head = 0
        else:
            head = self._2epochs(head)

        if tail is None:
            tail = EPOCHS_MAX
        else:
            tail = self._2epochs(tail)

        series = [self.series(sid, head=head, tail=tail, datetime=False)
                  for sid in sids]
        df = pd.concat(series, axis=1)
        if datetime is True:
            df.index = pd.to_datetime(df.index, unit="s", utc=True)
        return df


Instruction:
How would you code a function in Python 3 to
get the first available timestamp for a sensor.

Response:
def first_timestamp(self, sid, epoch=False):
        """
        Get the first available timestamp for a sensor

        Parameters
        ----------
        sid : str
            SensorID
        epoch : bool
            default False
            If True return as epoch
            If False return as pd.Timestamp

        Returns
        -------
        pd.Timestamp | int
        """
        first_block = self.dbcur.execute(SQL_TMPO_FIRST, (sid,)).fetchone()
        if first_block is None:
            return None

        timestamp = first_block[2]
        if not epoch:
            timestamp = pd.Timestamp.utcfromtimestamp(timestamp)
            timestamp = timestamp.tz_localize('UTC')
        return timestamp


Instruction:
How would you implement a function in Python 3 that
gets the theoretical last timestamp for a sensor.

Response:
def last_timestamp(self, sid, epoch=False):
        """
        Get the theoretical last timestamp for a sensor

        Parameters
        ----------
        sid : str
            SensorID
        epoch : bool
            default False
            If True return as epoch
            If False return as pd.Timestamp

        Returns
        -------
        pd.Timestamp | int
        """
        timestamp, value = self.last_datapoint(sid, epoch)
        return timestamp


Instruction:
How would you code a function in Python 3 to
return the last datapoint for a specific SensorId.

Response:
def last_datapoint(self, sid, epoch=False):
        """
        Parameters
        ----------
        sid : str
            SensorId
        epoch : bool
            default False
            If True return as epoch
            If False return as pd.Timestamp

        Returns
        -------
        pd.Timestamp | int, float
        """
        block = self._last_block(sid)
        if block is None:
            return None, None

        header = block['h']
        timestamp, value = header['tail']

        if not epoch:
            timestamp = pd.Timestamp.utcfromtimestamp(timestamp)
            timestamp = timestamp.tz_localize('UTC')

        return timestamp, value


Instruction:
Can you generate the documentation for the following Python 3 function
def _npdelta(self, a, delta):
        for x in np.nditer(a, op_flags=["readwrite"]):
            delta += x
            x[...] = delta
        return a

Response: Modify a by the delta


Instruction:
Implement a function in Python 3 to
take a string and parses it to get a dict of the keyword args and their values.

Response:
def sigStrToKwArgsDict(checkFuncSig):
    """ Take a check function signature (string), and parse it to get a dict
        of the keyword args and their values. """
    p1 = checkFuncSig.find('(')
    p2 = checkFuncSig.rfind(')')
    assert p1 > 0 and p2 > 0 and p2 > p1, "Invalid signature: "+checkFuncSig
    argParts = irafutils.csvSplit(checkFuncSig[p1+1:p2], ',', True)
    argParts = [x.strip() for x in argParts]
    retval = {}
    for argPair in argParts:
        argSpl = argPair.split('=', 1)
        if len(argSpl) > 1:
            if argSpl[0] in retval:
                if isinstance(retval[argSpl[0]], (list,tuple)):
                    retval[argSpl[0]]+=(irafutils.stripQuotes(argSpl[1]),) # 3rd
                else: # 2nd in, so convert to tuple
                    retval[argSpl[0]] = (retval[argSpl[0]],
                                         irafutils.stripQuotes(argSpl[1]),)
            else:
                retval[argSpl[0]] = irafutils.stripQuotes(argSpl[1]) # 1st in
        else:
            retval[argSpl[0]] = None #  eg. found "triggers=, max=6, ..."
    return retval


Instruction:
Can you tell what is the following Python 3 function doing
def separateKeywords(kwArgsDict):
    standardKws = {}
    ourKws = {}
    for k in kwArgsDict:
        if k in STANDARD_KEYS:
            standardKws[k]=kwArgsDict[k]
        else:
            ourKws[k]=kwArgsDict[k]
    return (standardKws, ourKws)

Response: Look through the keywords passed and separate the legal and standard ones.


Instruction:
Create a Python 3 function for
altering the passed function signature string to add the given kewords

Response:
def addKwdArgsToSig(sigStr, kwArgsDict):
    """ Alter the passed function signature string to add the given kewords """
    retval = sigStr
    if len(kwArgsDict) > 0:
        retval = retval.strip(' ,)') # open up the r.h.s. for more args
        for k in kwArgsDict:
            if retval[-1] != '(': retval += ", "
            retval += str(k)+"="+str(kwArgsDict[k])
        retval += ')'
    retval = retval
    return retval


Instruction:
Make a summary of the following Python 3 code
def _gauss_funct(p, fjac=None, x=None, y=None, err=None,
                 weights=None):

    """
    Defines the gaussian function to be used as the model.

    """
    if p[2] != 0.0:
        Z = (x - p[1]) / p[2]
        model = p[0] * np.e ** (-Z ** 2 / 2.0)
    else:
        model = np.zeros(np.size(x))

    status = 0
    if weights is not None:
        if err is not None:
            print("Warning: Ignoring errors and using weights.\n")

        return [status, (y - model) * weights]

    elif err is not None:
        return [status, (y - model) / err]

    else:
        return [status, y - model]

Response: Function to compute the gaussian function for the current state of the resource.


Instruction:
Make a summary of the following Python 3 code
def gfit1d(y, x=None, err=None, weights=None, par=None, parinfo=None,
           maxiter=200, quiet=0):
    """
    Return the gaussian fit as an object.

    Parameters
    ----------
    y:   1D Numpy array
        The data to be fitted
    x:   1D Numpy array
        (optional) The x values of the y array. x and y must
        have the same shape.
    err: 1D Numpy array
        (optional) 1D array with measurement errors, must be
        the same shape as y
    weights: 1D Numpy array
        (optiional) 1D array with weights, must be the same
        shape as y
    par:  List
        (optional) Starting values for the parameters to be fitted
    parinfo: Dictionary of lists
        (optional) provides additional information for the
        parameters. For a detailed description see nmpfit.py.
        Parinfo can be used to limit parameters or keep
        some of them fixed.
    maxiter: number
        Maximum number of iterations to perform
        Default: 200
    quiet: number
        if set to 1, nmpfit does not print to the screen
        Default: 0

    Examples
    --------
    >>> x = np.arange(10,20, 0.1)
    >>> y= 10*np.e**(-(x-15)**2/4)
    >>> print(gfit1d(y,x=x, maxiter=20,quiet=1).params)
    [10.         15.          1.41421356]

    """
    y = y.astype(np.float)
    if weights is not None:
        weights = weights.astype(np.float)
    if err is not None:
        err = err.astype(np.float)
    if x is None and len(y.shape) == 1:
        x = np.arange(len(y)).astype(np.float)
    if x.shape != y.shape:
        print("input arrays X and Y must be of equal shape.\n")
        return

    fa = {'x': x, 'y': y, 'err': err, 'weights': weights}

    if par is not None:
        p = par
    else:
        ysigma = y.std()
        ind = np.nonzero(y > ysigma)[0]
        if len(ind) != 0:
            xind = int(ind.mean())
            p2 = x[xind]
            p1 = y[xind]
            p3 = 1.0
        else:
            ymax = y.max()
            ymin = y.min()
            ymean= y.mean()
            if (ymax - ymean) > (abs(ymin - ymean)):
                p1 = ymax
            else: p1 = ymin
            ind = (np.nonzero(y == p1))[0]
            p2 = x.mean()
            p3 = 1.

        p = [p1, p2, p3]
    m = nmpfit.mpfit(_gauss_funct, p,parinfo = parinfo, functkw=fa,
    maxiter=maxiter, quiet=quiet)
    if (m.status <= 0): print('error message = ', m.errmsg)
    return m

Response: Returns the gaussian fit as an object.


Instruction:
Given the following Python 3 function, write the documentation
def filter(self, *args, **kwargs):
        obj = kwargs.pop(self.object_property_name, None)
        if obj is not None:
            kwargs['object_hash'] = self.model._compute_hash(obj)
        return super().filter(*args, **kwargs)

Response: lets django managers use objects. filter on a hashable object.


Instruction:
How would you explain what the following Python 3 function does
def load(self):
        if self.is_file_persisted:
            self.object_file.open()
            temp = dill.loads(self.object_file.read())
            self.set_object(temp)
            self.object_file.close()

Response: a private method that loads an estimator object from the filesystem


Instruction:
Can you write a function in Python 3 where it
returns an Estimator object given the path of the file relative to the MEDIA_ROOT

Response:
def create_from_file(cls, filename):
        """Return an Estimator object given the path of the file, relative to the MEDIA_ROOT"""
        obj = cls()
        obj.object_file = filename
        obj.load()
        return obj


Instruction:
Write a Python 3 script for
returning our application dir. Create it if it doesn t exist.

Response:
def getAppDir():
    """ Return our application dir.  Create it if it doesn't exist. """
    # Be sure the resource dir exists
    theDir = os.path.expanduser('~/.')+APP_NAME.lower()
    if not os.path.exists(theDir):
        try:
            os.mkdir(theDir)
        except OSError:
            print('Could not create "'+theDir+'" to save GUI settings.')
            theDir = "./"+APP_NAME.lower()
    return theDir


Instruction:
Given the following Python 3 function, write the documentation
def getObjectFromTaskArg(theTask, strict, setAllToDefaults):

    # Already in the form we need (instance of us or of subclass)
    if isinstance(theTask, ConfigObjPars):
        if setAllToDefaults:
            raise RuntimeError('Called getObjectFromTaskArg with existing'+\
                  ' object AND setAllToDefaults - is unexpected use case.')
        # If it is an existing object, make sure it's internal param list is
        # up to date with it's ConfigObj dict, since the user may have manually
        # edited the dict before calling us.
        theTask.syncParamList(False) # use strict somehow?
        # Note - some validation is done here in IrafPar creation, but it is
        # not the same validation done by the ConfigObj s/w (no check funcs).
        # Do we want to do that too here?
        return theTask

    # For example, a .cfg file
    if os.path.isfile(str(theTask)):
        try:
            return ConfigObjPars(theTask, strict=strict,
                                 setAllToDefaults=setAllToDefaults)
        except KeyError:
            # this might just be caused by a file sitting in the local cwd with
            # the same exact name as the package we want to import, let's see
            if theTask.find('.') > 0: # it has an extension, like '.cfg'
                raise # this really was an error
            # else we drop down to the next step - try it as a pkg name

    # Else it must be a Python package name to load
    if isinstance(theTask, str) and setAllToDefaults:
        # NOTE how we pass the task name string in setAllToDefaults
        return ConfigObjPars('', setAllToDefaults=theTask, strict=strict)
    else:
        return getParsObjForPyPkg(theTask, strict)

Response: Take the arg and return a ConfigObjPars object.


Instruction:
Here you have a function in Python 3, explain what it does
def getEmbeddedKeyVal(cfgFileName, kwdName, dflt=None):
    # Assume this is a ConfigObj file.  Use that s/w to quickly read it and
    # put it in dict format.  Assume kwd is at top level (not in a section).
    # The input may also be a .cfgspc file.
    #
    # Only use ConfigObj here as a tool to generate a dict from a file - do
    # not use the returned object as a ConfigObj per se.  As such, we can call
    # with "simple" format, ie. no cfgspc, no val'n, and "list_values"=False.
    try:
        junkObj = configobj.ConfigObj(cfgFileName, list_values=False)
    except:
        if kwdName == TASK_NAME_KEY:
            raise KeyError('Can not parse as a parameter config file: '+ \
                           '\n\t'+os.path.realpath(cfgFileName))
        else:
            raise KeyError('Unfound key "'+kwdName+'" while parsing: '+ \
                           '\n\t'+os.path.realpath(cfgFileName))

    if kwdName in junkObj:
        retval = junkObj[kwdName]
        del junkObj
        return retval
    # Not found
    if dflt is not None:
        del junkObj
        return dflt
    else:
        if kwdName == TASK_NAME_KEY:
            raise KeyError('Can not parse as a parameter config file: '+ \
                           '\n\t'+os.path.realpath(cfgFileName))
        else:
            raise KeyError('Unfound key "'+kwdName+'" while parsing: '+ \
                           '\n\t'+os.path.realpath(cfgFileName))

Response: Read a config file and pull out the value of a given keyword.


Instruction:
Can you write a function in Python 3 where it
locates the configuration files for a given python package.

Response:
def findCfgFileForPkg(pkgName, theExt, pkgObj=None, taskName=None):
    """ Locate the configuration files for/from/within a given python package.
    pkgName is a string python package name.  This is used unless pkgObj
    is given, in which case pkgName is taken from pkgObj.__name__.
    theExt is either '.cfg' or '.cfgspc'. If the task name is known, it is
    given as taskName, otherwise one is determined using the pkgName.
    Returns a tuple of (package-object, cfg-file-name). """
    # arg check
    ext = theExt
    if ext[0] != '.': ext = '.'+theExt

    # Do the import, if needed
    pkgsToTry = {}
    if pkgObj:
        pkgsToTry[pkgObj.__name__] = pkgObj
    else:
        # First try something simple like a regular or dotted import
        try:
            fl = []
            if pkgName.find('.') > 0:
                fl = [ pkgName[:pkgName.rfind('.')], ]
            pkgsToTry[str(pkgName)] = __import__(str(pkgName), fromlist=fl)
        except:
            throwIt = True
            # One last case to try is something like "csc_kill" from
            # "acstools.csc_kill", but this convenience capability will only be
            # allowed if the parent pkg (acstools) has already been imported.
            if isinstance(pkgName, string_types) and pkgName.find('.') < 0:
                matches = [x for x in sys.modules.keys() \
                           if x.endswith("."+pkgName)]
                if len(matches)>0:
                    throwIt = False
                    for mmm in matches:
                        pkgsToTry[mmm] = sys.modules[mmm]
            if throwIt:
                raise NoCfgFileError("Unfound package or "+ext+" file via: "+\
                                     "import "+str(pkgName))

    # Now that we have the package object (or a few of them to try), for each
    # one find the .cfg or .cfgspc file, and return
    # Return as soon as ANY match is found.
    for aPkgName in pkgsToTry:
        aPkg = pkgsToTry[aPkgName]
        path = os.path.dirname(aPkg.__file__)
        if len(path) < 1: path = '.'
        flist = irafutils.rglob(path, "*"+ext)
        if len(flist) < 1:
            continue

        # Go through these and find the first one for the assumed or given task
        # name.  The task name for 'BigBlackBox.drizzle' would be 'drizzle'.
        if taskName is None:
            taskName = aPkgName.split(".")[-1]
        flist.sort()
        for f in flist:
            # A .cfg file gets checked for _task_name_=val, but a .cfgspc file
            # will have a string check function signature as the val.
            if ext == '.cfg':
                itsTask = getEmbeddedKeyVal(f, TASK_NAME_KEY, '')
            else: # .cfgspc
                sigStr  = getEmbeddedKeyVal(f, TASK_NAME_KEY, '')
                # .cfgspc file MUST have an entry for TASK_NAME_KEY w/ a default
                itsTask = vtor_checks.sigStrToKwArgsDict(sigStr)['default']
            if itsTask == taskName:
                # We've found the correct file in an installation area.  Return
                # the package object and the found file.
                return aPkg, f

    # What, are you still here?
    raise NoCfgFileError('No valid '+ext+' files found in package: "'+ \
                         str(pkgName)+'" for task: "'+str(taskName)+'"')


Instruction:
Given the following Python 3 function, write the documentation
def findAllCfgTasksUnderDir(aDir):
    retval = {}
    for f in irafutils.rglob(aDir, '*.cfg'):
        retval[f] = getEmbeddedKeyVal(f, TASK_NAME_KEY, '')
    return retval

Response: Find all installed tasks under a given directory.


Instruction:
Can you tell what is the following Python 3 function doing
def getParsObjForPyPkg(pkgName, strict):
    # Get the python package and it's .cfg file - need this no matter what
    installedPkg, installedFile = findCfgFileForPkg(pkgName, '.cfg')
    theFile = None
    tname = getEmbeddedKeyVal(installedFile, TASK_NAME_KEY)

    # See if the user has any of their own .cfg files in the cwd for this task
    if theFile is None:
        flist = getCfgFilesInDirForTask(os.getcwd(), tname)
        if len(flist) > 0:
            if len(flist) == 1: # can skip file times sort
                theFile = flist[0]
            else:
                # There are a few different choices.  In the absence of
                # requirements to the contrary, just take the latest.  Set up a
                # list of tuples of (mtime, fname) so we can sort by mtime.
                ftups = [ (os.stat(f)[stat.ST_MTIME], f) for f in flist]
                ftups.sort()
                theFile = ftups[-1][1]

    # See if the user has any of their own app-dir .cfg files for this task
    if theFile is None:
        flist = getCfgFilesInDirForTask(getAppDir(), tname) # verifies tname
        flist = [f for f in flist if os.path.basename(f) == tname+'.cfg']
        if len(flist) > 0:
            theFile = flist[0]
            assert len(flist) == 1, str(flist) # should never happen

    # Add code to check an env. var defined area?  (speak to users first)

    # Did we find one yet?  If not, use the installed version
    useInstVer = False
    if theFile is None:
        theFile = installedFile
        useInstVer = True

    # Create a stand-in instance from this file.  Force a read-only situation
    # if we are dealing with the installed, (expected to be) unwritable file.
    return ConfigObjPars(theFile, associatedPkg=installedPkg,
                         forceReadOnly=useInstVer, strict=strict)

Response: Locate the appropriate ConfigObjPars object for the given python package.


Instruction:
How would you code a function in Python 3 to
return a list of. cfg files for a given python package.

Response:
def getUsrCfgFilesForPyPkg(pkgName):
    """ See if the user has one of their own local .cfg files for this task,
        such as might be created automatically during the save of a read-only
        package, and return their names. """
    # Get the python package and it's .cfg file
    thePkg, theFile = findCfgFileForPkg(pkgName, '.cfg')
    # See if the user has any of their own local .cfg files for this task
    tname = getEmbeddedKeyVal(theFile, TASK_NAME_KEY)
    flist = getCfgFilesInDirForTask(getAppDir(), tname)
    return flist


Instruction:
Create a Python 3 function to
check if the file is read - only and set it to read - only.

Response:
def checkSetReadOnly(fname, raiseOnErr = False):
    """ See if we have write-privileges to this file.  If we do, and we
    are not supposed to, then fix that case. """
    if os.access(fname, os.W_OK):
        # We can write to this but it is supposed to be read-only. Fix it.
        # Take away usr-write, leave group and other alone, though it
        # may be simpler to just force/set it to: r--r--r-- or r--------
        irafutils.setWritePrivs(fname, False, ignoreErrors= not raiseOnErr)


Instruction:
Given the following Python 3 function, write the documentation
def flattenDictTree(aDict):
    retval = {}
    for k in aDict:
        val = aDict[k]
        if isinstance(val, dict):
            # This val is a dict, get its data (recursively) into a flat dict
            subDict = flattenDictTree(val)
            # Merge its dict of data into ours, watching for NO collisions
            rvKeySet  = set(retval.keys())
            sdKeySet = set(subDict.keys())
            intr = rvKeySet.intersection(sdKeySet)
            if len(intr) > 0:
                raise DuplicateKeyError("Flattened dict already has "+ \
                    "key(s): "+str(list(intr))+" - cannot flatten this.")

            else:
                retval.update(subDict)
        else:
            if k in retval:
                raise DuplicateKeyError("Flattened dict already has key: "+\
                                        k+" - cannot flatten this.")
            else:
                retval[k] = val
    return retval

Response: Takes a dict of vals and dicts as input and returns a flat dict of all key - values and dicts as output.


Instruction:
Write a Python 3 function that can
return the number of times the given par exists in this dict - tree and the given key name.

Response:
def countKey(theDict, name):
    """ Return the number of times the given par exists in this dict-tree,
    since the same key name may be used in different sections/sub-sections. """

    retval = 0
    for key in theDict:
        val = theDict[key]
        if isinstance(val, dict):
            retval += countKey(val, name) # recurse
        else:
            if key == name:
                retval += 1
                # can't break, even tho we found a hit, other items on
                # this level will not be named "name", but child dicts
                # may have further counts
    return retval


Instruction:
Can you implement a function in Python 3 that
finds the first par in the given dictionary.

Response:
def findFirstPar(theDict, name, _depth=0):
    """ Find the given par.  Return tuple: (its own (sub-)dict, its value).
    Returns the first match found, without checking whether the given key name
    is unique or whether it is used in multiple sections. """

    for key in theDict:
        val = theDict[key]
#       print _depth*'   ', key, str(val)[:40]
        if isinstance(val, dict):
            retval = findFirstPar(val, name, _depth=_depth+1) # recurse
            if retval is not None:
                return retval
            # else keep looking
        else:
            if key == name:
                return theDict, theDict[name]
            # else keep looking
    # if we get here then we have searched this whole (sub)-section and its
    # descendants, and found no matches.  only raise if we are at the top.
    if _depth == 0:
        raise KeyError(name)
    else:
        return None


Instruction:
Implement a function in Python 3 to
find the given par in the given scope.

Response:
def findScopedPar(theDict, scope, name):
    """ Find the given par.  Return tuple: (its own (sub-)dict, its value). """
    # Do not search (like findFirstPar), but go right to the correct
    # sub-section, and pick it up.  Assume it is there as stated.
    if len(scope):
        theDict = theDict[scope] # ! only goes one level deep - enhance !
    return theDict, theDict[name]


Instruction:
How would you explain what the following Python 3 function does
def setPar(theDict, name, value):
    section, previousVal = findFirstPar(theDict, name)
    # "section" is the actual object, not a copy
    section[name] = value

Response: Sets a par s value without having to give its scope.


Instruction:
Make a summary of the following Python 3 code
def mergeConfigObj(configObj, inputDict):
    # Expanded upon Warren's version in astrodrizzle

    # Verify that all inputDict keys in configObj are unique within configObj
    for key in inputDict:
        if countKey(configObj, key) > 1:
            raise DuplicateKeyError(key)
    # Now update configObj with each inputDict item
    for key in inputDict:
        setPar(configObj, key, inputDict[key])

Response: Merge the inputDict values into an existing configObj instance.


Instruction:
How would you explain what the following Python 3 function does
def findTheLost(config_file, configspec_file, skipHidden=True):
    # do some sanity checking, but don't (yet) make this a serious error
    if not os.path.exists(config_file):
        print("ERROR: Config file not found: "+config_file)
        return []
    if not os.path.exists(configspec_file):
        print("ERROR: Configspec file not found: "+configspec_file)
        return []
    tmpObj = configobj.ConfigObj(config_file, configspec=configspec_file)
    simval = configobj.SimpleVal()
    test = tmpObj.validate(simval)
    if test == True:
        return []
    # If we get here, there is a dict returned of {key1: bool, key2: bool}
    # which matches the shape of the config obj.  We need to walk it to
    # find the Falses, since they are the missing pars.
    missing = []
    flattened = configobj.flatten_errors(tmpObj, test)
    # But, before we move on, skip/eliminate any 'hidden' items from our list,
    # since hidden items are really supposed to be missing from the .cfg file.
    if len(flattened) > 0 and skipHidden:
        keepers = []
        for tup in flattened:
            keep = True
            # hidden section
            if len(tup[0])>0 and isHiddenName(tup[0][-1]):
                keep = False
            # hidden par (in a section, or at the top level)
            elif tup[1] is not None and isHiddenName(tup[1]):
                keep = False
            if keep:
                keepers.append(tup)
        flattened = keepers
    flatStr = flattened2str(flattened, missing=True)
    return flatStr

Response: Find any lost or missing parameters in this cfg file.


Instruction:
Write a Python 3 script for
returning True if this string name denotes a hidden par or section

Response:
def isHiddenName(astr):
    """ Return True if this string name denotes a hidden par or section """
    if astr is not None and len(astr) > 2 and astr.startswith('_') and \
       astr.endswith('_'):
        return True
    else:
        return False


Instruction:
Can you create a Python 3 function that
returns a pretty - printed string version of the output of a list of flattened items.

Response:
def flattened2str(flattened, missing=False, extra=False):
    """ Return a pretty-printed multi-line string version of the output of
    flatten_errors. Know that flattened comes in the form of a list
    of keys that failed. Each member of the list is a tuple::

        ([list of sections...], key, result)

    so we turn that into a string. Set missing to True if all the input
    problems are from missing items.  Set extra to True if all the input
    problems are from extra items. """

    if flattened is None or len(flattened) < 1:
        return ''
    retval = ''
    for sections, key, result in flattened:
        # Name the section and item, to start the message line
        if sections is None or len(sections) == 0:
            retval += '\t"'+key+'"'
        elif len(sections) == 1:
            if key is None:
                # a whole section is missing at the top-level; see if hidden
                junk = sections[0]
                if isHiddenName(junk):
                    continue # this missing or extra section is not an error
                else:
                    retval += '\tSection "'+sections[0]+'"'
            else:
                retval += '\t"'+sections[0]+'.'+key+'"'
        else: # len > 1
            joined = '.'.join(sections)
            joined = '"'+joined+'"'
            if key is None:
                retval +=  '\tSection '+joined
            else:
                retval +=  '\t"'+key+'" from '+joined
        # End the msg line with "what seems to be the trouble" with this one
        if missing and result==False:
            retval += ' is missing.'
        elif extra:
            if result:
                retval += ' is an unexpected section. Is your file out of date?'
            else:
                retval += ' is an unexpected parameter. Is your file out of date?'
        elif isinstance(result, bool):
            retval += ' has an invalid value'
        else:
            retval += ' is invalid, '+result.message
        retval += '\n\n'
    return retval.rstrip()


Instruction:
Given the following Python 3 function, write the documentation
def getDefaultSaveFilename(self, stub=False):
        if stub:
            return self._rcDir+os.sep+self.__taskName+'_stub.cfg'
        else:
            return self._rcDir+os.sep+self.__taskName+'.cfg'

Response: Return the name of the default save file for this task.


Instruction:
Write a Python 3 function that can
set or reset the internal param list from the dict.

Response:
def syncParamList(self, firstTime, preserve_order=True):
        """ Set or reset the internal param list from the dict's contents. """
        # See the note in setParam about this design.

        # Get latest par values from dict.  Make sure we do not
        # change the id of the __paramList pointer here.
        new_list = self._getParamsFromConfigDict(self, initialPass=firstTime)
                                               # dumpCfgspcTo=sys.stdout)
        # Have to add this odd last one for the sake of the GUI (still?)
        if self._forUseWithEpar:
            new_list.append(basicpar.IrafParS(['$nargs','s','h','N']))

        if len(self.__paramList) > 0 and preserve_order:
            # Here we have the most up-to-date data from the actual data
            # model, the ConfigObj dict, and we need to use it to fill in
            # our param list.  BUT, we need to preserve the order our list
            # has had up until now (by unique parameter name).
            namesInOrder = [p.fullName() for p in self.__paramList]
            assert len(namesInOrder) == len(new_list), \
                   'Mismatch in num pars, had: '+str(len(namesInOrder))+ \
                   ', now we have: '+str(len(new_list))+', '+ \
                   str([p.fullName() for p in new_list])
            self.__paramList[:] = [] # clear list, keep same pointer
            # create a flat dict view of new_list, for ease of use in next step
            new_list_dict = {} # can do in one step in v2.7
            for par in new_list: new_list_dict[par.fullName()] = par
            # populate
            for fn in namesInOrder:
                self.__paramList.append(new_list_dict[fn])
        else:
            # Here we just take the data in whatever order it came.
            self.__paramList[:] = new_list


Instruction:
Write a Python 3 script to
return a par list just like ours but with all default values.

Response:
def getDefaultParList(self):
        """ Return a par list just like ours, but with all default values. """
        # The code below (create a new set-to-dflts obj) is correct, but it
        # adds a tenth of a second to startup.  Clicking "Defaults" in the
        # GUI does not call this.  But this can be used to set the order seen.

        # But first check for rare case of no cfg file name
        if self.filename is None:
            # this is a .cfgspc-only kind of object so far
            self.filename = self.getDefaultSaveFilename(stub=True)
            return copy.deepcopy(self.__paramList)

        tmpObj = ConfigObjPars(self.filename, associatedPkg=self.__assocPkg,
                               setAllToDefaults=True, strict=False)
        return tmpObj.getParList()


Instruction:
Here you have a function in Python 3, explain what it does
def setParam(self, name, val, scope='', check=1, idxHint=None):
        theDict, oldVal = findScopedPar(self, scope, name)

        # Set the value, even if invalid.  It needs to be set before
        # the validation step (next).
        theDict[name] = val

        # If need be, check the proposed value.  Ideally, we'd like to
        # (somehow elegantly) only check this one item. For now, the best
        # shortcut is to only validate this section.
        if check:
            ans=self.validate(self._vtor, preserve_errors=True, section=theDict)
            if ans != True:
                flatStr = "All values are invalid!"
                if ans != False:
                    flatStr = flattened2str(configobj.flatten_errors(self, ans))
                raise RuntimeError("Validation error: "+flatStr)

        # Note - this design needs work.  Right now there are two copies
        # of the data:  the ConfigObj dict, and the __paramList ...
        # We rely on the idxHint arg so we don't have to search the __paramList
        # every time this is called, which could really slows things down.
        assert idxHint is not None, "ConfigObjPars relies on a valid idxHint"
        assert name == self.__paramList[idxHint].name, \
               'Error in setParam, name: "'+name+'" != name at idxHint: "'+\
               self.__paramList[idxHint].name+'", idxHint: '+str(idxHint)
        self.__paramList[idxHint].set(val)

Response: Set the value of a parameter in the ConfigObj.


Instruction:
How would you implement a function in Python 3 that
writes the list of parameters to a file.

Response:
def saveParList(self, *args, **kw):
        """Write parameter data to filename (string or filehandle)"""
        if 'filename' in kw:
            filename = kw['filename']
        if not filename:
            filename = self.getFilename()
        if not filename:
            raise ValueError("No filename specified to save parameters")

        if hasattr(filename,'write'):
            fh = filename
            absFileName = os.path.abspath(fh.name)
        else:
            absFileName = os.path.expanduser(filename)
            absDir = os.path.dirname(absFileName)
            if len(absDir) and not os.path.isdir(absDir): os.makedirs(absDir)
            fh = open(absFileName,'w')
        numpars = len(self.__paramList)
        if self._forUseWithEpar: numpars -= 1
        if not self.final_comment: self.final_comment = [''] # force \n at EOF
        # Empty the ConfigObj version of section.defaults since that is based
        # on an assumption incorrect for us, and override with our own list.
        # THIS IS A BIT OF MONKEY-PATCHING!  WATCH FUTURE VERSION CHANGES!
        # See Trac ticket #762.
        while len(self.defaults):
            self.defaults.pop(-1) # empty it, keeping ref
        for key in self._neverWrite:
            self.defaults.append(key)
        # Note also that we are only overwriting the top/main section's
        # "defaults" list, but EVERY [sub-]section has such an attribute...

        # Now write to file, delegating work to ConfigObj (note that ConfigObj
        # write() skips any items listed by name in the self.defaults list)
        self.write(fh)
        fh.close()
        retval = str(numpars) + " parameters written to " + absFileName
        self.filename = absFileName # reset our own ConfigObj filename attr
        self.debug('Keys not written: '+str(self.defaults))
        return retval


Instruction:
Given the following Python 3 function, write the documentation
def run(self, *args, **kw):
        if self._runFunc is not None:
            # remove the two args sent by EditParDialog which we do not use
            if 'mode' in kw: kw.pop('mode')
            if '_save' in kw: kw.pop('_save')
            return self._runFunc(self, *args, **kw)
        else:
            raise taskpars.NoExecError('No way to run task "'+self.__taskName+\
                '". You must either override the "run" method in your '+ \
                'ConfigObjPars subclass, or you must supply a "run" '+ \
                'function in your package.')

Response: This method is overridden by a subclass to call the run method of the class.


Instruction:
Given the following Python 3 function, write the documentation
def triggerLogicToStr(self):
        try:
            import json
        except ImportError:
            return "Cannot dump triggers/dependencies/executes (need json)"
        retval = "TRIGGERS:\n"+json.dumps(self._allTriggers, indent=3)
        retval += "\nDEPENDENCIES:\n"+json.dumps(self._allDepdcs, indent=3)
        retval += "\nTO EXECUTE:\n"+json.dumps(self._allExecutes, indent=3)
        retval += "\n"
        return retval

Response: Print all the trigger logic to a string and return it.


Instruction:
Explain what the following Python 3 code does
def _findAssociatedConfigSpecFile(self, cfgFileName):

        # Handle simplest 2 cases first: co-located or local .cfgspc file
        retval = "."+os.sep+self.__taskName+".cfgspc"
        if os.path.isfile(retval): return retval

        retval = os.path.dirname(cfgFileName)+os.sep+self.__taskName+".cfgspc"
        if os.path.isfile(retval): return retval

        # Also try the resource dir
        retval = self.getDefaultSaveFilename()+'spc' # .cfgspc
        if os.path.isfile(retval): return retval

        # Now try and see if there is a matching .cfgspc file in/under an
        # associated package, if one is defined.
        if self.__assocPkg is not None:
            x, theFile = findCfgFileForPkg(None, '.cfgspc',
                                           pkgObj = self.__assocPkg,
                                           taskName = self.__taskName)
            return theFile

        # Finally try to import the task name and see if there is a .cfgspc
        # file in that directory
        x, theFile = findCfgFileForPkg(self.__taskName, '.cfgspc',
                                       taskName = self.__taskName)
        if os.path.exists(theFile):
            return theFile

        # unfound
        raise NoCfgFileError('Unfound config-spec file for task: "'+ \
                             self.__taskName+'"')

Response:
Given a config file find its associated config - spec file and and
        return the full pathname of the file.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _getParamsFromConfigDict(self, cfgObj, scopePrefix='',
                                 initialPass=False, dumpCfgspcTo=None):
        """ Walk the given ConfigObj dict pulling out IRAF-like parameters into
        a list. Since this operates on a dict this can be called recursively.
        This is also our chance to find and pull out triggers and such
        dependencies. """
        # init
        retval = []
        if initialPass and len(scopePrefix) < 1:
            self._posArgs = [] # positional args [2-tuples]: (index,scopedName)
            # FOR SECURITY: the following 3 chunks of data,
            #     _allTriggers, _allDepdcs, _allExecutes,
            # are collected ONLY from the .cfgspc file
            self._allTriggers = {}
            self._allDepdcs = {}
            self._allExecutes = {}

        # start walking ("tell yer story walkin, buddy")
        # NOTE: this relies on the "in" operator returning keys in the
        # order that they exist in the dict (which depends on ConfigObj keeping
        # the order they were found in the original file)
        for key in cfgObj:
            val = cfgObj[key]

            # Do we need to skip this - if not a par, like a rule or something
            toBeHidden = isHiddenName(key)
            if toBeHidden:
                if key not in self._neverWrite and key != TASK_NAME_KEY:
                    self._neverWrite.append(key)
                    # yes TASK_NAME_KEY is hidden, but it IS output to the .cfg

            # a section
            if isinstance(val, dict):
                if not toBeHidden:
                    if len(list(val.keys()))>0 and len(retval)>0:
                        # Here is where we sneak in the section comment
                        # This is so incredibly kludgy (as the code was), it
                        # MUST be revamped eventually! This is for the epar GUI.
                        prevPar = retval[-1]
                        # Use the key (or its comment?) as the section header
                        prevPar.set(prevPar.get('p_prompt')+'\n\n'+key,
                                    field='p_prompt', check=0)
                    if dumpCfgspcTo:
                        dumpCfgspcTo.write('\n['+key+']\n')
                    # a logical grouping (append its params)
                    pfx = scopePrefix+'.'+key
                    pfx = pfx.strip('.')
                    retval = retval + self._getParamsFromConfigDict(val, pfx,
                                      initialPass, dumpCfgspcTo) # recurse
            else:
                # a param
                fields = []
                choicesOrMin = None
                fields.append(key) # name
                dtype = 's'
                cspc = None
                if cfgObj.configspec:
                    cspc = cfgObj.configspec.get(key) # None if not found
                chk_func_name = ''
                chk_args_dict = {}
                if cspc:
                    chk_func_name = cspc[:cspc.find('(')]
                    chk_args_dict = vtor_checks.sigStrToKwArgsDict(cspc)
                if chk_func_name.find('option') >= 0:
                    dtype = 's'
                    # convert the choices string to a list (to weed out kwds)
                    x = cspc[cspc.find('(')+1:-1] # just the options() args
# cspc e.g.: option_kw("poly5","nearest","linear", default="poly5", comment="Interpolant (poly5,nearest,linear)")
                    x = x.split(',') # tokenize
                    # but! comment value may have commas in it, find it
                    # using it's equal sign, rm all after it
                    has_eq = [i for i in x if i.find('=')>=0]
                    if len(has_eq) > 0:
                        x = x[: x.index(has_eq[0]) ]
                    # rm spaces, extra quotes; rm kywd arg pairs
                    x = [i.strip("' ") for i in x if i.find('=')<0]
                    choicesOrMin = '|'+'|'.join(x)+'|' # IRAF format for enums
                elif chk_func_name.find('boolean') >= 0:     dtype = 'b'
                elif chk_func_name.find('float_or_') >= 0:   dtype = 'r'
                elif chk_func_name.find('float') >= 0:       dtype = 'R'
                elif chk_func_name.find('integer_or_') >= 0: dtype = 'i'
                elif chk_func_name.find('integer') >= 0:     dtype = 'I'
                elif chk_func_name.find('action') >= 0:      dtype = 'z'
                fields.append(dtype)
                fields.append('a')
                if type(val)==bool:
                    if val: fields.append('yes')
                    else:   fields.append('no')
                else:
                    fields.append(val)
                fields.append(choicesOrMin)
                fields.append(None)
                # Primarily use description from .cfgspc file (0). But, allow
                # overrides from .cfg file (1) if different.
                dscrp0 = chk_args_dict.get('comment','').strip() # ok if missing
                dscrp1 = cfgObj.inline_comments[key]
                if dscrp1 is None:
                    dscrp1 = ''

                while len(dscrp1) > 0 and dscrp1[0] in (' ','#'):
                    dscrp1 = dscrp1[1:] # .cfg file comments start with '#'

                dscrp1 = dscrp1.strip()
                # Now, decide what to do/say about the descriptions
                if len(dscrp1) > 0:
                    dscrp = dscrp0
                    if dscrp0 != dscrp1: # allow override if different
                        dscrp = dscrp1+eparoption.DSCRPTN_FLAG # flag it
                        if initialPass:
                            if dscrp0 == '' and cspc is None:
                                # this is a case where this par isn't in the
                                # .cfgspc; ignore, it is caught/error later
                                pass
                            else:
                                self.debug('Description of "'+key+ \
                                    '" overridden, from:  '+repr(dscrp0)+\
                                    '  to:  '+repr(dscrp1))
                    fields.append(dscrp)
                else:
                    # set the field for the GUI
                    fields.append(dscrp0)
                    # ALSO set it in the dict so it is written to file later
                    cfgObj.inline_comments[key] = '# '+dscrp0
                # This little section, while never intended to be used during
                # normal operation, could save a lot of manual work.
                if dumpCfgspcTo:
                    junk = cspc
                    junk = key+' = '+junk.strip()
                    if junk.find(' comment=')<0:
                        junk = junk[:-1]+", comment="+ \
                               repr(irafutils.stripQuotes(dscrp1.strip()))+")"
                    dumpCfgspcTo.write(junk+'\n')
                # Create the par
                if not toBeHidden or chk_func_name.find('action')==0:
                    par = basicpar.parFactory(fields, True)
                    par.setScope(scopePrefix)
                    retval.append(par)
                # else this is a hidden key

                # The next few items require a fully scoped name
                absKeyName = scopePrefix+'.'+key # assumed to be unique
                # Check for pars marked to be positional args
                if initialPass:
                    pos = chk_args_dict.get('pos')
                    if pos:
                        # we'll sort them later, on demand
                        self._posArgs.append( (int(pos), scopePrefix, key) )
                # Check for triggers and/or dependencies
                if initialPass:
                    # What triggers what? (thats why theres an 's' in the kwd)
                    # try "trigger" (old)
                    if chk_args_dict.get('trigger'):
                        print("WARNING: outdated version of .cfgspc!! for "+
                              self.__taskName+", 'trigger' unused for "+
                              absKeyName)
                    # try "triggers"
                    trgs = chk_args_dict.get('triggers')
                    if trgs and len(trgs)>0:
                        # eg. _allTriggers['STEP2.xy'] == ('_rule1_','_rule3_')
                        assert absKeyName not in self._allTriggers, \
                            'More than 1 of these in .cfgspc?: '+absKeyName
                        # we force this to always be a sequence
                        if isinstance(trgs, (list,tuple)):
                            self._allTriggers[absKeyName] = trgs
                        else:
                            self._allTriggers[absKeyName] = (trgs,)
                    # try "executes"
                    excs = chk_args_dict.get('executes')
                    if excs and len(excs)>0:
                        # eg. _allExecutes['STEP2.xy'] == ('_rule1_','_rule3_')
                        assert absKeyName not in self._allExecutes, \
                            'More than 1 of these in .cfgspc?: '+absKeyName
                        # we force this to always be a sequence
                        if isinstance(excs, (list,tuple)):
                            self._allExecutes[absKeyName] = excs
                        else:
                            self._allExecutes[absKeyName] = (excs,)

                    # Dependencies? (besides these used here, may someday
                    # add: 'range_from', 'warn_if', etc.)
                    depName = None
                    if not depName:
                        depType = 'active_if'
                        depName = chk_args_dict.get(depType) # e.g. =='_rule1_'
                    if not depName:
                        depType = 'inactive_if'
                        depName = chk_args_dict.get(depType)
                    if not depName:
                        depType = 'is_set_by'
                        depName = chk_args_dict.get(depType)
                    if not depName:
                        depType = 'set_yes_if'
                        depName = chk_args_dict.get(depType)
                    if not depName:
                        depType = 'set_no_if'
                        depName = chk_args_dict.get(depType)
                    if not depName:
                        depType = 'is_disabled_by'
                        depName = chk_args_dict.get(depType)
                    # NOTE - the above few lines stops at the first dependency
                    # found (depName) for a given par.  If, in the future a
                    # given par can have >1 dependency than we need to revamp!!
                    if depName:
                        # Add to _allDepdcs dict: (val is dict of pars:types)
                        #
                        # e.g. _allDepdcs['_rule1_'] == \
                        #        {'STEP3.ra':      'active_if',
                        #         'STEP3.dec':     'active_if',
                        #         'STEP3.azimuth': 'inactive_if'}
                        if depName in self._allDepdcs:
                            thisRulesDict = self._allDepdcs[depName]
                            assert not absKeyName in thisRulesDict, \
                                'Cant yet handle multiple actions for the '+ \
                                'same par and the same rule.  For "'+depName+ \
                                '" dict was: '+str(thisRulesDict)+ \
                                ' while trying to add to it: '+\
                                str({absKeyName:depType})
                            thisRulesDict[absKeyName] = depType
                        else:
                            self._allDepdcs[depName] = {absKeyName:depType}
                    # else no dependencies found for this chk_args_dict
        return retval

Response: Walks the given ConfigObj dict and returns a list of IRAF - like parameters.


Instruction:
Can you generate the documentation for the following Python 3 function
def getTriggerStrings(self, parScope, parName):
        # The data structure of _allTriggers was chosen for how easily/quickly
        # this particular access can be made here.
        fullName = parScope+'.'+parName
        return self._allTriggers.get(fullName)

Response: Returns all strings that are meant to trigger for a given item.


Instruction:
How would you implement a function in Python 3 that
returns all the execute strings for a given item.

Response:
def getExecuteStrings(self, parScope, parName):
        """ For a given item (scope + name), return all strings (in a tuple)
        that it is meant to execute, if any exist.  Returns None is none. """
        # The data structure of _allExecutes was chosen for how easily/quickly
        # this particular access can be made here.
        fullName = parScope+'.'+parName
        return self._allExecutes.get(fullName)


Instruction:
Make a summary of the following Python 3 code
def getPosArgs(self):
        if len(self._posArgs) < 1: return []
        # The first item in the tuple is the index, so we now sort by it
        self._posArgs.sort()
        # Build a return list
        retval = []
        for idx, scope, name in self._posArgs:
            theDict, val = findScopedPar(self, scope, name)
            retval.append(val)
        return retval

Response:
Return a list of all parameters marked with pos = N in
            the. cfgspc file.


Instruction:
Can you tell what is the following Python 3 function doing
def getKwdArgs(self, flatten = False):

        # Start with a full deep-copy.  What complicates this method is the
        # idea of sub-sections.  This dict can have dicts as values, and so on.
        dcopy = self.dict() # ConfigObj docs say this is a deep-copy

        # First go through the dict removing all positional args
        for idx,scope,name in self._posArgs:
            theDict, val = findScopedPar(dcopy, scope, name)
            # 'theDict' may be dcopy, or it may be a dict under it
            theDict.pop(name)

        # Then go through the dict removing all hidden items ('_item_name_')
        for k in list(dcopy.keys()):
            if isHiddenName(k):
                dcopy.pop(k)

        # Done with the nominal operation
        if not flatten:
            return dcopy

        # They have asked us to flatten the structure - to bring all parameters
        # up to the top level, even if they are in sub-sections.  So we look
        # for values that are dicts.  We will throw something if we end up
        # with name collisions at the top level as a result of this.
        return flattenDictTree(dcopy)

Response: Return a dict of all normal dict parameters - that is all normal dict parameters NOT marked with pos = N in the. cfgspc file.


Instruction:
How would you implement a function in Python 3 that
tries to set the value of the given item name and scope.

Response:
def tryValue(self, name, val, scope=''):
        """ For the given item name (and scope), we are being asked to try
            the given value to see if it would pass validation.  We are not
            to set it, but just try it.  We return a tuple:
            If it fails, we return: (False,  the last known valid value).
            On success, we return: (True, None). """

        # SIMILARITY BETWEEN THIS AND setParam() SHOULD BE CONSOLIDATED!

        # Set the value, even if invalid.  It needs to be set before
        # the validation step (next).
        theDict, oldVal = findScopedPar(self, scope, name)
        if oldVal == val: return (True, None) # assume oldVal is valid
        theDict[name] = val

        # Check the proposed value.  Ideally, we'd like to
        # (somehow elegantly) only check this one item. For now, the best
        # shortcut is to only validate this section.
        ans=self.validate(self._vtor, preserve_errors=True, section=theDict)

        # No matter what ans is, immediately return the item to its original
        # value since we are only checking the value here - not setting.
        theDict[name] = oldVal

        # Now see what the validation check said
        errStr = ''
        if ans != True:
            flatStr = "All values are invalid!"
            if ans != False:
                flatStr = flattened2str(configobj.flatten_errors(self, ans))
            errStr = "Validation error: "+flatStr # for now this info is unused

        # Done
        if len(errStr): return (False, oldVal) # was an error
        else:           return (True, None)


Instruction:
Explain what the following Python 3 code does
def listTheExtras(self, deleteAlso):
        # get list of extras
        extras = configobj.get_extra_values(self)
        # extras is in format: [(sections, key), (sections, key), ]
        # but we need: [(sections, key, result), ...] - set all results to
        # a bool just to make it the right shape.  BUT, since we are in
        # here anyway, make that bool mean something - hide info in it about
        # whether that extra item is a section (1) or just a single par (0)
        #
        # simplified, this is:  expanded = [ (x+(abool,)) for x in extras]
        expanded = [ (x+ \
                       ( bool(len(x[0])<1 and hasattr(self[x[1]], 'keys')), ) \
                     ) for x in extras]
        retval = ''
        if expanded:
            retval = flattened2str(expanded, extra=1)
        # but before we return, delete them (from ourself!) if requested to
        if deleteAlso:
            for tup_to_del in extras:
                target = self
                # descend the tree to the dict where this items is located.
                # (this works because target is not a copy (because the dict
                #  type is mutable))
                location = tup_to_del[0]
                for subdict in location: target = target[subdict]
                # delete it
                target.pop(tup_to_del[1])

        return retval

Response: Return a string similar to findTheLost.


Instruction:
Can you implement a function in Python 3 that
reloads the measurements from the backing store.

Response:
def get(self):
        """
        Reloads the measurements from the backing store.
        :return: 200 if success.
        """
        try:
            self._measurementController.reloadCompletedMeasurements()
            return None, 200
        except:
            logger.exception("Failed to reload measurements")
            return str(sys.exc_info()), 500


Instruction:
Create a Python 3 function to
write each sample to a csv file.

Response:
def handle(self, data):
        """
        Writes each sample to a csv file.
        :param data: the samples.
        :return:
        """
        self.logger.debug("Handling " + str(len(data)) + " data items")
        for datum in data:
            if isinstance(datum, dict):
                # these have to wrapped in a list for python 3.4 due to a change in the implementation
                # of OrderedDict in python 3.5+ (which means .keys() and .values() are sequences in 3.5+)
                if self._first:
                    self._csv.writerow(list(datum.keys()))
                    self._first = False
                self._csv.writerow(list(datum.values()))
            elif isinstance(datum, list):
                self._csv.writerow(datum)
            else:
                self.logger.warning("Ignoring unsupported data type " + str(type(datum)) + " : " + str(datum))


Instruction:
Create a Python 3 function to
send a start request to the target to tell it a named measurement is starting.

Response:
def start(self, measurementId):
        """
        Posts to the target to tell it a named measurement is starting.
        :param measurementId:
        """
        self.sendURL = self.rootURL + measurementId + '/' + self.deviceName
        self.startResponseCode = self._doPut(self.sendURL)


Instruction:
Can you create a Python 3 function that
handles the data request

Response:
def handle(self, data):
        """
        puts the data in the target.
        :param data: the data to post.
        :return:
        """
        self.dataResponseCode.append(self._doPut(self.sendURL + '/data', data=data))


Instruction:
Write a Python 3 script to
stop the measurement with the given id

Response:
def stop(self, measurementId, failureReason=None):
        """
        informs the target the named measurement has completed
        :param measurementId: the measurement that has completed.
        :return:
        """
        if failureReason is None:
            self.endResponseCode = self._doPut(self.sendURL + "/complete")
        else:
            self.endResponseCode = self._doPut(self.sendURL + "/failed", data={'failureReason': failureReason})
        self.sendURL = None


Instruction:
Make a summary of the following Python 3 code
def dottedQuadToNum(ip):

    # import here to avoid it when ip_addr values are not used
    import socket, struct

    try:
        return struct.unpack('!L',
            socket.inet_aton(ip.strip()))[0]
    except socket.error:
        raise ValueError('Not a good dotted-quad IP: %s' % ip)
    return

Response: Convert decimal dotted quad string to long integer


Instruction:
How would you code a function in Python 3 to
convert a numeric IP number to a dotted quad string.

Response:
def numToDottedQuad(num):
    """
    Convert long int to dotted quad string

    >>> numToDottedQuad(long(-1))
    Traceback (most recent call last):
    ValueError: Not a good numeric IP: -1
    >>> numToDottedQuad(long(1))
    '0.0.0.1'
    >>> numToDottedQuad(long(16777218))
    '1.0.0.2'
    >>> numToDottedQuad(long(16908291))
    '1.2.0.3'
    >>> numToDottedQuad(long(16909060))
    '1.2.3.4'
    >>> numToDottedQuad(long(4294967295))
    '255.255.255.255'
    >>> numToDottedQuad(long(4294967296))
    Traceback (most recent call last):
    ValueError: Not a good numeric IP: 4294967296
    """

    # import here to avoid it when ip_addr values are not used
    import socket, struct

    # no need to intercept here, 4294967295 is fine
    if num > 4294967295 or num < 0:
        raise ValueError('Not a good numeric IP: %s' % num)
    try:
        return socket.inet_ntoa(
            struct.pack('!L', long(num)))
    except (socket.error, struct.error, OverflowError):
        raise ValueError('Not a good numeric IP: %s' % num)


Instruction:
Create a Python 3 function to
return numbers from inputs or raise VdtParamError.

Response:
def _is_num_param(names, values, to_float=False):
    """
    Return numbers from inputs or raise VdtParamError.

    Lets ``None`` pass through.
    Pass in keyword argument ``to_float=True`` to
    use float for the conversion rather than int.

    >>> _is_num_param(('', ''), (0, 1.0))
    [0, 1]
    >>> _is_num_param(('', ''), (0, 1.0), to_float=True)
    [0.0, 1.0]
    >>> _is_num_param(('a'), ('a'))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtParamError: passed an incorrect value "a" for parameter "a".
    """
    fun = to_float and float or int
    out_params = []
    for (name, val) in zip(names, values):
        if val is None:
            out_params.append(val)
        elif isinstance(val, number_or_string_types):
            try:
                out_params.append(fun(val))
            except ValueError:
                raise VdtParamError(name, val)
        else:
            raise VdtParamError(name, val)
    return out_params


Instruction:
Here you have a function in Python 3, explain what it does
def is_integer(value, min=None, max=None):
    (min_val, max_val) = _is_num_param(('min', 'max'), (min, max))
    if not isinstance(value, int_or_string_types):
        raise VdtTypeError(value)
    if isinstance(value, string_types):
        # if it's a string - does it represent an integer ?
        try:
            value = int(value)
        except ValueError:
            raise VdtTypeError(value)
    if (min_val is not None) and (value < min_val):
        raise VdtValueTooSmallError(value)
    if (max_val is not None) and (value > max_val):
        raise VdtValueTooBigError(value)
    return value

Response: A test that a given value is an integer.


Instruction:
Can you tell what is the following Python 3 function doing
def is_boolean(value):
    if isinstance(value, string_types):
        try:
            return bool_dict[value.lower()]
        except KeyError:
            raise VdtTypeError(value)
    # we do an equality test rather than an identity test
    # this ensures Python 2.2 compatibilty
    # and allows 0 and 1 to represent True and False
    if value == False:
        return False
    elif value == True:
        return True
    else:
        raise VdtTypeError(value)

Response: Check if the value represents a boolean.


Instruction:
Can you generate the documentation for the following Python 3 function
def is_ip_addr(value):
    if not isinstance(value, string_types):
        raise VdtTypeError(value)
    value = value.strip()
    try:
        dottedQuadToNum(value)
    except ValueError:
        raise VdtValueError(value)
    return value

Response: Check that the supplied value is an Internet Protocol address v. 4 or dotted - quad string.


Instruction:
Can you create a Python 3 function that
checks that the value is a list of values.

Response:
def is_list(value, min=None, max=None):
    """
    Check that the value is a list of values.

    You can optionally specify the minimum and maximum number of members.

    It does no check on list members.

    >>> vtor = Validator()
    >>> vtor.check('list', ())
    []
    >>> vtor.check('list', [])
    []
    >>> vtor.check('list', (1, 2))
    [1, 2]
    >>> vtor.check('list', [1, 2])
    [1, 2]
    >>> vtor.check('list(3)', (1, 2))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtValueTooShortError: the value "(1, 2)" is too short.
    >>> vtor.check('list(max=5)', (1, 2, 3, 4, 5, 6))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtValueTooLongError: the value "(1, 2, 3, 4, 5, 6)" is too long.
    >>> vtor.check('list(min=3, max=5)', (1, 2, 3, 4))  # doctest: +SKIP
    [1, 2, 3, 4]
    >>> vtor.check('list', 0)  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "0" is of the wrong type.
    >>> vtor.check('list', '12')  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "12" is of the wrong type.
    """
    (min_len, max_len) = _is_num_param(('min', 'max'), (min, max))
    if isinstance(value, string_types):
        raise VdtTypeError(value)
    try:
        num_members = len(value)
    except TypeError:
        raise VdtTypeError(value)
    if min_len is not None and num_members < min_len:
        raise VdtValueTooShortError(value)
    if max_len is not None and num_members > max_len:
        raise VdtValueTooLongError(value)
    return list(value)


Instruction:
Can you create a Python 3 function that
checks that the value is a list of integers.

Response:
def is_int_list(value, min=None, max=None):
    """
    Check that the value is a list of integers.

    You can optionally specify the minimum and maximum number of members.

    Each list member is checked that it is an integer.

    >>> vtor = Validator()
    >>> vtor.check('int_list', ())
    []
    >>> vtor.check('int_list', [])
    []
    >>> vtor.check('int_list', (1, 2))
    [1, 2]
    >>> vtor.check('int_list', [1, 2])
    [1, 2]
    >>> vtor.check('int_list', [1, 'a'])  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "a" is of the wrong type.
    """
    return [is_integer(mem) for mem in is_list(value, min, max)]


Instruction:
Write a Python 3 function that can
check that the value is a list of booleans.

Response:
def is_bool_list(value, min=None, max=None):
    """
    Check that the value is a list of booleans.

    You can optionally specify the minimum and maximum number of members.

    Each list member is checked that it is a boolean.

    >>> vtor = Validator()
    >>> vtor.check('bool_list', ())
    []
    >>> vtor.check('bool_list', [])
    []
    >>> check_res = vtor.check('bool_list', (True, False))
    >>> check_res == [True, False]
    1
    >>> check_res = vtor.check('bool_list', [True, False])
    >>> check_res == [True, False]
    1
    >>> vtor.check('bool_list', [True, 'a'])  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "a" is of the wrong type.
    """
    return [is_boolean(mem) for mem in is_list(value, min, max)]


Instruction:
How would you code a function in Python 3 to
check that the value is a list of floats.

Response:
def is_float_list(value, min=None, max=None):
    """
    Check that the value is a list of floats.

    You can optionally specify the minimum and maximum number of members.

    Each list member is checked that it is a float.

    >>> vtor = Validator()
    >>> vtor.check('float_list', ())
    []
    >>> vtor.check('float_list', [])
    []
    >>> vtor.check('float_list', (1, 2.0))
    [1.0, 2.0]
    >>> vtor.check('float_list', [1, 2.0])
    [1.0, 2.0]
    >>> vtor.check('float_list', [1, 'a'])  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "a" is of the wrong type.
    """
    return [is_float(mem) for mem in is_list(value, min, max)]


Instruction:
Explain what the following Python 3 code does
def is_string_list(value, min=None, max=None):
    if isinstance(value, string_types):
        raise VdtTypeError(value)
    return [is_string(mem) for mem in is_list(value, min, max)]

Response: Check that the value is a list of strings.


Instruction:
Create a Python 3 function for
checking that the value is a list of IP addresses.

Response:
def is_ip_addr_list(value, min=None, max=None):
    """
    Check that the value is a list of IP addresses.

    You can optionally specify the minimum and maximum number of members.

    Each list member is checked that it is an IP address.

    >>> vtor = Validator()
    >>> vtor.check('ip_addr_list', ())
    []
    >>> vtor.check('ip_addr_list', [])
    []
    >>> vtor.check('ip_addr_list', ('1.2.3.4', '5.6.7.8'))
    ['1.2.3.4', '5.6.7.8']
    >>> vtor.check('ip_addr_list', ['a'])  # doctest: +SKIP
    Traceback (most recent call last):
    VdtValueError: the value "a" is unacceptable.
    """
    return [is_ip_addr(mem) for mem in is_list(value, min, max)]


Instruction:
How would you explain what the following Python 3 function does
def force_list(value, min=None, max=None):
    if not isinstance(value, (list, tuple)):
        value = [value]
    return is_list(value, min, max)

Response: Checks that a value is a list coercing strings into a list with one member.


Instruction:
Implement a Python 3 function for
checking that the value is a list of mixed members.

Response:
def is_mixed_list(value, *args):
    """
    Check that the value is a list.
    Allow specifying the type of each member.
    Work on lists of specific lengths.

    You specify each member as a positional argument specifying type

    Each type should be one of the following strings :
      'integer', 'float', 'ip_addr', 'string', 'boolean'

    So you can specify a list of two strings, followed by
    two integers as :

      mixed_list('string', 'string', 'integer', 'integer')

    The length of the list must match the number of positional
    arguments you supply.

    >>> vtor = Validator()
    >>> mix_str = "mixed_list('integer', 'float', 'ip_addr', 'string', 'boolean')"
    >>> check_res = vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a', True))
    >>> check_res == [1, 2.0, '1.2.3.4', 'a', True]
    1
    >>> check_res = vtor.check(mix_str, ('1', '2.0', '1.2.3.4', 'a', 'True'))
    >>> check_res == [1, 2.0, '1.2.3.4', 'a', True]
    1
    >>> vtor.check(mix_str, ('b', 2.0, '1.2.3.4', 'a', True))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "b" is of the wrong type.
    >>> vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a'))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtValueTooShortError: the value "(1, 2.0, '1.2.3.4', 'a')" is too short.
    >>> vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a', 1, 'b'))  # doctest: +SKIP
    Traceback (most recent call last):
    VdtValueTooLongError: the value "(1, 2.0, '1.2.3.4', 'a', 1, 'b')" is too long.
    >>> vtor.check(mix_str, 0)  # doctest: +SKIP
    Traceback (most recent call last):
    VdtTypeError: the value "0" is of the wrong type.

    This test requires an elaborate setup, because of a change in error string
    output from the interpreter between Python 2.2 and 2.3 .

    >>> res_seq = (
    ...     'passed an incorrect value "',
    ...     'yoda',
    ...     '" for parameter "mixed_list".',
    ... )
    >>> res_str = "'".join(res_seq)
    >>> try:
    ...     vtor.check('mixed_list("yoda")', ('a'))
    ... except VdtParamError as err:
    ...     str(err) == res_str
    1
    """
    try:
        length = len(value)
    except TypeError:
        raise VdtTypeError(value)
    if length < len(args):
        raise VdtValueTooShortError(value)
    elif length > len(args):
        raise VdtValueTooLongError(value)
    try:
        return [fun_dict[arg](val) for arg, val in zip(args, value)]
    except KeyError as e:
        raise(VdtParamError('mixed_list', e))


Instruction:
How would you explain what the following Python 3 function does
def is_option(value, *options):
    if not isinstance(value, string_types):
        raise VdtTypeError(value)
    if not value in options:
        raise VdtValueError(value)
    return value

Response: This function checks that the value is one of the options in the order they appear.


Instruction:
Write a Python 3 script to
check if a value is correct for a given check.

Response:
def check(self, check, value, missing=False):
        """
        Usage: check(check, value)

        Arguments:
            check: string representing check to apply (including arguments)
            value: object to be checked
        Returns value, converted to correct type if necessary

        If the check fails, raises a ``ValidateError`` subclass.

        >>> vtor = Validator()
        >>> vtor.check('yoda', '')  # doctest: +SKIP
        Traceback (most recent call last):
        VdtUnknownCheckError: the check "yoda" is unknown.
        >>> vtor.check('yoda()', '')  # doctest: +SKIP
        Traceback (most recent call last):
        VdtUnknownCheckError: the check "yoda" is unknown.

        >>> vtor.check('string(default="")', '', missing=True)
        ''
        """
        fun_name, fun_args, fun_kwargs, default = self._parse_with_caching(check)

        if missing:
            if default is None:
                # no information needed here - to be handled by caller
                raise VdtMissingValue()
            value = self._handle_none(default)

        if value is None:
            return None

        return self._check_value(value, fun_name, fun_args, fun_kwargs)


Instruction:
How would you explain what the following Python 3 function does
def _unquote(self, val):
        if (len(val) >= 2) and (val[0] in ("'", '"')) and (val[0] == val[-1]):
            val = val[1:-1]
        return val

Response: Unquote a value if necessary.


Instruction:
Make a summary of the following Python 3 code
def _list_handle(self, listmatch):
        out = []
        name = listmatch.group(1)
        args = listmatch.group(2)
        for arg in self._list_members.findall(args):
            out.append(self._unquote(arg))
        return name, out

Response: Take apart a keyword = list ( val ) type string.


Instruction:
Here you have a function in Python 3, explain what it does
def get_default_value(self, check):
        fun_name, fun_args, fun_kwargs, default = self._parse_with_caching(check)
        if default is None:
            raise KeyError('Check "%s" has no default value.' % check)
        value = self._handle_none(default)
        if value is None:
            return value
        return self._check_value(value, fun_name, fun_args, fun_kwargs)

Response: Given a check returns the default value for the check.


Instruction:
Can you tell what is the following Python 3 function doing
def match_header(cls, header):

        pixvalue = header.get('PIXVALUE')
        naxis = header.get('NAXIS', 0)

        return (super(_ConstantValueImageBaseHDU, cls).match_header(header) and
                (isinstance(pixvalue, float) or _is_int(pixvalue)) and
                naxis == 0)

Response: Match the header with the constant value image base HDU.


Instruction:
Can you write a function in Python 3 where it
verifies that the HDU s data is a constant value array.

Response:
def _check_constant_value_data(self, data):
        """Verify that the HDU's data is a constant value array."""

        arrayval = data.flat[0]
        if np.all(data == arrayval):
            return arrayval
        return None


Instruction:
How would you code a function in Python 3 to
return currently selected index or - 1 if no such index exists

Response:
def get_current_index(self):
        """ Return currently selected index (or -1) """

        # Need to convert to int; currently API returns a tuple of string
        curSel = self.__lb.curselection()
        if curSel and len(curSel) > 0:
            return int(curSel[0])
        else:
            return -1


Instruction:
Can you generate a brief explanation for the following Python 3 code
def convert(input):

    """Input GEIS files "input" will be read and a HDUList object will
       be returned that matches the waiver-FITS format written out by 'stwfits' in IRAF.

       The user can use the writeto method to write the HDUList object to
       a FITS file.
    """

    global dat
    cardLen = fits.Card.length

    # input file(s) must be of the form *.??h and *.??d
    if input[-1] != 'h' or input[-4] != '.':
        raise "Illegal input GEIS file name %s" % input

    data_file = input[:-1]+'d'

    _os = sys.platform
    if _os[:5] == 'linux' or _os[:5] == 'win32' or _os[:5] == 'sunos' or _os[:3] == 'osf' or _os[:6] == 'darwin':
        bytes_per_line = cardLen+1
    else:
        raise "Platform %s is not supported (yet)." % _os

    end_card = 'END'+' '* (cardLen-3)

    # open input file
    im = open(input)

    # Generate the primary HDU
    cards = []
    while 1:
        line = im.read(bytes_per_line)[:cardLen]
        line = line[:8].upper() + line[8:]
        if line == end_card:
            break
        cards.append(fits.Card.fromstring(line))

    phdr = fits.Header(cards)
    im.close()

    # Determine starting point for adding Group Parameter Block keywords to Primary header
    phdr_indx = phdr.index('PSIZE')

    _naxis0 = phdr.get('NAXIS', 0)
    _naxis = [phdr['NAXIS'+str(j)] for j in range(1, _naxis0+1)]
    _naxis.insert(0, _naxis0)
    _bitpix = phdr['BITPIX']
    _psize = phdr['PSIZE']
    if phdr['DATATYPE'][:4] == 'REAL':
        _bitpix = -_bitpix
    if _naxis0 > 0:
        size = reduce(lambda x,y:x*y, _naxis[1:])
        data_size = abs(_bitpix) * size // 8
    else:
        data_size = 0
    group_size = data_size + _psize // 8

    # decode the group parameter definitions,
    # group parameters will become extension table
    groups = phdr['GROUPS']
    gcount = phdr['GCOUNT']
    pcount = phdr['PCOUNT']

    formats = []
    bools = []
    floats = []
    cols = [] # column definitions used for extension table
    cols_dict = {} # provides name access to Column defs
    _range = range(1, pcount+1)
    key = [phdr['PTYPE'+str(j)] for j in _range]
    comm = [phdr.cards['PTYPE'+str(j)].comment for j in _range]

    # delete group parameter definition header keywords
    _list = ['PTYPE'+str(j) for j in _range] + \
            ['PDTYPE'+str(j) for j in _range] + \
            ['PSIZE'+str(j) for j in _range] + \
            ['DATATYPE', 'PSIZE', 'GCOUNT', 'PCOUNT', 'BSCALE', 'BZERO']

    # Construct record array formats for the group parameters
    # as interpreted from the Primary header file
    for i in range(1, pcount+1):
        ptype = key[i-1]
        pdtype = phdr['PDTYPE'+str(i)]
        star = pdtype.find('*')
        _type = pdtype[:star]
        _bytes = pdtype[star+1:]

        # collect boolean keywords since they need special attention later

        if _type == 'LOGICAL':
            bools.append(i)
        if pdtype == 'REAL*4':
            floats.append(i)

        # identify keywords which require conversion to special units
        if ptype in kw_DOUBLE:
            _type = 'DOUBLE'

        fmt = geis_fmt[_type] + _bytes
        formats.append((ptype,fmt))

        # Set up definitions for use in creating the group-parameter block table
        nrpt = ''
        nbits = str(int(_bytes)*8)
        if 'CHAR' in _type:
            nrpt = _bytes
            nbits = _bytes

        afmt = cols_fmt[_type]+ nbits
        if 'LOGICAL' in _type:
            afmt = cols_fmt[_type]
        cfmt = cols_pfmt[_type]+nrpt

        #print 'Column format for ',ptype,': ',cfmt,' with dtype of ',afmt
        cols_dict[ptype] = fits.Column(name=ptype,format=cfmt,array=numpy.zeros(gcount,dtype=afmt))
        cols.append(cols_dict[ptype]) # This keeps the columns in order

    _shape = _naxis[1:]
    _shape.reverse()
    _code = fits.BITPIX2DTYPE[_bitpix]
    _bscale = phdr.get('BSCALE', 1)
    _bzero = phdr.get('BZERO', 0)

    if phdr['DATATYPE'][:10] == 'UNSIGNED*2':
        _uint16 = 1
        _bzero = 32768
    else:
        _uint16 = 0

    # delete from the end, so it will not conflict with previous delete
    for i in range(len(phdr)-1, -1, -1):
        if phdr.cards[i].keyword in _list:
            del phdr[i]

    # clean up other primary header keywords
    phdr['SIMPLE'] = True
    phdr['GROUPS'] = False
    _after = 'NAXIS'
    if _naxis0 > 0:
        _after += str(_naxis0)
    phdr.set('EXTEND', value=True, comment="FITS dataset may contain extensions", after=_after)

    # Use copy-on-write for all data types since byteswap may be needed
    # in some platforms.
    f1 = open(data_file, mode='rb')
    dat = f1.read()
    errormsg = ""

    # Define data array for all groups
    arr_shape = _naxis[:]
    arr_shape[0] = gcount
    arr_stack = numpy.zeros(arr_shape,dtype=_code)

    loc = 0
    for k in range(gcount):
        ext_dat = numpy.fromstring(dat[loc:loc+data_size], dtype=_code)
        ext_dat = ext_dat.reshape(_shape)
        if _uint16:
            ext_dat += _bzero
        # Check to see whether there are any NaN's or infs which might indicate
        # a byte-swapping problem, such as being written out on little-endian
        #   and being read in on big-endian or vice-versa.
        if _code.find('float') >= 0 and \
            (numpy.any(numpy.isnan(ext_dat)) or numpy.any(numpy.isinf(ext_dat))):
            errormsg += "===================================\n"
            errormsg += "= WARNING:                        =\n"
            errormsg += "=  Input image:                   =\n"
            errormsg += input+"[%d]\n"%(k+1)
            errormsg += "=  had floating point data values =\n"
            errormsg += "=  of NaN and/or Inf.             =\n"
            errormsg += "===================================\n"
        elif _code.find('int') >= 0:
            # Check INT data for max values
            ext_dat_frac,ext_dat_exp = numpy.frexp(ext_dat)
            if ext_dat_exp.max() == int(_bitpix) - 1:
                # Potential problems with byteswapping
                errormsg += "===================================\n"
                errormsg += "= WARNING:                        =\n"
                errormsg += "=  Input image:                   =\n"
                errormsg += input+"[%d]\n"%(k+1)
                errormsg += "=  had integer data values        =\n"
                errormsg += "=  with maximum bitvalues.        =\n"
                errormsg += "===================================\n"

        arr_stack[k] = ext_dat
        #ext_hdu = fits.hdu.ImageHDU(data=ext_dat)

        rec = numpy.fromstring(dat[loc+data_size:loc+group_size], dtype=formats)

        loc += group_size

        # Add data from this GPB to table
        for i in range(1, pcount+1):
            val = rec[0][i-1]
            if i in bools:
                if val:
                    val = 'T'
                else:
                    val = 'F'
            cols[i-1].array[k] = val

        # Based on the first group, add GPB keywords to PRIMARY header
        if k == 0:
            # Create separate PyFITS Card objects for each entry in 'rec'
            # and update Primary HDU with these keywords after PSIZE
            for i in range(1, pcount+1):
                #val = rec.field(i-1)[0]
                val = rec[0][i-1]
                if val.dtype.kind == 'S':
                    val = val.decode('ascii')

                if i in bools:
                    if val:
                        val = True
                    else:
                        val = False

                elif i in floats:
                    # use fromstring, format in Card is deprecated in pyfits 0.9
                    _str = '%-8s= %20.13G / %s' % (key[i-1], val, comm[i-1])
                    _card = fits.Card.fromstring(_str)

                else:
                    _card = fits.Card(key=key[i-1], value=val, comment=comm[i-1])

                phdr.insert(phdr_indx+i, _card)

            # deal with bscale/bzero
            if (_bscale != 1 or _bzero != 0):
                phdr['BSCALE'] = _bscale
                phdr['BZERO'] = _bzero

        #hdulist.append(ext_hdu)
    # Define new table based on Column definitions
    ext_table = fits.TableHDU.from_columns(cols)
    ext_table.header.set('EXTNAME', value=input+'.tab', after='TFIELDS')
    # Add column descriptions to header of table extension to match stwfits output
    for i in range(len(key)):
        ext_table.header.append(fits.Card(keyword=key[i], value=comm[i]))

    if errormsg != "":
        errormsg += "===================================\n"
        errormsg += "=  This file may have been        =\n"
        errormsg += "=  written out on a platform      =\n"
        errormsg += "=  with a different byte-order.   =\n"
        errormsg += "=                                 =\n"
        errormsg += "=  Please verify that the values  =\n"
        errormsg += "=  are correct or apply the       =\n"
        errormsg += "=  '.byteswap()' method.          =\n"
        errormsg += "===================================\n"
        print(errormsg)

    f1.close()

    hdulist = fits.HDUList([fits.PrimaryHDU(header=phdr, data=arr_stack)])
    hdulist.append(ext_table)

    stsci2(hdulist,input)
    return hdulist

Response: Convert a GEIS file into a list of HDU objects.


Instruction:
Make a summary of the following Python 3 code
def _loadConfig(self):
        configPath = path.join(self._getConfigPath(), self._name + ".yml")
        if os.path.exists(configPath):
            self.logger.warning("Loading config from " + configPath)
            with open(configPath, 'r') as yml:
                return yaml.load(yml, Loader=yaml.FullLoader)
        defaultConfig = self.loadDefaultConfig()
        self._storeConfig(defaultConfig, configPath)
        return defaultConfig

Response: Loads the config from some predictable locations.


Instruction:
Can you implement a function in Python 3 that
stores the config to the configPath.

Response:
def _storeConfig(self, config, configPath):
        """
        Writes the config to the configPath.
        :param config a dict of config.
        :param configPath the path to the file to write to, intermediate dirs will be created as necessary.
        """
        self.logger.info("Writing to " + str(configPath))
        os.makedirs(os.path.dirname(configPath), exist_ok=True)
        with (open(configPath, 'w')) as yml:
            yaml.dump(config, yml, default_flow_style=False)


Instruction:
Can you generate the documentation for the following Python 3 function
def _getConfigPath(self):
        confHome = environ.get('VIBE_CONFIG_HOME')
        return confHome if confHome is not None else path.join(path.expanduser("~"), '.vibe')

Response: Gets the currently configured config path.