Issue #1916. Added isgenerator() and isgeneratorfunction() to
inspect.py.  Thanks Javi Mansilla for patch review and
corrections.
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 8ae50fc..42f2c31 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -7,8 +7,9 @@
 
 Here are some of the useful functions provided by this module:
 
-    ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
-        isframe(), iscode(), isbuiltin(), isroutine() - check object types
+    ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
+        isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
+        isroutine() - check object types
     getmembers() - get members of an object that satisfy a given condition
 
     getfile(), getsourcefile(), getsource() - find an object's source code
@@ -28,9 +29,19 @@
 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
 __date__ = '1 Jan 2001'
 
-import sys, os, types, string, re, dis, imp, tokenize, linecache
+import sys
+import os
+import types
+import string
+import re
+import dis
+import imp
+import tokenize
+import linecache
 from operator import attrgetter
 from collections import namedtuple
+from compiler.consts import (CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS,
+    CO_VARKEYWORDS, CO_GENERATOR)
 
 # ----------------------------------------------------------- type-checking
 def ismodule(object):
@@ -137,6 +148,33 @@
         func_name       (same as __name__)"""
     return isinstance(object, types.FunctionType)
 
+def isgeneratorfunction(object):
+    """Return true if the object is a user-defined generator function.
+
+    Generator function objects provides same attributes as functions.
+
+    See isfunction.__doc__ for attributes listing."""
+    if (isfunction(object) or ismethod(object)) and \
+        object.func_code.co_flags & CO_GENERATOR:
+        return True
+
+def isgenerator(object):
+    """Return true if the object is a generator.
+
+    Generator objects provide these attributes:
+        __iter__        defined to support interation over container
+        close           raises a new GeneratorExit exception inside the
+                        generator to terminate the iteration
+        gi_code         code object
+        gi_frame        frame object or possibly None once the generator has
+                        been exhausted
+        gi_running      set to 1 when generator is executing, 0 otherwise
+        next            return the next item from the container
+        send            resumes the generator and "sends" a value that becomes
+                        the result of the current yield-expression
+        throw           used to raise an exception inside the generator"""
+    return isinstance(object, types.GeneratorType)
+
 def istraceback(object):
     """Return true if the object is a traceback.
 
@@ -199,6 +237,10 @@
             or ismethod(object)
             or ismethoddescriptor(object))
 
+def isgenerator(object):
+    """Return true if the object is a generator object."""
+    return isinstance(object, types.GeneratorType)
+
 def getmembers(object, predicate=None):
     """Return all members of an object as (name, value) pairs sorted by name.
     Optionally, only return members that satisfy a given predicate."""
@@ -671,9 +713,6 @@
     return walktree(roots, children, None)
 
 # ------------------------------------------------ argument list extraction
-# These constants are from Python's compile.h.
-CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
-
 Arguments = namedtuple('Arguments', 'args varargs keywords')
 
 def getargs(co):