[Patches] [ python-Patches-448488 ] Implemenation of ImportNotFoundError PEP

noreply@sourceforge.net noreply@sourceforge.net
Tue, 25 Sep 2001 17:39:42 -0700


Patches item #448488, was opened at 2001-08-06 11:51
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=448488&group_id=5470

Category: Core (C code)
Group: None
Status: Closed
Resolution: Rejected
Priority: 5
Submitted By: Frederic Giacometti (giacometti)
Assigned to: Nobody/Anonymous (nobody)
Summary: Implemenation of ImportNotFoundError PEP

Initial Comment:

This is a reference implementation for the PEP proposal.
Here, the patch has existed before the PEP, therefore the PEP refers to the patch...
I need to create the patch before I submit the PEP :)))

Frederic Giacometti

-----------------------

PEP XXX: ImportNotFoundError Exception

fred@arakne.com (Frederic Giacometti)

Abstract

The object of this proposal is the definition of a specific
ImportNotFoundError error, along with its association to a new
import exception trapping mechanism
that will enable the extension of the import mechanism to generic global/static
objects.


Part 1: The ImportNotFoundError exception.

In the present code, the ImportError string exception
is used for all import failures; this does not permit us to catch efficiently
import failures caused specifically by a 'component not found' situation.

To fix this, we introduce a new exception, that we call ImportNotFoundError.
This exception is designed for use in the very specific situation where
an import string cannot be found by the import mechanism (as opposed to 'found'
but 'failed to open', failed to load', 'failed to initialize'...).

ImportNotFoundError instance raised within execution of
an import statement will have two attributes as follows:
  - 'parent': the element of sys.modules where the next import failed,
    or None if top-level import.
  - 'name': the string of the next .-separated component which failed

A formal Python definition of ImportErrorNotFound could be:

        class ImportNotFoundError( ImportError):
            def __init__( self, parent, name):
	       assert( hasattr( parent, '__name__'))
	       assert( sys.modules.has_key( parent.__name__))
	       assert( sys.modules[ parent.__name__] is parent)
	       assert( not hasattr( parent, name))
 	       ImportError.__init__( self, parent, name)
 	       self.parent = parent
 	       self.name = name


2) Alternative import customization hook in the module global scope
(__altimp__)

2.a: Why in the module global scope?
     (or: Why not overwrite builtins.__import__?)

Use of builtins.__import__ is not a preferred integration practice: Only
one __import__ value can be defined; and if you're integrating two components
with each its own __import__ version, you'll be stuck...

Furthermore, if one insists on overwriting __import__, one can still do it.
Meanwhile, if an application requires overwriting __import__,
and one does not want to, one is stuck again...

Since we want to keep options open, we're proposing to enhance
the import procedure defining a trapping mechanism
based on the presence of a globals()[ '__altimp__'] object, which is called
if present upon trigger of an ImportNotFoundError within an import statement.

In doing so, those who don't want (rightfully) to be bothered won't be,
unless they define __altimp__ in their module global scope, and a module's
usage of a certain implementation of __altimp__ won't bother other modules,
at all.


2.b Definition

If present, globals()[ '__altimp__'] will refer to a callable object specified
as follows:

def importextended( failedparent, failedname, name,
                    globs=None, locs=None, fromlist=None):
   failedparent: 'parent' attribute from the ImportnotFoundError exception
   failedname:   'name' attribute from the ImportnotFoundError exception
   (name, globs, locs, fromlist): same arguments as in __import__()

   return: same as in __import__() [object for insertion in sys.modules...]


Effect on existing code

There should be no effect on existing code, other than when code like
  exc.__class__ == ImportError
has been meant for
  isinstance( exc, ImportError)

(hopeless anyway? :(()


Applications:

Given that importext.py contains:

  __all__ = ('importextended')

  import sys

  def importextended( failedparent, failedname, name,
                      globs=None, locs=None, fromlist=None):
      curmod = failedparent
      remainder = name[ len( curmod.__name__) + 1:].split( '.')
      while remainder:
          curname = remainder.pop( 0)
          curmod = getattr( curmod, curname)
          sys.modules[ curmod.__name__] = curmod
      return curmod


A JPE file may contain:

  # import Java's javax.swing package in global scope

  from importext import importextended as __altimport__
  from java import Jstring
  from java.system.javax import swing

  frame = swing.JFrame( Jstring( 'HelloWorldSwing'))
  label = swing.JLabel( Jstring( 'Hello World'))
  frame.getContentPane().add(label)
  frame.setDefaultCloseOperation( swing.JFrame.EXIT_ON_CLOSE)
  frame.pack()
  frame.setVisible( 1)


A Metadynamic Python file can contain:

  # User is a Metaphase persistant class
  from importext import importextended as __altimport__
  from metadyn.mclass import User

  users = mclass.User.QueryDbItem( some_query)
  ...

Based on this feature, applications can easily be programmed
on the client side for any client/server situation,
including pulling Python modules from remote repository...


Reference Implementation:

A sample implementation of ImportErrorNotFoundError
in the current import mechanism, with
the __altimp__ hook is provided in patch href:attached_file.


----------------------------------------------------------------------

>Comment By: Frederic Giacometti (giacometti)
Date: 2001-09-25 17:39

Message:
Logged In: YES 
user_id=93657

How?
You could at least give a pointer, a word, something!

FG


----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-09-25 17:32

Message:
Logged In: YES 
user_id=6380

The existing import hooks have ways to do this without
catching the exception.

----------------------------------------------------------------------

Comment By: Frederic Giacometti (giacometti)
Date: 2001-09-25 17:18

Message:
Logged In: YES 
user_id=93657

There are two application scenarios for __altimp__, and the
__altimp__ implementation requires  ImportNotFoundError.

The introduction of ImportNotFoundError is the only way I
could find to implement efficiently __altimp__ .

I'm giving below an similar implementation in Python that
overrides __import__ (with the inconvenient that this
affects all import statements).
A possible importextended function is defined in the
[sample] 'Application' section of the PEP :

------------
pyimport = __import__
def altimport(  name, globs=None, locs=None, fromlist=None):
    try:
        return pyimport( globs, locs, fromlist)
    except ImportNotFoundError, iexc:
        return importextended( iexc.parent, iexc.name, name,
globs, locs, fromlist)
         
sys.__buildins__.__import__ = altimport
----------------------
Let's make clear that in this case I only want to catch the
ImportError's corresponding to something whose import fails
because it is not on the filesystem (not on PYTHONPATH....),
and that I do not want to catch any other case of
ImportError that could be raised.
Thus, a subclass of ImportError is needed:
ImportNotFoundError.

FG



----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-09-25 16:39

Message:
Logged In: YES 
user_id=6380

What's missing is why an application would need to catch
this kind of import failures. I have a limited imagination,
and I can't come up with a scenario that would require this.
That's what I meant by "motivation".

----------------------------------------------------------------------

Comment By: Frederic Giacometti (giacometti)
Date: 2001-09-25 15:11

Message:
Logged In: YES 
user_id=93657

The 'motivation' is at the beginning of the first section of
the PEP. I'm pasting it below:

Part 1: The ImportNotFoundError exception. 

                     In the present code, the ImportError
string exception 
                     is used for all import failures; this
does not permit us to catch efficiently 
                     import failures caused specifically by
a 'component not found' situation. 

                     To fix this, we introduce a new
exception, that we call ImportNotFoundError. 
                     This exception is designed for use in
the very specific situation where 
                     an import string cannot be found by the
import mechanism (as opposed to 'found' 
                     but 'failed to open', failed to load',
'failed to initialize'...). 


----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-09-25 06:36

Message:
Logged In: YES 
user_id=6380

Rejected. The "PEP" doesn't provide a motivation for the
ImportNotFound error, and I don't see a reason why this
particular condition should be excepted.

The __altimp__ idea is a nice one, but the elaboration here
is incomprehensible. I suggest that you submit this idea as
a separate patch.

----------------------------------------------------------------------

Comment By: Martin v. Löwis (loewis)
Date: 2001-08-07 21:54

Message:
Logged In: YES 
user_id=21627

There is in general no need to put the PEP into the SF 
comment. Just send it to the PEP editor, who should assign 
a PEP number and commit it into CVS in a timely manner.

I have a number of comments on this PEP, but I'll send 
them directly to you once the PEP is on python.sf.net/peps.


----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=448488&group_id=5470