Instruction:
Can you implement a function in Python 3 that
converts XML elementtree to dictionary.

Response:
def _elementtree_to_dict(self, element):
        """Convert XML elementtree to dictionary.

        Converts the actual response from the ILO for an API
        to the dictionary.
        """
        node = {}
        text = getattr(element, 'text')
        if text is not None:
            text = text.strip()
            if len(text) != 0:
                node['text'] = text
        node.update(element.items())  # element's attributes
        child_nodes = {}
        for child in element:  # element's children
            child_nodes.setdefault(child.tag, []).append(
                self._elementtree_to_dict(child))
        # convert all single-element lists into non-lists
        for key, value in child_nodes.items():
            if len(value) == 1:
                child_nodes[key] = value[0]
        node.update(child_nodes.items())
        return node


Instruction:
Can you generate the documentation for the following Python 3 function
def _validate_message(self, message):
        if message.tag != 'RIBCL':
            # the true case shall be unreachable for response
            # XML from Ilo as all messages are tagged with RIBCL
            # but still raise an exception if any invalid
            # XML response is returned by Ilo. Set status to some
            # arbitary non-zero value.
            status = -1
            raise exception.IloClientInternalError(message, status)

        for child in message:
            if child.tag != 'RESPONSE':
                return message
            status = int(child.get('STATUS'), 16)
            msg = child.get('MESSAGE')
            if status == 0 and msg != 'No error':
                return msg
            if status != 0:
                if 'syntax error' in msg or 'Feature not supported' in msg:
                    for cmd in BOOT_MODE_CMDS:
                        if cmd in msg:
                            platform = self.get_product_name()
                            msg = ("%(cmd)s is not supported on %(platform)s" %
                                   {'cmd': cmd, 'platform': platform})
                            LOG.debug(self._("Got invalid response with "
                                             "message: '%(message)s'"),
                                      {'message': msg})
                            raise (exception.IloCommandNotSupportedError
                                   (msg, status))
                    else:
                        LOG.debug(self._("Got invalid response with "
                                         "message: '%(message)s'"),
                                  {'message': msg})
                        raise exception.IloClientInternalError(msg, status)
                if (status in exception.IloLoginFailError.statuses or
                        msg in exception.IloLoginFailError.messages):
                    LOG.debug(self._("Got invalid response with "
                                     "message: '%(message)s'"),
                              {'message': msg})
                    raise exception.IloLoginFailError(msg, status)

                LOG.debug(self._("Got invalid response with "
                                 "message: '%(message)s'"),
                          {'message': msg})
                raise exception.IloError(msg, status)

Response: Validate the XML response from Ilo.


Instruction:
Can you tell what is the following Python 3 function doing
def _execute_command(self, create_command, tag_info, mode, dic={}):
        xml = self._create_dynamic_xml(
            create_command, tag_info, mode, dic)
        d = self._request_ilo(xml)
        data = self._parse_output(d)
        LOG.debug(self._("Received response data: %s"), data)
        return data

Response: Execute a command on the iLO.


Instruction:
How would you implement a function in Python 3 that
retrieves all license types key installation date etc.

Response:
def get_all_licenses(self):
        """Retrieve license type, key, installation date, etc."""
        data = self._execute_command('GET_ALL_LICENSES', 'RIB_INFO', 'read')
        d = {}
        for key, val in data['GET_ALL_LICENSES']['LICENSE'].items():
            if isinstance(val, dict):
                d[key] = data['GET_ALL_LICENSES']['LICENSE'][key]['VALUE']
        return d


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_vm_status(self, device='FLOPPY'):
        dic = {'DEVICE': device.upper()}
        data = self._execute_command(
            'GET_VM_STATUS', 'RIB_INFO', 'read', dic)
        return data['GET_VM_STATUS']

Response: Returns the virtual media drive status.


Instruction:
Given the following Python 3 function, write the documentation
def set_host_power(self, power):
        if power.upper() in POWER_STATE:
            dic = {'HOST_POWER': POWER_STATE[power.upper()]}
            data = self._execute_command(
                'SET_HOST_POWER', 'SERVER_INFO', 'write', dic)
            return data
        else:
            raise exception.IloInvalidInputError(
                "Invalid input. The expected input is ON or OFF.")

Response: Toggle the power button of server.


Instruction:
Write a Python 3 function that can
configure a single boot from a specific device.

Response:
def set_one_time_boot(self, value):
        """Configures a single boot from a specific device.

        :param value: specific device to which the boot option is set
        """
        dic = {'value': value}
        data = self._execute_command(
            'SET_ONE_TIME_BOOT', 'SERVER_INFO', 'write', dic)
        return data


Instruction:
Create a Python 3 function for
inserting a virtual media diskette image.

Response:
def insert_virtual_media(self, url, device='FLOPPY'):
        """Notifies iLO of the location of a virtual media diskette image."""
        dic = {
            'DEVICE': device.upper(),
            'IMAGE_URL': url,
        }
        data = self._execute_command(
            'INSERT_VIRTUAL_MEDIA', 'RIB_INFO', 'write', dic)
        return data


Instruction:
Make a summary of the following Python 3 code
def eject_virtual_media(self, device='FLOPPY'):
        vm_status = self.get_vm_status(device=device)
        if vm_status['IMAGE_INSERTED'] == 'NO':
            return

        dic = {'DEVICE': device.upper()}
        self._execute_command(
            'EJECT_VIRTUAL_MEDIA', 'RIB_INFO', 'write', dic)

Response: Ejects the Virtual Media image if one is inserted.


Instruction:
Can you tell what is the following Python 3 function doing
def set_vm_status(self, device='FLOPPY',
                      boot_option='BOOT_ONCE', write_protect='YES'):
        """Sets the Virtual Media drive status

        It also allows the boot options for booting from the virtual media.
        """
        dic = {'DEVICE': device.upper()}
        xml = self._create_dynamic_xml(
            'SET_VM_STATUS', 'RIB_INFO', 'write', dic)

        if six.PY2:
            child_iterator = xml.getiterator()
        else:
            child_iterator = xml.iter()

        for child in child_iterator:
            if child.tag == 'SET_VM_STATUS':
                etree.SubElement(child, 'VM_BOOT_OPTION',
                                 VALUE=boot_option.upper())
                etree.SubElement(child, 'VM_WRITE_PROTECT',
                                 VALUE=write_protect.upper())

        d = self._request_ilo(xml)
        data = self._parse_output(d)
        return data

Response: Sets the Virtual Media drive status


Instruction:
Implement a function in Python 3 to
retrieve the supported boot mode.

Response:
def get_supported_boot_mode(self):
        """Retrieves the supported boot mode.

        :returns: any one of the following proliantutils.ilo.constants:

            SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY,
            SUPPORTED_BOOT_MODE_UEFI_ONLY,
            SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI

        """
        data = self._execute_command(
            'GET_SUPPORTED_BOOT_MODE', 'SERVER_INFO', 'read')
        supported_boot_mode = (
            data['GET_SUPPORTED_BOOT_MODE']['SUPPORTED_BOOT_MODE']['VALUE'])
        return mappings.GET_SUPPORTED_BOOT_MODE_RIBCL_MAP.get(
            supported_boot_mode)


Instruction:
Implement a function in Python 3 to
configure the boot mode of the system from a specific boot mode.

Response:
def set_pending_boot_mode(self, value):
        """Configures the boot mode of the system from a specific boot mode."""
        dic = {'value': value}
        data = self._execute_command(
            'SET_PENDING_BOOT_MODE', 'SERVER_INFO', 'write', dic)
        return data


Instruction:
Make a summary of the following Python 3 code
def get_persistent_boot_device(self):
        result = self._get_persistent_boot()
        boot_mode = self._check_boot_mode(result)

        if boot_mode == 'bios':
            return result[0]['value']

        value = result[0]['DESCRIPTION']
        if 'HP iLO Virtual USB CD' in value:
            return 'CDROM'

        elif 'NIC' in value or 'PXE' in value:
            return 'NETWORK'

        elif common.isDisk(value):
            return 'HDD'

        else:
            return None

Response: Get the current persistent boot device set for the host.


Instruction:
Explain what the following Python 3 code does
def _set_persistent_boot(self, values=[]):

        xml = self._create_dynamic_xml(
            'SET_PERSISTENT_BOOT', 'SERVER_INFO', 'write')

        if six.PY2:
            child_iterator = xml.getiterator()
        else:
            child_iterator = xml.iter()

        for child in child_iterator:
            for val in values:
                if child.tag == 'SET_PERSISTENT_BOOT':
                    etree.SubElement(child, 'DEVICE', VALUE=val)
        d = self._request_ilo(xml)
        data = self._parse_output(d)
        return data

Response: Configures a boot from a specific device.


Instruction:
How would you explain what the following Python 3 function does
def _request_host(self):
        urlstr = 'https://%s/xmldata?item=all' % (self.host)
        kwargs = {}
        if self.cacert is not None:
            kwargs['verify'] = self.cacert
        else:
            kwargs['verify'] = False
        try:
            response = requests.get(urlstr, **kwargs)
            response.raise_for_status()
        except Exception as e:
            raise IloConnectionError(e)

        return response.text

Response: Request host info from the server.


Instruction:
Write a Python 3 script for
requesting host UUID of the server.

Response:
def get_host_uuid(self):
        """Request host UUID of the server.

        :returns: the host UUID of the server
        :raises: IloConnectionError if failed connecting to the iLO.
        """
        xml = self._request_host()
        root = etree.fromstring(xml)
        data = self._elementtree_to_dict(root)
        return data['HSI']['SPN']['text'], data['HSI']['cUUID']['text']


Instruction:
How would you implement a function in Python 3 that
requests host health data of the server.

Response:
def get_host_health_data(self, data=None):
        """Request host health data of the server.

        :param: the data to retrieve from the server, defaults to None.
        :returns: the dictionary containing the embedded health data.
        :raises: IloConnectionError if failed connecting to the iLO.
        :raises: IloError, on an error from iLO.
        """
        if not data or data and "GET_EMBEDDED_HEALTH_DATA" not in data:
            data = self._execute_command(
                'GET_EMBEDDED_HEALTH', 'SERVER_INFO', 'read')
        return data


Instruction:
Write a Python 3 function that can
request the health power supply information.

Response:
def get_host_health_power_supplies(self, data=None):
        """Request the health power supply information.

        :param: the data to retrieve from the server, defaults to None.
        :returns: the dictionary containing the power supply information.
        :raises: IloConnectionError if failed connecting to the iLO.
        :raises: IloError, on an error from iLO.
        """
        data = self.get_host_health_data(data)
        d = (data['GET_EMBEDDED_HEALTH_DATA']['POWER_SUPPLIES']['SUPPLY'])
        if not isinstance(d, list):
            d = [d]
        return d


Instruction:
Can you implement a function in Python 3 that
gets the health Temp Sensor report.

Response:
def get_host_health_temperature_sensors(self, data=None):
        """Get the health Temp Sensor report.

        :param: the data to retrieve from the server, defaults to None.
        :returns: the dictionary containing the temperature sensors
            information.
        :raises: IloConnectionError if failed connecting to the iLO.
        :raises: IloError, on an error from iLO.
        """
        data = self.get_host_health_data(data)
        d = data['GET_EMBEDDED_HEALTH_DATA']['TEMPERATURE']['TEMP']
        if not isinstance(d, list):
            d = [d]
        return d


Instruction:
Make a summary of the following Python 3 code
def get_host_health_fan_sensors(self, data=None):
        data = self.get_host_health_data(data)
        d = data['GET_EMBEDDED_HEALTH_DATA']['FANS']['FAN']
        if not isinstance(d, list):
            d = [d]
        return d

Response: Get the health Fan Sensor Report.


Instruction:
Make a summary of the following Python 3 code
def reset_ilo_credential(self, password):

        dic = {'USER_LOGIN': self.login}
        root = self._create_dynamic_xml(
            'MOD_USER', 'USER_INFO', 'write', dic)

        element = root.find('LOGIN/USER_INFO/MOD_USER')
        etree.SubElement(element, 'PASSWORD', VALUE=password)
        d = self._request_ilo(root)
        self._parse_output(d)

Response: Resets the iLO password.


Instruction:
Write a Python 3 script for
getting essential scheduling properties as required by ironic

Response:
def get_essential_properties(self):
        """Gets essential scheduling properties as required by ironic

        :returns: a dictionary of server properties like memory size,
                  disk size, number of cpus, cpu arch, port numbers
                  and mac addresses.
        :raises:IloError if iLO returns an error in command execution.

        """
        data = self.get_host_health_data()
        properties = {
            'memory_mb': self._parse_memory_embedded_health(data)
        }
        cpus, cpu_arch = self._parse_processor_embedded_health(data)
        properties['cpus'] = cpus
        properties['cpu_arch'] = cpu_arch
        properties['local_gb'] = self._parse_storage_embedded_health(data)
        macs = self._parse_nics_embedded_health(data)
        return_value = {'properties': properties, 'macs': macs}
        return return_value


Instruction:
Can you tell what is the following Python 3 function doing
def get_server_capabilities(self):
        capabilities = {}
        data = self.get_host_health_data()
        ilo_firmware = self._get_ilo_firmware_version(data)
        if ilo_firmware:
            capabilities.update(ilo_firmware)
        rom_firmware = self._get_rom_firmware_version(data)
        if rom_firmware:
            capabilities.update(rom_firmware)
        capabilities.update({'server_model': self.get_product_name()})
        capabilities.update(self._get_number_of_gpu_devices_connected(data))
        boot_modes = common.get_supported_boot_modes(
            self.get_supported_boot_mode())
        capabilities.update({
            'boot_mode_bios': boot_modes.boot_mode_bios,
            'boot_mode_uefi': boot_modes.boot_mode_uefi})
        return capabilities

Response: Gets the server properties which can be used for scheduling


Instruction:
Can you write a function in Python 3 where it
parses the get_host_health_data method for essential properties

Response:
def _parse_memory_embedded_health(self, data):
        """Parse the get_host_health_data() for essential properties

        :param data: the output returned by get_host_health_data()
        :returns: memory size in MB.
        :raises IloError, if unable to get the memory details.
        """
        memory_mb = 0
        memory = self._get_memory_details_value_based_on_model(data)

        if memory is None:
            msg = "Unable to get memory data. Error: Data missing"
            raise exception.IloError(msg)

        total_memory_size = 0
        for memory_item in memory:
            memsize = memory_item[self.MEMORY_SIZE_TAG]["VALUE"]
            if memsize != self.MEMORY_SIZE_NOT_PRESENT_TAG:
                memory_bytes = (
                    strutils.string_to_bytes(
                        memsize.replace(' ', ''), return_int=True))
                memory_mb = int(memory_bytes / (1024 * 1024))
                total_memory_size = total_memory_size + memory_mb
        return total_memory_size


Instruction:
Given the following Python 3 function, write the documentation
def _parse_processor_embedded_health(self, data):
        processor = self.get_value_as_list((data['GET_EMBEDDED_HEALTH_DATA']
                                           ['PROCESSORS']), 'PROCESSOR')
        if processor is None:
            msg = "Unable to get cpu data. Error: Data missing"
            raise exception.IloError(msg)
        cpus = 0
        for proc in processor:
            for val in proc.values():
                processor_detail = val['VALUE']
                proc_core_threads = processor_detail.split('; ')
                for x in proc_core_threads:
                    if "thread" in x:
                        v = x.split()
                        try:
                            cpus = cpus + int(v[0])
                        except ValueError:
                            msg = ("Unable to get cpu data. "
                                   "The Value %s returned couldn't be "
                                   "manipulated to get number of "
                                   "actual processors" % processor_detail)
                            raise exception.IloError(msg)
        cpu_arch = 'x86_64'
        return cpus, cpu_arch

Response: Parse the get_host_health_data method for essential properties


Instruction:
Can you generate the documentation for the following Python 3 function
def _parse_storage_embedded_health(self, data):
        local_gb = 0
        storage = self.get_value_as_list(data['GET_EMBEDDED_HEALTH_DATA'],
                                         'STORAGE')
        if storage is None:
            # We dont raise exception because this dictionary
            # is available only when RAID is configured.
            # If we raise error here then we will always fail
            # inspection where this module is consumed. Hence
            # as a workaround just return 0.
            return local_gb

        minimum = local_gb

        for item in storage:
            cntlr = self.get_value_as_list(item, 'CONTROLLER')
            if cntlr is None:
                continue
            for s in cntlr:
                drive = self.get_value_as_list(s, 'LOGICAL_DRIVE')
                if drive is None:
                    continue
                for item in drive:
                    for key, val in item.items():
                        if key == 'CAPACITY':
                            capacity = val['VALUE']
                            local_bytes = (strutils.string_to_bytes(
                                           capacity.replace(' ', ''),
                                           return_int=True))
                            local_gb = int(local_bytes / (1024 * 1024 * 1024))
                            if minimum >= local_gb or minimum == 0:
                                minimum = local_gb

        # Return disk size 1 less than the actual disk size. This prevents
        # the deploy to fail from Nova when root_gb is same as local_gb
        # in Ironic. When the disk size is used as root_device hints,
        # then it should be given as the actual size i.e.
        # ironic (node.properties['local_gb'] + 1) else root device
        # hint will fail.
        if minimum:
            minimum = minimum - 1
        return minimum

Response: Parses the get_embedded_health_data method for essential properties and returns the disk size in GB.


Instruction:
Can you tell what is the following Python 3 function doing
def _parse_nics_embedded_health(self, data):
        nic_data = self.get_value_as_list((data['GET_EMBEDDED_HEALTH_DATA']
                                          [self.NIC_INFORMATION_TAG]), 'NIC')

        if nic_data is None:
            msg = "Unable to get NIC details. Data missing"
            raise exception.IloError(msg)
        nic_dict = {}
        for item in nic_data:
            try:
                port = item['NETWORK_PORT']['VALUE']
                mac = item['MAC_ADDRESS']['VALUE']
                self._update_nic_data_from_nic_info_based_on_model(nic_dict,
                                                                   item, port,
                                                                   mac)

            except KeyError:
                msg = "Unable to get NIC details. Data missing"
                raise exception.IloError(msg)

        return nic_dict

Response: Parses the get_embedded_health data for essential properties and updates the NIC details based on the model of the NIC.


Instruction:
Explain what the following Python 3 code does
def _get_firmware_embedded_health(self, data):
        firmware = self.get_value_as_list(data['GET_EMBEDDED_HEALTH_DATA'],
                                          'FIRMWARE_INFORMATION')
        if firmware is None:
            return None
        return dict((y['FIRMWARE_NAME']['VALUE'],
                     y['FIRMWARE_VERSION']['VALUE'])
                    for x in firmware for y in x.values())

Response: Parse the get_host_health_data method for server capabilities


Instruction:
Here you have a function in Python 3, explain what it does
def _get_rom_firmware_version(self, data):
        firmware_details = self._get_firmware_embedded_health(data)
        if firmware_details:
            try:
                rom_firmware_version = (
                    firmware_details['HP ProLiant System ROM'])
                return {'rom_firmware_version': rom_firmware_version}
            except KeyError:
                return None

Response: Gets the rom firmware version for server capabilities


Instruction:
Can you implement a function in Python 3 that
returns the iLO firmware version for server capabilities

Response:
def _get_ilo_firmware_version(self, data):
        """Gets the ilo firmware version for server capabilities

        Parse the get_host_health_data() to retreive the firmware
        details.

        :param data: the output returned by get_host_health_data()
        :returns: a dictionary of iLO firmware version.

        """
        firmware_details = self._get_firmware_embedded_health(data)
        if firmware_details:
            try:
                return {'ilo_firmware_version': firmware_details['iLO']}
            except KeyError:
                return None


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_ilo_firmware_version_as_major_minor(self):
        data = self.get_host_health_data()
        firmware_details = self._get_firmware_embedded_health(data)
        if firmware_details:
            ilo_version_str = firmware_details.get('iLO', None)
            return common.get_major_minor(ilo_version_str)

Response: Gets the ilo firmware version for server capabilities and returns the major and minor version as a string.


Instruction:
Here you have a function in Python 3, explain what it does
def _get_number_of_gpu_devices_connected(self, data):
        temp = self.get_value_as_list((data['GET_EMBEDDED_HEALTH_DATA']
                                      ['TEMPERATURE']), 'TEMP')
        count = 0
        if temp is None:
            return {'pci_gpu_devices': count}

        for key in temp:
            for name, value in key.items():
                if name == 'LABEL' and 'GPU' in value['VALUE']:
                    count = count + 1

        return {'pci_gpu_devices': count}

Response: Parse the get_host_health_data method and get the count of GPU devices connected to the server.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def activate_license(self, key):
        root = self._create_dynamic_xml('LICENSE', 'RIB_INFO', 'write')
        element = root.find('LOGIN/RIB_INFO/LICENSE')
        etree.SubElement(element, 'ACTIVATE', KEY=key)
        d = self._request_ilo(root)
        self._parse_output(d)

Response:
Activates iLO license.

        :param key: iLO license key.
        :raises: IloError, on an error from iLO.


Instruction:
Here you have a function in Python 3, explain what it does
def update_firmware(self, filename, component_type):
        fw_img_processor = firmware_controller.FirmwareImageUploader(filename)

        LOG.debug(self._('Uploading firmware file: %s ...'), filename)
        cookie = fw_img_processor.upload_file_to((self.host, self.port),
                                                 self.timeout)
        LOG.debug(self._('Uploading firmware file: %s ... done'), filename)

        root = self._get_firmware_update_xml_for_file_and_component(
            filename, component_type)
        element = root.find('LOGIN/RIB_INFO')
        etree.SubElement(element, 'TPM_ENABLED', VALUE='Yes')
        extra_headers = {'Cookie': cookie}

        LOG.debug(self._('Flashing firmware file: %s ...'), filename)
        d = self._request_ilo(root, extra_headers=extra_headers)

        # wait till the firmware update completes.
        common.wait_for_ribcl_firmware_update_to_complete(self)
        self._parse_output(d)
        LOG.info(self._('Flashing firmware file: %s ... done'), filename)

Response: Updates the given firmware on the server for the given component type.


Instruction:
Create a Python 3 function for
creating the dynamic xml for flashing the firmware via iLO.

Response:
def _get_firmware_update_xml_for_file_and_component(
            self, filename, component):
        """Creates the dynamic xml for flashing the device firmware via iLO.

        This method creates the dynamic xml for flashing the firmware, based
        on the component type so passed.
        :param filename: location of the raw firmware file.
        :param component_type: Type of component to be applied to.
        :returns: the etree.Element for the root of the RIBCL XML
                  for flashing the device (component) firmware.
        """
        if component == 'ilo':
            cmd_name = 'UPDATE_RIB_FIRMWARE'
        else:
            # Note(deray): Not explicitly checking for all other supported
            # devices (components), as those checks have already happened
            # in the invoking methods and may seem redundant here.
            cmd_name = 'UPDATE_FIRMWARE'

        fwlen = os.path.getsize(filename)
        root = self._create_dynamic_xml(cmd_name,
                                        'RIB_INFO',
                                        'write',
                                        subelements={
                                            'IMAGE_LOCATION': filename,
                                            'IMAGE_LENGTH': str(fwlen)
                                        })
        return root


Instruction:
Create a Python 3 function for
getting the response body from gzipped content.

Response:
def _get_response_body_from_gzipped_content(self, url, response):
        """Get the response body from gzipped content

        Try to decode as gzip (we should check the headers for
        Content-Encoding=gzip)

          if response.headers['content-encoding'] == "gzip":
            ...

        :param url: the url for which response was sent
        :type url: str
        :param response: response content object, probably gzipped
        :type response: object
        :returns: returns response body
        :raises IloError: if the content is **not** gzipped
        """
        try:
            gzipper = gzip.GzipFile(fileobj=six.BytesIO(response.text))

            LOG.debug(self._("Received compressed response for "
                             "url %(url)s."), {'url': url})
            uncompressed_string = (gzipper.read().decode('UTF-8'))
            response_body = json.loads(uncompressed_string)

        except Exception as e:
            LOG.debug(
                self._("Error occurred while decompressing body. "
                       "Got invalid response '%(response)s' for "
                       "url %(url)s: %(error)s"),
                {'url': url, 'response': response.text, 'error': e})
            raise exception.IloError(e)

        return response_body


Instruction:
Explain what the following Python 3 code does
def _rest_op(self, operation, suburi, request_headers, request_body):

        url = urlparse.urlparse('https://' + self.host + suburi)
        # Used for logging on redirection error.
        start_url = url.geturl()

        LOG.debug(self._("%(operation)s %(url)s"),
                  {'operation': operation, 'url': start_url})

        if request_headers is None or not isinstance(request_headers, dict):
            request_headers = {}

        # Use self.login/self.password and Basic Auth
        if self.login is not None and self.password is not None:
            auth_data = self.login + ":" + self.password
            hr = "BASIC " + base64.b64encode(
                auth_data.encode('ascii')).decode("utf-8")
            request_headers['Authorization'] = hr

        if request_body is not None:
            if (isinstance(request_body, dict)
                    or isinstance(request_body, list)):
                request_headers['Content-Type'] = 'application/json'
            else:
                request_headers['Content-Type'] = ('application/'
                                                   'x-www-form-urlencoded')

        """Helper methods to retry and keep retrying on redirection - START"""

        def retry_if_response_asks_for_redirection(response):
            # NOTE:Do not assume every HTTP operation will return a JSON
            # request_body. For example, ExtendedError structures are only
            # required for HTTP 400 errors and are optional elsewhere as they
            # are mostly redundant for many of the other HTTP status code.
            # In particular, 200 OK responses should not have to return any
            # request_body.

            # NOTE:  this makes sure the headers names are all lower cases
            # because HTTP says they are case insensitive
            # Follow HTTP redirect
            if response.status_code == 301 and 'location' in response.headers:
                retry_if_response_asks_for_redirection.url = (
                    urlparse.urlparse(response.headers['location']))
                LOG.debug(self._("Request redirected to %s."),
                          retry_if_response_asks_for_redirection.url.geturl())
                return True
            return False

        @retrying.retry(
            # Note(deray): Return True if we should retry, False otherwise.
            # In our case, when the url response we receive asks for
            # redirection then we retry.
            retry_on_result=retry_if_response_asks_for_redirection,
            # Note(deray): Return True if we should retry, False otherwise.
            # In our case, when it's an IloConnectionError we don't retry.
            # ``requests`` already takes care of issuing max number of
            # retries if the URL service is unavailable.
            retry_on_exception=(
                lambda e: not isinstance(e, exception.IloConnectionError)),
            stop_max_attempt_number=REDIRECTION_ATTEMPTS)
        def _fetch_response():

            url = retry_if_response_asks_for_redirection.url

            kwargs = {'headers': request_headers,
                      'data': json.dumps(request_body)}
            if self.cacert is not None:
                kwargs['verify'] = self.cacert
            else:
                kwargs['verify'] = False

            LOG.debug(self._('\n\tHTTP REQUEST: %(restreq_method)s'
                             '\n\tPATH: %(restreq_path)s'
                             '\n\tBODY: %(restreq_body)s'
                             '\n'),
                      {'restreq_method': operation,
                       'restreq_path': url.geturl(),
                       'restreq_body': request_body})

            request_method = getattr(requests, operation.lower())
            try:
                response = request_method(url.geturl(), **kwargs)
            except Exception as e:
                LOG.debug(self._("Unable to connect to iLO. %s"), e)
                raise exception.IloConnectionError(e)

            return response

        """Helper methods to retry and keep retrying on redirection - END"""

        try:
            # Note(deray): This is a trick to use the function attributes
            # to overwrite variable/s (in our case ``url``) and use the
            # modified one in nested functions, i.e. :func:`_fetch_response`
            # and :func:`retry_if_response_asks_for_redirection`
            retry_if_response_asks_for_redirection.url = url

            response = _fetch_response()
        except retrying.RetryError as e:
            # Redirected for REDIRECTION_ATTEMPTS - th time. Throw error
            msg = (self._("URL Redirected %(times)s times continuously. "
                          "URL used: %(start_url)s More info: %(error)s") %
                   {'start_url': start_url, 'times': REDIRECTION_ATTEMPTS,
                    'error': str(e)})
            LOG.debug(msg)
            raise exception.IloConnectionError(msg)

        response_body = {}
        if response.text:
            try:
                response_body = json.loads(response.text)
            except (TypeError, ValueError):
                # Note(deray): If it doesn't decode as json, then
                # resources may return gzipped content.
                # ``json.loads`` on python3 raises TypeError when
                # ``response.text`` is gzipped one.
                response_body = (
                    self._get_response_body_from_gzipped_content(url,
                                                                 response))

        LOG.debug(self._('\n\tHTTP RESPONSE for %(restreq_path)s:'
                         '\n\tCode: %(status_code)s'
                         '\n\tResponse Body: %(response_body)s'
                         '\n'),
                  {'restreq_path': url.geturl(),
                   'status_code': response.status_code,
                   'response_body': response_body})
        return response.status_code, response.headers, response_body

Response: Generic REST Operation handler.


Instruction:
How would you implement a function in Python 3 that
rests PATCH operation. HTTP response codes could be 500, 404, 202 etc.

Response:
def _rest_patch(self, suburi, request_headers, request_body):
        """REST PATCH operation.

        HTTP response codes could be 500, 404, 202 etc.
        """
        return self._rest_op('PATCH', suburi, request_headers, request_body)


Instruction:
Write a Python 3 script for
resting PUT operation. HTTP response codes could be 500, 404, 202 etc.

Response:
def _rest_put(self, suburi, request_headers, request_body):
        """REST PUT operation.

        HTTP response codes could be 500, 404, 202 etc.
        """
        return self._rest_op('PUT', suburi, request_headers, request_body)


Instruction:
Explain what the following Python 3 code does
def _rest_post(self, suburi, request_headers, request_body):
        return self._rest_op('POST', suburi, request_headers, request_body)

Response:
REST POST operation.

        The response body after the operation could be the new resource, or
        ExtendedError, or it could be empty.


Instruction:
How would you explain what the following Python 3 function does
def get(self, cycle_list, dataitem=None, isotope=None, sparse=1):
        '''
        Get Data from HDF5 files.

        There are three ways to call this function

        1. get(dataitem)

            Fetches the datatiem for all cycles. If dataitem is a header
            attribute or list of attributes then the data is retured.
            If detaitem an individulal or list of column attributes,
            data columns or isotopes/elements the data is returned for
            all cycles.

        2. get(cycle_list, dataitem)

            Fetches the dataitem or list of dataitems for the cycle
            or list of cycles. The variable dataitems can contain column
            attributes, data columns, and isotopes/elemnts.

        3. get(cycle_list, dataitem, isotope)

            Fetches the dataitems like the seccond method except that
            one of the dataitems must be either "iso_massf" or "yps",
            and in the data returned "iso_massf" and "yps" are replaced
            with the data from the isotopes.  The isotopes must be in
            the form given by se.isotopes or se.elements.

        Parameters
        ----------
        cycle_list : list, integer or string
            If cycle_list is a list or string and all of the entries
            are header attributes then the attributes are returned.

            If cycle_list is a list or string of dataitems then the
            dataitems are fetched for all cycles.

            If cycle_list is a list, integer or string of cycle numbers
            then data is returned for those cycles.
        dataitem: list or string, optional
            If dataitem is not None then the data for each item is
            returned for the cycle or list of cycles. dataitem may be an
            individual or a mixed list of column attributes, column
            data or isotopes/elements. If dataitem is None then
            cycle_list must be a string.  The default is None.
        isotope: list or string, optional
            If one of the dataitems is "iso_massf" or "yps" then it is
            replaced with the data from the individual isotopes/elements
            listed in isotope.  The default is None.
        sparse : int
            Implements a sparsity factor on the fetched data i.e. only
            the i th cycle in cycle_list data is returned,
            where i = sparse.

        '''

#    Check out the inputs
        t1=time.time()
        isotopes_of_interest = []

        nested_list = False
        # if one of cycle_list, dataitem or isotope is given as a string convert it to a list
        if isinstance(cycle_list, basestring):
            cycle_list = [cycle_list]
        else:
            try:
                if len(cycle_list) == 1:
                    nested_list = True
            except TypeError:
                pass #leave nested_list as false
        if isinstance(dataitem, basestring):
            dataitem = [dataitem]
        if isinstance(isotope, basestring):
            isotope = [isotope]

        if dataitem==None and isotope==None:
            option_ind = 1
            dataitem = cycle_list

            if not any([item in self.hattrs for item in dataitem]):
                cycle_list = self.cycles
            else:
                first_file = mrT.File(self.h5s[0].filename,'r')
                dat = []
                # get all dataitems from header attributes
                for item in dataitem:
                    tmp = first_file.attrs.get(item, None)
                    try:
                        if len(tmp) == 1:
                            tmp = tmp[0]
                    except TypeError: #if a scaler is returned do nothing
                        pass
                    dat.append(tmp)
                # if only one header attribute is required dont return as a list
                if (len(dat) == 1) and (not nested_list):
                    dat = dat[0]
                first_file.close()
                return dat
            if any([item.split('-')[0] in self.isos for item in dataitem]):
                return self.get(cycle_list,dataitem,sparse=sparse)
        elif isotope==None:
            option_ind = 2
            cycle_list = cycle_list
            dataitem = dataitem
            # if one dataitem is given as a string convert it to a list
            if isinstance(dataitem, basestring):
                dataitem = [dataitem]
            new_dataitem = []
            new_isotopes = []
            for item in dataitem:
                if item.split('-')[0] in self.isos:
                    new_isotopes.append(item)
                else:
                    new_dataitem.append(item)
            if len(new_isotopes) != 0:
                tmp = []
                try:
                    tmp = self.get(cycle_list,new_dataitem + ['iso_massf'],new_isotopes,sparse=sparse)
                except: # in some old se files there maybe still yps as the name for the abundance arrays
                    tmp =  self.get(cycle_list,new_dataitem + ['yps'],new_isotopes,sparse=sparse)
                # modify the dat list so dat is structured like dataitems
                dat = []
                #make sure tmp containes the data as a list of cycles
                if isinstance(cycle_list, basestring):
                    tmp = [tmp]
                else:
                    try:
                        if len(cycle_list) == 1:
                            tmp = [tmp]
                    except TypeError:
                        tmp = [tmp]
                for cyc in tmp:
                    temp_dataitem = []
                    for item in dataitem:
                        if item in new_dataitem:
                            temp_dataitem.append(cyc[new_dataitem.index(item)])
                        else:
                            if len(new_dataitem) == 0:
                                temp_dataitem = cyc
                            else:
                                if len(new_isotopes) == 1:
                                    temp_dataitem.append(cyc[-1])
                                else:
                                    temp_dataitem.append(cyc[-1][new_isotopes.index(item)])
                    dat.append(temp_dataitem)
                if (len(dat) == 1) and (not nested_list):
                    dat = dat[0]
                return dat
        else:
# there is an implicite rule here that if you want 2D arrays you have
# to give 3 args, or, in other words you have to give a cycle or cycle
# array; there is no good reason for that, except the programmers
# laziness
            option_ind = 3
            cycle_list = cycle_list
            dataitem = dataitem
            isotopes_of_interest = isotope
# we need to find out the shellnb to know if any yps array may just be
# a one row array, as - for example- in the surf.h5 files
            # SJONES: I think here we only need to look at the first shellnb(!)
            #shellnb=self.get(cycle_list,'shellnb')
            try: #check if cycle_list is not a list
                cycle_list[0]
            except (TypeError,IndexError):
                cycle_list = [cycle_list]
            shellnb=self.get(cycle_list[0],'shellnb')

        if sparse <1:
            sparse=1

        #    Just in case the user inputs integers
        try:
            for x in range(len(cycle_list)):
                cycle_list[x] = str(cycle_list[x])
        except TypeError:
            cycle_list = [str(cycle_list)]

        if option_ind != 1:

            try: #if it is a single cycle make sure its formatted correctly
                if cycle_list.isdigit():
                    cycle_list = [cycle_list]
                    for cycle in cycle_list:
                        if len(cycle) != len(self.cycles[0]):
                                #print "a"
                            diff = len(self.cycles[0])-len(cycle)
                            OO = ''
                            while diff >=1:
                                OO+='0'

                            cycle = OO+cycle

            except AttributeError: ##if it is a list of cycles make sure its formatted correctly
                if cycle_list[0].isdigit():

                    for x in range(len(cycle_list)):
                        if len(str(cycle_list[x])) != len(str(self.cycles[0])):
                            #print "b"
                            diff = len(str(self.cycles[0]))-len(str(cycle_list[x]))

                            OO = ''
                            while diff >=1:
                                OO+='0'
                                diff-=1

                            try:
                                cycle_list[x] = OO+cycle_list[x]
                            except TypeError:
                                cycle_list[0] = OO+cycle_list[0]

        dat = []
        cycle_list.sort()

        cyclelist=np.array(list(map(int, cycle_list)))

        # cycles_requested is a list of indices from cyclelist
        # The index of the larges and smallest indices should be stored
        # in sorted order. As new requests are made if the requests
        # border or over lap then only keep the index of the larges and
        # smallest indices.
        cycles_requested = []

        # Sometimes bad data or last restart.h5 files contain no cycles,
        # causing the code to crash. Do a simple try/except here:
        file_min=[]
        file_max=[]
        try:
            for h5 in self.h5s:
                file_min.append(int(h5.cycle[0]))
                file_max.append(int(h5.cycle[-1]))
        except IndexError:
            print('File '+h5.filename+' contains no data, please remove or rename it')
            print('Once the file has been removed or renamed, the preprocessor file must be re-written. Do this by either removing the file h5Preproc.txt from the data directory or by invoking the se instance with rewrite=True')
            print('At present, h5T cannot check for empty files since the overhead using the mounted VOSpace would be too great.')
            raise IOError('Cycle-less file encountered')
        file_min.sort()
        file_max.sort()

        for h5 in self.h5s:
            #initalize file metadata
            min_file = int(h5.cycle[0])
            max_file = int(h5.cycle[-1])
            min_list = int(cyclelist[0])
            max_list = int(cyclelist[-1])
            index_min = None #if None start at begining
            index_max = None #if None finish at end

            # SJONES Now we need to add the case that the set only contains one file:
            if len(file_min) == 1:
                min_file = min_list - 1
                max_file = max_list + 1
            else:
                file_index = file_min.index(min_file)
                if file_index == 0:
                    if min_list - 1 < min_file:
                        min_file = min_list - 1
                    max_file = (file_min[file_index + 1] + max_file)//2
                elif file_index == len(file_min) - 1:
                    min_file = (file_max[file_index - 1] + min_file)//2 + 1
                    if max_list + 1 > max_file:
                        max_file = max_list + 1
                else:
                    min_file = (file_max[file_index - 1] + min_file)//2 + 1
                    max_file = (file_min[file_index + 1] + max_file)//2

            # calculate the left and right limits of the intersection
            # of the lists h5.cycle and cyclelist
            if (max_list < min_file) or (max_file < min_list):
            # the lists do not intersect
                continue
            elif (min_list <= min_file) and (max_file <= max_list):
                # all of h5.cycle is within cyclelist
                index_min = bisect.bisect_left(cyclelist, min_file)
                index_max = bisect.bisect_right(cyclelist, max_file)
            elif (min_file <= min_list) and (max_list <= max_file):
                # all of cyclelist is within h5.cycle
                index_min = None
                index_max = None
            else:
                if min_list > min_file:
                # cyclelist overlaps the right edge of h5.cycle
                    index_min = None
                    index_max = bisect.bisect_right(cyclelist, max_file)
                else:
                    # cyclelist overlaps the left edge of h5.cylce
                    index_min = bisect.bisect_left(cyclelist, min_file)
                    index_max = None

            # maintin list of all requested cycles by keeping trak of
            # the maximum and minimum indices
            imin = index_min
            if index_min == None:
                imin = 0

            imax = index_max
            if index_max == None:
                imax = len(cyclelist)

            request_min = bisect.bisect_left(cycles_requested, imin)
            request_max = bisect.bisect_right(cycles_requested, imax)

            # if the new request overlabs older request remove them
            del cycles_requested[request_min:request_max]
            if ((request_max-request_min) % 2) ==1:
                # new and old request overlaped on one edge only
                if request_min % 2 == 0:
                    # add new starting index
                    cycles_requested.insert(request_min, imin)
                else:
                    # add new ending index
                    cycles_requested.insert(request_min, imax)
            else:
                # new and old requests overlaped on two edges
                if request_min % 2 == 0:
                    # old request was contained with in new request
                    cycles_requested.insert(request_min, imin)
                    cycles_requested.insert(request_min + 1, imax)
                else:
                    # new request wat contained within old request
                    pass

            if not self.h5sStarted[self.h5s.index(h5)]:
                h5.start()
                h5.join()
                temp = h5.fetch_data_sam(dataitem,cycle_list[index_min:index_max],len(cycle_list),len(dat))
                self.h5sStarted[self.h5s.index(h5)]=True
            else:
                temp = h5.fetch_data_sam(dataitem,cycle_list[index_min:index_max],len(cycle_list),len(dat))

            temp_dat = []
            for temp_num, temp_cycle in enumerate(temp):
                temp_dataforcycle = []
                for dataitem_num, temp_dataitem in enumerate(temp_cycle):
                    # identify what cycle the temp data was collected from
                    temp_dataitem=self.red_dim(temp_dataitem)
#                    if option_ind == 3 and isotopes_of_interest != []:
                    if (dataitem[dataitem_num] == 'iso_massf' or dataitem[dataitem_num] == 'yps') and isotopes_of_interest != []:
                    #    Figure out the index
                        index = []
                        iso_tmp = []

                        if 'iso' in dataitem[dataitem_num]: #if we are looking at an isotope
                            iso_tmp = self.isotopes
                        else:
                            iso_tmp = self.elements

                        for iso in isotopes_of_interest: #finds the location of the isotope
                            x = iso_tmp.index(iso)
                            index.append(x)

                        if index == []:
                            # if none of the isotopes of interest are found
                            # then the index defaults to [0], so that the loop
                            # will still try to acess the data in t.
                            index = [0]
                        islist=True

                        if len(cycle_list)==1:
                            islist=False

#                        shellnb_index = 0
#                        if index_min == None:
#                            shellnb_index = temp_num
#                        else:
#                            shellnb_index = index_min + temp_num
                        temp_multicyc = []
                        for i in index:
#                            if islist:
#                                if shellnb[shellnb_index] == 1:    # again take care of 1-row 2D arrays
                                if shellnb == 1:    # again take care of 1-row 2D arrays
                                    temp_multicyc.append(temp_dataitem[i])
                                else:
                                    temp_multicyc.append(temp_dataitem[:,i])
#                            else:
#                                if shellnb == 1:    # again take care of 1-row 2D arrays
#                                    temp_multicyc.append(temp_dataitem[i])
#                                else:
#                                    temp_multicyc.append(temp_dataitem[:,i])
                        if len(temp_multicyc) == 1: # agian take care of 1-row arrays
                            temp_multicyc = temp_multicyc[0]
                        temp_dataitem = temp_multicyc
                    temp_dataforcycle.append(temp_dataitem)
                if len(temp_dataforcycle) == 1: # agian take care of 1-row arrays
                    temp_dataforcycle = temp_dataforcycle[0]
                # Now add the information to the list we pass back
                temp_dat.append(temp_dataforcycle)
            # calculate the proper insertion point for the data colected from
            # the file h5 in self.h5s
            insert_pnt = 0
            if index_min is not None: #alex: in py2: x < None == False
                for i in range(len(cycles_requested)):
                    if i % 2 == 1:
                        if cycles_requested[i] < index_min:
                            insert_pnt += cycles_requested[i] - cycles_requested[i-1]
                        elif cycles_requested[i - 1] < index_min:
                            insert_pnt += index_min - cycles_requested[i - 1]
            # insert the cycle data from the current file into the apropiat place
            # in the output data.
            dat[insert_pnt:insert_pnt] = temp_dat

        #check if cycles were not requested from the file
# SJONES comment
#        missing_cycles = np.array([])
#        if len(cycles_requested) != 2:
#            if len(cycles_requested) == 0:
#                missing_cycles = np.array([cycle_list])
#            else:
#                cycles_requested = [None] + cycles_requested + [None]
#                for i in xrange(0, len(cycles_requested), 2):
#                    min = cycles_requested[i]
#                    max = cycles_requested[i + 1]
#                    missing_cycles = np.append(missing_cycles, cycle_list[min:max])
#            print "The requested cycles: " + str(missing_cycles) + " are not available in this data set"
#        elif (cycles_requested[0] != 0) or (cycles_requested[1] != len(cyclelist)):
#            min = cycles_requested[0]
#            max = cycles_requested[1]
#            missing_cycles = np.append(missing_cycles, cycle_list[0:min])
#            missing_cycles = np.append(missing_cycles, cycle_list[max:])
#            print "The requested cycles: " + str(missing_cycles) + " are not available in this data set"

        if len(dat) < 2 and option_ind != 3 and (not nested_list):
            try:
                dat = dat[0]
            except IndexError:
                None
            except TypeError:
                None
        try:
            if len(dat) < 2 and isotopes_of_interest != []:
                dat = dat[0]
        except TypeError:
            None
        except IndexError:
            None
        t2=time.time()
        return dat

Response: Get the data from HDF5 files.


Instruction:
Here you have a function in Python 3, explain what it does
def _perform_request(self, request, parser=None, parser_args=None, operation_context=None):
        '''
        Sends the request and return response. Catches HTTPError and hands it
        to error handler
        '''
        operation_context = operation_context or _OperationContext()
        retry_context = RetryContext()
        retry_context.is_emulated = self.is_emulated

        # Apply the appropriate host based on the location mode
        self._apply_host(request, operation_context, retry_context)

        # Apply common settings to the request
        _update_request(request, self._X_MS_VERSION, self._USER_AGENT_STRING)
        client_request_id_prefix = str.format("Client-Request-ID={0}", request.headers['x-ms-client-request-id'])

        while True:
            try:
                try:
                    # Execute the request callback
                    if self.request_callback:
                        self.request_callback(request)

                    # Add date and auth after the callback so date doesn't get too old and
                    # authentication is still correct if signed headers are added in the request
                    # callback. This also ensures retry policies with long back offs
                    # will work as it resets the time sensitive headers.
                    _add_date_header(request)
                    self.authentication.sign_request(request)

                    # Set the request context
                    retry_context.request = request

                    # Log the request before it goes out
                    logger.info("%s Outgoing request: Method=%s, Path=%s, Query=%s, Headers=%s.",
                                client_request_id_prefix,
                                request.method,
                                request.path,
                                request.query,
                                str(request.headers).replace('\n', ''))

                    # Perform the request
                    response = self._httpclient.perform_request(request)

                    # Execute the response callback
                    if self.response_callback:
                        self.response_callback(response)

                    # Set the response context
                    retry_context.response = response

                    # Log the response when it comes back
                    logger.info("%s Receiving Response: "
                                "%s, HTTP Status Code=%s, Message=%s, Headers=%s.",
                                client_request_id_prefix,
                                self.extract_date_and_request_id(retry_context),
                                response.status,
                                response.message,
                                str(request.headers).replace('\n', ''))

                    # Parse and wrap HTTP errors in AzureHttpError which inherits from AzureException
                    if response.status >= 300:
                        # This exception will be caught by the general error handler
                        # and raised as an azure http exception
                        _http_error_handler(
                            HTTPError(response.status, response.message, response.headers, response.body))

                    # Parse the response
                    if parser:
                        if parser_args:
                            args = [response]
                            args.extend(parser_args)
                            return parser(*args)
                        else:
                            return parser(response)
                    else:
                        return
                except AzureException as ex:
                    retry_context.exception = ex
                    raise ex
                except Exception as ex:
                    retry_context.exception = ex
                    if sys.version_info >= (3,):
                        # Automatic chaining in Python 3 means we keep the trace
                        raise AzureException(ex.args[0])
                    else:
                        # There isn't a good solution in 2 for keeping the stack trace
                        # in general, or that will not result in an error in 3
                        # However, we can keep the previous error type and message
                        # TODO: In the future we will log the trace
                        msg = ""
                        if len(ex.args) > 0:
                            msg = ex.args[0]
                        raise AzureException('{}: {}'.format(ex.__class__.__name__, msg))

            except AzureException as ex:
                # only parse the strings used for logging if logging is at least enabled for CRITICAL
                if logger.isEnabledFor(logging.CRITICAL):
                    exception_str_in_one_line = str(ex).replace('\n', '')
                    status_code = retry_context.response.status if retry_context.response is not None else 'Unknown'
                    timestamp_and_request_id = self.extract_date_and_request_id(retry_context)

                logger.info("%s Operation failed: checking if the operation should be retried. "
                            "Current retry count=%s, %s, HTTP status code=%s, Exception=%s.",
                            client_request_id_prefix,
                            retry_context.count if hasattr(retry_context, 'count') else 0,
                            timestamp_and_request_id,
                            status_code,
                            exception_str_in_one_line)

                # Decryption failures (invalid objects, invalid algorithms, data unencrypted in strict mode, etc)
                # will not be resolved with retries.
                if str(ex) == _ERROR_DECRYPTION_FAILURE:
                    logger.error("%s Encountered decryption failure: this cannot be retried. "
                                 "%s, HTTP status code=%s, Exception=%s.",
                                 client_request_id_prefix,
                                 timestamp_and_request_id,
                                 status_code,
                                 exception_str_in_one_line)
                    raise ex

                # Determine whether a retry should be performed and if so, how
                # long to wait before performing retry.
                retry_interval = self.retry(retry_context)
                if retry_interval is not None:
                    # Execute the callback
                    if self.retry_callback:
                        self.retry_callback(retry_context)

                    logger.info(
                        "%s Retry policy is allowing a retry: Retry count=%s, Interval=%s.",
                        client_request_id_prefix,
                        retry_context.count,
                        retry_interval)

                    # Sleep for the desired retry interval
                    sleep(retry_interval)
                else:
                    logger.error("%s Retry policy did not allow for a retry: "
                                 "%s, HTTP status code=%s, Exception=%s.",
                                 client_request_id_prefix,
                                 timestamp_and_request_id,
                                 status_code,
                                 exception_str_in_one_line)
                    raise ex
            finally:
                # If this is a location locked operation and the location is not set,
                # this is the first request of that operation. Set the location to
                # be used for subsequent requests in the operation.
                if operation_context.location_lock and not operation_context.host_location:
                    # note: to cover the emulator scenario, the host_location is grabbed
                    # from request.host_locations(which includes the dev account name)
                    # instead of request.host(which at this point no longer includes the dev account name)
                    operation_context.host_location = {retry_context.location_mode: request.host_locations[retry_context.location_mode]}

Response: Perform a request and return the response. Catches HTTPError and hands it to error handler.


Instruction:
How would you implement a function in Python 3 that
plots a chart with fluxes Parameters ---------- file_name : string Name of the file of fluxes we are looking at. plotaxis : list [xmin, xmax, ymin, ymax], where on x axis there is neutron number and on y axis there is Z. plot_types : integer Set to 0 for standard flux plot. Set to 1 if fluxes focused on one specie. which_flux : integer, optional Set to 0 for nucleosynthesis flux plot. Set to 1 is for energy flux plot. Seting to None is the same a 0. The default is None. I_am_the_target : list, optional A 2xArray used only if plot_type=1, and is given by [neutron number, proton number]. The default is None. prange : integer, optional The range of fluxes to be considered. If prange is None, then 8 fluxes are consdered. The default is None. Notes ----- This script is terribly slow and needs to be improved. For now I put here in data_plot: [1]: import data_plot [2]: data_plot.flux_chart('file_name', [xmin, xmax, ymin, ymax], int, which_flux, I_am_the_target, prange) The pdf is created, but an error bumped up and the gui is empty. To avoid this, I had to set 'text.usetex': False. See below. Also, for the same reason no label in x axys is written using 'text.usetex': True. Note also that the GUI works really slow with this plot. So, we need to optimize from the graphic point of view. This need to be included in ppn.py I think, and set in multi option too, in case we want to read more flux files at the same time. Finally, you need to have stable.dat to read in to make it work ...

Response:
def flux_chart(file_name, plotaxis, plot_type, which_flux=None,
               I_am_the_target=None, prange=None):
    '''
    Plots a chart with fluxes

    Parameters
    ----------
    file_name : string
        Name of the file of fluxes we are looking at.
    plotaxis : list
        [xmin, xmax, ymin, ymax], where on x axis there is neutron
        number and on y axis there is Z.
    plot_types : integer
        Set to 0 for standard flux plot.  Set to 1 if fluxes focused
        on one specie.
    which_flux : integer, optional
        Set to 0 for nucleosynthesis flux plot.  Set to 1 is for energy
        flux plot.  Seting to None is the same a 0.  The default is
        None.
    I_am_the_target : list, optional
        A 2xArray used only if plot_type=1, and is given by [neutron
        number, proton number].  The default is None.
    prange : integer, optional
        The range of fluxes to be considered.  If prange is None, then
        8 fluxes are consdered.  The default is None.

    Notes
    -----
    This script is terribly slow and needs to be improved.  For now I
    put here in data_plot:

    [1]: import data_plot

    [2]: data_plot.flux_chart('file_name', [xmin, xmax, ymin, ymax],
                              int, which_flux, I_am_the_target, prange)

    The pdf is created, but an error bumped up and the gui is empty.
    To avoid this, I had to set 'text.usetex': False.  See below.  Also,
    for the same reason no label in x axys is written using
    'text.usetex': True.

    Note also that the GUI works really slow with this plot.  So, we
    need to optimize from the graphic point of view.  This need to be
    included in ppn.py I think, and set in multi option too, in case
    we want to read more flux files at the same time.

    Finally, you need to have stable.dat to read in to make it work ...

    '''

    import numpy as np
    import matplotlib.pyplot as plt
    #from matplotlib.mpl import colors,cm # deppreciated in mpl ver 1.3
                                          # use line below instead
    from matplotlib import colors,cm
    from matplotlib.patches import Rectangle, Arrow
    from matplotlib.collections import PatchCollection
    from matplotlib.offsetbox import AnchoredOffsetbox, TextArea
    import sys

    print_max_flux_in_plot =  True

    f = open(file_name)
    lines = f.readline()
    lines = f.readlines()
    f.close()

    # starting point of arrow
    coord_x_1 = []
    coord_y_1 = []
    # ending point of arrow (option 1)
    coord_x_2 = []
    coord_y_2 = []
    # ending point of arrow (option 2)
    coord_x_3 = []
    coord_y_3 = []
    # fluxes
    flux_read = []
    flux_log10 = []

    if which_flux == None or which_flux == 0:
        print('chart for nucleosynthesis fluxes [dYi/dt]')
        line_to_read = 9
    elif which_flux == 1:
        print('chart for energy fluxes')
        line_to_read = 10
    elif which_flux == 2:
        print('chart for timescales')
        line_to_read = 11
    elif which_flux > 2:
        print("you have only option 0, 1 or 2, not larger than 2")

    single_line = []
    for i in range(len(lines)):
        single_line.append(lines[i].split())
        coord_y_1.append(float(single_line[i][1]))
        coord_x_1.append(float(single_line[i][2])-coord_y_1[i])
        coord_y_2.append(float(single_line[i][5]))
        coord_x_2.append(float(single_line[i][6])-coord_y_2[i])
        coord_y_3.append(float(single_line[i][7]))
        coord_x_3.append(float(single_line[i][8])-coord_y_3[i])
        try:
            flux_read.append(float(single_line[i][line_to_read]))
        except ValueError: # this is done to avoid format issues like 3.13725-181...
            flux_read.append(1.0E-99)
        flux_log10.append(np.log10(flux_read[i]+1.0e-99))

    print('file read!')

    # I need to select smaller sample, with only fluxes inside plotaxis.
    coord_y_1_small=[]
    coord_x_1_small=[]
    coord_y_2_small=[]
    coord_x_2_small=[]
    coord_y_3_small=[]
    coord_x_3_small=[]
    flux_log10_small = []
    for i in range(len(flux_log10)):
        I_am_in = 0
        if coord_y_1[i] > plotaxis[2] and coord_y_1[i] < plotaxis[3] and coord_x_1[i] > plotaxis[0] and coord_x_1[i] < plotaxis[1]:
            I_am_in = 1
            coord_y_1_small.append(coord_y_1[i])
            coord_x_1_small.append(coord_x_1[i])
            coord_y_2_small.append(coord_y_2[i])
            coord_x_2_small.append(coord_x_2[i])
            coord_y_3_small.append(coord_y_3[i])
            coord_x_3_small.append(coord_x_3[i])
            flux_log10_small.append(flux_log10[i])
        if coord_y_3[i] > plotaxis[2] and coord_y_3[i] < plotaxis[3] and coord_x_3[i] > plotaxis[0] and coord_x_3[i] < plotaxis[1] and I_am_in == 0:
            I_am_in = 1
            coord_y_1_small.append(coord_y_1[i])
            coord_x_1_small.append(coord_x_1[i])
            coord_y_2_small.append(coord_y_2[i])
            coord_x_2_small.append(coord_x_2[i])
            coord_y_3_small.append(coord_y_3[i])
            coord_x_3_small.append(coord_x_3[i])
            flux_log10_small.append(flux_log10[i])

    if plot_type == 1:
        print('I_am_the_target=',I_am_the_target)
        #I_am_the_target = [56.-26.,26.]
    # here below need for plotting
    # plotaxis = [xmin,xmax,ymin,ymax]
    #plotaxis=[1,20,1,20]
    #plotaxis=[0,0,0,0]

    # elemental labels off/on [0/1]
    ilabel = 1

    # label for isotopic masses off/on [0/1]
    imlabel = 1

    # turn lines for magic numbers off/on [0/1]
    imagic = 0

    # flow is plotted over "prange" dex. If flow < maxflow-prange it is not plotted
    if prange == None:
        print('plot range given by default')
        prange = 8.

    #############################################

    # we should scale prange on plot_axis range, not on max_flux!
    max_flux = max(flux_log10)
    ind_max_flux = flux_log10.index(max_flux)
    max_flux_small = max(flux_log10_small)
    min_flux = min(flux_log10)
    ind_min_flux = flux_log10.index(min_flux)
    min_flux_small = min(flux_log10_small)

    #nzmax = int(max(max(coord_y_1),max(coord_y_2),max(coord_y_3)))+1
    #nnmax = int(max(max(coord_x_1),max(coord_x_2),max(coord_x_3)))+1
    nzmax = int(max(max(coord_y_1_small),max(coord_y_2_small),max(coord_y_3_small)))+1
    nnmax = int(max(max(coord_x_1_small),max(coord_x_2_small),max(coord_x_3_small)))+1

    nzycheck = np.zeros([nnmax,nzmax,3])
    #coord_x_out = np.zeros(len(coord_x_2))
    #coord_y_out = np.zeros(len(coord_y_2))
    #for i in range(len(flux_log10)):
    #       nzycheck[coord_x_1[i],coord_y_1[i],0] = 1
    #       nzycheck[coord_x_1[i],coord_y_1[i],1] = flux_log10[i]
    #       if coord_x_2[i] >= coord_x_3[i]:
    #                coord_x_out[i] = coord_x_2[i]
    #                coord_y_out[i] = coord_y_2[i]
    #               nzycheck[coord_x_out[i],coord_y_out[i],0] = 1
    #               nzycheck[coord_x_out[i],coord_y_out[i],1] = flux_log10[i]
    #        elif coord_x_2[i] < coord_x_3[i]:
    #                coord_x_out[i] = coord_x_3[i]
    #                coord_y_out[i] = coord_y_3[i]
    #               nzycheck[coord_x_out[i],coord_y_out[i],0] = 1
    #               nzycheck[coord_x_out[i],coord_y_out[i],1] = flux_log10[i]
    #       if flux_log10[i]>max_flux-prange:
    #               nzycheck[coord_x_1[i],coord_y_1[i],2] = 1
    #               nzycheck[coord_x_out[i],coord_y_out[i],2] = 1
    coord_x_out = np.zeros(len(coord_x_2_small))
    coord_y_out = np.zeros(len(coord_y_2_small))
    for i in range(len(flux_log10_small)):
        nzycheck[coord_x_1_small[i],coord_y_1_small[i],0] = 1
        nzycheck[coord_x_1_small[i],coord_y_1_small[i],1] = flux_log10_small[i]
        if coord_x_2_small[i] >= coord_x_3_small[i]:
            coord_x_out[i] = coord_x_2_small[i]
            coord_y_out[i] = coord_y_2_small[i]
            nzycheck[coord_x_out[i],coord_y_out[i],0] = 1
            nzycheck[coord_x_out[i],coord_y_out[i],1] = flux_log10_small[i]
        elif coord_x_2_small[i] < coord_x_3_small[i]:
            coord_x_out[i] = coord_x_3_small[i]
            coord_y_out[i] = coord_y_3_small[i]
            nzycheck[coord_x_out[i],coord_y_out[i],0] = 1
            nzycheck[coord_x_out[i],coord_y_out[i],1] = flux_log10_small[i]
        if which_flux == None or which_flux < 2 and flux_log10_small[i]>max_flux_small-prange:
            nzycheck[coord_x_1_small[i],coord_y_1_small[i],2] = 1
            nzycheck[coord_x_out[i],coord_y_out[i],2] = 1
        elif which_flux == 2 and flux_log10_small[i]<min_flux_small+prange:
            nzycheck[coord_x_1_small[i],coord_y_1_small[i],2] = 1
            nzycheck[coord_x_out[i],coord_y_out[i],2] = 1

    #######################################################################
    # elemental names: elname(i) is the name of element with Z=i
    elname= ('none','H','He','Li','Be','B','C','N','O','F','Ne','Na','Mg','Al','Si','P','S','Cl','Ar','K','Ca','Sc','Ti','V','Cr','Mn','Fe',
    'Co','Ni','Cu','Zn','Ga','Ge','As','Se','Br','Kr','Rb','Sr','Y','Zr','Nb','Mo','Tc','Ru','Rh','Pd','Ag','Cd','In','Sn','Sb',
    'Te', 'I','Xe','Cs','Ba','La','Ce','Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu','Hf','Ta','W','Re','Os',
    'Ir','Pt','Au','Hg','Tl','Pb','Bi','Po','At','Rn','Fr','Ra','Ac','Th','Pa','U','Np','Pu')

    #### create plot

    ## define axis and plot style (colormap, size, fontsize etc.)
    if plotaxis==[0,0,0,0]:
        xdim=10
        ydim=6
    else:
        dx = plotaxis[1]-plotaxis[0]
        dy = plotaxis[3]-plotaxis[2]
        ydim = 6
        xdim = ydim*dx/dy

    format = 'pdf'
    # note that I had to set 'text.usetex': False, to avoid Exception in Tkinter callback.
    # and to make the GUI work properly. Why? some missing package?
    params = {'axes.labelsize':  15,
      'text.fontsize':   15,
      'legend.fontsize': 15,
      'xtick.labelsize': 15,
      'ytick.labelsize': 15,
      'text.usetex': False}
    plt.rcParams.update(params)
    fig=plt.figure(figsize=(xdim,ydim),dpi=100)
    axx = 0.10
    axy = 0.10
    axw = 0.85
    axh = 0.8
    ax=plt.axes([axx,axy,axw,axh])

    # color map choice for abundances
    cmapa = cm.jet
    # color map choice for arrows
    if which_flux == None or which_flux < 2:
        cmapr = cm.autumn
    elif  which_flux == 2:
        cmapr = cm.autumn_r
    # if a value is below the lower limit its set to white
    cmapa.set_under(color='w')
    cmapr.set_under(color='w')
    # set value range for abundance colors (log10(Y))
    norma = colors.Normalize(vmin=-20,vmax=0)
    # set x- and y-axis scale aspect ratio to 1
    ax.set_aspect('equal')
    #print time,temp and density on top
    #temp = '%8.3e' %ff['temp']
    #time = '%8.3e' %ff['time']
    #dens = '%8.3e' %ff['dens']

    #box1 = TextArea("t : " + time + " s~~/~~T$_{9}$ : " + temp + "~~/~~$\\rho_{b}$ : " \
    #      + dens + ' g/cm$^{3}$', textprops=dict(color="k"))
    #anchored_box = AnchoredOffsetbox(loc=3,
    #        child=box1, pad=0.,
    #        frameon=False,
    #        bbox_to_anchor=(0., 1.02),
    #        bbox_transform=ax.transAxes,
    #        borderpad=0.,
    #        )
    #ax.add_artist(anchored_box)

    # Add black frames for stable isotopes
    f = open('stable.dat')

    head = f.readline()
    stable = []

    for line in f.readlines():
        tmp = line.split()
        zz = int(tmp[2])
        nn = int(tmp[3])
        xy = nn-0.5,zz-0.5
        rect = Rectangle(xy,1,1,ec='k',fc='None',fill='False',lw=3.)
        rect.set_zorder(2)
        ax.add_patch(rect)

    apatches = []
    acolor = []
    m = old_div(0.8,prange)#0.8/prange
    if which_flux == None or which_flux < 2:
        vmax=np.ceil(max(flux_log10_small))
        vmin=max(flux_log10_small)-prange
        b=-vmin*m+0.1
    elif which_flux == 2:
        vmin=min(flux_log10_small)
        vmax=np.ceil(min(flux_log10_small)+prange)
        b=vmax*m+0.1
    if which_flux == None or which_flux < 3:
        normr = colors.Normalize(vmin=vmin,vmax=vmax)
        print('vmin and vmax =',vmin,vmax)
    ymax=0.
    xmax=0.

    for i in range(len(flux_log10_small)):
        x = coord_x_1_small[i]
        y = coord_y_1_small[i]
        dx = coord_x_out[i]-coord_x_1_small[i]
        dy = coord_y_out[i]-coord_y_1_small[i]
        if plot_type == 0:
            if which_flux == None or which_flux < 2:
                if flux_log10_small[i]>=vmin:
                    arrowwidth = flux_log10_small[i]*m+b
                    arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                    if xmax<x:
                        xmax=x
                    if ymax<y:
                        ymax=y
                    acol = flux_log10_small[i]
                    apatches.append(arrow)
                    acolor.append(acol)
            elif which_flux == 2:
                if flux_log10_small[i]<=vmax:
                    arrowwidth = -flux_log10_small[i]*m+b
                    arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                    if xmax<x:
                        xmax=x
                    if ymax<y:
                        ymax=y
                    acol = flux_log10_small[i]
                    apatches.append(arrow)
                    acolor.append(acol)
        elif plot_type == 1 and which_flux != 2:
            if x==I_am_the_target[0] and y==I_am_the_target[1] and flux_log10_small[i]>=vmin:
                arrowwidth = flux_log10_small[i]*m+b
                arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                if xmax<x:
                    xmax=x
                if ymax<y:
                    ymax=y
                acol = flux_log10_small[i]
                apatches.append(arrow)
                acolor.append(acol)
            if x+dx==I_am_the_target[0] and y+dy==I_am_the_target[1] and flux_log10_small[i]>=vmin:
                arrowwidth = flux_log10_small[i]*m+b
                arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                if xmax<x:
                    xmax=x
                if ymax<y:
                    ymax=y
                acol = flux_log10_small[i]
                apatches.append(arrow)
                acolor.append(acol)
        elif plot_type == 1 and which_flux == 2:
            if x==I_am_the_target[0] and y==I_am_the_target[1] and flux_log10_small[i]<=vmax:
                arrowwidth = -flux_log10_small[i]*m+b
                arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                if xmax<x:
                    xmax=x
                if ymax<y:
                    ymax=y
                acol = flux_log10_small[i]
                apatches.append(arrow)
                acolor.append(acol)
            if x+dx==I_am_the_target[0] and y+dy==I_am_the_target[1] and flux_log10_small[i]<=vmax:
                arrowwidth = -flux_log10_small[i]*m+b
                arrow = Arrow(x,y,dx,dy, width=arrowwidth)
                if xmax<x:
                    xmax=x
                if ymax<y:
                    ymax=y
                acol = flux_log10_small[i]
                apatches.append(arrow)
                acolor.append(acol)

    #apatches = []
    #acolor = []
    #m = 0.8/prange
    #vmax=np.ceil(max(flux_log10))
    #vmin=max(flux_log10)-prange
    #b=-vmin*m+0.1
    #normr = colors.Normalize(vmin=vmin,vmax=vmax)
    #ymax=0.
    #xmax=0.

    #for i in range(len(flux_log10)):
    #       x = coord_x_1[i]
    #       y = coord_y_1[i]
    #       dx = coord_x_out[i]-coord_x_1[i]
    #       dy = coord_y_out[i]-coord_y_1[i]
    #       if plot_type == 0:
    #               if flux_log10[i]>=vmin:
    #                       arrowwidth = flux_log10[i]*m+b
    #                       arrow = Arrow(x,y,dx,dy, width=arrowwidth)
    #                       if xmax<x:
    #                               xmax=x
    #                       if ymax<y:
    #                               ymax=y
    #                       acol = flux_log10[i]
    #                       apatches.append(arrow)
    #                       acolor.append(acol)
    #       elif plot_type == 1:
    #               if x==I_am_the_target[0] and y==I_am_the_target[1] and flux_log10[i]>=vmin:
    #                       arrowwidth = flux_log10[i]*m+b
    #                       arrow = Arrow(x,y,dx,dy, width=arrowwidth)
    #                       if xmax<x:
    #                               xmax=x
    #                       if ymax<y:
    #                               ymax=y
    #                       acol = flux_log10[i]
    #                       apatches.append(arrow)
    #                       acolor.append(acol)
    #               if x+dx==I_am_the_target[0] and y+dy==I_am_the_target[1] and flux_log10[i]>=vmin:
    #                       arrowwidth = flux_log10[i]*m+b
    #                       arrow = Arrow(x,y,dx,dy, width=arrowwidth)
    #                       if xmax<x:
    #                               xmax=x
    #                       if ymax<y:
    #                               ymax=y
    #                       acol = flux_log10[i]
    #                       apatches.append(arrow)
    #                       acolor.append(acol)
    #

        xy = x-0.5,y-0.5
        rect = Rectangle(xy,1,1,ec='k',fc='None',fill='False',lw=1.)
        rect.set_zorder(2)
        ax.add_patch(rect)
        xy = x+dx-0.5,y+dy-0.5
        rect = Rectangle(xy,1,1,ec='k',fc='None',fill='False',lw=1.)
        rect.set_zorder(2)
        ax.add_patch(rect)

    a = PatchCollection(apatches, cmap=cmapr, norm=normr)
    a.set_array(np.array(acolor))
    a.set_zorder(3)
    ax.add_collection(a)
    cb = plt.colorbar(a)

    # colorbar label
    if which_flux == None or which_flux == 0:
        cb.set_label('log$_{10}$(f)')
    elif which_flux ==1:
        cb.set_label('log$_{10}$(E)')
    elif which_flux ==2:
        cb.set_label('log$_{10}$(timescale)')

    # plot file name
    graphname = 'flow-chart.'+format

    # decide which array to take for label positions
    iarr = 2

    # plot element labels
    for z in range(nzmax):
        try:
            nmin = min(np.argwhere(nzycheck[:,z,iarr-2]))[0]-1
            ax.text(nmin,z,elname[z],horizontalalignment='center',verticalalignment='center',fontsize='medium',clip_on=True)
        except ValueError:
            continue

    # plot mass numbers
    if imlabel==1:
        for z in range(nzmax):
            for n in range(nnmax):
                a = z+n
                if nzycheck[n,z,iarr-2]==1:
                    ax.text(n,z,a,horizontalalignment='center',verticalalignment='center',fontsize='small',clip_on=True)

    # plot lines at magic numbers
    if imagic==1:
        ixymagic=[2, 8, 20, 28, 50, 82, 126]
        nmagic = len(ixymagic)
        for magic in ixymagic:
            if magic<=nzmax:
                try:
                    xnmin = min(np.argwhere(nzycheck[:,magic,iarr-2]))[0]
                    xnmax = max(np.argwhere(nzycheck[:,magic,iarr-2]))[0]
                    line = ax.plot([xnmin,xnmax],[magic,magic],lw=3.,color='r',ls='-')
                except ValueError:
                    dummy=0
            if magic<=nnmax:
                try:
                    yzmin = min(np.argwhere(nzycheck[magic,:,iarr-2]))[0]
                    yzmax = max(np.argwhere(nzycheck[magic,:,iarr-2]))[0]
                    line = ax.plot([magic,magic],[yzmin,yzmax],lw=3.,color='r',ls='-')
                except ValueError:
                    dummy=0

    # set axis limits
    if plotaxis==[0,0,0,0]:
        ax.axis([-0.5,xmax+0.5,-0.5,ymax+0.5])
    else:
        ax.axis(plotaxis)

    # set x- and y-axis label
    ax.set_xlabel('neutron number')
    ax.set_ylabel('proton number')
    if which_flux == None or which_flux == 0:
        max_flux_label="max flux = "+str('{0:.4f}'.format(max_flux))
    elif which_flux == 1:
        max_flux_label="max energy flux = "+str('{0:.4f}'.format(max_flux))
    elif which_flux == 2:
        min_flux_label="min timescale [s] = "+str('{0:.4f}'.format(min_flux))
    if print_max_flux_in_plot:
        if which_flux == None or which_flux < 2:
            ax.text(plotaxis[1]-1.8,plotaxis[2]+0.1,max_flux_label,fontsize=10.)
        elif which_flux == 2:
            ax.text(plotaxis[1]-1.8,plotaxis[2]+0.1,min_flux_label,fontsize=10.)

    fig.savefig(graphname)
    print(graphname,'is done')
    if which_flux == None or which_flux < 2:
        print(max_flux_label,'for reaction =',ind_max_flux+1)
    elif which_flux == 2:
        print(min_flux_label,'for reaction =',ind_min_flux+1)

    plt.show()


Instruction:
Explain what the following Python 3 code does
def _sparse(self, x, y, sparse):
        tmpX=[]
        tmpY=[]

        for i in range(len(x)):
            if sparse == 1:
                return x,y
            if (i%sparse)==0:
                tmpX.append(x[i])
                tmpY.append(y[i])
        return tmpX, tmpY

Response: Method that removes every non - sparse th element from the list x and y.


Instruction:
Can you tell what is the following Python 3 function doing
def plotMulti(self, atrix, atriy, cyclist, title, path='/',
                  legend=None, labelx=None, labely=None, logx=False,
                  logy=False, base=10, sparse=1, pdf=False,
                  limits=None):
        '''
        Method for plotting multiple plots and saving it to multiple
        pngs or PDFs.

        Parameters
        ----------
        atrix : string
            The name of the attribute you want on the x axis.
        atriy : string
            The name of the attribute you want on the Y axis.
        cyclist : list
            List of cycles that you would like plotted.
        title : string
            The title of the graph and the name of the file.
        path : string, optional
            The file path. The default is '/'
        Legend : list or intager, optional
            A list of legends for each of your cycles, or one legend for
            all of the cycles. The default is None.
        labelx : string, optional
            The label on the X axis. The default is None.
        labely : string, optional
            The label on the Y axis. The default is None.
        logx : boolean, optional
            A boolean of whether the user wants the x axis
            logarithmically. The default is False.
        logy : boolean, optional
            A boolean of whether the user wants the Y axis
            logarithmically. The default is False.
        base : integer, optional
            The base of the logarithm. The default is 10.
        sparse : integer, optional
            Argument that skips every so many data points.  For example
            if this argument was 5, This method would plot the 0th,
            5th, 10th ... elements. The default is 1.
        pdf : boolean, optional
            A boolean of if the image should be saved to a pdf file.
            xMin, xMax, yMin, YMax:  plot coordinates.  The default is
            False.
        limits : list, optional
            The length four list of the x and y limits.  The order of
            the list is xmin, xmax, ymin, ymax. The default is None.

        '''
        if str(legend.__class__)!="<type 'list'>":# Determines the legend is a list
            legendList=False
        else:
            legendList=True

        if legendList and len(cyclist) !=len(legend): #if it is a list, make sure there is an entry for each cycle
            print('Please input a proper legend, with correct length, aborting plot')
            return None
        for i in range(len(cyclist)):
            if legendList:
                self.plot(atrix,atriy,cyclist[i],'ndump',legend[i],labelx,labely,base=base,sparse=sparse, \
                                  logx=logx,logy=logy,show=False,limits=limits)
            else:
                self.plot(atrix,atriy,cyclist[i],'ndump',legend,labelx,labely,base=base,sparse=sparse, \
                                  logx=logx,logy=logy,show=False,limits=limits)

            pl.title(title)
            if not pdf:
                currentDir = os.getcwd()
                os.chdir(path)
                pl.savefig(title+str(cyclist[i])+'.png', dpi=400)
                os.chdir(currentDir)
            else:
                currentDir = os.getcwd()
                os.chdir(path)
                pl.savefig(title+str(cyclist[i])+'.pdf', dpi=400)
                os.chdir(currentDir)
            pl.clf()
        return None

Response: Method for plotting multiple plots and saving it to multiple PDFs.