Re: OT: dotted names

Alice Bevan–McGregor <alice-h+KYGxXtFYrqlBn2x/[email protected]>
Newsgroups gmane.comp.python.web
Message-ID <[email protected]>
On 2011-04-15 22:33:08 +0000, P.J. Eby said:

> At 04:11 PM 4/15/2011 -0400, Fred Drake wrote:
>> These end users don't really care if the object identified is a class or
>> function in module, a nested attribute on a class, or anything else, so
>> long as it does what it's advertised to do.  By not pushing implementation
>> details into the identifier, the package maintainer is free to change the
>> implementation in more ways, without creating backward incompatibility.
> 
> That would be one advantage of using entry points
> instead.  ;-)  (i.e., the user doesn't specify the object location,
> the package author does.)
> 
> Note, however, that one must perform considerably more work to
> resolve a name, when you don't know whether each part of the name is
> a module or an attribute.

Not if, as you mention, you use an explicit format.  The format my 
resolver code uses (and this code is utilized in marrow.mailer for 
manager/transport lookup, marrow.server.http's command-line script to 
resolve WSGI applications, and marrow.templating to resolve templates) 
covers the following:

:: <object>
:: entrypoint_name
:: ../relative/path/to/something
:: ./relative/path/to/something
:: /absolute/path/to/something
:: package.relative/path/to/something
:: package.absolute.path
:: package.submodule:object
:: package.submodule:object.attribute

What is allowed on any given resolution depends on if the resolver 
request is looking for an on-disk path or object.

Using the above as an example, you can define the use of the SMTP 
transport within marrow.mailer in two ways:

from marrow.mailer.transport.smtp import SMTPTransport
config = dict(transport=SMTPTransport) # direct reference
config = dict(transport="smtp") # entry point
config = dict( # object lookup
    transport = "marrow.mailer.transport.smtp:SMTPTransport"
  )

When configuring m.s.http to load an app, you can:

# p-code
HTTPServer.serve("project.application:WSGIApp.factory")

When choosing templates, OTOH, you can do the following:

return "./templates/foo.html", dict()
return "/var/www/foo.html", dict()
return "myapp.templates.foo", dict()
return "myapp/templates/foo.html", dict()
return "myapp.stemplates:email.welcome", dict()

> Either you have to get an AttributeError first, and then fall back to 
> importing, or get an ImportError first, and fall back to getattr.

If you examine the above closely, the differing formats are easily 
identifiable using a few == and 'in' conditionals:

if not isinstance(ref, basestring):
    return ref

if ref[0] == '.': pass # relative
if ref[0] == '/': pass # absolute
if '/' not in ref and '.' not in ref and ':' not in ref:
    pass # entrypoint
if ':' in ref:
    import_, _, attrs = ref.partition(':')
    base = __import__(import_)
    for attr in attrs.split('.'):
        base = getattr(base, attr)
    return attr
if '/' in ref:
    import_, _, path = ref.partition('/')
    pass # use pkg_resources + path to pull file from package

> If the syntax is explicit, OTOH, then you don't have to guess, thereby 
> saving lots of work and wasteful exceptions.

:)

	— Alice.


_______________________________________________
Web-SIG mailing list
[email protected]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.