{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Iterable Operation Extensions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<--- Back"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Table of Contents for this notebook\n",
    "\n",
    "- [The Iterable Operation Extensions](#The-Iterable-Operation-Extensions)\n",
    "- [Table of Contents for this notebook](#Table-of-Contents-for-this-notebook)\n",
    "- [Overview](#Overview)\n",
    "- [IterEnumerateInstances](#IterEnumerateInstances)\n",
    "- [IterEnumerateInstancePaths](#IterEnumerateInstancePaths)\n",
    "- [IterAssociatorInstances](#IterAssociatorInstances)\n",
    "- [IterAssociatorInstancePaths](#IterAssociatorInstancePaths)\n",
    "- [IterReferenceInstances](#IterReferenceInstances)\n",
    "- [IterReferenceInstancePaths](#IterReferenceInstancePaths)\n",
    "- [IterQueryInstances](#IterQueryInstances)\n",
    "- [Using list comprehensions with iter operations](#Using-list-comprehensions-with-iter-operations)\n",
    "- [Using iter operations and forcing the use of traditional operations](#Using-iter-operations-and-forcing-the-use-of-traditional-operations)\n",
    "- [Using iter operations and forcing the use of pull operations](#Using-iter-operations-and-forcing-the-use-of-pull-operations)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The iterable operation extensions (short: *iter operations*) are a set of methods added to [`pywbem.WBEMConnection`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection) class in pywbem version 0.10.0 to simplify the use of the pull vs. traditional operations (the original enumeration operations such as EnumerateInstances).\n",
    "\n",
    "They simplify executing instance enumerations (EnumerateInstances, Associators, and References) by merging the traditional operations and pull operations so the client developer only has to code the iter operations and the Pywbem environment uses the Pull or traditional operations based on the server characteristics.\n",
    "\n",
    "The purpose and function and usage of these WBEMConnection methods is defined in the [`Concepts section`] (https://pywbem.readthedocs.io/en/latest/concepts.html#iter-operations) of the online pywbem documentation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## IterEnumerateInstances"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterEnumerateInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterEnumerateInstances) method requests the instances of a class from the server. It uses either the [`OpenEnumerateInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenEnumerateInstances) if the server supports it or otherwise [`EnumerateInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstances).\n",
    "\n",
    "The operation returns an iterator for instances, that is being processed in a for-loop."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pywbem\n",
    "\n",
    "# Global variables used by all examples:\n",
    "server = 'http://localhost'\n",
    "username = 'user'\n",
    "password = 'password'\n",
    "namespace = 'root/cimv2'\n",
    "\n",
    "classname = 'CIM_ComputerSystem'\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    inst_iterator = conn.IterEnumerateInstances(classname,\n",
    "                                                MaxObjectCount=max_obj_cnt)\n",
    "    for inst in inst_iterator:\n",
    "        print('path=%s' % inst.path)\n",
    "        print(inst.tomof())\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example (and the examples below), the connection has a default namespace set. This allows us to omit the namespace from the subsequent [`IterEnumerateInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterEnumerateInstances) method.\n",
    "\n",
    "This example and the following examples also shows exception handling with pywbem: Pywbem wraps any exceptions that are considered runtime errors, and raises them as subclasses of [`pywbem.Error`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.Error). Any other exceptions are considered programming errors. Therefore, the code above only needs to catch [`pywbem.Error`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.Error).\n",
    "\n",
    "Note that the creation of the [`pywbem.WBEMConnection`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection) object in the code above does not need to be protected by exception handling; its initialization code does not raise any pywbem runtime errors."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## IterEnumerateInstancePaths"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterEnumerateInstancePaths()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterEnumerateInstancePaths) method requests the instance paths of the instances of a class from the server. It uses either the [`OpenEnumerateInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenEnumerateInstancePaths) if the server supports it or otherwise [`EnumerateInstanceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstanceNames).\n",
    "\n",
    "The operation returns an iterator for instance paths, that is being processed in a for-loop:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    path_iterator = conn.IterEnumerateInstancePaths(classname,\n",
    "                                                    MaxObjectCount=max_obj_cnt)\n",
    "    for path in path_iterator:\n",
    "        print('path=%s' % path)\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## IterAssociatorInstances"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterAssociatorInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterAssociatorInstances) method requests the instances associated with a source instance from the server. It uses either the [`OpenAssociatorInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenAssociatorInstances) if the server supports it or otherwise [`Associators()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.Associators).\n",
    "\n",
    "The operation returns an iterator for instances, that is being processed in a for-loop.\n",
    "\n",
    "The following code executes [`EnumerateInstanceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstanceNames) to enumerate instances of a class and selects the first instance to act as a source instance for the association operation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    # Find an instance path for the source end of an association.\n",
    "    source_paths = conn.EnumerateInstanceNames(classname)\n",
    "    if source_paths:\n",
    "        inst_iterator = conn.IterAssociatorInstances(source_paths[0],\n",
    "                                                     MaxObjectCount=max_obj_cnt)\n",
    "        for inst in inst_iterator:\n",
    "            print('path=%s' % inst.path)\n",
    "            print(inst.tomof())\n",
    "    else:\n",
    "        print('%s class has no instances and therefore no associations', classname)\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## IterAssociatorInstancePaths"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterAssociatorInstancePaths()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterAssociatorInstancePaths) method requests the instance paths of the instances associated with a source instance from the server. It uses either the [`OpenAssociatorInstancePaths()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenAssociatorInstancePaths) if the server supports it or otherwise [`AssociatorNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.AssociatorNames).\n",
    "\n",
    "The operation returns an iterator for instance paths, that is being processed in a for-loop.\n",
    "\n",
    "The following code executes [`EnumerateInstanceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstanceNames) to enumerate instances of a class and selects the first instance to act as a source instance for the association operation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    # Find an instance path for the source end of an association.\n",
    "    source_paths = conn.EnumerateInstanceNames(classname)\n",
    "    if source_paths:\n",
    "        path_iterator = conn.IterAssociatorInstancePaths(source_paths[0],\n",
    "                                                         MaxObjectCount=max_obj_cnt)\n",
    "        for path in path_iterator:\n",
    "            print('path=%s' % path)\n",
    "    else:\n",
    "        print('%s class has no instances and therefore no instance associations', classname)\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## IterReferenceInstances"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterReferenceInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterReferenceInstances) method requests the instances referencing a source instance from the server. It uses either the [`OpenReferenceInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenReferenceInstances) if the server supports it or otherwise [`References()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.References).\n",
    "\n",
    "The operation returns an iterator for instances, that is being processed in a for-loop.\n",
    "\n",
    "The following code executes [`EnumerateInstanceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstanceNames) to enumerate instances of a class and selects the first instance to act as a source instance for the reference operation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    # Find an instance path for the source end of an association.\n",
    "    source_paths = conn.EnumerateInstanceNames(classname)\n",
    "    if source_paths:\n",
    "        inst_iterator = conn.IterAssociatorInstances(source_paths[0],\n",
    "                                                     MaxObjectCount=max_obj_cnt)\n",
    "        for instance in inst_iterator:\n",
    "            print('path=%s' % inst.path)\n",
    "            print(inst.tomof())\n",
    "    else:\n",
    "        print('%s class has no instances and therefore no instance associations', classname)\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## IterReferenceInstancePaths"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterReferenceInstancePaths()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterReferenceInstancePaths) method requests the instance paths of the instances referencing a source instance from the server. It uses either the [`OpenReferenceInstancePaths()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenReferenceInstances) if the server supports it or otherwise [`ReferenceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.ReferenceNames).\n",
    "\n",
    "The operation returns an iterator for instance paths, that is being processed in a for-loop.\n",
    "\n",
    "The following code executes [`EnumerateInstanceNames()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.EnumerateInstanceNames) to enumerate instances of a class and selects the first instance to act as a source instance for the reference operation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    # Find an instance path for the source end of an association.\n",
    "    source_paths = conn.EnumerateInstanceNames(classname)\n",
    "    if source_paths:\n",
    "        path_iterator = conn.IterReferenceInstancePaths(source_paths[0],\n",
    "                                                        MaxObjectCount=max_obj_cnt)\n",
    "        for path in path_iterator:\n",
    "            print('path=%s' % path)\n",
    "    else:\n",
    "        print('%s class has no instances and therefore no instance associations', classname)\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## IterQueryInstances"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The [`IterQueryInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.IterQueryInstances) method requests the instances returned by a query from the server. It uses either the [`OpenQueryInstances()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.OpenQueryInstances) if the server supports it or otherwise [`ExecQuery()`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection.ExecQuery).\n",
    "\n",
    "This operation returns an object with two properties: \n",
    "\n",
    "1. `query_result_class` (CIMClass): The query result class, if requested via the `ReturnQueryResultClass` parameter which is only used with the [`OpenQueryInstances()`]​ operation and is not available with the [`ExecQuery()`] operation. None, if a query result class was not requested.\n",
    "\n",
    "2. `generator` - A generator object that allows the user to iterate the CIM instances representing the query result. These instances do not have an instance path set.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "query_language = \"DMTF:CQL\"\n",
    "query = 'Select * from Pywbem_Person'\n",
    "max_obj_cnt = 10\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "try:\n",
    "    inst_result = conn.IterQueryInstances(query_language, query,\n",
    "                                            MaxObjectCount=max_obj_cnt)\n",
    "    for inst in inst_result.generator:\n",
    "        print(inst.tomof())\n",
    "    else:\n",
    "        print('query has no result')\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Using list comprehensions with iter operations\n",
    "\n",
    "As an alternative to the for-loop processing of the iterator returned by the `Iter...()` method, a list comprehension can be use to perform the entire processing sequence in a single statement:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True)\n",
    "\n",
    "try:\n",
    "    paths = [path for path in conn.IterEnumerateInstancePaths(classname,\n",
    "                                                              MaxObjectCount=max_obj_cnt)]\n",
    "    print(*paths, sep='\\n')\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Using iter operations and forcing the use of traditional operations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The following example forces the use of the traditional operations by setting the `use_pull_operations` flag on the connection to `False`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True,\n",
    "                             use_pull_operations=False)\n",
    "\n",
    "try:\n",
    "    inst_iterator = conn.IterEnumerateInstances(classname,\n",
    "                                                MaxObjectCount=max_obj_cnt)\n",
    "    for inst in inst_iterator:\n",
    "        print('path=%s' % inst.path)\n",
    "        print(inst.tomof())\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using iter operations and forcing the use of pull operations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The following example forces the use of the pull operations by setting the `use_pull_operations` flag on the connection to `True`. If the server does not support pull operations an exception \"CIM_ERR_NOT_SUPPORTED\" will be returned."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global variables from first example are used\n",
    "\n",
    "max_obj_cnt = 100\n",
    "\n",
    "conn = pywbem.WBEMConnection(server, (username, password),\n",
    "                             default_namespace=namespace,\n",
    "                             no_verification=True,\n",
    "                             use_pull_operations=True)\n",
    "\n",
    "try:\n",
    "    inst_iterator = conn.IterEnumerateInstances(classname,\n",
    "                                                MaxObjectCount=max_obj_cnt)\n",
    "    for inst in inst_iterator:\n",
    "        print('path=%s' % inst.path)\n",
    "        print(inst.tomof())\n",
    "except pywbem.Error as exc:\n",
    "    print('Operation failed: %s' % exc)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
