launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01109
[Merge] lp:~mwhudson/launchpad/move-some-code-vocabularies into lp:launchpad/devel
Michael Hudson-Doyle has proposed merging lp:~mwhudson/launchpad/move-some-code-vocabularies into lp:launchpad/devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Hi,
This lunch hour branch moves the remaining code-related vocabularies to the lp.code tree.
Cheers,
mwh
--
https://code.launchpad.net/~mwhudson/launchpad/move-some-code-vocabularies/+merge/35974
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~mwhudson/launchpad/move-some-code-vocabularies into lp:launchpad/devel.
=== modified file 'lib/canonical/launchpad/browser/tests/test_widgets.py'
--- lib/canonical/launchpad/browser/tests/test_widgets.py 2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/browser/tests/test_widgets.py 2010-09-20 00:51:46 +0000
@@ -24,7 +24,7 @@
login,
logout,
)
-from canonical.launchpad.vocabularies import (
+from lp.code.vocabularies.branch import (
BranchRestrictedOnProductVocabulary,
BranchVocabulary,
)
=== modified file 'lib/canonical/launchpad/doc/vocabularies.txt'
--- lib/canonical/launchpad/doc/vocabularies.txt 2010-08-27 14:27:22 +0000
+++ lib/canonical/launchpad/doc/vocabularies.txt 2010-09-20 00:51:46 +0000
@@ -364,143 +364,6 @@
[('pmount', u'pmount')]
-BranchVocabulary
-................
-
-The list of bzr branches registered in Launchpad.
-
-Searchable by branch name or URL, registrant name, and project name.
-Results are not restricted in any way by the context, but the results
-are restricted based on who is asking (as far as private branches is
-concerned).
-
- # Just use None as the context.
- >>> branch_vocabulary = get_naked_vocab(None, "Branch")
- >>> def print_vocab_branches(vocab, search):
- ... for term in vocab.searchForTerms(search):
- ... print term.value.unique_name
-
- >>> print_vocab_branches(branch_vocabulary, 'main')
- ~name12/firefox/main
- ~stevea/thunderbird/main
- ~justdave/+junk/main
- ~kiko/+junk/main
- ~vcs-imports/evolution/main
- ~name12/gnome-terminal/main
-
- >>> print_vocab_branches(branch_vocabulary, 'vcs-imports')
- ~vcs-imports/gnome-terminal/import
- ~vcs-imports/evolution/import
- ~vcs-imports/evolution/main
-
- >>> print_vocab_branches(branch_vocabulary, 'evolution')
- ~carlos/evolution/2.0
- ~vcs-imports/evolution/import
- ~vcs-imports/evolution/main
-
-A search with the full branch unique name should also find the branch.
-
- >>> print_vocab_branches(branch_vocabulary, '~name12/firefox/main')
- ~name12/firefox/main
-
-The tokens used by terms retrieved from BranchVocabulary use the
-branch unique name as an ID:
-
- >>> from lp.code.interfaces.branchlookup import IBranchLookup
- >>> branch = getUtility(IBranchLookup).get(15)
- >>> print branch.unique_name
- ~name12/gnome-terminal/main
- >>> term = branch_vocabulary.toTerm(branch)
- >>> print term.token
- ~name12/gnome-terminal/main
-
-The BranchVocabulary recognises both unique names and URLs as tokens:
-
- >>> term = branch_vocabulary.getTermByToken('~name12/gnome-terminal/main')
- >>> term.value == branch
- True
- >>> term = branch_vocabulary.getTermByToken(
- ... 'http://bazaar.launchpad.dev/~name12/gnome-terminal/main/')
- >>> term.value == branch
- True
- >>> term = branch_vocabulary.getTermByToken(
- ... 'http://example.com/gnome-terminal/main')
- >>> term.value == branch
- True
-
-The searches that the BranchVocabulary does are private branch aware.
-The results are effectively filtered on what the logged in user is
-able to see.
-
- >>> print_vocab_branches(branch_vocabulary, 'trunk')
- ~spiv/+junk/trunk
- ~limi/+junk/trunk
- ~landscape-developers/landscape/trunk
-
- >>> login('no-priv@xxxxxxxxxxxxx')
- >>> print_vocab_branches(branch_vocabulary, 'trunk')
- ~spiv/+junk/trunk
- ~limi/+junk/trunk
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
-
-
-BranchRestrictedOnProduct
-.........................
-
-The BranchRestrictedOnProduct vocabulary restricts the result set to
-those of the product of the context. Currently only two types of
-context are supported: Product; and Branch. If a branch is the context,
-then the product of the branch is used to restrict the query.
-
- >>> gnome_terminal = getUtility(IProductSet)["gnome-terminal"]
- >>> branch_vocabulary = vocabulary_registry.get(
- ... gnome_terminal, "BranchRestrictedOnProduct")
- >>> print_vocab_branches(branch_vocabulary, 'main')
- ~name12/gnome-terminal/main
-
- >>> print_vocab_branches(branch_vocabulary, 'vcs-imports')
- ~vcs-imports/gnome-terminal/import
-
-If a full unique name is entered that has a different product, the
-branch is not part of the vocabulary.
-
- >>> print_vocab_branches(branch_vocabulary, '~name12/gnome-terminal/main')
- ~name12/gnome-terminal/main
-
- >>> print_vocab_branches(branch_vocabulary, '~name12/firefox/main')
-
-
-The BranchRestrictedOnProduct behaves the same way as the more generic
-BranchVocabulary with respect to the tokens and privacy awareness.
-
-
-HostedBranchRestrictedOnOwner
-.............................
-
-Here's a vocabulary for all hosted branches owned by the current user.
-
- >>> from lp.code.enums import BranchType
-
- >>> a_user = factory.makePerson(name='a-branching-user')
- >>> product1 = factory.makeProduct(name='product-one')
- >>> mirrored_branch = factory.makeBranch(
- ... owner=a_user, product=product1, name='mirrored',
- ... branch_type=BranchType.MIRRORED)
- >>> product2 = factory.makeProduct(name='product-two')
- >>> hosted_branch = factory.makeBranch(
- ... owner=a_user, product=product2, name='hosted')
- >>> foreign_branch = factory.makeBranch()
-
-It returns branches owned by the user, but not ones owned by others, nor
-ones that aren't hosted on Launchpad.
-
- >>> branch_vocabulary = vocabulary_registry.get(
- ... a_user, "HostedBranchRestrictedOnOwner")
- >>> print_vocab_branches(branch_vocabulary, None)
- ~a-branching-user/product-two/hosted
-
-
Processor
.........
=== modified file 'lib/canonical/launchpad/vocabularies/configure.zcml'
--- lib/canonical/launchpad/vocabularies/configure.zcml 2010-08-25 04:12:59 +0000
+++ lib/canonical/launchpad/vocabularies/configure.zcml 2010-09-20 00:51:46 +0000
@@ -13,45 +13,6 @@
</class>
<securedutility
- name="Branch"
- component="canonical.launchpad.vocabularies.BranchVocabulary"
- provides="zope.schema.interfaces.IVocabularyFactory"
- >
- <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
- </securedutility>
-
- <class class="canonical.launchpad.vocabularies.BranchVocabulary">
- <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
- </class>
-
-
- <securedutility
- name="HostedBranchRestrictedOnOwner"
- component="canonical.launchpad.vocabularies.HostedBranchRestrictedOnOwnerVocabulary"
- provides="zope.schema.interfaces.IVocabularyFactory"
- >
- <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
- </securedutility>
-
- <class class="canonical.launchpad.vocabularies.HostedBranchRestrictedOnOwnerVocabulary">
- <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
- </class>
-
-
- <securedutility
- name="BranchRestrictedOnProduct"
- component="canonical.launchpad.vocabularies.BranchRestrictedOnProductVocabulary"
- provides="zope.schema.interfaces.IVocabularyFactory"
- >
- <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
- </securedutility>
-
- <class class="canonical.launchpad.vocabularies.BranchRestrictedOnProductVocabulary">
- <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
- </class>
-
-
- <securedutility
name="Bug"
component="canonical.launchpad.vocabularies.BugVocabulary"
provides="zope.schema.interfaces.IVocabularyFactory"
=== modified file 'lib/canonical/launchpad/vocabularies/dbobjects.py'
--- lib/canonical/launchpad/vocabularies/dbobjects.py 2010-08-27 14:27:22 +0000
+++ lib/canonical/launchpad/vocabularies/dbobjects.py 2010-09-20 00:51:46 +0000
@@ -1,5 +1,5 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
+# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the GNU
+# Affero General Public License version 3 (see the file LICENSE).
"""Vocabularies pulling stuff from the database.
@@ -10,8 +10,6 @@
__metaclass__ = type
__all__ = [
- 'BranchRestrictedOnProductVocabulary',
- 'BranchVocabulary',
'BugNominatableDistroSeriesVocabulary',
'BugNominatableProductSeriesVocabulary',
'BugNominatableSeriesVocabulary',
@@ -26,7 +24,6 @@
'FilteredFullLanguagePackVocabulary',
'FilteredLanguagePackVocabulary',
'FutureSprintVocabulary',
- 'HostedBranchRestrictedOnOwnerVocabulary',
'LanguageVocabulary',
'PackageReleaseVocabulary',
'PPAVocabulary',
@@ -92,15 +89,8 @@
from lp.bugs.interfaces.bugtracker import BugTrackerType
from lp.bugs.model.bug import Bug
from lp.bugs.model.bugtracker import BugTracker
-from lp.code.enums import BranchType
-from lp.code.interfaces.branch import IBranch
-from lp.code.interfaces.branchcollection import IAllBranches
-from lp.code.model.branch import Branch
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distroseries import IDistroSeries
-from lp.registry.interfaces.person import IPerson
-from lp.registry.interfaces.product import IProduct
-from lp.registry.interfaces.productseries import IProductSeries
from lp.registry.interfaces.projectgroup import IProjectGroup
from lp.registry.interfaces.series import SeriesStatus
from lp.registry.model.distribution import Distribution
@@ -146,106 +136,6 @@
return SimpleTerm(obj, obj.id, obj.name)
-class BranchVocabularyBase(SQLObjectVocabularyBase):
- """A base class for Branch vocabularies.
-
- Override `BranchVocabularyBase._getCollection` to provide the collection
- of branches which make up the vocabulary.
- """
-
- implements(IHugeVocabulary)
-
- _table = Branch
- _orderBy = ['name', 'id']
- displayname = 'Select a branch'
-
- def toTerm(self, branch):
- """The display should include the URL if there is one."""
- return SimpleTerm(branch, branch.unique_name, branch.unique_name)
-
- def getTermByToken(self, token):
- """See `IVocabularyTokenized`."""
- search_results = self.searchForTerms(token)
- if search_results.count() == 1:
- return iter(search_results).next()
- raise LookupError(token)
-
- def _getCollection(self):
- """Override this to return the collection to which the search is
- restricted.
- """
- raise NotImplementedError(self._getCollection)
-
- def searchForTerms(self, query=None):
- """See `IHugeVocabulary`."""
- logged_in_user = getUtility(ILaunchBag).user
- collection = self._getCollection().visibleByUser(logged_in_user)
- if query is None:
- branches = collection.getBranches()
- else:
- branches = collection.search(query)
- return CountableIterator(branches.count(), branches, self.toTerm)
-
- def __len__(self):
- """See `IVocabulary`."""
- return self.search().count()
-
-
-class BranchVocabulary(BranchVocabularyBase):
- """A vocabulary for searching branches.
-
- The name and URL of the branch, the name of the product, and the
- name of the registrant of the branches is checked for the entered
- value.
- """
-
- def _getCollection(self):
- return getUtility(IAllBranches)
-
-
-class BranchRestrictedOnProductVocabulary(BranchVocabularyBase):
- """A vocabulary for searching branches restricted on product.
-
- The query entered checks the name or URL of the branch, or the
- name of the registrant of the branch.
- """
-
- def __init__(self, context=None):
- BranchVocabularyBase.__init__(self, context)
- if IProduct.providedBy(self.context):
- self.product = self.context
- elif IProductSeries.providedBy(self.context):
- self.product = self.context.product
- elif IBranch.providedBy(self.context):
- self.product = self.context.product
- else:
- # An unexpected type.
- raise AssertionError('Unexpected context type')
-
- def _getCollection(self):
- return getUtility(IAllBranches).inProduct(self.product)
-
-
-class HostedBranchRestrictedOnOwnerVocabulary(BranchVocabularyBase):
- """A vocabulary for hosted branches owned by the current user.
-
- These are branches that the user is guaranteed to be able to push
- to.
- """
-
- def __init__(self, context=None):
- """Pass a Person as context, or anything else for the current user."""
- super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context)
- if IPerson.providedBy(self.context):
- self.user = context
- else:
- self.user = getUtility(ILaunchBag).user
-
- def _getCollection(self):
- return getUtility(IAllBranches).ownedBy(self.user).withBranchType(
- BranchType.HOSTED)
-
-
class BugVocabulary(SQLObjectVocabularyBase):
_table = Bug
=== modified file 'lib/canonical/launchpad/webapp/configure.zcml'
--- lib/canonical/launchpad/webapp/configure.zcml 2010-09-10 06:38:15 +0000
+++ lib/canonical/launchpad/webapp/configure.zcml 2010-09-20 00:51:46 +0000
@@ -828,7 +828,7 @@
<view
type="zope.publisher.interfaces.browser.IBrowserRequest"
for="zope.schema.interfaces.IChoice
- canonical.launchpad.vocabularies.dbobjects.BranchVocabularyBase"
+ lp.code.vocabularies.branch.BranchVocabularyBase"
provides="zope.app.form.interfaces.IInputWidget"
factory="canonical.launchpad.browser.widgets.BranchPopupWidget"
permission="zope.Public"
=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml 2010-08-24 02:17:19 +0000
+++ lib/lp/code/browser/configure.zcml 2010-09-20 00:51:46 +0000
@@ -1306,19 +1306,5 @@
factory="canonical.launchpad.webapp.breadcrumb.NameBreadcrumb"
permission="zope.Public"/>
</facet>
- <securedutility
- name="BuildableDistroSeries"
- component="lp.code.vocabularies.sourcepackagerecipe.buildable_distroseries_vocabulary"
- provides="zope.schema.interfaces.IVocabularyFactory"
- >
- <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
- </securedutility>
- <securedutility
- name="TargetPPAs"
- component="lp.code.vocabularies.sourcepackagerecipe.target_ppas_vocabulary"
- provides="zope.schema.interfaces.IVocabularyFactory"
- >
- <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
- </securedutility>
</configure>
=== modified file 'lib/lp/code/configure.zcml'
--- lib/lp/code/configure.zcml 2010-09-13 04:56:29 +0000
+++ lib/lp/code/configure.zcml 2010-09-20 00:51:46 +0000
@@ -11,6 +11,7 @@
xmlns:webservice="http://namespaces.canonical.com/webservice"
i18n_domain="launchpad">
<include package=".browser"/>
+ <include package=".vocabularies"/>
<authorizations module="lp.code.security" />
<publisher
=== added file 'lib/lp/code/vocabularies/branch.py'
--- lib/lp/code/vocabularies/branch.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/vocabularies/branch.py 2010-09-20 00:51:46 +0000
@@ -0,0 +1,132 @@
+# Copyright 2009 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Vocabularies that contain branches."""
+
+
+__metaclass__ = type
+
+__all__ = [
+ 'BranchRestrictedOnProductVocabulary',
+ 'BranchVocabulary',
+ 'HostedBranchRestrictedOnOwnerVocabulary',
+ ]
+
+from zope.component import getUtility
+from zope.interface import implements
+from zope.schema.vocabulary import SimpleTerm
+
+from canonical.launchpad.webapp.interfaces import ILaunchBag
+from canonical.launchpad.webapp.vocabulary import (
+ CountableIterator,
+ IHugeVocabulary,
+ SQLObjectVocabularyBase,
+ )
+
+from lp.code.enums import BranchType
+from lp.code.interfaces.branch import IBranch
+from lp.code.interfaces.branchcollection import IAllBranches
+from lp.code.model.branch import Branch
+from lp.registry.interfaces.person import IPerson
+from lp.registry.interfaces.product import IProduct
+from lp.registry.interfaces.productseries import IProductSeries
+
+
+class BranchVocabularyBase(SQLObjectVocabularyBase):
+ """A base class for Branch vocabularies.
+
+ Override `BranchVocabularyBase._getCollection` to provide the collection
+ of branches which make up the vocabulary.
+ """
+
+ implements(IHugeVocabulary)
+
+ _table = Branch
+ _orderBy = ['name', 'id']
+ displayname = 'Select a branch'
+
+ def toTerm(self, branch):
+ """The display should include the URL if there is one."""
+ return SimpleTerm(branch, branch.unique_name, branch.unique_name)
+
+ def getTermByToken(self, token):
+ """See `IVocabularyTokenized`."""
+ search_results = self.searchForTerms(token)
+ if search_results.count() == 1:
+ return iter(search_results).next()
+ raise LookupError(token)
+
+ def _getCollection(self):
+ """Override this to return the collection to which the search is
+ restricted.
+ """
+ raise NotImplementedError(self._getCollection)
+
+ def searchForTerms(self, query=None):
+ """See `IHugeVocabulary`."""
+ logged_in_user = getUtility(ILaunchBag).user
+ collection = self._getCollection().visibleByUser(logged_in_user)
+ if query is None:
+ branches = collection.getBranches()
+ else:
+ branches = collection.search(query)
+ return CountableIterator(branches.count(), branches, self.toTerm)
+
+ def __len__(self):
+ """See `IVocabulary`."""
+ return self.search().count()
+
+
+class BranchVocabulary(BranchVocabularyBase):
+ """A vocabulary for searching branches.
+
+ The name and URL of the branch, the name of the product, and the
+ name of the registrant of the branches is checked for the entered
+ value.
+ """
+
+ def _getCollection(self):
+ return getUtility(IAllBranches)
+
+
+class BranchRestrictedOnProductVocabulary(BranchVocabularyBase):
+ """A vocabulary for searching branches restricted on product.
+
+ The query entered checks the name or URL of the branch, or the
+ name of the registrant of the branch.
+ """
+
+ def __init__(self, context=None):
+ BranchVocabularyBase.__init__(self, context)
+ if IProduct.providedBy(self.context):
+ self.product = self.context
+ elif IProductSeries.providedBy(self.context):
+ self.product = self.context.product
+ elif IBranch.providedBy(self.context):
+ self.product = self.context.product
+ else:
+ # An unexpected type.
+ raise AssertionError('Unexpected context type')
+
+ def _getCollection(self):
+ return getUtility(IAllBranches).inProduct(self.product)
+
+
+class HostedBranchRestrictedOnOwnerVocabulary(BranchVocabularyBase):
+ """A vocabulary for hosted branches owned by the current user.
+
+ These are branches that the user is guaranteed to be able to push
+ to.
+ """
+
+ def __init__(self, context=None):
+ """Pass a Person as context, or anything else for the current user."""
+ super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context)
+ if IPerson.providedBy(self.context):
+ self.user = context
+ else:
+ self.user = getUtility(ILaunchBag).user
+
+ def _getCollection(self):
+ return getUtility(IAllBranches).ownedBy(self.user).withBranchType(
+ BranchType.HOSTED)
=== added file 'lib/lp/code/vocabularies/configure.zcml'
--- lib/lp/code/vocabularies/configure.zcml 1970-01-01 00:00:00 +0000
+++ lib/lp/code/vocabularies/configure.zcml 2010-09-20 00:51:46 +0000
@@ -0,0 +1,54 @@
+<!-- Copyright 2010 Canonical Ltd. This software is licensed under the
+ GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <securedutility
+ name="BuildableDistroSeries"
+ component=".sourcepackagerecipe.buildable_distroseries_vocabulary"
+ provides="zope.schema.interfaces.IVocabularyFactory">
+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
+ </securedutility>
+
+ <securedutility
+ name="TargetPPAs"
+ component=".sourcepackagerecipe.target_ppas_vocabulary"
+ provides="zope.schema.interfaces.IVocabularyFactory">
+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
+ </securedutility>
+
+ <securedutility
+ name="Branch"
+ component=".branch.BranchVocabulary"
+ provides="zope.schema.interfaces.IVocabularyFactory">
+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
+ </securedutility>
+
+ <class class=".branch.BranchVocabulary">
+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
+ </class>
+
+ <securedutility
+ name="HostedBranchRestrictedOnOwner"
+ component=".branch.HostedBranchRestrictedOnOwnerVocabulary"
+ provides="zope.schema.interfaces.IVocabularyFactory">
+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
+ </securedutility>
+
+ <class class=".branch.HostedBranchRestrictedOnOwnerVocabulary">
+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
+ </class>
+
+ <securedutility
+ name="BranchRestrictedOnProduct"
+ component=".branch.BranchRestrictedOnProductVocabulary"
+ provides="zope.schema.interfaces.IVocabularyFactory">
+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
+ </securedutility>
+
+ <class class=".branch.BranchRestrictedOnProductVocabulary">
+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
+ </class>
+
+</configure>
=== added file 'lib/lp/code/vocabularies/tests/branch.txt'
--- lib/lp/code/vocabularies/tests/branch.txt 1970-01-01 00:00:00 +0000
+++ lib/lp/code/vocabularies/tests/branch.txt 2010-09-20 00:51:46 +0000
@@ -0,0 +1,148 @@
+Branch Vocabularies
+===================
+
+Launchpad has a few vocabularies that contain branches filtered in
+various ways.
+
+ >>> from zope.schema.vocabulary import getVocabularyRegistry
+ >>> vocabulary_registry = getVocabularyRegistry()
+
+BranchVocabulary
+----------------
+
+The list of bzr branches registered in Launchpad.
+
+Searchable by branch name or URL, registrant name, and project name.
+Results are not restricted in any way by the context, but the results
+are restricted based on who is asking (as far as private branches is
+concerned).
+
+ # Just use None as the context.
+ >>> branch_vocabulary = vocabulary_registry.get(None, "Branch")
+ >>> def print_vocab_branches(vocab, search):
+ ... for term in vocab.searchForTerms(search):
+ ... print term.value.unique_name
+
+ >>> print_vocab_branches(branch_vocabulary, 'main')
+ ~name12/firefox/main
+ ~stevea/thunderbird/main
+ ~justdave/+junk/main
+ ~kiko/+junk/main
+ ~vcs-imports/evolution/main
+ ~name12/gnome-terminal/main
+
+ >>> print_vocab_branches(branch_vocabulary, 'vcs-imports')
+ ~vcs-imports/gnome-terminal/import
+ ~vcs-imports/evolution/import
+ ~vcs-imports/evolution/main
+
+ >>> print_vocab_branches(branch_vocabulary, 'evolution')
+ ~carlos/evolution/2.0
+ ~vcs-imports/evolution/import
+ ~vcs-imports/evolution/main
+
+A search with the full branch unique name should also find the branch.
+
+ >>> print_vocab_branches(branch_vocabulary, '~name12/firefox/main')
+ ~name12/firefox/main
+
+The tokens used by terms retrieved from BranchVocabulary use the
+branch unique name as an ID:
+
+ >>> from lp.code.interfaces.branchlookup import IBranchLookup
+ >>> branch = getUtility(IBranchLookup).get(15)
+ >>> print branch.unique_name
+ ~name12/gnome-terminal/main
+ >>> from zope.security.proxy import removeSecurityProxy
+ >>> term = removeSecurityProxy(branch_vocabulary).toTerm(branch)
+ >>> print term.token
+ ~name12/gnome-terminal/main
+
+The BranchVocabulary recognises both unique names and URLs as tokens:
+
+ >>> term = branch_vocabulary.getTermByToken('~name12/gnome-terminal/main')
+ >>> term.value == branch
+ True
+ >>> term = branch_vocabulary.getTermByToken(
+ ... 'http://bazaar.launchpad.dev/~name12/gnome-terminal/main/')
+ >>> term.value == branch
+ True
+ >>> term = branch_vocabulary.getTermByToken(
+ ... 'http://example.com/gnome-terminal/main')
+ >>> term.value == branch
+ True
+
+The searches that the BranchVocabulary does are private branch aware.
+The results are effectively filtered on what the logged in user is
+able to see.
+
+ >>> from lp.testing import login, ANONYMOUS
+ >>> from lp.testing.sampledata import ADMIN_EMAIL
+
+ >>> login(ADMIN_EMAIL)
+ >>> print_vocab_branches(branch_vocabulary, 'trunk')
+ ~spiv/+junk/trunk
+ ~limi/+junk/trunk
+ ~landscape-developers/landscape/trunk
+
+ >>> login(ANONYMOUS)
+ >>> print_vocab_branches(branch_vocabulary, 'trunk')
+ ~spiv/+junk/trunk
+ ~limi/+junk/trunk
+
+
+BranchRestrictedOnProduct
+-------------------------
+
+The BranchRestrictedOnProduct vocabulary restricts the result set to
+those of the product of the context. Currently only two types of
+context are supported: Product; and Branch. If a branch is the context,
+then the product of the branch is used to restrict the query.
+
+ >>> from lp.registry.interfaces.product import IProductSet
+ >>> gnome_terminal = getUtility(IProductSet)["gnome-terminal"]
+ >>> branch_vocabulary = vocabulary_registry.get(
+ ... gnome_terminal, "BranchRestrictedOnProduct")
+ >>> print_vocab_branches(branch_vocabulary, 'main')
+ ~name12/gnome-terminal/main
+
+ >>> print_vocab_branches(branch_vocabulary, 'vcs-imports')
+ ~vcs-imports/gnome-terminal/import
+
+If a full unique name is entered that has a different product, the
+branch is not part of the vocabulary.
+
+ >>> print_vocab_branches(branch_vocabulary, '~name12/gnome-terminal/main')
+ ~name12/gnome-terminal/main
+
+ >>> print_vocab_branches(branch_vocabulary, '~name12/firefox/main')
+
+
+The BranchRestrictedOnProduct behaves the same way as the more generic
+BranchVocabulary with respect to the tokens and privacy awareness.
+
+
+HostedBranchRestrictedOnOwner
+-----------------------------
+
+Here's a vocabulary for all hosted branches owned by the current user.
+
+ >>> from lp.code.enums import BranchType
+
+ >>> a_user = factory.makePerson(name='a-branching-user')
+ >>> product1 = factory.makeProduct(name='product-one')
+ >>> mirrored_branch = factory.makeBranch(
+ ... owner=a_user, product=product1, name='mirrored',
+ ... branch_type=BranchType.MIRRORED)
+ >>> product2 = factory.makeProduct(name='product-two')
+ >>> hosted_branch = factory.makeBranch(
+ ... owner=a_user, product=product2, name='hosted')
+ >>> foreign_branch = factory.makeBranch()
+
+It returns branches owned by the user, but not ones owned by others, nor
+ones that aren't hosted on Launchpad.
+
+ >>> branch_vocabulary = vocabulary_registry.get(
+ ... a_user, "HostedBranchRestrictedOnOwner")
+ >>> print_vocab_branches(branch_vocabulary, None)
+ ~a-branching-user/product-two/hosted
=== modified file 'lib/lp/code/vocabularies/tests/test_branch_vocabularies.py'
--- lib/lp/code/vocabularies/tests/test_branch_vocabularies.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/vocabularies/tests/test_branch_vocabularies.py 2010-09-20 00:51:46 +0000
@@ -17,7 +17,7 @@
login,
logout,
)
-from canonical.launchpad.vocabularies.dbobjects import (
+from lp.code.vocabularies.branch import (
BranchRestrictedOnProductVocabulary,
BranchVocabulary,
)
=== added file 'lib/lp/code/vocabularies/tests/test_doc.py'
--- lib/lp/code/vocabularies/tests/test_doc.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/vocabularies/tests/test_doc.py 2010-09-20 00:51:46 +0000
@@ -0,0 +1,17 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""
+Run the doctests.
+"""
+
+import os
+
+from lp.services.testing import build_doctest_suite
+
+
+here = os.path.dirname(os.path.realpath(__file__))
+
+
+def test_suite():
+ return build_doctest_suite(here, '')