launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #17731
[Merge] lp:~cjwatson/launchpad/branchnamespace-names into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/branchnamespace-names into lp:launchpad.
Commit message:
Rename branch namespace classes to make it clearer that they're specifically for branches.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/branchnamespace-names/+merge/247868
Rename branch namespace classes to make it clearer that they're specifically for branches. While we're here, rename Product[Branch]Namespace to ProjectBranchNamespace, in line with the general direction of product/project/project-group naming.
This paves the way for other namespaces which are not for branches.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/branchnamespace-names into lp:launchpad.
=== modified file 'lib/lp/code/configure.zcml'
--- lib/lp/code/configure.zcml 2014-11-28 22:07:05 +0000
+++ lib/lp/code/configure.zcml 2015-01-28 17:00:36 +0000
@@ -503,15 +503,15 @@
max_diff_lines
review_level"/>
</class>
- <class class="lp.code.model.branchnamespace.PackageNamespace">
- <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespace"/>
- <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespacePolicy"/>
- </class>
- <class class="lp.code.model.branchnamespace.PersonalNamespace">
- <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespace"/>
- <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespacePolicy"/>
- </class>
- <class class="lp.code.model.branchnamespace.ProductNamespace">
+ <class class="lp.code.model.branchnamespace.PackageBranchNamespace">
+ <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespace"/>
+ <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespacePolicy"/>
+ </class>
+ <class class="lp.code.model.branchnamespace.PersonalBranchNamespace">
+ <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespace"/>
+ <allow interface="lp.code.interfaces.branchnamespace.IBranchNamespacePolicy"/>
+ </class>
+ <class class="lp.code.model.branchnamespace.ProjectBranchNamespace">
<allow interface="lp.code.interfaces.branchnamespace.IBranchNamespace"/>
<allow interface="lp.code.interfaces.branchnamespace.IBranchNamespacePolicy"/>
</class>
=== modified file 'lib/lp/code/model/branchnamespace.py'
--- lib/lp/code/model/branchnamespace.py 2013-06-20 05:50:00 +0000
+++ lib/lp/code/model/branchnamespace.py 2015-01-28 17:00:36 +0000
@@ -6,10 +6,10 @@
__metaclass__ = type
__all__ = [
'BranchNamespaceSet',
- 'PackageNamespace',
- 'PersonalNamespace',
+ 'PackageBranchNamespace',
+ 'PersonalBranchNamespace',
'BRANCH_POLICY_ALLOWED_TYPES',
- 'ProductNamespace',
+ 'ProjectBranchNamespace',
]
@@ -111,7 +111,7 @@
}
-class _BaseNamespace:
+class _BaseBranchNamespace:
"""Common code for branch namespaces."""
def createBranch(self, branch_type, name, registrant, url=None,
@@ -287,7 +287,7 @@
raise NotImplementedError
-class PersonalNamespace(_BaseNamespace):
+class PersonalBranchNamespace(_BaseBranchNamespace):
"""A namespace for personal (or 'junk') branches.
Branches in this namespace have names like '~foo/+junk/bar'.
@@ -335,11 +335,11 @@
return IBranchTarget(self.owner)
-class ProductNamespace(_BaseNamespace):
- """A namespace for product branches.
+class ProjectBranchNamespace(_BaseBranchNamespace):
+ """A namespace for project branches.
This namespace is for all the branches owned by a particular person in a
- particular product.
+ particular project.
"""
implements(IBranchNamespace, IBranchNamespacePolicy)
@@ -391,7 +391,7 @@
return default_type
-class PackageNamespace(_BaseNamespace):
+class PackageBranchNamespace(_BaseBranchNamespace):
"""A namespace for source package branches.
This namespace is for all the branches owned by a particular person in a
@@ -440,15 +440,15 @@
"product implies no distroseries or sourcepackagename. "
"Got %r, %r, %r."
% (product, distroseries, sourcepackagename))
- return ProductNamespace(person, product)
+ return ProjectBranchNamespace(person, product)
elif distroseries is not None:
assert sourcepackagename is not None, (
"distroseries implies sourcepackagename. Got %r, %r"
% (distroseries, sourcepackagename))
- return PackageNamespace(
+ return PackageBranchNamespace(
person, SourcePackage(sourcepackagename, distroseries))
else:
- return PersonalNamespace(person)
+ return PersonalBranchNamespace(person)
def parse(self, namespace_name):
"""See `IBranchNamespaceSet`."""
=== modified file 'lib/lp/code/model/branchtarget.py'
--- lib/lp/code/model/branchtarget.py 2014-11-28 22:07:05 +0000
+++ lib/lp/code/model/branchtarget.py 2015-01-28 17:00:36 +0000
@@ -82,9 +82,8 @@
def getNamespace(self, owner):
"""See `IBranchTarget`."""
- from lp.code.model.branchnamespace import (
- PackageNamespace)
- return PackageNamespace(owner, self.sourcepackage)
+ from lp.code.model.branchnamespace import PackageBranchNamespace
+ return PackageBranchNamespace(owner, self.sourcepackage)
@property
def collection(self):
@@ -216,9 +215,8 @@
def getNamespace(self, owner):
"""See `IBranchTarget`."""
- from lp.code.model.branchnamespace import (
- PersonalNamespace)
- return PersonalNamespace(owner)
+ from lp.code.model.branchnamespace import PersonalBranchNamespace
+ return PersonalBranchNamespace(owner)
@property
def collection(self):
@@ -302,9 +300,8 @@
def getNamespace(self, owner):
"""See `IBranchTarget`."""
- from lp.code.model.branchnamespace import (
- ProductNamespace)
- return ProductNamespace(owner, self.product)
+ from lp.code.model.branchnamespace import ProjectBranchNamespace
+ return ProjectBranchNamespace(owner, self.product)
@property
def collection(self):
=== modified file 'lib/lp/code/model/tests/test_branchnamespace.py'
--- lib/lp/code/model/tests/test_branchnamespace.py 2012-12-11 15:42:43 +0000
+++ lib/lp/code/model/tests/test_branchnamespace.py 2015-01-28 17:00:36 +0000
@@ -36,9 +36,9 @@
)
from lp.code.interfaces.branchtarget import IBranchTarget
from lp.code.model.branchnamespace import (
- PackageNamespace,
- PersonalNamespace,
- ProductNamespace,
+ PackageBranchNamespace,
+ PersonalBranchNamespace,
+ ProjectBranchNamespace,
)
from lp.registry.enums import (
BranchSharingPolicy,
@@ -283,8 +283,8 @@
name=name)
-class TestPersonalNamespace(TestCaseWithFactory, NamespaceMixin):
- """Tests for `PersonalNamespace`."""
+class TestPersonalBranchNamespace(TestCaseWithFactory, NamespaceMixin):
+ """Tests for `PersonalBranchNamespace`."""
layer = DatabaseFunctionalLayer
@@ -297,25 +297,25 @@
# A personal namespace has branches with names starting with
# ~foo/+junk.
person = self.factory.makePerson()
- namespace = PersonalNamespace(person)
+ namespace = PersonalBranchNamespace(person)
self.assertEqual('~%s/+junk' % person.name, namespace.name)
def test_owner(self):
# The person passed to a personal namespace is the owner.
person = self.factory.makePerson()
- namespace = PersonalNamespace(person)
+ namespace = PersonalBranchNamespace(person)
self.assertEqual(person, removeSecurityProxy(namespace).owner)
def test_target(self):
# The target of a personal namespace is the branch target of the owner
# of that namespace.
person = self.factory.makePerson()
- namespace = PersonalNamespace(person)
+ namespace = PersonalBranchNamespace(person)
self.assertEqual(IBranchTarget(person), namespace.target)
-class TestProductNamespace(TestCaseWithFactory, NamespaceMixin):
- """Tests for `ProductNamespace`."""
+class TestProjectBranchNamespace(TestCaseWithFactory, NamespaceMixin):
+ """Tests for `ProjectBranchNamespace`."""
layer = DatabaseFunctionalLayer
@@ -329,7 +329,7 @@
# A product namespace has branches with names starting with ~foo/bar.
person = self.factory.makePerson()
product = self.factory.makeProduct()
- namespace = ProductNamespace(person, product)
+ namespace = ProjectBranchNamespace(person, product)
self.assertEqual(
'~%s/%s' % (person.name, product.name), namespace.name)
@@ -337,7 +337,7 @@
# The person passed to a product namespace is the owner.
person = self.factory.makePerson()
product = self.factory.makeProduct()
- namespace = ProductNamespace(person, product)
+ namespace = ProjectBranchNamespace(person, product)
self.assertEqual(person, removeSecurityProxy(namespace).owner)
def test_target(self):
@@ -345,7 +345,7 @@
# product.
person = self.factory.makePerson()
product = self.factory.makeProduct()
- namespace = ProductNamespace(person, product)
+ namespace = ProjectBranchNamespace(person, product)
self.assertEqual(IBranchTarget(product), namespace.target)
def test_validateMove_vcs_imports_rename_import_branch(self):
@@ -357,7 +357,7 @@
registrant=owner, target=IBranchTarget(product), branch_name=name)
branch = code_import.branch
new_name = self.factory.getUniqueString()
- namespace = ProductNamespace(owner, product)
+ namespace = ProjectBranchNamespace(owner, product)
with celebrity_logged_in('vcs_imports') as mover:
self.assertIsNone(
namespace.validateMove(branch, mover, name=new_name))
@@ -370,13 +370,14 @@
registrant=owner, target=IBranchTarget(product))
branch = code_import.branch
new_owner = self.factory.makePerson()
- new_namespace = ProductNamespace(new_owner, product)
+ new_namespace = ProjectBranchNamespace(new_owner, product)
with celebrity_logged_in('vcs_imports') as mover:
self.assertIsNone(new_namespace.validateMove(branch, mover))
-class TestProductNamespacePrivacyWithInformationType(TestCaseWithFactory):
- """Tests for the privacy aspects of `ProductNamespace`.
+class TestProjectBranchNamespacePrivacyWithInformationType(
+ TestCaseWithFactory):
+ """Tests for the privacy aspects of `ProjectBranchNamespace`.
This tests the behaviour for a product using the new
branch_sharing_policy rules.
@@ -384,18 +385,18 @@
layer = DatabaseFunctionalLayer
- def makeProductNamespace(self, sharing_policy, person=None):
+ def makeProjectBranchNamespace(self, sharing_policy, person=None):
if person is None:
person = self.factory.makePerson()
product = self.factory.makeProduct()
self.factory.makeCommercialSubscription(product=product)
with person_logged_in(product.owner):
product.setBranchSharingPolicy(sharing_policy)
- namespace = ProductNamespace(person, product)
+ namespace = ProjectBranchNamespace(person, product)
return namespace
def test_public_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PUBLIC)
self.assertContentEqual(
FREE_INFORMATION_TYPES, namespace.getAllowedInformationTypes())
@@ -403,13 +404,13 @@
InformationType.PUBLIC, namespace.getDefaultInformationType())
def test_forbidden_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.FORBIDDEN)
self.assertContentEqual([], namespace.getAllowedInformationTypes())
self.assertEqual(None, namespace.getDefaultInformationType())
def test_public_or_proprietary_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PUBLIC_OR_PROPRIETARY)
self.assertContentEqual(
NON_EMBARGOED_INFORMATION_TYPES,
@@ -418,13 +419,13 @@
InformationType.PUBLIC, namespace.getDefaultInformationType())
def test_proprietary_or_public_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY_OR_PUBLIC)
self.assertContentEqual([], namespace.getAllowedInformationTypes())
self.assertIs(None, namespace.getDefaultInformationType())
def test_proprietary_or_public_owner_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY_OR_PUBLIC)
with person_logged_in(namespace.product.owner):
getUtility(IService, 'sharing').sharePillarInformation(
@@ -438,7 +439,7 @@
namespace.getDefaultInformationType())
def test_proprietary_or_public_caller_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY_OR_PUBLIC)
grantee = self.factory.makePerson()
with person_logged_in(namespace.product.owner):
@@ -453,13 +454,13 @@
namespace.getDefaultInformationType(grantee))
def test_proprietary_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY)
self.assertContentEqual([], namespace.getAllowedInformationTypes())
self.assertIs(None, namespace.getDefaultInformationType())
def test_proprietary_branch_owner_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY)
with person_logged_in(namespace.product.owner):
getUtility(IService, 'sharing').sharePillarInformation(
@@ -473,7 +474,7 @@
namespace.getDefaultInformationType())
def test_proprietary_caller_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.PROPRIETARY)
grantee = self.factory.makePerson()
with person_logged_in(namespace.product.owner):
@@ -488,13 +489,13 @@
namespace.getDefaultInformationType(grantee))
def test_embargoed_or_proprietary_anyone(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.EMBARGOED_OR_PROPRIETARY)
self.assertContentEqual([], namespace.getAllowedInformationTypes())
self.assertIs(None, namespace.getDefaultInformationType())
def test_embargoed_or_proprietary_owner_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.EMBARGOED_OR_PROPRIETARY)
with person_logged_in(namespace.product.owner):
getUtility(IService, 'sharing').sharePillarInformation(
@@ -508,7 +509,7 @@
namespace.getDefaultInformationType())
def test_embargoed_or_proprietary_caller_grantee(self):
- namespace = self.makeProductNamespace(
+ namespace = self.makeProjectBranchNamespace(
BranchSharingPolicy.EMBARGOED_OR_PROPRIETARY)
grantee = self.factory.makePerson()
with person_logged_in(namespace.product.owner):
@@ -523,8 +524,8 @@
namespace.getDefaultInformationType(grantee))
-class TestPackageNamespace(TestCaseWithFactory, NamespaceMixin):
- """Tests for `PackageNamespace`."""
+class TestPackageBranchNamespace(TestCaseWithFactory, NamespaceMixin):
+ """Tests for `PackageBranchNamespace`."""
layer = DatabaseFunctionalLayer
@@ -542,7 +543,7 @@
person = self.factory.makePerson()
distroseries = self.factory.makeDistroSeries()
sourcepackagename = self.factory.makeSourcePackageName()
- namespace = PackageNamespace(
+ namespace = PackageBranchNamespace(
person, SourcePackage(sourcepackagename, distroseries))
self.assertEqual(
'~%s/%s/%s/%s' % (
@@ -555,7 +556,7 @@
person = self.factory.makePerson()
distroseries = self.factory.makeDistroSeries()
sourcepackagename = self.factory.makeSourcePackageName()
- namespace = PackageNamespace(
+ namespace = PackageBranchNamespace(
person, SourcePackage(sourcepackagename, distroseries))
self.assertEqual(person, removeSecurityProxy(namespace).owner)
@@ -564,7 +565,7 @@
# sourcepackage.
person = self.factory.makePerson()
package = self.factory.makeSourcePackage()
- namespace = PackageNamespace(person, package)
+ namespace = PackageBranchNamespace(person, package)
self.assertEqual(IBranchTarget(package), namespace.target)
@@ -580,13 +581,13 @@
def test_get_personal(self):
person = self.factory.makePerson()
namespace = get_branch_namespace(person=person)
- self.assertIsInstance(namespace, PersonalNamespace)
+ self.assertIsInstance(namespace, PersonalBranchNamespace)
def test_get_product(self):
person = self.factory.makePerson()
product = self.factory.makeProduct()
namespace = get_branch_namespace(person=person, product=product)
- self.assertIsInstance(namespace, ProductNamespace)
+ self.assertIsInstance(namespace, ProjectBranchNamespace)
def test_get_package(self):
person = self.factory.makePerson()
@@ -595,14 +596,14 @@
namespace = get_branch_namespace(
person=person, distroseries=distroseries,
sourcepackagename=sourcepackagename)
- self.assertIsInstance(namespace, PackageNamespace)
+ self.assertIsInstance(namespace, PackageBranchNamespace)
def test_lookup_personal(self):
# lookup_branch_namespace returns a personal namespace if given a junk
# path.
person = self.factory.makePerson()
namespace = lookup_branch_namespace('~%s/+junk' % person.name)
- self.assertIsInstance(namespace, PersonalNamespace)
+ self.assertIsInstance(namespace, PersonalBranchNamespace)
self.assertEqual(person, removeSecurityProxy(namespace).owner)
def test_lookup_personal_not_found(self):
@@ -616,7 +617,7 @@
product = self.factory.makeProduct()
namespace = lookup_branch_namespace(
'~%s/%s' % (person.name, product.name))
- self.assertIsInstance(namespace, ProductNamespace)
+ self.assertIsInstance(namespace, ProjectBranchNamespace)
self.assertEqual(person, removeSecurityProxy(namespace).owner)
self.assertEqual(product, removeSecurityProxy(namespace).product)
@@ -631,7 +632,7 @@
sourcepackage = self.factory.makeSourcePackage()
namespace = lookup_branch_namespace(
'~%s/%s' % (person.name, sourcepackage.path))
- self.assertIsInstance(namespace, PackageNamespace)
+ self.assertIsInstance(namespace, PackageBranchNamespace)
self.assertEqual(person, removeSecurityProxy(namespace).owner)
namespace = removeSecurityProxy(namespace)
self.assertEqual(sourcepackage, namespace.sourcepackage)
@@ -929,29 +930,29 @@
namespace.canCreateBranches(self.factory.makePerson()))
-class TestPersonalNamespaceCanCreateBranches(TestCaseWithFactory,
- BaseCanCreateBranchesMixin):
+class TestPersonalBranchNamespaceCanCreateBranches(TestCaseWithFactory,
+ BaseCanCreateBranchesMixin):
def _getNamespace(self, owner):
- return PersonalNamespace(owner)
-
-
-class TestPackageNamespaceCanCreateBranches(TestCaseWithFactory,
- BaseCanCreateBranchesMixin):
+ return PersonalBranchNamespace(owner)
+
+
+class TestPackageBranchNamespaceCanCreateBranches(TestCaseWithFactory,
+ BaseCanCreateBranchesMixin):
def _getNamespace(self, owner):
source_package = self.factory.makeSourcePackage()
- return PackageNamespace(owner, source_package)
-
-
-class TestProductNamespaceCanCreateBranches(TestCaseWithFactory,
- BaseCanCreateBranchesMixin):
+ return PackageBranchNamespace(owner, source_package)
+
+
+class TestProjectBranchNamespaceCanCreateBranches(TestCaseWithFactory,
+ BaseCanCreateBranchesMixin):
def _getNamespace(self, owner,
branch_sharing_policy=BranchSharingPolicy.PUBLIC):
product = self.factory.makeProduct(
branch_sharing_policy=branch_sharing_policy)
- return ProductNamespace(owner, product)
+ return ProjectBranchNamespace(owner, product)
def setUp(self):
# Setting visibility policies is an admin only task.
@@ -985,15 +986,15 @@
self.assertFalse(namespace.canCreateBranches(other_person))
-class TestPersonalNamespaceAllowedInformationTypes(TestCaseWithFactory):
- """Tests for PersonalNamespace.getAllowedInformationTypes."""
+class TestPersonalBranchNamespaceAllowedInformationTypes(TestCaseWithFactory):
+ """Tests for PersonalBranchNamespace.getAllowedInformationTypes."""
layer = DatabaseFunctionalLayer
def test_anyone(self):
# +junk branches are not private for individuals
person = self.factory.makePerson()
- namespace = PersonalNamespace(person)
+ namespace = PersonalBranchNamespace(person)
self.assertContentEqual(
FREE_INFORMATION_TYPES,
namespace.getAllowedInformationTypes())
@@ -1001,7 +1002,7 @@
def test_public_team(self):
# +junk branches for public teams cannot be private
team = self.factory.makeTeam()
- namespace = PersonalNamespace(team)
+ namespace = PersonalBranchNamespace(team)
self.assertContentEqual(
FREE_INFORMATION_TYPES,
namespace.getAllowedInformationTypes())
@@ -1009,14 +1010,14 @@
def test_private_team(self):
# +junk branches can be private or public for private teams
team = self.factory.makeTeam(visibility=PersonVisibility.PRIVATE)
- namespace = PersonalNamespace(team)
+ namespace = PersonalBranchNamespace(team)
self.assertContentEqual(
NON_EMBARGOED_INFORMATION_TYPES,
namespace.getAllowedInformationTypes())
-class TestPackageNamespaceAllowedInformationTypes(TestCaseWithFactory):
- """Tests for PackageNamespace.getAllowedInformationTypes."""
+class TestPackageBranchNamespaceAllowedInformationTypes(TestCaseWithFactory):
+ """Tests for PackageBranchNamespace.getAllowedInformationTypes."""
layer = DatabaseFunctionalLayer
@@ -1024,7 +1025,7 @@
# Source package branches are always public.
source_package = self.factory.makeSourcePackage()
person = self.factory.makePerson()
- namespace = PackageNamespace(person, source_package)
+ namespace = PackageBranchNamespace(person, source_package)
self.assertContentEqual(
PUBLIC_INFORMATION_TYPES,
namespace.getAllowedInformationTypes())
@@ -1100,27 +1101,27 @@
namespace.validateBranchName, 'a' + c)
-class TestPersonalNamespaceValidateNewBranch(TestCaseWithFactory,
- BaseValidateNewBranchMixin):
+class TestPersonalBranchNamespaceValidateNewBranch(TestCaseWithFactory,
+ BaseValidateNewBranchMixin):
def _getNamespace(self, owner):
- return PersonalNamespace(owner)
-
-
-class TestPackageNamespaceValidateNewBranch(TestCaseWithFactory,
- BaseValidateNewBranchMixin):
+ return PersonalBranchNamespace(owner)
+
+
+class TestPackageBranchNamespaceValidateNewBranch(TestCaseWithFactory,
+ BaseValidateNewBranchMixin):
def _getNamespace(self, owner):
source_package = self.factory.makeSourcePackage()
- return PackageNamespace(owner, source_package)
-
-
-class TestProductNamespaceValidateNewBranch(TestCaseWithFactory,
- BaseValidateNewBranchMixin):
+ return PackageBranchNamespace(owner, source_package)
+
+
+class TestProjectBranchNamespaceValidateNewBranch(TestCaseWithFactory,
+ BaseValidateNewBranchMixin):
def _getNamespace(self, owner):
product = self.factory.makeProduct()
- return ProductNamespace(owner, product)
+ return ProjectBranchNamespace(owner, product)
class JunkBranches(TestCaseWithFactory):
@@ -1232,7 +1233,7 @@
branch = self.factory.makeAnyBranch(name="test")
team = self.factory.makeTeam(branch.owner)
product = self.factory.makeProduct()
- namespace = ProductNamespace(team, product)
+ namespace = ProjectBranchNamespace(team, product)
namespace.moveBranch(branch, branch.owner)
self.assertEqual(team, branch.owner)
# And for paranoia.
Follow ups