[Python-checkins] python/dist/src/Lib doctest.py, 1.36.2.12, 1.36.2.13

edloper at users.sourceforge.net edloper at users.sourceforge.net
Wed Aug 4 16:05:17 CEST 2004


Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27639

Modified Files:
      Tag: tim-doctest-branch
	doctest.py 
Log Message:
- In DocTestFinder:
  - When exploring a class's contents, check that they're not imported
    (this should fix the Zope3 bug with __provides__).
  - Added parameter ignore_imports (default=True).  Use this to replace
    the '(None)' hack.
  - Describe `module` in the DocTestFinder.find docstring
  - _from_module, assume that properties are always from their class's
    module.
- Added an implementation of Tester.merge()


Index: doctest.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/doctest.py,v
retrieving revision 1.36.2.12
retrieving revision 1.36.2.13
diff -C2 -d -r1.36.2.12 -r1.36.2.13
*** doctest.py	4 Aug 2004 01:06:40 -0000	1.36.2.12
--- doctest.py	4 Aug 2004 14:05:14 -0000	1.36.2.13
***************
*** 299,304 ****
      'DocTestTestCase',
      'DocTestSuite',
! #    'testsource',
! #    'debug',
  #    'master',
  ]
--- 299,304 ----
      'DocTestTestCase',
      'DocTestSuite',
!     'testsource',
!     'debug',
  #    'master',
  ]
***************
*** 658,662 ****
  
      def find(self, obj, name=None, module=None, globs=None,
!              extraglobs=None):
          """
          Return a list of the DocTests that are defined by the given
--- 658,662 ----
  
      def find(self, obj, name=None, module=None, globs=None,
!              extraglobs=None, ignore_imports=True):
          """
          Return a list of the DocTests that are defined by the given
***************
*** 664,667 ****
--- 664,680 ----
          docstrings.
  
+         The optional parameter `module` is the module that contains
+         the given object.  If the module is not specified, then the
+         test finder will attempt to automatically determine the
+         correct module.  The object's module is used:
+ 
+             - As a default namespace, if `globs` is not specified.
+             - To prevent the DocTestFinder from extracting DocTests
+               from objects that are imported from other modules
+               (as long as `ignore_imports` is true).
+             - To find the name of the file containing the object.
+             - To help find the line number of the object within its
+               file.
+ 
          The globals for each DocTest is formed by combining `globs`
          and `extraglobs` (bindings in `extraglobs` override bindings
***************
*** 671,674 ****
--- 684,692 ----
          otherwise.  If `extraglobs` is not specified, then it defaults
          to {}.
+ 
+         If the optional flag `ignore_imports` is true, then the
+         doctest finder will ignore any contained objects whose module
+         does not match `module`.  Otherwise, it will extract tests
+         from all contained objects, including imported objects.
          """
          # If name was not specified, then extract it from the object.
***************
*** 682,700 ****
          # Find the module that contains the given object (if obj is
          # a module, then module=obj.).  Note: this may fail, in which
!         # case, module will be None.
          if module is None:
              module = inspect.getmodule(obj)
  
-         # This is a hack to help Tester.rundict.  Setting module=None
-         # in Tester.rundict should make the tester ignore which module
-         # a function comes from; but DocTestFinder.find will attempt
-         # to derive the correct module if one isn't specified.  So
-         # Tester.rundict can explicitly request that no module be
-         # found by using module='(None)'.  Note that this means that
-         # DocTestFinder will be unable to find the test examples'
-         # filenames and line numbers, so they will be set to None.
-         if module == '(None)':
-             module = None
- 
          # Read the module's source code.  This is used by
          # DocTestFinder._find_lineno to find the line number for a
--- 700,707 ----
          # Find the module that contains the given object (if obj is
          # a module, then module=obj.).  Note: this may fail, in which
!         # case module will be None.
          if module is None:
              module = inspect.getmodule(obj)
  
          # Read the module's source code.  This is used by
          # DocTestFinder._find_lineno to find the line number for a
***************
*** 721,725 ****
          # Recursively expore `obj`, extracting DocTests.
          tests = []
!         self._find(tests, obj, name, module, source_lines, globs, {})
          return tests
  
--- 728,733 ----
          # Recursively expore `obj`, extracting DocTests.
          tests = []
!         self._find(tests, obj, name, module, source_lines,
!                    globs, ignore_imports, {})
          return tests
  
***************
*** 746,753 ****
          elif inspect.getmodule(object) is not None:
              return module is inspect.getmodule(object)
          else:
              raise ValueError("object must be a class or function")
  
!     def _find(self, tests, obj, name, module, source_lines, globs, seen):
          """
          Find tests for the given object and any contained objects, and
--- 754,766 ----
          elif inspect.getmodule(object) is not None:
              return module is inspect.getmodule(object)
+         elif hasattr(object, '__module__'):
+             return module.__name__ == object.__module__
+         elif isinstance(object, property):
+             return True # [XX] no way not be sure.
          else:
              raise ValueError("object must be a class or function")
  
!     def _find(self, tests, obj, name, module, source_lines,
!               globs, ignore_imports, seen):
          """
          Find tests for the given object and any contained objects, and
***************
*** 775,782 ****
                  valname = '%s.%s' % (name, valname)
                  # Recurse to functions & classes.
!                 if ((inspect.isfunction(val) or inspect.isclass(val))
!                     and self._from_module(module, val)):
!                     self._find(tests, val, valname, module,
!                                source_lines, globs, seen)
  
          # Look for tests in a module's __test__ dictionary.
--- 788,795 ----
                  valname = '%s.%s' % (name, valname)
                  # Recurse to functions & classes.
!                 if ((inspect.isfunction(val) or inspect.isclass(val)) and
!                     (self._from_module(module, val) or not ignore_imports)):
!                     self._find(tests, val, valname, module, source_lines,
!                                globs, ignore_imports, seen)
  
          # Look for tests in a module's __test__ dictionary.
***************
*** 795,800 ****
                                       (type(val),))
                  valname = '%s.%s' % (name, valname)
!                 self._find(tests, val, valname, module,
!                            source_lines, globs, seen)
  
          # Look for tests in a class's contained objects.
--- 808,813 ----
                                       (type(val),))
                  valname = '%s.%s' % (name, valname)
!                 self._find(tests, val, valname, module, source_lines,
!                            globs, ignore_imports, seen)
  
          # Look for tests in a class's contained objects.
***************
*** 811,819 ****
  
                  # Recurse to methods, properties, and nested classes.
!                 if (inspect.isfunction(val) or inspect.isclass(val) or
!                     isinstance(val, property)):
                      valname = '%s.%s' % (name, valname)
!                     self._find(tests, val, valname, module,
!                                source_lines, globs, seen)
  
      def _get_test(self, obj, name, module, globs, source_lines):
--- 824,833 ----
  
                  # Recurse to methods, properties, and nested classes.
!                 if ((inspect.isfunction(val) or inspect.isclass(val) or
!                     isinstance(val, property)) and
!                     (self._from_module(module, val) or not ignore_imports)):
                      valname = '%s.%s' % (name, valname)
!                     self._find(tests, val, valname, module, source_lines,
!                                globs, ignore_imports, seen)
  
      def _get_test(self, obj, name, module, globs, source_lines):
***************
*** 1171,1184 ****
                                 re.MULTILINE | re.DOTALL)
  
!     _OPTION_DIRECTIVE_RE = re.compile('\s*doctest:\s*(?P<flags>[^#]*)')
  
      def __handle_directive(self, example):
          """
          Check if the given example is actually a directive to doctest
!         (to turn an optionflag on or off; and if it is, then handle
          the directive.
  
          Return true iff the example is actually a directive (and so
          should not be executed).
          """
          m = self._OPTION_DIRECTIVE_RE.match(example.source)
--- 1185,1199 ----
                                 re.MULTILINE | re.DOTALL)
  
!     _OPTION_DIRECTIVE_RE = re.compile('\s*doctest:\s*(?P<flags>[^#\n]*)')
  
      def __handle_directive(self, example):
          """
          Check if the given example is actually a directive to doctest
!         (to turn an optionflag on or off); and if it is, then handle
          the directive.
  
          Return true iff the example is actually a directive (and so
          should not be executed).
+ 
          """
          m = self._OPTION_DIRECTIVE_RE.match(example.source)
***************
*** 1209,1213 ****
          failures = tries = 0
  
!         # Save the option flags (since doctest directives can be used
          # to modify them).
          original_optionflags = self.optionflags
--- 1224,1228 ----
          failures = tries = 0
  
!         # Save the option flags (since option directives can be used
          # to modify them).
          original_optionflags = self.optionflags
***************
*** 1579,1586 ****
          return (f,t)
  
!     def rundoc(self, object, name=None, module=None):
          f = t = 0
          tests = self.testfinder.find(object, name, module=module,
!                                      globs=self.globs)
          for test in tests:
              (f2, t2) = self.testrunner.run(test)
--- 1594,1602 ----
          return (f,t)
  
!     def rundoc(self, object, name=None, module=None, ignore_imports=True):
          f = t = 0
          tests = self.testfinder.find(object, name, module=module,
!                                      globs=self.globs,
!                                      ignore_imports=ignore_imports)
          for test in tests:
              (f2, t2) = self.testrunner.run(test)
***************
*** 1592,1597 ****
          m = new.module(name)
          m.__dict__.update(d)
!         if module is None: module = '(None)'
!         return self.rundoc(m, name, module)
  
      def run__test__(self, d, name):
--- 1608,1613 ----
          m = new.module(name)
          m.__dict__.update(d)
!         ignore_imports = (module is not None)
!         return self.rundoc(m, name, module, ignore_imports)
  
      def run__test__(self, d, name):
***************
*** 1605,1609 ****
  
      def merge(self, other):
!         pass # [XX] not implemented yet.
  
  ######################################################################
--- 1621,1633 ----
  
      def merge(self, other):
!         d = self.testrunner._name2ft
!         for name, (f, t) in other.testrunner._name2ft.items():
!             if name in d:
!                 print "*** Tester.merge: '" + name + "' in both" \
!                     " testers; summing outcomes."
!                 f2, t2 = d[name]
!                 f = f + f2
!                 t = t + t2
!             d[name] = f, t
  
  ######################################################################



More information about the Python-checkins mailing list