Merge lp:~spiv/bzr/hooks-refactoring into lp:bzr
| Status: | Merged |
|---|---|
| Merged at revision: | 5500 |
| Proposed branch: | lp:~spiv/bzr/hooks-refactoring |
| Merge into: | lp:bzr |
| Diff against target: |
786 lines (+334/-124) 16 files modified
NEWS (+9/-1) bzrlib/bundle/serializer/__init__.py (+5/-3) bzrlib/bzrdir.py (+3/-5) bzrlib/export/__init__.py (+5/-3) bzrlib/hooks.py (+69/-52) bzrlib/pyutils.py (+91/-0) bzrlib/registry.py (+7/-16) bzrlib/repository.py (+4/-3) bzrlib/tests/TestUtil.py (+3/-12) bzrlib/tests/__init__.py (+11/-9) bzrlib/tests/per_transport.py (+2/-6) bzrlib/tests/test_hooks.py (+15/-2) bzrlib/tests/test_pyutils.py (+88/-0) bzrlib/tests/test_registry.py (+8/-0) bzrlib/tests/test_selftest.py (+0/-12) doc/developers/code-style.txt (+14/-0) |
| To merge this branch: | bzr merge lp:~spiv/bzr/hooks-refactoring |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Vincent Ladeuil | Needs Information on 2010-10-11 | ||
| Martin Pool | 2010-09-21 | Needs Fixing on 2010-09-28 | |
|
Review via email:
|
|||
Commit Message
Add bzrlib/pyutils.py, and replace many awkward (and sometimes buggy) uses of __import__ with calls to bzrlib.
Description of the Change
While reviewing <https:/
1. hooks.py was more confusing than necessary
2. _LazyObjectGett
This patch definitely addresses 2, but hopefully helps 1 as well.
It adds a new module, bzrlib.pyutils, which has a get_named_object helper for resolving a pair like ('module.submodle', 'attr.another_
I'm not thrilled by the name of the new module, or the helpers in it. I'm open to suggestions.
The main use of __import__ that I didn't replace is lazy_import.py, partly because it would be a shame to make it less standalone, but mainly because it needs to go to the effort of breaking the import statements down into "import this module, get a reference to module, get this attribute from that module" steps anyway, because it's parsing actual "import" statements in all their varied forms... so get_named_object isn't a drop-in replacement for its current logic.
One thing get_named_object does slightly differently than many __import__ calls it replaces is resolving a module name of 'x.y.z' by importing x.y.z, then fetching it from sys.modules[
- 5438. By Andrew Bennetts on 2010-09-28
-
Merge lp:bzr.
- 5439. By Andrew Bennetts on 2010-09-28
-
Add NEWS entry.
- 5440. By Andrew Bennetts on 2010-09-28
-
Add section to code-style.txt recommending get_named_object.
- 5441. By Andrew Bennetts on 2010-09-28
-
Tweak builtin known_hooks registration per poolie's review.
- 5442. By Andrew Bennetts on 2010-09-28
-
Add doctest-able example to get_named_object docstring. Make doctest skip calc_parent_name docstring.
- 5443. By Andrew Bennetts on 2010-09-28
-
Docstring tweaks prompted by review.
| Andrew Bennetts (spiv) wrote : | # |
Martin Pool wrote:
> Review: Needs Fixing
> I would mention get_named_object in the api section of the news, and in the coding standard, so that people do use it in future.
Done.
> > 2. _LazyObjectGett
>
> Is there an actual bug number or user impact for this, or is it just buggy in the sense of being hard to use correctly (which is of course still worth fixing.)
No bug number I found, but it came up during a review (of a currently back in
work-in-progress) patch to add pre- and post-export hooks. There was a strange
workaround in the hook registration to do with some sort of interaction with the
hook point being a module-global in a __init__.py, rather than an attribute of
an object.
> Knowing the modules where all the hook objects can be found seems a bit
> roundabout to me compared to just actually having the hooks directly in the
> registry where they can be saved/restored altogether. But this is a cleaner
> way to implement it.
Hmm, quite possibly. I don't have any incentive to worry about that atm, though
:)
> +known_
> 197 +known_
> 198 +known_
> 199 + 'bzrlib.commands', 'Command.hooks', 'CommandHooks')
>
> For the sake of readability and to avoid all the line wrapping, could you turn this into a
>
> for (hook_module, hook_attribute_
> known_hooks.
Ok, done, although a couple of them still needed to be wrapped.
> +"""Some convenience functions for general Python, such as a wrapper around
> +``_import__``.
> +"""
>
> Should be a single line.
Really? I don't think you can mean those three lines should be on one, because
that's over 80 columns.
I guess you mean the closing triple-
the final line of the text. I interpret this situation as a multiline
docstring, where AIUI the convention is closing quotes get their own line. I
guess you consider the fact it's one sentence to mean it's more like a single
line docstring?
Anyway, changed, because while I disagree I also don't care very much :)
If it really bugs us too much just add another paragraph to that docstring to
make the situation unambiguous... ;)
> +def get_named_
>
> It's a pretty generic name. Perhaps the name should include 'import' to give
> you a bit more of a clue, like import_
It is pretty generic :(, but it seems other projects solving this problem have
chosen similarly generic names, so perhaps it's unavoidable. There's some
overlap with twisted.
getObjectFromName which is also similar in purpose. So it appears the broader
Python community tends towards this sort of generic name (and this feature
should be part of core Python, clearly...)
I think “import” is perhaps a misleading hint, because that's only part of what
it does.
> I think this could do with a docstring example (add it to the...
| Martin Pool (mbp) wrote : | # |
On 28 September 2010 18:37, Andrew Bennetts
<email address hidden> wrote:
>> +"""Some convenience functions for general Python, such as a wrapper around
>> +``_import__``.
>> +"""
>>
>> Should be a single line.
>
> Really? I don't think you can mean those three lines should be on one, because
> that's over 80 columns.
>
> I guess you mean the closing triple-
> the final line of the text. I interpret this situation as a multiline
> docstring, where AIUI the convention is closing quotes get their own line. I
> guess you consider the fact it's one sentence to mean it's more like a single
> line docstring?
No, I meant that I thought the Python convention was that docstrings
should be a single sentence that fits on a single line, such as
"""General Python convenience functions.
"""
Perhaps it doesn't matter if it's on one line and it just needs to be
a single-sentence paragraph?
>
> Anyway, changed, because while I disagree I also don't care very much :)
>
> If it really bugs us too much just add another paragraph to that docstring to
> make the situation unambiguous... ;)
>
>> +def get_named_
>>
>> It's a pretty generic name. Perhaps the name should include 'import' to give
>> you a bit more of a clue, like import_
>
> It is pretty generic :(, but it seems other projects solving this problem have
> chosen similarly generic names, so perhaps it's unavoidable. There's some
> overlap with twisted.
> getObjectFromName which is also similar in purpose. So it appears the broader
> Python community tends towards this sort of generic name (and this feature
> should be part of core Python, clearly...)
>
> I think “import” is perhaps a misleading hint, because that's only part of what
> it does.
ok
>
>> I think this could do with a docstring example (add it to the list of
>> docstrings to test) and it should be feasible to test that way without too
>> much complication. You need to add it to the list anyhow to make the
>> calc_parent_name doctest run.
>
> I've added a doctest-friendly example to get_named_object, and added to the list
> of doctested modules.
>
> The calc_parent_name example is not a doctest, though. It's simply
> documentation, because the effort to contrive a doctest-runnable example is a
> bit disproportionate (and so I think would detract from the clarity of the
> example as documentation). So it fails when I add pyutils to the list of
> doctestable modules, and I have to sprinkle #doctest: +SKIP to avoid that. The
> docstring example is pretty much verbatim how I expect the actual callers of the
> code to look.
>
>> + :param module_name: a module name, as found in sys.module. It may contain
>> + dots. e.g. 'sys' or 'os.path'.
>>
>> This seems to imply that it needs to already be in sys.module, but in fact
>> it's fine to call this with a module that might not already be loaded?
>
> Updated to:
>
> :param module_name: a module name, as would be found in sys.modules if
> the module is already imported. It may contain dots. e.g. 'sys' or
> ...
| Robert Collins (lifeless) wrote : | # |
On Wed, Sep 29, 2010 at 3:43 PM, Martin Pool <email address hidden> wrote:
> No, I meant that I thought the Python convention was that docstrings
> should be a single sentence that fits on a single line, such as
>
> """General Python convenience functions.
> """
I may be misunderstanding, but that particular layout really squicks.
"""General Python convenience functions."""
or
"""General Python convenience functions.
More detail here.
"""
> Perhaps it doesn't matter if it's on one line and it just needs to be
> a single-sentence paragraph?
http://
"The closing quotes are on the same line as the opening quotes. This
looks better for one-liners."
etc.
_Rob
| Martin Pool (mbp) wrote : | # |
I don't personally care very much where the quotes are, but what I was
asking for, was, from pep 257
>> Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description. The summary line may be used by automatic indexing tools; it is important that it fits on one line and is separated from the rest of the docstring by a blank line.
If you have eight characters of indent plus six characters of quotes
and a limit around 72-80 you do need to come up with a pretty terse
(down to 58 chars) summary sentence.
--
Martin
| Robert Collins (lifeless) wrote : | # |
On Wed, Sep 29, 2010 at 4:25 PM, Martin Pool <email address hidden> wrote:
>>> Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description. The summary line may be used by automatic indexing tools; it is important that it fits on one line and is separated from the rest of the docstring by a blank line.
>
> If you have eight characters of indent plus six characters of quotes
> and a limit around 72-80 you do need to come up with a pretty terse
> (down to 58 chars) summary sentence.
Yea, it can be quite Zen sometimes. I wonder if trying for koans would help.
-Rob
| Andrew Bennetts (spiv) wrote : | # |
Martin Pool wrote:
> On 28 September 2010 18:37, Andrew Bennetts
> <email address hidden> wrote:
> >> +"""Some convenience functions for general Python, such as a wrapper around
> >> +``_import__``.
> >> +"""
> >>
> >> Should be a single line.
> >
> > Really? I don't think you can mean those three lines should be on one, because
> > that's over 80 columns.
> >
> > I guess you mean the closing triple-
> > the final line of the text. I interpret this situation as a multiline
> > docstring, where AIUI the convention is closing quotes get their own line. I
> > guess you consider the fact it's one sentence to mean it's more like a single
> > line docstring?
>
> No, I meant that I thought the Python convention was that docstrings
> should be a single sentence that fits on a single line, such as
>
> """General Python convenience functions.
> """
>
> Perhaps it doesn't matter if it's on one line and it just needs to be
> a single-sentence paragraph?
In this instance, your proposed one-liner is good enough for me, so let's do
that.
In general, I don't bend over backwards to make the summary sentence fit on one
line: sometimes things really are a bit complex and a short, vague “does stuff”
that forces you to read the body seems to do the reader more of a disservice a
slightly-
It's probably worth checking what pydoc and epydoc do with these overrunning
sentences... As a core developer I'm primarily reading them in the
source directly, but that might not be true for authors of code using bzrlib.
-Andrew.
| Martin Pool (mbp) wrote : | # |
On 5 October 2010 10:55, Andrew Bennetts <email address hidden> wrote:
> In this instance, your proposed one-liner is good enough for me, so let's do
> that.
>
> In general, I don't bend over backwards to make the summary sentence fit on one
> line: sometimes things really are a bit complex and a short, vague “does stuff”
> that forces you to read the body seems to do the reader more of a disservice a
> slightly-
>
> It's probably worth checking what pydoc and epydoc do with these overrunning
> sentences... As a core developer I'm primarily reading them in the
> source directly, but that might not be true for authors of code using bzrlib.
I agree with all that. I stick to it in the unverifiied belief it
might prevent epydoc printing truncated sentences as summaries. It's
not a big deal, just something I noticed.
--
Martin
| Vincent Ladeuil (vila) wrote : | # |
Are there still bits pending review here ?
Or is there a consensus already ?
| Vincent Ladeuil (vila) wrote : | # |
In other words: do you need help from patch pilot or can this be landed ?
| Vincent Ladeuil (vila) wrote : | # |
Ping.
https:/

I would mention get_named_object in the api section of the news, and in the coding standard, so that people do use it in future.
> 2. _LazyObjectGett er(...) .get_obj( ) was buggy,
Is there an actual bug number or user impact for this, or is it just buggy in the sense of being hard to use correctly (which is of course still worth fixing.)
Knowing the modules where all the hook objects can be found seems a bit roundabout to me compared to just actually having the hooks directly in the registry where they can be saved/restored altogether. But this is a cleaner way to implement it.
+known_ hooks.register_ lazy_hook( 'bzrlib. branch' , 'Branch.hooks', 'BranchHooks') hooks.register_ lazy_hook( 'bzrlib. bzrdir' , 'BzrDir.hooks', 'BzrDirHooks') hooks.register_ lazy_hook(
197 +known_
198 +known_
199 + 'bzrlib.commands', 'Command.hooks', 'CommandHooks')
For the sake of readability and to avoid all the line wrapping, could you turn this into a
for (hook_module, hook_attribute_ name, hook_class) in _builtin_ known_hooks: hooks.register_ lazy_hook( hook_module, hook_attribute_ name, hook_class)
known_
+"""Some convenience functions for general Python, such as a wrapper around
+``_import__``.
+"""
Should be a single line.
+def get_named_ object( module_ name, member_name=None):
It's a pretty generic name. Perhaps the name should include 'import' to give you a bit more of a clue, like import_ named_object?
I think this could do with a docstring example (add it to the list of docstrings to test) and it should be feasible to test that way without too much complication. You need to add it to the list anyhow to make the calc_parent_name doctest run.
+ :param module_name: a module name, as found in sys.module. It may contain
+ dots. e.g. 'sys' or 'os.path'.
This seems to imply that it needs to already be in sys.module, but in fact it's fine to call this with a module that might not already be loaded?
Nice removal of duplications there.
tweak