launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29427
[Merge] ~cjwatson/launchpad:name-blocklist into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:name-blocklist into launchpad:master.
Commit message:
Rename NameBlacklist to NameBlocklist
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/433583
`/+nameblacklist` is now `/+nameblocklist`, and I've left a redirection behind.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:name-blocklist into launchpad:master.
diff --git a/database/replication/helpers.py b/database/replication/helpers.py
index 5ab5b50..66c9fef 100644
--- a/database/replication/helpers.py
+++ b/database/replication/helpers.py
@@ -46,7 +46,7 @@ LPMAIN_SEED = frozenset(
("public", "person"),
("public", "databasereplicationlag"),
("public", "fticache"),
- ("public", "nameblacklist"),
+ ("public", "nameblocklist"),
("public", "openidconsumerassociation"),
("public", "openidconsumernonce"),
("public", "codeimportmachine"),
diff --git a/database/sampledata/current-dev.sql b/database/sampledata/current-dev.sql
index 43507f2..2f4ef1b 100644
--- a/database/sampledata/current-dev.sql
+++ b/database/sampledata/current-dev.sql
@@ -5429,7 +5429,7 @@ ALTER TABLE public.mirrorproberecord ENABLE TRIGGER ALL;
ALTER TABLE public.nameblocklist DISABLE TRIGGER ALL;
-INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (1, 'blacklist', 'For testing purposes', NULL);
+INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (1, 'blocklist', 'For testing purposes', NULL);
INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (2, '^admin', NULL, NULL);
diff --git a/database/sampledata/current.sql b/database/sampledata/current.sql
index bf2b999..ff2880d 100644
--- a/database/sampledata/current.sql
+++ b/database/sampledata/current.sql
@@ -5343,7 +5343,7 @@ ALTER TABLE public.mirrorproberecord ENABLE TRIGGER ALL;
ALTER TABLE public.nameblocklist DISABLE TRIGGER ALL;
-INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (1, 'blacklist', 'For testing purposes', NULL);
+INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (1, 'blocklist', 'For testing purposes', NULL);
INSERT INTO public.nameblocklist (id, regexp, comment, admin) VALUES (2, '^admin', NULL, NULL);
diff --git a/lib/lp/app/browser/launchpad.py b/lib/lp/app/browser/launchpad.py
index 2621eba..a4eba0a 100644
--- a/lib/lp/app/browser/launchpad.py
+++ b/lib/lp/app/browser/launchpad.py
@@ -87,7 +87,7 @@ from lp.registry.interfaces.announcement import IAnnouncementSet
from lp.registry.interfaces.codeofconduct import ICodeOfConductSet
from lp.registry.interfaces.distribution import IDistributionSet
from lp.registry.interfaces.karma import IKarmaActionSet
-from lp.registry.interfaces.nameblacklist import INameBlacklistSet
+from lp.registry.interfaces.nameblocklist import INameBlocklistSet
from lp.registry.interfaces.person import IPersonSet
from lp.registry.interfaces.pillar import IPillarNameSet
from lp.registry.interfaces.poll import IPollSet
@@ -864,6 +864,10 @@ class LaunchpadRootNavigation(Navigation):
def redirect_feature_changelog(self):
return "/+feature-rules/changelog"
+ @redirection("+nameblacklist", status=301) # wokeignore:rule=blacklist
+ def redirect_nameblacklist(self): # wokeignore:rule=blacklist
+ return "+nameblocklist"
+
# XXX cprov 2009-03-19 bug=345877: path segments starting with '+'
# should never correspond to a valid traversal, they confuse the
# hierarchical navigation model.
@@ -887,7 +891,7 @@ class LaunchpadRootNavigation(Navigation):
"+imports": ITranslationImportQueue,
"+languages": ILanguageSet,
"livefses": ILiveFSSet,
- "+nameblacklist": INameBlacklistSet,
+ "+nameblocklist": INameBlocklistSet,
"package-sets": IPackagesetSet,
"people": IPersonSet,
"pillars": IPillarNameSet,
diff --git a/lib/lp/app/stories/basics/notfound-traversals.rst b/lib/lp/app/stories/basics/notfound-traversals.rst
index 01b859e..b154dc5 100644
--- a/lib/lp/app/stories/basics/notfound-traversals.rst
+++ b/lib/lp/app/stories/basics/notfound-traversals.rst
@@ -176,6 +176,10 @@ Check legacy URL redirects
>>> check_redirect("/people/stub", status=301)
http://launchpad.test/~stub
+ # wokeignore:rule=blacklist
+ >>> check_redirect("/+nameblacklist", auth=True, status=301)
+ +nameblocklist
+
Check redirects of Unicode URLs works
>>> check_not_found("/ubuntu/foo%C3%A9")
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index b90507b..80a57d0 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -1832,52 +1832,52 @@
/>
<browser:page
name="+edit"
- for="lp.registry.interfaces.nameblacklist.INameBlacklist"
- class="lp.registry.browser.nameblacklist.NameBlacklistEditView"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklist"
+ class="lp.registry.browser.nameblocklist.NameBlocklistEditView"
permission="launchpad.Edit"
template="../../app/templates/generic-edit.pt"
/>
<browser:url
- for="lp.registry.interfaces.nameblacklist.INameBlacklistSet"
- path_expression="string:+nameblacklist"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklistSet"
+ path_expression="string:+nameblocklist"
parent_utility="lp.services.webapp.interfaces.ILaunchpadRoot"
/>
<browser:url
- for="lp.registry.interfaces.nameblacklist.INameBlacklist"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklist"
path_expression="string:${id}"
- parent_utility="lp.registry.interfaces.nameblacklist.INameBlacklistSet"
+ parent_utility="lp.registry.interfaces.nameblocklist.INameBlocklistSet"
/>
<browser:defaultView
name="+index"
- for="lp.registry.interfaces.nameblacklist.INameBlacklistSet"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklistSet"
/>
<browser:page
name="+index"
- for="lp.registry.interfaces.nameblacklist.INameBlacklistSet"
- class="lp.registry.browser.nameblacklist.NameBlacklistSetView"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklistSet"
+ class="lp.registry.browser.nameblocklist.NameBlocklistSetView"
permission="launchpad.View"
- template="../templates/nameblacklists-index.pt"
+ template="../templates/nameblocklists-index.pt"
/>
<browser:page
name="+add"
- for="lp.registry.interfaces.nameblacklist.INameBlacklistSet"
- class="lp.registry.browser.nameblacklist.NameBlacklistAddView"
+ for="lp.registry.interfaces.nameblocklist.INameBlocklistSet"
+ class="lp.registry.browser.nameblocklist.NameBlocklistAddView"
permission="launchpad.Edit"
template="../../app/templates/generic-edit.pt"
/>
<browser:navigation
- module="lp.registry.browser.nameblacklist"
- classes="NameBlacklistSetNavigation"
+ module="lp.registry.browser.nameblocklist"
+ classes="NameBlocklistSetNavigation"
/>
<browser:menus
- module="lp.registry.browser.nameblacklist"
+ module="lp.registry.browser.nameblocklist"
classes="
- NameBlacklistNavigationMenu
- NameBlacklistSetNavigationMenu
+ NameBlocklistNavigationMenu
+ NameBlocklistSetNavigationMenu
"
/>
<adapter
- factory="lp.registry.browser.nameblacklist.NameBlacklistSetBreadcrumb"
+ factory="lp.registry.browser.nameblocklist.NameBlocklistSetBreadcrumb"
/>
<browser:page
name="+addseries"
diff --git a/lib/lp/registry/browser/nameblacklist.py b/lib/lp/registry/browser/nameblocklist.py
similarity index 61%
rename from lib/lp/registry/browser/nameblacklist.py
rename to lib/lp/registry/browser/nameblocklist.py
index 2c2e175..dad4965 100644
--- a/lib/lp/registry/browser/nameblacklist.py
+++ b/lib/lp/registry/browser/nameblocklist.py
@@ -2,11 +2,11 @@
# GNU Affero General Public License version 3 (see the file LICENSE).
__all__ = [
- "NameBlacklistAddView",
- "NameBlacklistEditView",
- "NameBlacklistNavigationMenu",
- "NameBlacklistSetNavigationMenu",
- "NameBlacklistSetView",
+ "NameBlocklistAddView",
+ "NameBlocklistEditView",
+ "NameBlocklistNavigationMenu",
+ "NameBlocklistSetNavigationMenu",
+ "NameBlocklistSetView",
]
import re
@@ -18,9 +18,9 @@ from zope.interface import implementer
from lp.app.browser.launchpadform import LaunchpadFormView, action
from lp.registry.browser import RegistryEditFormView
-from lp.registry.interfaces.nameblacklist import (
- INameBlacklist,
- INameBlacklistSet,
+from lp.registry.interfaces.nameblocklist import (
+ INameBlocklist,
+ INameBlocklistSet,
)
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.interfaces import IBreadcrumb
@@ -37,7 +37,7 @@ from lp.services.webapp.publisher import (
)
-class NameBlacklistValidationMixin:
+class NameBlocklistValidationMixin:
"""Validate regular expression when adding or editing."""
def validate(self, data):
@@ -45,15 +45,15 @@ class NameBlacklistValidationMixin:
regexp = data["regexp"]
try:
re.compile(regexp)
- name_blacklist_set = getUtility(INameBlacklistSet)
+ name_blocklist_set = getUtility(INameBlocklistSet)
if (
- INameBlacklistSet.providedBy(self.context)
+ INameBlocklistSet.providedBy(self.context)
or self.context.regexp != regexp
):
# Check if the regular expression already exists if a
# new expression is being created or if an existing
# regular expression has been modified.
- if name_blacklist_set.getByRegExp(regexp) is not None:
+ if name_blocklist_set.getByRegExp(regexp) is not None:
self.setFieldError(
"regexp", "This regular expression already exists."
)
@@ -61,29 +61,29 @@ class NameBlacklistValidationMixin:
self.setFieldError("regexp", "Invalid regular expression: %s" % e)
-class NameBlacklistEditView(
- NameBlacklistValidationMixin, RegistryEditFormView
+class NameBlocklistEditView(
+ NameBlocklistValidationMixin, RegistryEditFormView
):
- """View for editing a blacklist expression."""
+ """View for editing a blocklist expression."""
- schema = INameBlacklist
+ schema = INameBlocklist
field_names = ["regexp", "admin", "comment"]
- label = "Edit a blacklist expression"
+ label = "Edit a blocklist expression"
page_title = label
@property
def cancel_url(self):
- return canonical_url(getUtility(INameBlacklistSet))
+ return canonical_url(getUtility(INameBlocklistSet))
next_url = cancel_url
-class NameBlacklistAddView(NameBlacklistValidationMixin, LaunchpadFormView):
- """View for adding a blacklist expression."""
+class NameBlocklistAddView(NameBlocklistValidationMixin, LaunchpadFormView):
+ """View for adding a blocklist expression."""
- schema = INameBlacklist
+ schema = INameBlocklist
field_names = ["regexp", "admin", "comment"]
- label = "Add a new blacklist expression"
+ label = "Add a new blocklist expression"
page_title = label
custom_widget_regexp = CustomWidgetFactory(TextWidget, displayWidth=60)
@@ -95,66 +95,66 @@ class NameBlacklistAddView(NameBlacklistValidationMixin, LaunchpadFormView):
next_url = cancel_url
- @action("Add to blacklist", name="add")
+ @action("Add to blocklist", name="add")
def add_action(self, action, data):
- name_blacklist_set = getUtility(INameBlacklistSet)
- name_blacklist_set.create(
+ name_blocklist_set = getUtility(INameBlocklistSet)
+ name_blocklist_set.create(
regexp=data["regexp"],
comment=data["comment"],
admin=data["admin"],
)
self.request.response.addInfoNotification(
- 'Regular expression "%s" has been added to the name blacklist.'
+ 'Regular expression "%s" has been added to the name blocklist.'
% data["regexp"]
)
-class NameBlacklistSetView(LaunchpadView):
- """View for /+nameblacklists top level collection."""
+class NameBlocklistSetView(LaunchpadView):
+ """View for /+nameblocklists top level collection."""
- label = "Blacklist for names of Launchpad pillars and persons"
+ label = "Blocklist for names of Launchpad pillars and persons"
page_title = label
-class NameBlacklistSetNavigation(Navigation):
+class NameBlocklistSetNavigation(Navigation):
- usedfor = INameBlacklistSet
+ usedfor = INameBlocklistSet
def traverse(self, name):
return self.context.get(name)
-class NameBlacklistSetNavigationMenu(NavigationMenu):
- """Action menu for NameBlacklistSet."""
+class NameBlocklistSetNavigationMenu(NavigationMenu):
+ """Action menu for NameBlocklistSet."""
- usedfor = INameBlacklistSet
+ usedfor = INameBlocklistSet
facet = "overview"
links = [
- "add_blacklist_expression",
+ "add_blocklist_expression",
]
@enabled_with_permission("launchpad.Edit")
- def add_blacklist_expression(self):
- return Link("+add", "Add blacklist expression", icon="add")
+ def add_blocklist_expression(self):
+ return Link("+add", "Add blocklist expression", icon="add")
-class NameBlacklistNavigationMenu(ApplicationMenu):
- """Action menu for NameBlacklist."""
+class NameBlocklistNavigationMenu(ApplicationMenu):
+ """Action menu for NameBlocklist."""
- usedfor = INameBlacklist
+ usedfor = INameBlocklist
facet = "overview"
links = [
- "edit_blacklist_expression",
+ "edit_blocklist_expression",
]
@enabled_with_permission("launchpad.Edit")
- def edit_blacklist_expression(self):
- return Link("+edit", "Edit blacklist expression", icon="edit")
+ def edit_blocklist_expression(self):
+ return Link("+edit", "Edit blocklist expression", icon="edit")
-@adapter(INameBlacklistSet)
+@adapter(INameBlocklistSet)
@implementer(IBreadcrumb)
-class NameBlacklistSetBreadcrumb(Breadcrumb):
- """Return a breadcrumb for an `INameBlackListSet`."""
+class NameBlocklistSetBreadcrumb(Breadcrumb):
+ """Return a breadcrumb for an `INameBlockListSet`."""
- text = "Name Blacklist"
+ text = "Name Blocklist"
diff --git a/lib/lp/registry/browser/tests/nameblacklist-views.rst b/lib/lp/registry/browser/tests/nameblocklist-views.rst
similarity index 78%
rename from lib/lp/registry/browser/tests/nameblacklist-views.rst
rename to lib/lp/registry/browser/tests/nameblocklist-views.rst
index 47d3d80..ef6bfeb 100644
--- a/lib/lp/registry/browser/tests/nameblacklist-views.rst
+++ b/lib/lp/registry/browser/tests/nameblocklist-views.rst
@@ -1,12 +1,12 @@
-NameBlacklist pages
+NameBlocklist pages
===================
>>> import transaction
>>> from zope.component import getUtility
>>> from lp.testing.sampledata import ADMIN_EMAIL
>>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
- >>> from lp.registry.interfaces.nameblacklist import INameBlacklistSet
- >>> name_blacklist_set = getUtility(INameBlacklistSet)
+ >>> from lp.registry.interfaces.nameblocklist import INameBlocklistSet
+ >>> name_blocklist_set = getUtility(INameBlocklistSet)
>>> from lp.testing.pages import extract_text, find_tag_by_id
>>> registry_experts = getUtility(ILaunchpadCelebrities).registry_experts
>>> registry_expert = factory.makePerson()
@@ -18,24 +18,24 @@ NameBlacklist pages
View all
--------
-All the blacklisted regular expressions that filter pillar names and
-person names can be seen on the /+nameblacklist page.
+All the blocklisted regular expressions that filter pillar names and
+person names can be seen on the /+nameblocklist page.
>>> ignored = login_person(registry_expert)
>>> view = create_initialized_view(
- ... name_blacklist_set, "+index", principal=registry_expert
+ ... name_blocklist_set, "+index", principal=registry_expert
... )
>>> print(
... extract_text(
- ... find_tag_by_id(view.render(), "blacklist"), formatter="html"
+ ... find_tag_by_id(view.render(), "blocklist"), formatter="html"
... )
... )
Regular Expression Admin Comment
- ^admin Edit blacklist expression —
- blacklist Edit blacklist expression — For testing purposes
+ ^admin Edit blocklist expression —
+ blocklist Edit blocklist expression — For testing purposes
-Add expression to blacklist
+Add expression to blocklist
---------------------------
An invalid regular expression cannot be added.
@@ -44,9 +44,9 @@ An invalid regular expression cannot be added.
... "field.regexp": "(",
... "field.admin": registry_experts.name,
... "field.comment": "old-comment",
- ... "field.actions.add": "Add to blacklist",
+ ... "field.actions.add": "Add to blocklist",
... }
- >>> view = create_initialized_view(name_blacklist_set, "+add", form=form)
+ >>> view = create_initialized_view(name_blocklist_set, "+add", form=form)
>>> for error in view.errors:
... print(error)
...
@@ -54,8 +54,8 @@ An invalid regular expression cannot be added.
A duplicate regular expression cannot be added.
- >>> form["field.regexp"] = "blacklist"
- >>> view = create_initialized_view(name_blacklist_set, "+add", form=form)
+ >>> form["field.regexp"] = "blocklist"
+ >>> view = create_initialized_view(name_blocklist_set, "+add", form=form)
>>> for error in view.errors:
... print(error)
...
@@ -64,21 +64,21 @@ A duplicate regular expression cannot be added.
After adding a regular expression, a notification will be displayed.
>>> form["field.regexp"] = "foo"
- >>> view = create_initialized_view(name_blacklist_set, "+add", form=form)
+ >>> view = create_initialized_view(name_blocklist_set, "+add", form=form)
>>> for notification in view.request.response.notifications:
... print(notification.message)
...
- Regular expression "foo" has been added to the name blacklist.
+ Regular expression "foo" has been added to the name blocklist.
>>> transaction.commit()
- >>> foo_exp = name_blacklist_set.getByRegExp("foo")
+ >>> foo_exp = name_blocklist_set.getByRegExp("foo")
>>> print(foo_exp.regexp)
foo
>>> print(foo_exp.admin.name)
registry
-Edit expression in blacklist
+Edit expression in blocklist
----------------------------
When a regular expression is edited, it still must be valid.
@@ -97,7 +97,7 @@ When a regular expression is edited, it still must be valid.
It cannot changed to conflict with another regular expression.
- >>> form["field.regexp"] = "blacklist"
+ >>> form["field.regexp"] = "blocklist"
>>> view = create_initialized_view(foo_exp, "+edit", form=form)
>>> for error in view.errors:
... print(error)
diff --git a/lib/lp/registry/browser/tests/test_breadcrumbs.py b/lib/lp/registry/browser/tests/test_breadcrumbs.py
index 1ecb14a..635ea95 100644
--- a/lib/lp/registry/browser/tests/test_breadcrumbs.py
+++ b/lib/lp/registry/browser/tests/test_breadcrumbs.py
@@ -5,7 +5,7 @@ from zope.component import getUtility
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.registry.browser.tests.test_pillar_sharing import SharingBaseTestCase
-from lp.registry.interfaces.nameblacklist import INameBlacklistSet
+from lp.registry.interfaces.nameblocklist import INameBlocklistSet
from lp.services.webapp.publisher import canonical_url
from lp.testing import login_person
from lp.testing.breadcrumbs import BaseBreadcrumbTestCase
@@ -155,26 +155,26 @@ class TestPollBreadcrumb(BaseBreadcrumbTestCase):
self.assertEqual(self.poll.title, last_crumb.text)
-class TestNameblacklistBreadcrumb(BaseBreadcrumbTestCase):
- """Test breadcrumbs for +nameblacklist."""
+class TestNameblocklistBreadcrumb(BaseBreadcrumbTestCase):
+ """Test breadcrumbs for +nameblocklist."""
def setUp(self):
super().setUp()
- self.name_blacklist_set = getUtility(INameBlacklistSet)
+ self.name_blocklist_set = getUtility(INameBlocklistSet)
self.registry_expert = self.factory.makeRegistryExpert()
login_person(self.registry_expert)
- def test_nameblacklist(self):
- expected = [("Name Blacklist", "http://launchpad.test/+nameblacklist")]
- self.assertBreadcrumbs(expected, self.name_blacklist_set)
+ def test_nameblocklist(self):
+ expected = [("Name Blocklist", "http://launchpad.test/+nameblocklist")]
+ self.assertBreadcrumbs(expected, self.name_blocklist_set)
- def test_nameblacklist_edit(self):
- blacklist = self.name_blacklist_set.getByRegExp("blacklist")
+ def test_nameblocklist_edit(self):
+ blocklist = self.name_blocklist_set.getByRegExp("blocklist")
expected = [
- ("Name Blacklist", "http://launchpad.test/+nameblacklist"),
+ ("Name Blocklist", "http://launchpad.test/+nameblocklist"),
(
- "Edit a blacklist expression",
- "http://launchpad.test/+nameblacklist/1/+edit",
+ "Edit a blocklist expression",
+ "http://launchpad.test/+nameblocklist/1/+edit",
),
]
- self.assertBreadcrumbs(expected, blacklist, view_name="+edit")
+ self.assertBreadcrumbs(expected, blocklist, view_name="+edit")
diff --git a/lib/lp/registry/configure.zcml b/lib/lp/registry/configure.zcml
index 585bbf1..64cb8a2 100644
--- a/lib/lp/registry/configure.zcml
+++ b/lib/lp/registry/configure.zcml
@@ -203,27 +203,27 @@
<allow interface=".interfaces.productjob.IThirtyDayCommercialExpirationJob"/>
</class>
- <!-- INameBlacklist -->
+ <!-- INameBlocklist -->
<securedutility
- class="lp.registry.model.nameblacklist.NameBlacklistSet"
- provides="lp.registry.interfaces.nameblacklist.INameBlacklistSet">
+ class="lp.registry.model.nameblocklist.NameBlocklistSet"
+ provides="lp.registry.interfaces.nameblocklist.INameBlocklistSet">
<allow
- interface="lp.registry.interfaces.nameblacklist.INameBlacklistSet"/>
+ interface="lp.registry.interfaces.nameblocklist.INameBlocklistSet"/>
</securedutility>
- <class class="lp.registry.model.nameblacklist.NameBlacklistSet">
+ <class class="lp.registry.model.nameblocklist.NameBlocklistSet">
<require
permission="launchpad.Edit"
- interface="lp.registry.interfaces.nameblacklist.INameBlacklistSet"/>
+ interface="lp.registry.interfaces.nameblocklist.INameBlocklistSet"/>
</class>
- <class class="lp.registry.model.nameblacklist.NameBlacklist">
+ <class class="lp.registry.model.nameblocklist.NameBlocklist">
<require
permission="launchpad.View"
- interface="lp.registry.interfaces.nameblacklist.INameBlacklist"/>
+ interface="lp.registry.interfaces.nameblocklist.INameBlocklist"/>
<require
permission="launchpad.Edit"
- set_schema="lp.registry.interfaces.nameblacklist.INameBlacklist"/>
+ set_schema="lp.registry.interfaces.nameblocklist.INameBlocklist"/>
</class>
<!-- Location -->
diff --git a/lib/lp/registry/doc/pillar-aliases-field.rst b/lib/lp/registry/doc/pillar-aliases-field.rst
index 9e0294a..e9176f6 100644
--- a/lib/lp/registry/doc/pillar-aliases-field.rst
+++ b/lib/lp/registry/doc/pillar-aliases-field.rst
@@ -71,10 +71,10 @@ Also, they must not be identical to the pillar's own name.
...
lp.app.validators.LaunchpadValidationError: This is your name: firefox
-Black-listed names are not accepted as aliases either.
+Blocklisted names are not accepted as aliases either.
- >>> bound_field.validate("blacklisted")
+ >>> bound_field.validate("blocklisted")
Traceback (most recent call last):
...
lp.app.validators.LaunchpadValidationError:
- The name 'blacklisted' has been blocked...
+ The name 'blocklisted' has been blocked...
diff --git a/lib/lp/registry/interfaces/nameblacklist.py b/lib/lp/registry/interfaces/nameblocklist.py
similarity index 70%
rename from lib/lp/registry/interfaces/nameblacklist.py
rename to lib/lp/registry/interfaces/nameblocklist.py
index fcac7fc..d418362 100644
--- a/lib/lp/registry/interfaces/nameblacklist.py
+++ b/lib/lp/registry/interfaces/nameblocklist.py
@@ -1,11 +1,11 @@
# Copyright 2010 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-"""NameBlacklist interfaces."""
+"""NameBlocklist interfaces."""
__all__ = [
- "INameBlacklist",
- "INameBlacklistSet",
+ "INameBlocklist",
+ "INameBlocklistSet",
]
from zope.interface import Interface
@@ -14,15 +14,15 @@ from zope.schema import Choice, Int, Text, TextLine
from lp import _
-class INameBlacklist(Interface):
- """The interface for the NameBlacklist table."""
+class INameBlocklist(Interface):
+ """The interface for the NameBlocklist table."""
id = Int(title=_("ID"), required=True, readonly=True)
regexp = TextLine(title=_("Regular expression"), required=True)
comment = Text(
title=_("Comment"),
description=_(
- "Why is the name blacklisted? Does the namespace belong to an "
+ "Why is the name blocklisted? Does the namespace belong to an "
"organization or is the namespace reserved by the application?"
),
required=False,
@@ -38,17 +38,17 @@ class INameBlacklist(Interface):
)
-class INameBlacklistSet(Interface):
- """The set of INameBlacklist objects."""
+class INameBlocklistSet(Interface):
+ """The set of INameBlocklist objects."""
def getAll():
- """Return all the name blacklist expressions."""
+ """Return all the name blocklist expressions."""
def create(regexp, comment=None):
- """Create and return a new NameBlacklist with given arguments."""
+ """Create and return a new NameBlocklist with given arguments."""
def get(id):
- """Return the NameBlacklist with the given id or None."""
+ """Return the NameBlocklist with the given id or None."""
def getByRegExp(regexp):
- """Return the NameBlacklist with the given regexp or None."""
+ """Return the NameBlocklist with the given regexp or None."""
diff --git a/lib/lp/registry/interfaces/person.py b/lib/lp/registry/interfaces/person.py
index 228b8e4..d962b73 100644
--- a/lib/lp/registry/interfaces/person.py
+++ b/lib/lp/registry/interfaces/person.py
@@ -130,7 +130,7 @@ from lp.registry.interfaces.teammembership import (
from lp.registry.interfaces.wikiname import IWikiName
from lp.services.database.sqlbase import block_implicit_flushes
from lp.services.fields import (
- BlacklistableContentNameField,
+ BlocklistableContentNameField,
IconImageUpload,
LogoImageUpload,
MugshotImageUpload,
@@ -469,11 +469,11 @@ class PersonCreationRationale(DBEnumeratedType):
)
-class PersonNameField(BlacklistableContentNameField):
- """A `Person` team name, which is unique and performs pseudo blacklisting.
+class PersonNameField(BlocklistableContentNameField):
+ """A `Person` team name, which is unique and performs pseudo blocklisting.
If the team name is not unique, and the clash is with a private team,
- return the blacklist message. Also return the blacklist message if the
+ return the blocklist message. Also return the blocklist message if the
private prefix is used but the user is not privileged to create private
teams.
"""
@@ -500,19 +500,19 @@ class PersonNameField(BlacklistableContentNameField):
# private prefix.
if input.startswith(PRIVATE_TEAM_PREFIX):
- raise LaunchpadValidationError(self.blacklistmessage % input)
+ raise LaunchpadValidationError(self.blocklistmessage % input)
# If a non-privileged user attempts to use an existing name AND
- # the existing project is private, then return the blacklist
+ # the existing project is private, then return the blocklist
# message rather than the message indicating the project exists.
existing_object = self._getByAttribute(input)
if (
existing_object is not None
and existing_object.visibility != PersonVisibility.PUBLIC
):
- raise LaunchpadValidationError(self.blacklistmessage % input)
+ raise LaunchpadValidationError(self.blocklistmessage % input)
- # Perform the normal validation, including the real blacklist checks.
+ # Perform the normal validation, including the real blocklist checks.
super()._validate(input)
@@ -2466,12 +2466,12 @@ class IPersonSetPublic(Interface):
def getTopContributors(limit=50):
"""Return the top contributors in Launchpad, up to the given limit."""
- def isNameBlacklisted(name, user=None):
- """Is the given name blacklisted by Launchpad Administrators?
+ def isNameBlocklisted(name, user=None):
+ """Is the given name blocklisted by Launchpad Administrators?
:param name: The name to be checked.
:param user: The `IPerson` that wants to use the name. If the user
- is an admin for the nameblacklist expression, they can use the
+ is an admin for the nameblocklist expression, they can use the
name.
"""
diff --git a/lib/lp/registry/model/nameblacklist.py b/lib/lp/registry/model/nameblacklist.py
deleted file mode 100644
index a35d78c..0000000
--- a/lib/lp/registry/model/nameblacklist.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2010 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Classes for managing the NameBlacklist table."""
-
-__all__ = [
- "NameBlacklist",
- "NameBlacklistSet",
-]
-
-
-from storm.locals import Int, Reference, Unicode
-from zope.interface import implementer
-
-from lp.registry.interfaces.nameblacklist import (
- INameBlacklist,
- INameBlacklistSet,
-)
-from lp.registry.model.person import Person
-from lp.services.database.interfaces import IStore
-from lp.services.database.stormbase import StormBase
-
-
-@implementer(INameBlacklist)
-class NameBlacklist(StormBase):
- """Class for the NameBlacklist table."""
-
- __storm_table__ = "NameBlacklist"
-
- id = Int(primary=True)
- regexp = Unicode(name="regexp", allow_none=False)
- comment = Unicode(name="comment", allow_none=True)
- admin_id = Int(name="admin", allow_none=True)
- admin = Reference(admin_id, Person.id)
-
-
-@implementer(INameBlacklistSet)
-class NameBlacklistSet:
- """Class for creating and retrieving NameBlacklist objects."""
-
- def getAll(self):
- """See `INameBlacklistSet`."""
- store = IStore(NameBlacklist)
- return store.find(NameBlacklist).order_by(NameBlacklist.regexp)
-
- def create(self, regexp, comment=None, admin=None):
- """See `INameBlacklistSet`."""
- nameblacklist = NameBlacklist()
- nameblacklist.regexp = regexp
- nameblacklist.comment = comment
- nameblacklist.admin = admin
- store = IStore(NameBlacklist)
- store.add(nameblacklist)
- return nameblacklist
-
- def get(self, id):
- """See `INameBlacklistSet`."""
- try:
- id = int(id)
- except ValueError:
- return None
- store = IStore(NameBlacklist)
- return store.find(NameBlacklist, NameBlacklist.id == id).one()
-
- def getByRegExp(self, regexp):
- """See `INameBlacklistSet`."""
- store = IStore(NameBlacklist)
- return store.find(NameBlacklist, NameBlacklist.regexp == regexp).one()
diff --git a/lib/lp/registry/model/nameblocklist.py b/lib/lp/registry/model/nameblocklist.py
new file mode 100644
index 0000000..157726a
--- /dev/null
+++ b/lib/lp/registry/model/nameblocklist.py
@@ -0,0 +1,68 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Classes for managing the NameBlocklist table."""
+
+__all__ = [
+ "NameBlocklist",
+ "NameBlocklistSet",
+]
+
+
+from storm.locals import Int, Reference, Unicode
+from zope.interface import implementer
+
+from lp.registry.interfaces.nameblocklist import (
+ INameBlocklist,
+ INameBlocklistSet,
+)
+from lp.registry.model.person import Person
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
+
+
+@implementer(INameBlocklist)
+class NameBlocklist(StormBase):
+ """Class for the NameBlocklist table."""
+
+ __storm_table__ = "NameBlocklist"
+
+ id = Int(primary=True)
+ regexp = Unicode(name="regexp", allow_none=False)
+ comment = Unicode(name="comment", allow_none=True)
+ admin_id = Int(name="admin", allow_none=True)
+ admin = Reference(admin_id, Person.id)
+
+
+@implementer(INameBlocklistSet)
+class NameBlocklistSet:
+ """Class for creating and retrieving NameBlocklist objects."""
+
+ def getAll(self):
+ """See `INameBlocklistSet`."""
+ store = IStore(NameBlocklist)
+ return store.find(NameBlocklist).order_by(NameBlocklist.regexp)
+
+ def create(self, regexp, comment=None, admin=None):
+ """See `INameBlocklistSet`."""
+ nameblocklist = NameBlocklist()
+ nameblocklist.regexp = regexp
+ nameblocklist.comment = comment
+ nameblocklist.admin = admin
+ store = IStore(NameBlocklist)
+ store.add(nameblocklist)
+ return nameblocklist
+
+ def get(self, id):
+ """See `INameBlocklistSet`."""
+ try:
+ id = int(id)
+ except ValueError:
+ return None
+ store = IStore(NameBlocklist)
+ return store.find(NameBlocklist, NameBlocklist.id == id).one()
+
+ def getByRegExp(self, regexp):
+ """See `INameBlocklistSet`."""
+ store = IStore(NameBlocklist)
+ return store.find(NameBlocklist, NameBlocklist.regexp == regexp).one()
diff --git a/lib/lp/registry/model/person.py b/lib/lp/registry/model/person.py
index bfdee1a..175ccfc 100644
--- a/lib/lp/registry/model/person.py
+++ b/lib/lp/registry/model/person.py
@@ -3794,7 +3794,7 @@ class PersonSet:
def __init__(self):
self.title = "People registered with Launchpad"
- def isNameBlacklisted(self, name, user=None):
+ def isNameBlocklisted(self, name, user=None):
"""See `IPersonSet`."""
if user is None:
user_id = 0
@@ -3802,7 +3802,7 @@ class PersonSet:
user_id = user.id
cur = cursor()
cur.execute(
- "SELECT is_blacklisted_name(%(name)s, %(user_id)s)",
+ "SELECT is_blocklisted_name(%(name)s, %(user_id)s)",
{"name": name, "user_id": user_id},
)
return bool(cur.fetchone()[0])
@@ -5311,7 +5311,7 @@ def generate_nick(email_addr, is_registered=_is_nick_registered):
It is technically possible for this function to raise a
NicknameGenerationError, but this will only occur if an operator
- has majorly screwed up the name blacklist.
+ has majorly screwed up the name blocklist.
"""
email_addr = email_addr.strip().lower()
@@ -5330,7 +5330,7 @@ def generate_nick(email_addr, is_registered=_is_nick_registered):
return False
elif is_registered(nick):
return False
- elif person_set.isNameBlacklisted(nick):
+ elif person_set.isNameBlocklisted(nick):
return False
else:
return True
@@ -5381,7 +5381,7 @@ def generate_nick(email_addr, is_registered=_is_nick_registered):
raise NicknameGenerationError(
"No nickname could be generated. "
"This should be impossible to trigger unless some twonk has "
- "registered a match everything regexp in the black list."
+ "registered a match everything regexp in the blocklist."
)
finally:
diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py
index fce1289..505f4e8 100644
--- a/lib/lp/registry/scripts/closeaccount.py
+++ b/lib/lp/registry/scripts/closeaccount.py
@@ -86,7 +86,7 @@ def close_account(username, log):
def table_notification(table):
log.debug("Handling the %s table" % table)
- # All names starting with 'removed' are blacklisted, so this will always
+ # All names starting with 'removed' are blocklisted, so this will always
# succeed.
new_name = "removed%d" % person.id
diff --git a/lib/lp/registry/security.py b/lib/lp/registry/security.py
index ad48865..17c201f 100644
--- a/lib/lp/registry/security.py
+++ b/lib/lp/registry/security.py
@@ -41,9 +41,9 @@ from lp.registry.interfaces.gpg import IGPGKey
from lp.registry.interfaces.irc import IIrcID
from lp.registry.interfaces.location import IPersonLocation
from lp.registry.interfaces.milestone import IMilestone, IProjectGroupMilestone
-from lp.registry.interfaces.nameblacklist import (
- INameBlacklist,
- INameBlacklistSet,
+from lp.registry.interfaces.nameblocklist import (
+ INameBlocklist,
+ INameBlocklistSet,
)
from lp.registry.interfaces.ociproject import IOCIProject
from lp.registry.interfaces.ociprojectseries import IOCIProjectSeries
@@ -1211,24 +1211,24 @@ class AddPOTemplate(OnlyRosettaExpertsAndAdmins):
usedfor = IProductSeries
-class ViewNameBlacklist(EditByRegistryExpertsOrAdmins):
+class ViewNameBlocklist(EditByRegistryExpertsOrAdmins):
permission = "launchpad.View"
- usedfor = INameBlacklist
+ usedfor = INameBlocklist
-class EditNameBlacklist(EditByRegistryExpertsOrAdmins):
+class EditNameBlocklist(EditByRegistryExpertsOrAdmins):
permission = "launchpad.Edit"
- usedfor = INameBlacklist
+ usedfor = INameBlocklist
-class ViewNameBlacklistSet(EditByRegistryExpertsOrAdmins):
+class ViewNameBlocklistSet(EditByRegistryExpertsOrAdmins):
permission = "launchpad.View"
- usedfor = INameBlacklistSet
+ usedfor = INameBlocklistSet
-class EditNameBlacklistSet(EditByRegistryExpertsOrAdmins):
+class EditNameBlocklistSet(EditByRegistryExpertsOrAdmins):
permission = "launchpad.Edit"
- usedfor = INameBlacklistSet
+ usedfor = INameBlocklistSet
class AdminDistroSeriesTranslations(AuthorizationBase):
diff --git a/lib/lp/registry/stories/object/xx-nameblacklist.rst b/lib/lp/registry/stories/object/xx-nameblocklist.rst
similarity index 73%
rename from lib/lp/registry/stories/object/xx-nameblacklist.rst
rename to lib/lp/registry/stories/object/xx-nameblocklist.rst
index d820568..9b05b9b 100644
--- a/lib/lp/registry/stories/object/xx-nameblacklist.rst
+++ b/lib/lp/registry/stories/object/xx-nameblocklist.rst
@@ -1,29 +1,29 @@
-The NameBlacklist table contains a central blacklist of disallowed names.
-For objects using this blacklist, it is impossible to create an object
-with a blacklisted name, or rename an object to a blacklisted name.
+The NameBlocklist table contains a central blocklist of disallowed names.
+For objects using this blocklist, it is impossible to create an object
+with a blocklisted name, or rename an object to a blocklisted name.
-Try creating a project with a blacklisted name:
+Try creating a project with a blocklisted name:
>>> admin_browser.open("http://launchpad.test/projectgroups/+new")
- >>> admin_browser.getControl("Name", index=0).value = "blacklisted"
+ >>> admin_browser.getControl("Name", index=0).value = "blocklisted"
>>> admin_browser.getControl("Display Name").value = "Whatever"
>>> admin_browser.getControl("Project Group Summary").value = "Whatever"
>>> admin_browser.getControl("Description").value = "Whatever"
>>> admin_browser.getControl("Add").click()
>>> (
- ... "The name 'blacklisted' has been blocked"
+ ... "The name 'blocklisted' has been blocked"
... in admin_browser.contents
... )
True
-Try renaming a project to a blacklisted name:
+Try renaming a project to a blocklisted name:
>>> admin_browser.open("http://launchpad.test/mozilla")
>>> admin_browser.getLink("Administer").click()
- >>> admin_browser.getControl("Name", index=0).value = "blacklisted"
+ >>> admin_browser.getControl("Name", index=0).value = "blocklisted"
>>> admin_browser.getControl("Change Details").click()
>>> (
- ... "The name 'blacklisted' has been blocked"
+ ... "The name 'blocklisted' has been blocked"
... in admin_browser.contents
... )
True
@@ -32,10 +32,10 @@ Same behaviour for products:
>>> admin_browser.open("http://launchpad.test/firefox")
>>> admin_browser.getLink("Administer").click()
- >>> admin_browser.getControl("Name").value = "blacklisted"
+ >>> admin_browser.getControl("Name").value = "blocklisted"
>>> admin_browser.getControl("Change").click()
>>> (
- ... "The name 'blacklisted' has been blocked"
+ ... "The name 'blocklisted' has been blocked"
... in admin_browser.contents
... )
True
@@ -52,14 +52,14 @@ Same behaviour for people:
... )
True
-Note that it is possible to have an object with a blacklisted name. These
-objects were either created before the blacklist was implemented, or have
+Note that it is possible to have an object with a blocklisted name. These
+objects were either created before the blocklist was implemented, or have
been created or renamed manually by the DBA. Being able to manually set
-names to a blacklisted name is a desirable feature, as a use case of
-the black list is to prevent social engineering attacks by pretending to
+names to a blocklisted name is a desirable feature, as a use case of
+the blocklist is to prevent social engineering attacks by pretending to
be a Launchpad Celebrity.
-We can edit the details of an object with a blacklisted name quite
+We can edit the details of an object with a blocklisted name quite
happily without generating
>>> admin_browser.open("http://launchpad.test/~admins")
diff --git a/lib/lp/registry/templates/nameblacklists-index.pt b/lib/lp/registry/templates/nameblocklists-index.pt
similarity index 90%
rename from lib/lp/registry/templates/nameblacklists-index.pt
rename to lib/lp/registry/templates/nameblocklists-index.pt
index d9af3be..20f6472 100644
--- a/lib/lp/registry/templates/nameblacklists-index.pt
+++ b/lib/lp/registry/templates/nameblocklists-index.pt
@@ -17,19 +17,19 @@
<div metal:fill-slot="main" class="main-portlet">
<p>
- There are two kinds of blacklisted names:
+ There are two kinds of blocklisted names:
</p>
<ul class="bulleted">
<li>
- Organisational blacklisted names have an administering team
+ Organisational blocklisted names have an administering team
that is permitted to use the name for projects and teams.
</li>
<li>
- Application blacklisted names cannot have an administering team.
+ Application blocklisted names cannot have an administering team.
No one can override them.
</li>
</ul>
- <table id="blacklist" class="listing sortable">
+ <table id="blocklist" class="listing sortable">
<thead>
<th>Regular Expression</th>
<th>Admin</th>
@@ -41,7 +41,7 @@
<tt tal:content="item/regexp"/>
<tal:link replace="
structure
- item/menu:overview/edit_blacklist_expression/fmt:icon"/>
+ item/menu:overview/edit_blocklist_expression/fmt:icon"/>
</td>
<td>
<a
diff --git a/lib/lp/registry/tests/test_nameblacklist.py b/lib/lp/registry/tests/test_nameblacklist.py
deleted file mode 100644
index 3b41e88..0000000
--- a/lib/lp/registry/tests/test_nameblacklist.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test the person_sort_key stored procedure."""
-
-from zope.component import getUtility
-from zope.interface.verify import verifyObject
-
-from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-from lp.registry.interfaces.nameblacklist import (
- INameBlacklist,
- INameBlacklistSet,
-)
-from lp.services.database.interfaces import IStore
-from lp.services.webapp.authorization import check_permission
-from lp.testing import ANONYMOUS, TestCaseWithFactory, login, login_celebrity
-from lp.testing.layers import DatabaseFunctionalLayer, ZopelessDatabaseLayer
-
-
-class TestNameBlacklist(TestCaseWithFactory):
- layer = ZopelessDatabaseLayer
-
- def setUp(self):
- super().setUp()
- self.name_blacklist_set = getUtility(INameBlacklistSet)
- self.caret_foo_exp = self.name_blacklist_set.create("^foo")
- self.foo_exp = self.name_blacklist_set.create("foo")
- self.verbose_exp = self.name_blacklist_set.create("v e r b o s e")
- team = self.factory.makeTeam()
- self.admin_exp = self.name_blacklist_set.create("fnord", admin=team)
- self.store = IStore(self.foo_exp)
- self.store.flush()
-
- def name_blacklist_match(self, name, user_id=None):
- """Return the result of the name_blacklist_match stored procedure."""
- user_id = user_id or 0
- result = self.store.execute(
- "SELECT name_blacklist_match(%s, %s)", (name, user_id)
- )
- return result.get_one()[0]
-
- def is_blacklisted_name(self, name, user_id=None):
- """Return the result of the is_blacklisted_name stored procedure."""
- user_id = user_id or 0
- result = self.store.execute(
- "SELECT is_blacklisted_name(%s, %s)", (name, user_id)
- )
- blacklisted = result.get_one()[0]
- self.assertIsNotNone(blacklisted, "is_blacklisted_name returned NULL")
- return bool(blacklisted)
-
- def test_name_blacklist_match(self):
-
- # A name that is not blacklisted returns NULL/None
- self.assertIsNone(self.name_blacklist_match("bar"))
-
- # A name that is blacklisted returns the id of the row in the
- # NameBlacklist table that matched. Rows are tried in order, and the
- # first match is returned.
- self.assertEqual(
- self.name_blacklist_match("foobar"), self.caret_foo_exp.id
- )
- self.assertEqual(self.name_blacklist_match("barfoo"), self.foo_exp.id)
-
- def test_name_blacklist_match_admin_does_not_match(self):
- # A user in the expresssion's admin team is exempt from the
- # backlisted name restriction.
- user = self.admin_exp.admin.teamowner
- self.assertEqual(None, self.name_blacklist_match("fnord", user.id))
-
- def test_name_blacklist_match_launchpad_admin_can_change(self):
- # A Launchpad admin is exempt from any backlisted name restriction
- # that has an admin.
- user = self.factory.makePerson()
- admins = getUtility(ILaunchpadCelebrities).admin
- admins.addMember(user, user)
- self.assertEqual(None, self.name_blacklist_match("fnord", user.id))
-
- def test_name_blacklist_match_launchpad_admin_cannot_change(self):
- # A Launchpad admin cannot override backlisted names without admins.
- user = self.factory.makePerson()
- admins = getUtility(ILaunchpadCelebrities).admin
- admins.addMember(user, user)
- self.assertEqual(
- self.foo_exp.id, self.name_blacklist_match("barfoo", user.id)
- )
-
- def test_name_blacklist_match_cache(self):
- # If the blacklist is changed in the DB, these changes are noticed.
- # This test is needed because the stored procedure keeps a cache
- # of the compiled regular expressions.
- self.assertEqual(
- self.name_blacklist_match("foobar"), self.caret_foo_exp.id
- )
- self.caret_foo_exp.regexp = "nomatch"
- self.assertEqual(self.name_blacklist_match("foobar"), self.foo_exp.id)
- self.foo_exp.regexp = "nomatch2"
- self.assertIsNone(self.name_blacklist_match("foobar"))
-
- def test_is_blacklisted_name(self):
- # is_blacklisted_name() is just a wrapper around name_blacklist_match
- # that is friendlier to use in a boolean context.
- self.assertFalse(self.is_blacklisted_name("bar"))
- self.assertTrue(self.is_blacklisted_name("foo"))
- self.caret_foo_exp.regexp = "bar"
- self.foo_exp.regexp = "bar2"
- self.assertFalse(self.is_blacklisted_name("foo"))
-
- def test_is_blacklisted_name_admin_false(self):
- # Users in the expression's admin team are will return False.
- user = self.admin_exp.admin.teamowner
- self.assertFalse(self.is_blacklisted_name("fnord", user.id))
-
- def test_case_insensitive(self):
- self.assertTrue(self.is_blacklisted_name("Foo"))
-
- def test_verbose(self):
- # Testing the VERBOSE flag is used when compiling the regexp
- self.assertTrue(self.is_blacklisted_name("verbose"))
-
-
-class TestNameBlacklistSet(TestCaseWithFactory):
-
- layer = DatabaseFunctionalLayer
-
- def setUp(self):
- super().setUp()
- login_celebrity("registry_experts")
- self.name_blacklist_set = getUtility(INameBlacklistSet)
-
- def test_create_with_one_arg(self):
- # Test NameBlacklistSet.create(regexp).
- name_blacklist = self.name_blacklist_set.create("foo")
- self.assertTrue(verifyObject(INameBlacklist, name_blacklist))
- self.assertEqual("foo", name_blacklist.regexp)
- self.assertIs(None, name_blacklist.comment)
-
- def test_create_with_two_args(self):
- # Test NameBlacklistSet.create(regexp, comment).
- name_blacklist = self.name_blacklist_set.create("foo", "bar")
- self.assertTrue(verifyObject(INameBlacklist, name_blacklist))
- self.assertEqual("foo", name_blacklist.regexp)
- self.assertEqual("bar", name_blacklist.comment)
-
- def test_create_with_three_args(self):
- # Test NameBlacklistSet.create(regexp, comment, admin).
- team = self.factory.makeTeam()
- name_blacklist = self.name_blacklist_set.create("foo", "bar", team)
- self.assertTrue(verifyObject(INameBlacklist, name_blacklist))
- self.assertEqual("foo", name_blacklist.regexp)
- self.assertEqual("bar", name_blacklist.comment)
- self.assertEqual(team, name_blacklist.admin)
-
- def test_get_int(self):
- # Test NameBlacklistSet.get() with int id.
- name_blacklist = self.name_blacklist_set.create("foo", "bar")
- store = IStore(name_blacklist)
- store.flush()
- retrieved = self.name_blacklist_set.get(name_blacklist.id)
- self.assertEqual(name_blacklist, retrieved)
-
- def test_get_string(self):
- # Test NameBlacklistSet.get() with string id.
- name_blacklist = self.name_blacklist_set.create("foo", "bar")
- store = IStore(name_blacklist)
- store.flush()
- retrieved = self.name_blacklist_set.get(str(name_blacklist.id))
- self.assertEqual(name_blacklist, retrieved)
-
- def test_get_returns_None_instead_of_ValueError(self):
- # Test that NameBlacklistSet.get() will return None instead of
- # raising a ValueError when it tries to cast the id to an int,
- # so that traversing an invalid url causes a Not Found error
- # instead of an error that is recorded as an oops.
- self.assertIs(None, self.name_blacklist_set.get("asdf"))
-
- def test_getAll(self):
- # Test NameBlacklistSet.getAll().
- result = [
- (item.regexp, item.comment)
- for item in self.name_blacklist_set.getAll()
- ]
- expected = [
- ("^admin", None),
- ("blacklist", "For testing purposes"),
- ]
- self.assertEqual(expected, result)
-
- def test_NameBlacklistSet_permissions(self):
- # Verify that non-registry-experts do not have permission to
- # access the NameBlacklistSet.
- self.assertTrue(
- check_permission("launchpad.View", self.name_blacklist_set)
- )
- self.assertTrue(
- check_permission("launchpad.Edit", self.name_blacklist_set)
- )
- login(ANONYMOUS)
- self.assertFalse(
- check_permission("launchpad.View", self.name_blacklist_set)
- )
- self.assertFalse(
- check_permission("launchpad.Edit", self.name_blacklist_set)
- )
-
- def test_NameBlacklist_permissions(self):
- # Verify that non-registry-experts do not have permission to
- # access the NameBlacklist.
- name_blacklist = self.name_blacklist_set.create("foo")
- self.assertTrue(check_permission("launchpad.View", name_blacklist))
- self.assertTrue(check_permission("launchpad.Edit", name_blacklist))
- login(ANONYMOUS)
- self.assertFalse(check_permission("launchpad.View", name_blacklist))
- self.assertFalse(check_permission("launchpad.Edit", name_blacklist))
diff --git a/lib/lp/registry/tests/test_nameblocklist.py b/lib/lp/registry/tests/test_nameblocklist.py
new file mode 100644
index 0000000..d92ee61
--- /dev/null
+++ b/lib/lp/registry/tests/test_nameblocklist.py
@@ -0,0 +1,214 @@
+# Copyright 2009 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test the person_sort_key stored procedure."""
+
+from zope.component import getUtility
+from zope.interface.verify import verifyObject
+
+from lp.app.interfaces.launchpad import ILaunchpadCelebrities
+from lp.registry.interfaces.nameblocklist import (
+ INameBlocklist,
+ INameBlocklistSet,
+)
+from lp.services.database.interfaces import IStore
+from lp.services.webapp.authorization import check_permission
+from lp.testing import ANONYMOUS, TestCaseWithFactory, login, login_celebrity
+from lp.testing.layers import DatabaseFunctionalLayer, ZopelessDatabaseLayer
+
+
+class TestNameBlocklist(TestCaseWithFactory):
+ layer = ZopelessDatabaseLayer
+
+ def setUp(self):
+ super().setUp()
+ self.name_blocklist_set = getUtility(INameBlocklistSet)
+ self.caret_foo_exp = self.name_blocklist_set.create("^foo")
+ self.foo_exp = self.name_blocklist_set.create("foo")
+ self.verbose_exp = self.name_blocklist_set.create("v e r b o s e")
+ team = self.factory.makeTeam()
+ self.admin_exp = self.name_blocklist_set.create("fnord", admin=team)
+ self.store = IStore(self.foo_exp)
+ self.store.flush()
+
+ def name_blocklist_match(self, name, user_id=None):
+ """Return the result of the name_blocklist_match stored procedure."""
+ user_id = user_id or 0
+ result = self.store.execute(
+ "SELECT name_blocklist_match(%s, %s)", (name, user_id)
+ )
+ return result.get_one()[0]
+
+ def is_blocklisted_name(self, name, user_id=None):
+ """Return the result of the is_blocklisted_name stored procedure."""
+ user_id = user_id or 0
+ result = self.store.execute(
+ "SELECT is_blocklisted_name(%s, %s)", (name, user_id)
+ )
+ blocklisted = result.get_one()[0]
+ self.assertIsNotNone(blocklisted, "is_blocklisted_name returned NULL")
+ return bool(blocklisted)
+
+ def test_name_blocklist_match(self):
+
+ # A name that is not blocklisted returns NULL/None
+ self.assertIsNone(self.name_blocklist_match("bar"))
+
+ # A name that is blocklisted returns the id of the row in the
+ # NameBlocklist table that matched. Rows are tried in order, and the
+ # first match is returned.
+ self.assertEqual(
+ self.name_blocklist_match("foobar"), self.caret_foo_exp.id
+ )
+ self.assertEqual(self.name_blocklist_match("barfoo"), self.foo_exp.id)
+
+ def test_name_blocklist_match_admin_does_not_match(self):
+ # A user in the expresssion's admin team is exempt from the
+ # blocklisted name restriction.
+ user = self.admin_exp.admin.teamowner
+ self.assertEqual(None, self.name_blocklist_match("fnord", user.id))
+
+ def test_name_blocklist_match_launchpad_admin_can_change(self):
+ # A Launchpad admin is exempt from any blocklisted name restriction
+ # that has an admin.
+ user = self.factory.makePerson()
+ admins = getUtility(ILaunchpadCelebrities).admin
+ admins.addMember(user, user)
+ self.assertEqual(None, self.name_blocklist_match("fnord", user.id))
+
+ def test_name_blocklist_match_launchpad_admin_cannot_change(self):
+ # A Launchpad admin cannot override blocklisted names without admins.
+ user = self.factory.makePerson()
+ admins = getUtility(ILaunchpadCelebrities).admin
+ admins.addMember(user, user)
+ self.assertEqual(
+ self.foo_exp.id, self.name_blocklist_match("barfoo", user.id)
+ )
+
+ def test_name_blocklist_match_cache(self):
+ # If the blocklist is changed in the DB, these changes are noticed.
+ # This test is needed because the stored procedure keeps a cache
+ # of the compiled regular expressions.
+ self.assertEqual(
+ self.name_blocklist_match("foobar"), self.caret_foo_exp.id
+ )
+ self.caret_foo_exp.regexp = "nomatch"
+ self.assertEqual(self.name_blocklist_match("foobar"), self.foo_exp.id)
+ self.foo_exp.regexp = "nomatch2"
+ self.assertIsNone(self.name_blocklist_match("foobar"))
+
+ def test_is_blocklisted_name(self):
+ # is_blocklisted_name() is just a wrapper around name_blocklist_match
+ # that is friendlier to use in a boolean context.
+ self.assertFalse(self.is_blocklisted_name("bar"))
+ self.assertTrue(self.is_blocklisted_name("foo"))
+ self.caret_foo_exp.regexp = "bar"
+ self.foo_exp.regexp = "bar2"
+ self.assertFalse(self.is_blocklisted_name("foo"))
+
+ def test_is_blocklisted_name_admin_false(self):
+ # Users in the expression's admin team are will return False.
+ user = self.admin_exp.admin.teamowner
+ self.assertFalse(self.is_blocklisted_name("fnord", user.id))
+
+ def test_case_insensitive(self):
+ self.assertTrue(self.is_blocklisted_name("Foo"))
+
+ def test_verbose(self):
+ # Testing the VERBOSE flag is used when compiling the regexp
+ self.assertTrue(self.is_blocklisted_name("verbose"))
+
+
+class TestNameBlocklistSet(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super().setUp()
+ login_celebrity("registry_experts")
+ self.name_blocklist_set = getUtility(INameBlocklistSet)
+
+ def test_create_with_one_arg(self):
+ # Test NameBlocklistSet.create(regexp).
+ name_blocklist = self.name_blocklist_set.create("foo")
+ self.assertTrue(verifyObject(INameBlocklist, name_blocklist))
+ self.assertEqual("foo", name_blocklist.regexp)
+ self.assertIs(None, name_blocklist.comment)
+
+ def test_create_with_two_args(self):
+ # Test NameBlocklistSet.create(regexp, comment).
+ name_blocklist = self.name_blocklist_set.create("foo", "bar")
+ self.assertTrue(verifyObject(INameBlocklist, name_blocklist))
+ self.assertEqual("foo", name_blocklist.regexp)
+ self.assertEqual("bar", name_blocklist.comment)
+
+ def test_create_with_three_args(self):
+ # Test NameBlocklistSet.create(regexp, comment, admin).
+ team = self.factory.makeTeam()
+ name_blocklist = self.name_blocklist_set.create("foo", "bar", team)
+ self.assertTrue(verifyObject(INameBlocklist, name_blocklist))
+ self.assertEqual("foo", name_blocklist.regexp)
+ self.assertEqual("bar", name_blocklist.comment)
+ self.assertEqual(team, name_blocklist.admin)
+
+ def test_get_int(self):
+ # Test NameBlocklistSet.get() with int id.
+ name_blocklist = self.name_blocklist_set.create("foo", "bar")
+ store = IStore(name_blocklist)
+ store.flush()
+ retrieved = self.name_blocklist_set.get(name_blocklist.id)
+ self.assertEqual(name_blocklist, retrieved)
+
+ def test_get_string(self):
+ # Test NameBlocklistSet.get() with string id.
+ name_blocklist = self.name_blocklist_set.create("foo", "bar")
+ store = IStore(name_blocklist)
+ store.flush()
+ retrieved = self.name_blocklist_set.get(str(name_blocklist.id))
+ self.assertEqual(name_blocklist, retrieved)
+
+ def test_get_returns_None_instead_of_ValueError(self):
+ # Test that NameBlocklistSet.get() will return None instead of
+ # raising a ValueError when it tries to cast the id to an int,
+ # so that traversing an invalid url causes a Not Found error
+ # instead of an error that is recorded as an oops.
+ self.assertIs(None, self.name_blocklist_set.get("asdf"))
+
+ def test_getAll(self):
+ # Test NameBlocklistSet.getAll().
+ result = [
+ (item.regexp, item.comment)
+ for item in self.name_blocklist_set.getAll()
+ ]
+ expected = [
+ ("^admin", None),
+ ("blocklist", "For testing purposes"),
+ ]
+ self.assertEqual(expected, result)
+
+ def test_NameBlocklistSet_permissions(self):
+ # Verify that non-registry-experts do not have permission to
+ # access the NameBlocklistSet.
+ self.assertTrue(
+ check_permission("launchpad.View", self.name_blocklist_set)
+ )
+ self.assertTrue(
+ check_permission("launchpad.Edit", self.name_blocklist_set)
+ )
+ login(ANONYMOUS)
+ self.assertFalse(
+ check_permission("launchpad.View", self.name_blocklist_set)
+ )
+ self.assertFalse(
+ check_permission("launchpad.Edit", self.name_blocklist_set)
+ )
+
+ def test_NameBlocklist_permissions(self):
+ # Verify that non-registry-experts do not have permission to
+ # access the NameBlocklist.
+ name_blocklist = self.name_blocklist_set.create("foo")
+ self.assertTrue(check_permission("launchpad.View", name_blocklist))
+ self.assertTrue(check_permission("launchpad.Edit", name_blocklist))
+ login(ANONYMOUS)
+ self.assertFalse(check_permission("launchpad.View", name_blocklist))
+ self.assertFalse(check_permission("launchpad.Edit", name_blocklist))
diff --git a/lib/lp/registry/tests/test_personset.py b/lib/lp/registry/tests/test_personset.py
index 1469c89..9eb351d 100644
--- a/lib/lp/registry/tests/test_personset.py
+++ b/lib/lp/registry/tests/test_personset.py
@@ -27,7 +27,7 @@ from lp.registry.errors import (
NoSuchAccount,
NotPlaceholderAccount,
)
-from lp.registry.interfaces.nameblacklist import INameBlacklistSet
+from lp.registry.interfaces.nameblocklist import INameBlocklistSet
from lp.registry.interfaces.person import (
IPerson,
IPersonSet,
@@ -96,21 +96,21 @@ class TestPersonSet(TestCaseWithFactory):
self.addCleanup(logout)
self.person_set = getUtility(IPersonSet)
- def test_isNameBlacklisted(self):
+ def test_isNameBlocklisted(self):
cursor().execute(
- "INSERT INTO NameBlacklist(id, regexp) VALUES (-100, 'foo')"
+ "INSERT INTO NameBlocklist(id, regexp) VALUES (-100, 'foo')"
)
- self.assertTrue(self.person_set.isNameBlacklisted("foo"))
- self.assertFalse(self.person_set.isNameBlacklisted("bar"))
+ self.assertTrue(self.person_set.isNameBlocklisted("foo"))
+ self.assertFalse(self.person_set.isNameBlocklisted("bar"))
- def test_isNameBlacklisted_user_is_admin(self):
+ def test_isNameBlocklisted_user_is_admin(self):
team = self.factory.makeTeam()
- name_blacklist_set = getUtility(INameBlacklistSet)
- self.admin_exp = name_blacklist_set.create("fnord", admin=team)
+ name_blocklist_set = getUtility(INameBlocklistSet)
+ self.admin_exp = name_blocklist_set.create("fnord", admin=team)
self.store = IStore(self.admin_exp)
self.store.flush()
user = team.teamowner
- self.assertFalse(self.person_set.isNameBlacklisted("fnord", user))
+ self.assertFalse(self.person_set.isNameBlocklisted("fnord", user))
def test_getByEmail_ignores_case_and_whitespace(self):
person1_email = "foo.bar@xxxxxxxxxxxxx"
diff --git a/lib/lp/services/fields/__init__.py b/lib/lp/services/fields/__init__.py
index 1887615..1949b7a 100644
--- a/lib/lp/services/fields/__init__.py
+++ b/lib/lp/services/fields/__init__.py
@@ -4,7 +4,7 @@
__all__ = [
"AnnouncementDate",
"BaseImageUpload",
- "BlacklistableContentNameField",
+ "BlocklistableContentNameField",
"BugField",
"ContentNameField",
"Description",
@@ -499,22 +499,22 @@ class ContentNameField(UniqueField):
UniqueField._validate(self, name)
-class BlacklistableContentNameField(ContentNameField):
- """ContentNameField that also checks that a name is not blacklisted"""
+class BlocklistableContentNameField(ContentNameField):
+ """ContentNameField that also checks that a name is not blocklisted"""
- blacklistmessage = _(
+ blocklistmessage = _(
"The name '%s' has been blocked by the Launchpad "
"administrators. Contact Launchpad Support if you "
"want to use this name."
)
def _validate(self, input):
- """Check that the given name is valid, unique and not blacklisted."""
+ """Check that the given name is valid, unique and not blocklisted."""
super()._validate(input)
# Although this check is performed in UniqueField._validate(), we need
# to do it here again to avoid checking whether or not the name is
- # blacklisted when it hasn't been changed.
+ # blocklisted when it hasn't been changed.
if self.unchanged(input):
# The attribute wasn't changed.
return
@@ -523,8 +523,8 @@ class BlacklistableContentNameField(ContentNameField):
from lp.registry.interfaces.person import IPersonSet
user = getUtility(ILaunchBag).user
- if getUtility(IPersonSet).isNameBlacklisted(input, user):
- raise LaunchpadValidationError(self.blacklistmessage % input)
+ if getUtility(IPersonSet).isNameBlocklisted(input, user):
+ raise LaunchpadValidationError(self.blocklistmessage % input)
class PillarAliases(TextLine):
@@ -823,7 +823,7 @@ class MugshotImageUpload(BaseImageUpload):
max_size = 100 * 1024
-class PillarNameField(BlacklistableContentNameField):
+class PillarNameField(BlocklistableContentNameField):
"""Base field used for names of distros/project groups/products."""
errormessage = _("%s is already used by another project")
diff --git a/lib/lp/services/fields/tests/test_fields.py b/lib/lp/services/fields/tests/test_fields.py
index 665ce95..cbbaa9f 100644
--- a/lib/lp/services/fields/tests/test_fields.py
+++ b/lib/lp/services/fields/tests/test_fields.py
@@ -14,11 +14,11 @@ from zope.schema.interfaces import TooShort
from lp.app.validators import LaunchpadValidationError
from lp.blueprints.enums import SpecificationWorkItemStatus
from lp.registry.enums import EXCLUSIVE_TEAM_POLICY, INCLUSIVE_TEAM_POLICY
-from lp.registry.interfaces.nameblacklist import INameBlacklistSet
+from lp.registry.interfaces.nameblocklist import INameBlocklistSet
from lp.services.database.interfaces import IStore
from lp.services.fields import (
BaseImageUpload,
- BlacklistableContentNameField,
+ BlocklistableContentNameField,
FormattableDate,
StrippableText,
WorkItemsText,
@@ -536,15 +536,15 @@ class TestWorkItemsText(TestCase):
)
-class TestBlacklistableContentNameField(TestCaseWithFactory):
+class TestBlocklistableContentNameField(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
super().setUp()
- name_blacklist_set = getUtility(INameBlacklistSet)
+ name_blocklist_set = getUtility(INameBlocklistSet)
self.team = self.factory.makeTeam()
- admin_exp = name_blacklist_set.create("fnord", admin=self.team)
+ admin_exp = name_blocklist_set.create("fnord", admin=self.team)
IStore(admin_exp).flush()
def makeTestField(self):
@@ -553,7 +553,7 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
class ITestInterface(Interface):
pass
- class TestField(BlacklistableContentNameField):
+ class TestField(BlocklistableContentNameField):
_content_iface = ITestInterface
def _getByName(self, name):
@@ -561,15 +561,15 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
return TestField(__name__="test")
- def test_validate_fails_with_blacklisted_name_anonymous(self):
+ def test_validate_fails_with_blocklisted_name_anonymous(self):
# Anonymous users, processes, cannot create a name that matches
- # a blacklisted name.
+ # a blocklisted name.
field = self.makeTestField()
date_value = "fnord"
self.assertRaises(LaunchpadValidationError, field.validate, date_value)
- def test_validate_fails_with_blacklisted_name_not_admin(self):
- # Users who do not adminster a blacklisted name cannot create
+ def test_validate_fails_with_blocklisted_name_not_admin(self):
+ # Users who do not administer a blocklisted name cannot create
# a matching name.
field = self.makeTestField()
date_value = "fnord"
@@ -577,7 +577,7 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
self.assertRaises(LaunchpadValidationError, field.validate, date_value)
def test_validate_passes_for_admin(self):
- # Users in the team that adminsters a blacklisted name may create
+ # Users in the team that administers a blocklisted name may create
# matching names.
field = self.makeTestField()
date_value = "fnord"