review needs-info
> === modified file 'lib/canonical/launchpad/scripts/logger.py' > --- lib/canonical/launchpad/scripts/logger.py 2009-06-25 05:30:52 +0000 > +++ lib/canonical/launchpad/scripts/logger.py 2009-07-22 02:16:56 +0000 > @@ -113,8 +113,8 @@ > def __init__(self): > self.buffer = StringIO() > > - def message(self, prefix, *stuff, **kw): > - self.buffer.write('%s: %s\n' % (prefix, ' '.join(stuff))) > + def message(self, prefix, msg, *stuff, **kw): > + self.buffer.write('%s: %s\n' % (prefix, msg % stuff))
What is the impact of other code using message?
This to me looks like it'll brake things.
> === modified file 'lib/lp/codehosting/rewrite.py' > --- lib/lp/codehosting/rewrite.py 2009-07-20 21:32:15 +0000 > +++ lib/lp/codehosting/rewrite.py 2009-07-22 03:24:19 +0000 > @@ -5,38 +5,71 @@ > """ > > import time > -import xmlrpclib > > from bzrlib import urlutils > > -from lp.codehosting.vfs import ( > - branch_id_to_path, BranchFileSystemClient) > +from canonical.launchpad.webapp.interfaces import ( > + IStoreSelector, MAIN_STORE, SLAVE_FLAVOR) > +from zope.component import getUtility > +from lp.code.model.branch import Branch > +from lp.codehosting.vfs import branch_id_to_path > + > from canonical.config import config > -from lp.code.interfaces.codehosting import ( > - BRANCH_TRANSPORT, LAUNCHPAD_ANONYMOUS) > -from canonical.launchpad.xmlrpc import faults > -from canonical.twistedsupport import extract_result > > __all__ = ['BranchRewriter'] > > > class BranchRewriter: > > - def __init__(self, logger, proxy): > + def __init__(self, logger, _now=None): > """ > > :param logger: Logger than messages about what the rewriter is doing > will be sent to. > :param proxy: A blocking proxy for a branchfilesystem endpoint. > """ > + if _now is None: > + self._now = time.time > + else: > + self._now = _now > self.logger = logger > - self.client = BranchFileSystemClient(proxy, LAUNCHPAD_ANONYMOUS, 10.0) > + self.store = getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR) > + self._cache = {} > > def _codebrowse_url(self, path): > return urlutils.join( > config.codehosting.internal_codebrowse_root, > path) > > + def _getBranchIdAndTrailingPath(self, location): > + """Return the branch id and trailing path for 'location'. > + > + In addition this method returns whether the answer can from the cache > + or from the database. > + """ > + parts = location[1:].split('/') > + prefixes = [] > + for i in range(1, len(parts) + 1): > + prefix = '/'.join(parts[:i]) > + if prefix in self._cache: > + branch_id, inserted_time = self._cache[prefix] > + if (self._now() < inserted_time + > + config.codehosting.branch_rewrite_cache_lifetime): > + trailing = location[len(prefix) + 1:] > + return branch_id, trailing, "HIT" > + prefixes.append(prefix) > + result = self.store.find( > + Branch, > + Branch.unique_name.is_in(prefixes), Branch.private == False) > + try: > + branch_id, unique_name = result.values( > + Branch.id, Branch.unique_name).next() > + except StopIteration: > + return None, None, "MISS"
How about:
result = self.store.find( (Branch.id, Branch.unique_name), Branch.unique_name.is_in(prefixes), Branch.private == False).one()
That way result should be None if not found, and a tuple of id and unique_name if it was found.
That'll make this code a little cleaner.
> === modified file 'lib/lp/codehosting/tests/test_rewrite.py' > --- lib/lp/codehosting/tests/test_rewrite.py 2009-07-17 00:26:05 +0000 > +++ lib/lp/codehosting/tests/test_rewrite.py 2009-07-22 03:23:28 +0000 > class TestBranchRewriterScript(TestCaseWithFactory): > > - layer = ZopelessAppServerLayer > + layer = DatabaseFunctionalLayer > > def test_script(self):
I think a comment here explaining why you have '\n'.join(expected) + '\n' would be *really* helpful.
I think it has todo with how the rewriting works through apache, but a comment would help.
> - branch = self.factory.makeAnyBranch() > - input = "/%s/.bzr/README\n" % branch.unique_name > - expected = ( > - "file:///var/tmp/bzrsync/%s/.bzr/README\n" > - % branch_id_to_path(branch.id)) > - self.layer.txn.commit() > + branches = [ > + self.factory.makeProductBranch(), > + self.factory.makePersonalBranch(), > + self.factory.makePackageBranch()] > + input = [ > + "/%s/.bzr/README" % branch.unique_name > + for branch in branches] + [ > + "/%s/changes" % branch.unique_name > + for branch in branches] > + expected = [ > + 'file:///var/tmp/bzrsync/%s/.bzr/README' > + % branch_id_to_path(branch.id) > + for branch in branches] + [ > + 'http://localhost:8080/%s/changes' % branch.unique_name > + for branch in branches] > + transaction.commit() > script_file = os.path.join( > config.root, 'scripts', 'branch-rewrite.py') > proc = subprocess.Popen( > [script_file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, > stderr=subprocess.PIPE, bufsize=0) > - proc.stdin.write(input) > - output = proc.stdout.readline() > + proc.stdin.write('\n'.join(input) + '\n')
A comment here too about why the extra carriage return.
> + output = [] > + for i in range(len(input)): > + output.append(proc.stdout.readline()) > os.kill(proc.pid, signal.SIGINT) > err = proc.stderr.read() > # The script produces logging output, but not to stderr. > self.assertEqual('', err) > - self.assertEqual(expected, output) > + self.assertEqual('\n'.join(expected) + '\n', ''.join(output)) > > > def test_suite(): >
I look forward to seeing this tested live :)
Thanks Tim
« Back to merge proposal
review needs-info
> === modified file 'lib/canonical/ launchpad/ scripts/ logger. py' launchpad/ scripts/ logger. py 2009-06-25 05:30:52 +0000 launchpad/ scripts/ logger. py 2009-07-22 02:16:56 +0000 write(' %s: %s\n' % (prefix, ' '.join(stuff))) write(' %s: %s\n' % (prefix, msg % stuff))
> --- lib/canonical/
> +++ lib/canonical/
> @@ -113,8 +113,8 @@
> def __init__(self):
> self.buffer = StringIO()
>
> - def message(self, prefix, *stuff, **kw):
> - self.buffer.
> + def message(self, prefix, msg, *stuff, **kw):
> + self.buffer.
What is the impact of other code using message?
This to me looks like it'll brake things.
> === modified file 'lib/lp/ codehosting/ rewrite. py' codehosting/ rewrite. py 2009-07-20 21:32:15 +0000 codehosting/ rewrite. py 2009-07-22 03:24:19 +0000 mClient) launchpad. webapp. interfaces import ( model.branch import Branch interfaces. codehosting import ( ANONYMOUS) launchpad. xmlrpc import faults twistedsupport import extract_result mClient( proxy, LAUNCHPAD_ ANONYMOUS, IStoreSelector) .get(MAIN_ STORE, url(self, path): codehosting. internal_ codebrowse_ root, TrailingPath( self, location): 1:].split( '/') codehosting. branch_ rewrite_ cache_lifetime) : len(prefix) + 1:] append( prefix) unique_ name.is_ in(prefixes) , Branch.private == False) unique_ name).next( )
> --- lib/lp/
> +++ lib/lp/
> @@ -5,38 +5,71 @@
> """
>
> import time
> -import xmlrpclib
>
> from bzrlib import urlutils
>
> -from lp.codehosting.vfs import (
> - branch_id_to_path, BranchFileSyste
> +from canonical.
> + IStoreSelector, MAIN_STORE, SLAVE_FLAVOR)
> +from zope.component import getUtility
> +from lp.code.
> +from lp.codehosting.vfs import branch_id_to_path
> +
> from canonical.config import config
> -from lp.code.
> - BRANCH_TRANSPORT, LAUNCHPAD_
> -from canonical.
> -from canonical.
>
> __all__ = ['BranchRewriter']
>
>
> class BranchRewriter:
>
> - def __init__(self, logger, proxy):
> + def __init__(self, logger, _now=None):
> """
>
> :param logger: Logger than messages about what the rewriter is
doing
> will be sent to.
> :param proxy: A blocking proxy for a branchfilesystem endpoint.
> """
> + if _now is None:
> + self._now = time.time
> + else:
> + self._now = _now
> self.logger = logger
> - self.client = BranchFileSyste
10.0)
> + self.store = getUtility(
SLAVE_FLAVOR)
> + self._cache = {}
>
> def _codebrowse_
> return urlutils.join(
> config.
> path)
>
> + def _getBranchIdAnd
> + """Return the branch id and trailing path for 'location'.
> +
> + In addition this method returns whether the answer can from the
cache
> + or from the database.
> + """
> + parts = location[
> + prefixes = []
> + for i in range(1, len(parts) + 1):
> + prefix = '/'.join(parts[:i])
> + if prefix in self._cache:
> + branch_id, inserted_time = self._cache[prefix]
> + if (self._now() < inserted_time +
> + config.
> + trailing = location[
> + return branch_id, trailing, "HIT"
> + prefixes.
> + result = self.store.find(
> + Branch,
> + Branch.
> + try:
> + branch_id, unique_name = result.values(
> + Branch.id, Branch.
> + except StopIteration:
> + return None, None, "MISS"
How about:
result = self.store.find(
(Branch. id, Branch. unique_ name),
Branch. unique_ name.is_ in(prefixes) , Branch.private == False).one()
That way result should be None if not found, and a tuple of id and unique_name
if it was found.
That'll make this code a little cleaner.
> === modified file 'lib/lp/ codehosting/ tests/test_ rewrite. py' codehosting/ tests/test_ rewrite. py 2009-07-17 00:26:05 +0000 codehosting/ tests/test_ rewrite. py 2009-07-22 03:23:28 +0000 terScript( TestCaseWithFac tory): erLayer nalLayer
> --- lib/lp/
> +++ lib/lp/
> class TestBranchRewri
>
> - layer = ZopelessAppServ
> + layer = DatabaseFunctio
>
> def test_script(self):
I think a comment here explaining why you have '\n'.join(expected) + '\n'
would be *really* helpful.
I think it has todo with how the rewriting works through apache, but a
comment would help.
> - branch = self.factory. makeAnyBranch( ) //var/tmp/ bzrsync/ %s/.bzr/ README\ n" id_to_path( branch. id)) txn.commit( ) makeProductBran ch(), makePersonalBra nch(), makePackageBran ch()] //var/tmp/ bzrsync/ %s/.bzr/ README' id_to_path( branch. id) localhost: 8080/%s/ changes' % branch.unique_name commit( ) rewrite. py') s.PIPE, stdout= subprocess. PIPE, subprocess. PIPE, bufsize=0) write(input) readline( ) write(' \n'.join( input) + '\n')
> - input = "/%s/.bzr/README\n" % branch.unique_name
> - expected = (
> - "file:/
> - % branch_
> - self.layer.
> + branches = [
> + self.factory.
> + self.factory.
> + self.factory.
> + input = [
> + "/%s/.bzr/README" % branch.unique_name
> + for branch in branches] + [
> + "/%s/changes" % branch.unique_name
> + for branch in branches]
> + expected = [
> + 'file:/
> + % branch_
> + for branch in branches] + [
> + 'http://
> + for branch in branches]
> + transaction.
> script_file = os.path.join(
> config.root, 'scripts', 'branch-
> proc = subprocess.Popen(
> [script_file], stdin=subproces
> stderr=
> - proc.stdin.
> - output = proc.stdout.
> + proc.stdin.
A comment here too about why the extra carriage return.
> + output = [] append( proc.stdout. readline( )) l('', err) l(expected, output) l('\n'. join(expected) + '\n', ''.join(output))
> + for i in range(len(input)):
> + output.
> os.kill(proc.pid, signal.SIGINT)
> err = proc.stderr.read()
> # The script produces logging output, but not to stderr.
> self.assertEqua
> - self.assertEqua
> + self.assertEqua
>
>
> def test_suite():
>
I look forward to seeing this tested live :)
Thanks
Tim