<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:p="urn:schemas-microsoft-com:office:powerpoint" xmlns:a="urn:schemas-microsoft-com:office:access" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:b="urn:schemas-microsoft-com:office:publisher" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:odc="urn:schemas-microsoft-com:office:odc" xmlns:oa="urn:schemas-microsoft-com:office:activation" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:q="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtc="http://microsoft.com/officenet/conferencing" xmlns:D="DAV:" xmlns:Repl="http://schemas.microsoft.com/repl/" xmlns:mt="http://schemas.microsoft.com/sharepoint/soap/meetings/" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ppda="http://www.passport.com/NameSpace.xsd" xmlns:ois="http://schemas.microsoft.com/sharepoint/soap/ois/" xmlns:dir="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sub="http://schemas.microsoft.com/sharepoint/soap/2002/1/alerts/" xmlns:ec="http://www.w3.org/2001/04/xmlenc#" xmlns:sp="http://schemas.microsoft.com/sharepoint/" xmlns:sps="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:udcs="http://schemas.microsoft.com/data/udc/soap" xmlns:udcxf="http://schemas.microsoft.com/data/udc/xmlfile" xmlns:udcp2p="http://schemas.microsoft.com/data/udc/parttopart" xmlns:wf="http://schemas.microsoft.com/sharepoint/soap/workflow/" xmlns:dsss="http://schemas.microsoft.com/office/2006/digsig-setup" xmlns:dssi="http://schemas.microsoft.com/office/2006/digsig" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature" xmlns:mver="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns:mrels="http://schemas.openxmlformats.org/package/2006/relationships" xmlns:spwp="http://microsoft.com/sharepoint/webpartpages" xmlns:ex12t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ex12m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:pptsl="http://schemas.microsoft.com/sharepoint/soap/SlideLibrary/" xmlns:spsl="http://microsoft.com/webservices/SharePointPortalServer/PublishedLinksService" xmlns:Z="urn:schemas-microsoft-com:" xmlns:st="" xmlns="http://www.w3.org/TR/REC-html40">

<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
 <o:shapelayout v:ext="edit">
  <o:idmap v:ext="edit" data="1" />
 </o:shapelayout></xml><![endif]-->
</head>

<body lang=EN-GB link=blue vlink=purple>

<div class=Section1>

<p class=MsoNormal>I’ve heard people complain that we have lots of ways
of doing lazy import of modules (i.e. loading them on demand, so that you don’t
need the dependency unless you’re actually using the functionality) and
that we should standardize on one.<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal>So, which one should we standardize on?<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal>To kick the conversation off, I don’t like the way
that nova.utils.{import_object,import_class} work today, having recently chased
down a problem that was completely hidden by them.  I had an object A that
was lazy-loaded using import_object, and A in turn imported B, which was
missing.  import_object caught the ImportError for B, decided that it
meant that A wasn’t present, attempted to import it using import_class,
and that failed too, and then it eventually got logged as ‘Class A cannot
be found’.  This was wrong firstly because A was not missing, and
secondly because A wasn’t a class, and thirdly because the code didn’t
ask to import it as a class!  There was no indication that B was missing.<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal>This took me a long time to unpick, so if we’re going
to standardize around nova.utils.import_x, then we need to figure out a better
way for them to work.<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal>Thanks,<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal>Ewan.<o:p></o:p></p>

<p class=MsoNormal><o:p> </o:p></p>

<p class=MsoNormal><span style='font-family:Consolas'>def
import_class(import_str):<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>   
"""Returns a class from a string including module and
class"""<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>   
mod_str, _sep, class_str = import_str.rpartition('.')<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>    try:<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
__import__(mod_str)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
return getattr(sys.modules[mod_str], class_str)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>    except
(ImportError, ValueError, AttributeError), exc:<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
logging.debug(_('Inner Exception: %s'), exc)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
raise exception.NotFound(_('Class %s cannot be found') % class_str)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'> <o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>def
import_object(import_str):<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>   
"""Returns an object including a module or module and
class"""<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>    try:<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
__import__(import_str)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
return sys.modules[import_str]<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>    except
ImportError:<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
cls = import_class(import_str)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'>       
return cls()<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p>

</div>

</body>

</html>