Merge lp:~vila/bzr/712474-module-available into lp:bzr

Proposed by Vincent Ladeuil
Status: Merged
Approved by: John A Meinel
Approved revision: no longer in the source branch.
Merged at revision: 6076
Proposed branch: lp:~vila/bzr/712474-module-available
Merge into: lp:bzr
Diff against target: 40 lines (+14/-4)
2 files modified
bzrlib/tests/features.py (+10/-4)
doc/en/release-notes/bzr-2.5.txt (+4/-0)
To merge this branch: bzr merge lp:~vila/bzr/712474-module-available
Reviewer Review Type Date Requested Status
John A Meinel Approve
bzr-core Pending
Review via email: mp+48474@code.launchpad.net

Commit message

ModuleAvailableFeature don't try to imported already imported modules.

Description of the change

__import__ doesn't check that a module has already been imported, don't use it.

See the bug report for a real life use case (bzr-svn plugin).

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

I think checking sys.modules should do instead, something like:

    sentinel = object()
    module = sys.modules.get(self.module_name)
    if module is None:
        return False
    if module is sentinel:
        try:
            module = __import__(self.module_name, {}, {}, [''])
        except ImportError: # import can raise other things, but that's a bug
            return False
    return True

That should save me worrying needlessly about exec on an interpolated string.

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2/3/2011 9:44 AM, Martin [gz] wrote:
> I think checking sys.modules should do instead, something like:
>
> sentinel = object()
> module = sys.modules.get(self.module_name)
> if module is None:
> return False
> if module is sentinel:
> try:
> module = __import__(self.module_name, {}, {}, [''])
> except ImportError: # import can raise other things, but that's a bug
> return False
> return True
>
> That should save me worrying needlessly about exec on an interpolated string.

I think you wanted

module = sys.modules.get(self.module_name, sentinel)

And regardless, this should probably be pulled out into a separate
helper function. I think the bzrlib.plugin code would like something
like this. Though we can see how related it is.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk1Kz4sACgkQJdeBCYSNAAPLjgCfaPi842OVTWonJ6f9yKDI6gCg
udAAoKV/XVWEaH+Srs7NS/bsm0VqwA+u
=ZTnz
-----END PGP SIGNATURE-----

Revision history for this message
John A Meinel (jameinel) wrote :

We'd really like to get away from "exec 'import %s'" if you can have it done a different way. I'm not particularly worried about code injection because importing a plugin can do whatever the heck it wants anyway.

review: Needs Fixing
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

ping?

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 8/16/2011 4:21 PM, Vincent Ladeuil wrote:
> You have been requested to review the proposed merge of
> lp:~vila/bzr/712474-module-available into lp:bzr.
>
> For more details, see:
> https://code.launchpad.net/~vila/bzr/712474-module-available/+merge/48474
>
> __import__ doesn't check that a module has already been imported,
> don't use it.
>
> See the bug report for a real life use case (bzr-svn plugin).
>
>

Your cover letter is a bit incorrect. You're still using "__import__"
you're just guarding it with a check that the module isn't already imported.

 merge: approve

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk5KgpwACgkQJdeBCYSNAAN9OgCeIiAvxAQ57XRprJEOikfhFbff
4akAniys+2FQugggnC0uV2pLm4ISxJYQ
=Sf+E
-----END PGP SIGNATURE-----

review: Approve
Revision history for this message
Vincent Ladeuil (vila) wrote :

> Your cover letter is a bit incorrect. You're still using "__import__"

But never twice for the same module.

> you're just guarding it with a check that the module isn't already imported.

Indeed. Anyway, rephrased to avoid confusion.

Revision history for this message
Vincent Ladeuil (vila) wrote :

Ha, *cover* letter, yeah sorry, I didn't update it.

Revision history for this message
Vincent Ladeuil (vila) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/tests/features.py'
--- bzrlib/tests/features.py 2011-08-11 10:09:27 +0000
+++ bzrlib/tests/features.py 2011-08-16 15:21:51 +0000
@@ -166,11 +166,17 @@
166 self.module_name = module_name166 self.module_name = module_name
167167
168 def _probe(self):168 def _probe(self):
169 try:169 sentinel = object()
170 self._module = __import__(self.module_name, {}, {}, [''])170 module = sys.modules.get(self.module_name, sentinel)
171 if module is sentinel:
172 try:
173 self._module = __import__(self.module_name, {}, {}, [''])
174 return True
175 except ImportError:
176 return False
177 else:
178 self._module = module
171 return True179 return True
172 except ImportError:
173 return False
174180
175 @property181 @property
176 def module(self):182 def module(self):
177183
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- doc/en/release-notes/bzr-2.5.txt 2011-08-16 09:33:16 +0000
+++ doc/en/release-notes/bzr-2.5.txt 2011-08-16 15:21:51 +0000
@@ -196,6 +196,10 @@
196* ``LockDir`` can now be run when the local hostname is ``localhost``.196* ``LockDir`` can now be run when the local hostname is ``localhost``.
197 (Jelmer Vernooij, #825994)197 (Jelmer Vernooij, #825994)
198198
199* ``ModuleAvailableFeature`` won't try to import already imported modules,
200 allowing it to be used for modules with side-effects.
201 (Vincent Ladeuil, #712474)
202
199* `TestCaseWithMemoryTransport` is faster now: `_check_safety_net` now203* `TestCaseWithMemoryTransport` is faster now: `_check_safety_net` now
200 just compares the bytes in the dirstate file to its pristine state,204 just compares the bytes in the dirstate file to its pristine state,
201 rather than opening the WorkingTree and calling ``last_revision()``.205 rather than opening the WorkingTree and calling ``last_revision()``.