[Python-Dev] PEP 246, redux

Clark C. Evans cce at clarkevans.com
Wed Jan 12 23:54:46 CET 2005


On Wed, Jan 12, 2005 at 04:07:37PM -0600, Ian Bicking wrote:
| A two-step adaptation encodes specific intention that it seems transitive 
| adaption would be blind to.

Exactly.  Nice example Ian. To parrot your example a bit more
concretely, the problem happens when you get two different 
adaptation paths. 

   String -> PathName -> File
   String -> StringIO -> File

Originally, Python may ship with the String->StringIO and
StringIO->File adapters pre-loaded, and if my code was reliant upon
this transitive chain, the following will work just wonderfully,

    def parse(file: File):
        ...

    parse("helloworld")

by parsing "helloworld" content via a StringIO intermediate object.  But
then, let's say a new component "pathutils" registers another adapter pair:

   String->PathName and PathName->File

This ambiguity causes a few problems:

  - How does one determine which adapter path to use?
  - If a different path is picked, what sort of subtle bugs occur?
  - If the default path isn't what you want, how do you specify 
    the other path?
 
I think Phillip's suggestion is the only resonable one here, ambiguous
cases are an error; ask the user to register the adapter they need, or
do a specific cast when calling parse().

| As I think these things through, I'm realizing that registered 
| adaptators really should be 100% accurate (i.e., no information loss, 
| complete substitutability), because a registered adapter that seems 
| pragmatically useful in one place could mess up unrelated code, since 
| registered adapters have global effects.

I think this isn't all that useful; it's unrealistic to assume that
adapters are always perfect.   If transitive adaptation is even
permitted, it should be unambiguous.  Demanding that adaption is
100% perfect is a matter of perspective.  I think String->StringIO
and StringIO->File are perfectly pure.

| Perhaps transitivity seems dangerous because that has the potential to 
| dramatically increase the global effects of those registered adapters.

I'd prefer,
  
    1. adaptation to _not_ be transitive (be explicit)

    2. a simple mechanism for a user to register an explicit
       adaptation path from a source to a destination:

           adapt.path(String,PathName,File)

       to go from String->File, using PathName as an intermediate.

    3. an error message, AdaptationError, to list all possible
       adaptation paths:

          Could not convert 'String' object to 'File' beacuse
          there is not a suitable adapter.  Please consider an
          explicit conversion, or register a composite adapter
          with one of the following paths:

             adapt.path(String,PathName,File)
             adapt.path(String,StringIO,File)

    3. raise an exception when _registering_ a 'path' which would
       conflict with any existing adapter:
       
          "Could not complete adapt.path(String,PathName,File) 
           since an existing direct adapter from String to Path
           already exists."
           
          "Could not complete adapt.path(String,PathName,File)
           since an existing path String->StringIO->File is
           already registered".

I'd rather have the latter error occur when "importing" modules
rather than at run-time.  This way, the exception is pinned on
the correct library developer.

Best,

Clark


More information about the Python-Dev mailing list