<type>documentation</type>
<domain>debug</domain>
<id>debugger-limitations</id>
<title>Debugger Limitations</title>
<date>$Date$</date>
<version>$Revision$</version>
<product>per+</product>

.. note::

  If you are having problems getting the debugger to stop at breakpoints or to display
  source as you step through your code, always read the `Trouble-shooting Failure to Debug
  <ref:install/trouble-debug>`__ section first. 

This section documents all know limitations in the debugger implementation.  Many of 
these are extremely rare and esoteric:

(1) Your source files must be stored on disk and accessible to the IDE. If you are trying
to debug code fragments, try writing them to disk temporarily and setting the ``__file__``
variable in the module name space before invoking Python's ``exec`` or ``eval``. This will
allow Wing's debugger to map code objects to the source you've temporarily written to
disk.
  
(2) Running without saving will lead to incorrect display of breakpoints and run position
because the debug process runs against the on-disk version of the source file. Wing will
indicate that some files are out of sync so this case should only occur if you ignore its
warnings.

(3) There are several cases where Wing may fail to stop at breakpoints or exceptions, or
may fail to find source files. All of these are caused by storage of incorrect file names
in ``*.pyc`` files:

* Moving ``*.pyc`` files on disk after they are generated invalidates the file name stored
  in the file if it is a partial relative path. This happens if your ``PYTHONPATH`` or
  ``sys.path`` contains partial relative path names.

* A similar problem may result from use of ``compileall.py`` and some other utilities that
  don't record a correct filename in the ``*.pyc`` file.

* If you run the same code twice using different paths to the same working directory, as
  is possible on Linux and macOS with symbolic links, the file names left in ``*.pyc`` may
  contain a mix of each of these paths. If the symbolic link that was used is subsequently
  removed, some of the file names become invalid.

The fix for all of these problems is to remove the ``*.pyc`` files and let Python
regenerate them from the corresponding ``*.py`` files with the correct file name
information.

Hint: You can open ``*.pyc`` files in most text editors to inspect the stored file names.

(4) For code that spends much of its time in C/C++ without calling Python at all, the
debugger may not reliably stop at breakpoints added during a run session, and may not
respond to ``Pause`` requests. See `Debugging Non-Python Mainloops
<ref:debug/non-python-mainloops>`__ for details.

(5) You cannot use ``pdb`` or other debuggers together with Wing's debugger. The two
debuggers conflict because they attempt to use the same debug tracer in the Python
interpreter.

(6) If you override ``__import__`` in your code, you will break the debugger's ability to
stop at breakpoints unless you call the original ``__import__`` as part of your code
whenever a module is actually imported. If you cannot call the original ``__import__`` for
some reason, it may be possible to instead use ``wingdbstub`` and then call
``wingdbstub.debugger.NotifyImport(mod)`` from your import handler, where ``mod`` is the
module that was just imported.

(7) If you set ``__file__`` in a module's name space to a value other than its original,
Wing will be unable to stop at breakpoints in the module and may fail to report exceptions
to the IDE's user interface.

(8) If you use an extension module to call C/C++ level ``stdio`` calls instead of using
the Python-level facilities, the debug process will remain unresponsive to Wing while
waiting for keyboard input, I/O redirection to the ``Debug Console`` in Wing Pro will fail,
and you may run into out-of-order character reads in some cases. Details can be found in
`Debug Process I/O <ref:debug/debug-process-i-o>`__.

(9) Using partial path names in module ``__file__`` attributes can in rare cases cause
Wing to fail to stop on breakpoints and exceptions, to fail to display source files, or to
confuse source files of the same name.

A partial path name may end up in ``__file__`` only when (a) invoking Python code with a
partial path name, for example with ``python myfile.py`` instead of ``python``
``/path/to/myfile.py``, (b) sending partial path names into ``exec``, (c) using partial
path names in your ``PYTHONPATH`` or ``sys.path``, or (d) using ``compileall.py`` or
similar tool to compile modules with a partial path name.

Because Wing does everything possible to avoid this problem in practice, it actually only
occurs in the following rare cases:

* When modules are loaded with partial path names and ``os.chdir()`` is called before
  debugging is started. This is only possible when using ``wingdbstub``.

* When modules are loaded with partial path names and ``os.chdir()`` is called after
  ``wingdbstub.debugger.SuspendDebug()`` and before ``wingdbstub.debugger.ResumeDebug()``.

* When modules are loaded with partial path names and removed from ``sys.modules`` before
  the debugger is started or while debugging is suspended.

* When code objects are created on the fly using ``compile()`` or the C API, a relative
  filename or an incorrect filename are used for the filename argument, and ``os.chdir()``
  is called before the code is executed.

(10) Wing tries to identify when source code in the IDE matches or does not match the code
that is running in the debug process. There are certain very rare cases where this will
fail, which may lead to failure to stop on breakpoints and other problems even when files
are identified by the IDE as being synchronized:

Using ``execfile()``, ``eval()``, or ``exec`` with a globals dict that contains
``__file__`` will cause Wing to incorrectly assert that the specified file has been
reloaded. In practice, this scenario usually occurs when ``execfile()`` is called from the
top level of a module, in which case the module is in fact being loaded or reloaded (so no
mis-identification of module load status occurs). However, in cases where a module load
takes a long time or involves a long-running loop at the top level, the ``execfile()``,
``eval()``, or ``exec`` may occur **after** edits to the module have been made and saved.
In this case, Wing will mis-identify the module as having been reloaded with the new
edits.

This problem can also be triggered if a ``globals`` with ``__file__`` is explicitly passed
to ``execfile()``, ``eval()``, or ``exec``. However, it will only occur in this case when
the code object file name is ``?``, and ``locals`` and ``globals`` dictionaries are the
same, as they are by default for these calls.

(11) Naming a file ``<string>`` will prevent the debugger from debugging that file because
it is confused with the default file name used in Python for code that is not located in a
file.

(12) The debugger may fail to step or start after stopping at a breakpoint if the floating
point mode is set to single precision (24 bit) on Intel x86 and potentially other
processors. This is sometimes done by graphics libraries such as DirectX or by other code
that optimizes floating point calculations.
