[Launchpad-reviewers] [Merge] ~pappacena/launchpad:oci-project-of-project-git-namespace into launchpad:master
Thiago F. Pappacena has proposed merging ~pappacena/launchpad:oci-project-of-project-git-namespace into launchpad:master. Commit message: Adding support for GitNamespace of OCIProjects based on projects (not only distribution) Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395110 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:oci-project-of-project-git-namespace into launchpad:master. diff --git a/lib/lp/code/model/gitlookup.py b/lib/lp/code/model/gitlookup.py index a59134d..d4641ca 100644 --- a/lib/lp/code/model/gitlookup.py +++ b/lib/lp/code/model/gitlookup.py @@ -142,6 +142,19 @@ class ProjectGitTraversable(_BaseGitTraversable): From here, you can traverse to a named project repository. """ +def traverse(self, owner, name, segments): +if name == "+oci": +try: +spn_name = next(segments) +except StopIteration: +raise InvalidNamespace("/".join(segments.traversed)) +oci_project = self.context.getOCIProject(spn_name) +if oci_project is None: +raise NoSuchOCIProjectName(spn_name) +return owner, oci_project, None +return super(ProjectGitTraversable, self).traverse( +owner, name, segments) + def getNamespace(self, owner): return getUtility(IGitNamespaceSet).get(owner, project=self.context) diff --git a/lib/lp/code/model/tests/test_gitlookup.py b/lib/lp/code/model/tests/test_gitlookup.py index d527b06..69f209b 100644 --- a/lib/lp/code/model/tests/test_gitlookup.py +++ b/lib/lp/code/model/tests/test_gitlookup.py @@ -1,4 +1,4 @@ -# Copyright 2015-2018 Canonical Ltd. This software is licensed under the +# Copyright 2015-2020 Canonical Ltd. This software is licensed under the # GNU Affero General Public License version 3 (see the file LICENSE). """Tests for the IGitLookup implementation.""" @@ -242,8 +242,8 @@ class TestGetByUrl(TestCaseWithFactory): def test_getByUrl_with_trailing_segments(self): # URLs with trailing segments beyond the repository are rejected. self.makeProjectRepository() -self.assertIsNone( -self.lookup.getByUrl("git://git.launchpad.test/~aa/bb/+git/cc/foo")) +self.assertIsNone(self.lookup.getByUrl( +"git://git.launchpad.test/~aa/bb/+git/cc/foo")) def test_getByUrl_with_git(self): # getByUrl recognises LP repositories for git URLs. @@ -410,6 +410,16 @@ class TestGitTraverser(TestCaseWithFactory): path = "%s/+oci/%s" % (oci_project.pillar.name, oci_project.name) self.assertTraverses(path, None, oci_project) +def test_ociproject_based_on_project(self): +# `traverse_path` resolves '~person/product/+oci/ociproject' to the OCI +# project. +project = self.factory.makeProduct() +oci_project = self.factory.makeOCIProject(pillar=project) +path = "~%s/%s/+oci/%s" % ( +oci_project.registrant.name, oci_project.pillar.name, +oci_project.name) +self.assertTraverses(path, oci_project.registrant, oci_project) + def test_ociproject_no_named_repositories(self): # OCI projects do not have named repositories without an owner # context, so trying to traverse to them raises `InvalidNamespace`. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:stormify-announcement into launchpad:master
Thiago F. Pappacena has proposed merging ~pappacena/launchpad:stormify-announcement into launchpad:master. Commit message: Converting Announcements to Storm Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395106 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:stormify-announcement into launchpad:master. diff --git a/lib/lp/registry/model/announcement.py b/lib/lp/registry/model/announcement.py index 45b5740..a2c9ac9 100644 --- a/lib/lp/registry/model/announcement.py +++ b/lib/lp/registry/model/announcement.py @@ -11,12 +11,21 @@ __all__ = [ 'MakesAnnouncements', ] -from sqlobject import ( -BoolCol, -ForeignKey, -SQLObjectNotFound, -StringCol, +import pytz +import six +from storm.expr import ( +And, +LeftJoin, +Or, +Select, ) +from storm.properties import ( +Bool, +DateTime, +Int, +Unicode, +) +from storm.references import Reference from zope.interface import implementer from lp.registry.interfaces.announcement import ( @@ -28,40 +37,72 @@ from lp.registry.interfaces.person import validate_public_person from lp.registry.interfaces.product import IProduct from lp.registry.interfaces.projectgroup import IProjectGroup from lp.services.database.constants import UTC_NOW -from lp.services.database.datetimecol import UtcDateTimeCol -from lp.services.database.sqlbase import ( -SQLBase, -sqlvalues, +from lp.services.database.interfaces import ( +IMasterStore, +IStore, ) +from lp.services.database.stormbase import StormBase from lp.services.utils import utc_now @implementer(IAnnouncement) -class Announcement(SQLBase): +class Announcement(StormBase): """A news item. These allow us to generate lists of recent news for project groups, products and distributions. """ -_defaultOrder = ['-date_announced', '-date_created'] - -date_created = UtcDateTimeCol( -dbName='date_created', notNull=True, default=UTC_NOW) -date_announced = UtcDateTimeCol(default=None) -date_last_modified = UtcDateTimeCol( -dbName='date_updated', default=None) -registrant = ForeignKey( -dbName='registrant', foreignKey='Person', -storm_validator=validate_public_person, notNull=True) -product = ForeignKey(dbName='product', foreignKey='Product') -projectgroup = ForeignKey(dbName='project', foreignKey='ProjectGroup') -distribution = ForeignKey( -dbName='distribution', foreignKey='Distribution') -title = StringCol(notNull=True) -summary = StringCol(default=None) -url = StringCol(default=None) -active = BoolCol(notNull=True, default=True) +__storm_table__ = 'Announcement' + +__storm_order__ = ('-date_announced', '-date_created') + +id = Int(primary=True) + +date_created = DateTime(allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC) +date_announced = DateTime(allow_none=True, default=None, tzinfo=pytz.UTC) +date_last_modified = DateTime( +name='date_updated', allow_none=True, default=None, tzinfo=pytz.UTC) + +registrant_id = Int( +name="registrant", allow_none=False, validator=validate_public_person) +registrant = Reference(registrant_id, "Person.id") + +product_id = Int(name="product", allow_none=True, default=None) +product = Reference(product_id, "Product.id") + +projectgroup_id = Int(name="project", allow_none=True, default=None) +projectgroup = Reference(projectgroup_id, "ProjectGroup.id") + +distribution_id = Int(name="distribution", allow_none=True, default=None) +distribution = Reference(distribution_id, "Distribution.id") + +title = Unicode(allow_none=False) +summary = Unicode(allow_none=True, default=None) +url = Unicode(allow_none=True, default=None) +active = Bool(allow_none=False, default=True) + +def __init__(self, registrant, title, summary=None, url=None, + active=True, date_created=UTC_NOW, date_announced=None, + date_last_modified=None, product=None, projectgroup=None, + distribution=None): +self.registrant = registrant +self.title = title +self.summary = summary +self.url = url +self.active = active +self.date_created = date_created +self.date_announced = date_announced +self.date_last_modified = date_last_modified +self.product = product +self.projectgroup = projectgroup +self.distribution = distribution + +def destroySelf(self): +IMasterStore(self).remove(self) def modify(self, title, summary, url): +title = six.text_type(title) if title is not None else None +summary = six.text_type(summary) if summary is not None else None +url = six.text_type(url) if url is not None else None if
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:bugtask-oci-project into launchpad:master
Review: Approve Looks mostly good to me, aside from the possible BugSummary issue I mentioned in https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/393460. Diff comments: > diff --git a/lib/lp/registry/interfaces/ociproject.py > b/lib/lp/registry/interfaces/ociproject.py > index 82ba8ad..a189654 100644 > --- a/lib/lp/registry/interfaces/ociproject.py > +++ b/lib/lp/registry/interfaces/ociproject.py > @@ -189,7 +202,8 @@ class IOCIProjectLegitimate(Interface): > @exported_as_webservice_entry( > publish_web_link=True, as_of="devel", singular_name="oci_project") > class IOCIProject(IOCIProjectView, IOCIProjectEdit, > - IOCIProjectEditableAttributes, IOCIProjectLegitimate): > + IOCIProjectEditableAttributes, IOCIProjectLegitimate, > + IHasBugSupervisor, IHasExpirableBugs): I'm not sure IHasExpirableBugs is quite right yet - you haven't edited lp.bugs.browser.buglisting.target_has_expirable_bugs_listing, at least. Maybe that belongs in a separate MP? > """A project containing Open Container Initiative recipes.""" > > -- https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/393570 Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:stormify-bug-task. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:oci-bug-add-oci-columns into launchpad:db-devel
Diff comments: > diff --git a/database/schema/patch-2210-22-0.sql > b/database/schema/patch-2210-22-0.sql > new file mode 100644 > index 000..e1dd712 > --- /dev/null > +++ b/database/schema/patch-2210-22-0.sql > @@ -0,0 +1,488 @@ > +-- Copyright 2020 Canonical Ltd. This software is licensed under the > +-- GNU Affero General Public License version 3 (see the file LICENSE). > + > +SET client_min_messages=ERROR; > + > +-- This patch can be applied "cold", in a "fast-downtime" way. It basically > +-- adds the new OCI database columns, and rename current indexes so they can > be > +-- removed and replaced with new ones that includes the new columns. > + > +ALTER TABLE BugTask > +ADD COLUMN ociproject integer REFERENCES ociproject, > +ADD COLUMN ociprojectseries integer REFERENCES ociprojectseries, > +DROP CONSTRAINT bugtask_assignment_checks, > +ADD CONSTRAINT bugtask_assignment_checks CHECK ( > +CASE > +WHEN product IS NOT NULL THEN productseries IS NULL AND > distribution IS NULL AND distroseries IS NULL AND sourcepackagename IS NULL > +WHEN productseries IS NOT NULL THEN distribution IS NULL AND > distroseries IS NULL AND sourcepackagename IS NULL AND ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN distribution IS NOT NULL THEN distroseries IS NULL > +WHEN distroseries IS NOT NULL THEN ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN ociproject IS NOT NULL THEN ociprojectseries IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +WHEN ociprojectseries IS NOT NULL THEN ociproject IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +ELSE false > +END) NOT VALID; > + > +ALTER INDEX bugtask_distinct_sourcepackage_assignment > +RENAME TO old__bugtask_distinct_sourcepackage_assignment; > + > +ALTER INDEX bugtask__product__bug__key > +RENAME TO old__bugtask__product__bug__key; > + > +ALTER TABLE BugTaskFlat > +ADD COLUMN ociproject integer, > +ADD COLUMN ociprojectseries integer; > + > +ALTER TABLE BugSummary > +ADD COLUMN ociproject integer REFERENCES ociproject, > +ADD COLUMN ociprojectseries integer REFERENCES ociprojectseries, > +DROP CONSTRAINT bugtask_assignment_checks, > +ADD CONSTRAINT bugtask_assignment_checks CHECK ( > +CASE > +WHEN product IS NOT NULL THEN productseries IS NULL AND > distribution IS NULL AND distroseries IS NULL AND sourcepackagename IS NULL > +WHEN productseries IS NOT NULL THEN distribution IS NULL AND > distroseries IS NULL AND sourcepackagename IS NULL AND ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN distribution IS NOT NULL THEN distroseries IS NULL > +WHEN distroseries IS NOT NULL THEN ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN ociproject IS NOT NULL THEN ociprojectseries IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +WHEN ociprojectseries IS NOT NULL THEN ociproject IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +ELSE false > +END) NOT VALID; > + > +ALTER INDEX bugsummary__unique > +RENAME TO old__bugsummary__unique; > + > +ALTER TABLE BugSummaryJournal > +ADD COLUMN ociproject integer, > +ADD COLUMN ociprojectseries integer; > + > +-- Functions > + > +CREATE OR REPLACE FUNCTION bugtask_flatten(task_id integer, check_only > boolean) > +RETURNS boolean > +LANGUAGE plpgsql SECURITY DEFINER SET search_path = public > +AS $$ > +DECLARE > +bug_row Bug%ROWTYPE; > +task_row BugTask%ROWTYPE; > +old_flat_row BugTaskFlat%ROWTYPE; > +new_flat_row BugTaskFlat%ROWTYPE; > +_product_active boolean; > +_access_policies integer[]; > +_access_grants integer[]; > +BEGIN > +-- This is the master function to update BugTaskFlat, but there are > +-- maintenance triggers and jobs on the involved tables that update > +-- it directly. Any changes here probably require a corresponding > +-- change in other trigger functions. > + > +SELECT * INTO task_row FROM BugTask WHERE id = task_id; > +SELECT * INTO old_flat_row FROM BugTaskFlat WHERE bugtask = task_id; > + > +-- If the task doesn't exist, ensure that there's no flat row. > +IF task_row.id IS NULL THEN > +IF old_flat_row.bugtask IS NOT NULL THEN > +IF NOT check_only THEN > +DELETE FROM BugTaskFlat WHERE bugtask = task_id; > +END IF; > +RETURN FALSE; > +ELSE > +RETURN TRUE; > +END IF; > +END IF; > + > +SELECT * FROM bug INTO bug_row WHERE id = task_row.bug; > + > +-- If it's a product(series) task, we must consult the active flag. > +IF task_row.product IS NOT NULL THEN > +SELECT product.active INTO _product_active > +FROM product WHERE product.id = task_row.product
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:oci-bug-add-oci-columns into launchpad:db-devel
Diff comments: > diff --git a/database/schema/patch-2210-22-0.sql > b/database/schema/patch-2210-22-0.sql > new file mode 100644 > index 000..e1dd712 > --- /dev/null > +++ b/database/schema/patch-2210-22-0.sql > @@ -0,0 +1,488 @@ > +-- Copyright 2020 Canonical Ltd. This software is licensed under the > +-- GNU Affero General Public License version 3 (see the file LICENSE). > + > +SET client_min_messages=ERROR; > + > +-- This patch can be applied "cold", in a "fast-downtime" way. It basically > +-- adds the new OCI database columns, and rename current indexes so they can > be > +-- removed and replaced with new ones that includes the new columns. > + > +ALTER TABLE BugTask > +ADD COLUMN ociproject integer REFERENCES ociproject, > +ADD COLUMN ociprojectseries integer REFERENCES ociprojectseries, > +DROP CONSTRAINT bugtask_assignment_checks, > +ADD CONSTRAINT bugtask_assignment_checks CHECK ( > +CASE > +WHEN product IS NOT NULL THEN productseries IS NULL AND > distribution IS NULL AND distroseries IS NULL AND sourcepackagename IS NULL > +WHEN productseries IS NOT NULL THEN distribution IS NULL AND > distroseries IS NULL AND sourcepackagename IS NULL AND ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN distribution IS NOT NULL THEN distroseries IS NULL > +WHEN distroseries IS NOT NULL THEN ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN ociproject IS NOT NULL THEN ociprojectseries IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +WHEN ociprojectseries IS NOT NULL THEN ociproject IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +ELSE false > +END) NOT VALID; > + > +ALTER INDEX bugtask_distinct_sourcepackage_assignment > +RENAME TO old__bugtask_distinct_sourcepackage_assignment; > + > +ALTER INDEX bugtask__product__bug__key > +RENAME TO old__bugtask__product__bug__key; > + > +ALTER TABLE BugTaskFlat > +ADD COLUMN ociproject integer, > +ADD COLUMN ociprojectseries integer; > + > +ALTER TABLE BugSummary > +ADD COLUMN ociproject integer REFERENCES ociproject, > +ADD COLUMN ociprojectseries integer REFERENCES ociprojectseries, > +DROP CONSTRAINT bugtask_assignment_checks, > +ADD CONSTRAINT bugtask_assignment_checks CHECK ( > +CASE > +WHEN product IS NOT NULL THEN productseries IS NULL AND > distribution IS NULL AND distroseries IS NULL AND sourcepackagename IS NULL > +WHEN productseries IS NOT NULL THEN distribution IS NULL AND > distroseries IS NULL AND sourcepackagename IS NULL AND ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN distribution IS NOT NULL THEN distroseries IS NULL > +WHEN distroseries IS NOT NULL THEN ociproject IS NULL AND > ociprojectseries IS NULL > +WHEN ociproject IS NOT NULL THEN ociprojectseries IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +WHEN ociprojectseries IS NOT NULL THEN ociproject IS NULL AND > (distribution IS NOT NULL OR product IS NOT NULL) > +ELSE false > +END) NOT VALID; > + > +ALTER INDEX bugsummary__unique > +RENAME TO old__bugsummary__unique; > + > +ALTER TABLE BugSummaryJournal > +ADD COLUMN ociproject integer, > +ADD COLUMN ociprojectseries integer; > + > +-- Functions > + > +CREATE OR REPLACE FUNCTION bugtask_flatten(task_id integer, check_only > boolean) > +RETURNS boolean > +LANGUAGE plpgsql SECURITY DEFINER SET search_path = public > +AS $$ > +DECLARE > +bug_row Bug%ROWTYPE; > +task_row BugTask%ROWTYPE; > +old_flat_row BugTaskFlat%ROWTYPE; > +new_flat_row BugTaskFlat%ROWTYPE; > +_product_active boolean; > +_access_policies integer[]; > +_access_grants integer[]; > +BEGIN > +-- This is the master function to update BugTaskFlat, but there are > +-- maintenance triggers and jobs on the involved tables that update > +-- it directly. Any changes here probably require a corresponding > +-- change in other trigger functions. > + > +SELECT * INTO task_row FROM BugTask WHERE id = task_id; > +SELECT * INTO old_flat_row FROM BugTaskFlat WHERE bugtask = task_id; > + > +-- If the task doesn't exist, ensure that there's no flat row. > +IF task_row.id IS NULL THEN > +IF old_flat_row.bugtask IS NOT NULL THEN > +IF NOT check_only THEN > +DELETE FROM BugTaskFlat WHERE bugtask = task_id; > +END IF; > +RETURN FALSE; > +ELSE > +RETURN TRUE; > +END IF; > +END IF; > + > +SELECT * FROM bug INTO bug_row WHERE id = task_row.bug; > + > +-- If it's a product(series) task, we must consult the active flag. > +IF task_row.product IS NOT NULL THEN > +SELECT product.active INTO _product_active > +FROM product WHERE product.id = task_row.product
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:bugfix-email-change-error-msg-1907173 into launchpad:master
The proposal to merge ~pappacena/launchpad:bugfix-email-change-error-msg-1907173 into launchpad:master has been updated. Status: Approved => Merged For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395036 -- Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:bugfix-email-change-error-msg-1907173. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:bugfix-email-change-error-msg-1907173 into launchpad:master
The proposal to merge ~pappacena/launchpad:bugfix-email-change-error-msg-1907173 into launchpad:master has been updated. Status: Needs review => Approved For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395036 -- Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:bugfix-email-change-error-msg-1907173. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:bugfix-email-change-error-msg-1907173 into launchpad:master
Diff comments: > diff --git a/lib/lp/registry/browser/team.py b/lib/lp/registry/browser/team.py > index c309d57..d10af5a 100644 > --- a/lib/lp/registry/browser/team.py > +++ b/lib/lp/registry/browser/team.py > @@ -520,8 +521,10 @@ class TeamContactAddressView(MailingListTeamBaseView): > # We need to wrap this in structured, so that the > # markup is preserved. Note that this puts the > # responsibility for security on the exception thrower. > -self.setFieldError('contact_address', > - structured(str(error))) > +msg = error.args[0] > +if not isinstance(msg, structured): Ok! > +msg = structured(six.text_type(msg)) > +self.setFieldError('contact_address', msg) > elif data['contact_method'] == TeamContactMethod.HOSTED_LIST: > mailing_list = getUtility(IMailingListSet).get(self.context.name) > if mailing_list is None or not mailing_list.is_usable: > diff --git a/lib/lp/registry/browser/tests/test_team.py > b/lib/lp/registry/browser/tests/test_team.py > index 672c59d..44a1d63 100644 > --- a/lib/lp/registry/browser/tests/test_team.py > +++ b/lib/lp/registry/browser/tests/test_team.py > @@ -967,3 +970,28 @@ class TestPersonIndexVisibilityView(TestCaseWithFactory): > 'private team link', 'a', > attrs={'href': '/~private-team', 'class': 'sprite team private'}, > text='Private Team')) > + > + > +class TestTeamContactAddressView(TestCaseWithFactory): > + > +layer = DatabaseFunctionalLayer > + > +def test_team_change_contact_address_to_existing_address(self): > +# Test that a team can change the contact address. Ok! > +someone_email = "some...@canonical.com" > +someone = self.factory.makePerson( > +displayname="Unicode Person \xc9", email=someone_email) > +someone_url = canonical_url(someone) > +team = self.factory.makeTeam(email="t...@canonical.com") > +with admin_logged_in(): > +form = { > +'field.contact_method': 'EXTERNAL_ADDRESS', > +'field.contact_address': 'some...@canonical.com', > +'field.actions.change': 'Change', > +} > +view = create_initialized_view(team, '+contactaddress', > form=form) > +expected_msg = ( > +'%s is already registered in Launchpad and is associated ' > +'with Unicode Person \xc9.') > +expected_msg %= (someone_email, someone_url) > +self.assertEqual([expected_msg], view.errors) -- https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395036 Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:bugfix-email-change-error-msg-1907173. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~cjwatson/launchpad:script-activity-statsd into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:script-activity-statsd into launchpad:master. Commit message: Send script activity timings to statsd as well Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/395074 This will make it easier to add graphs, use modern alerting systems, and so on. -- Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:script-activity-statsd into launchpad:master. diff --git a/lib/lp/services/scripts/doc/script-monitoring.txt b/lib/lp/services/scripts/doc/script-monitoring.txt index 9e22745..eeb3604 100644 --- a/lib/lp/services/scripts/doc/script-monitoring.txt +++ b/lib/lp/services/scripts/doc/script-monitoring.txt @@ -22,21 +22,38 @@ IScriptActivitySet.recordSuccess(): >>> import socket >>> import subprocess >>> import tempfile +>>> from textwrap import dedent + +>>> from fixtures import MockPatchObject >>> import pytz >>> import transaction >>> from zope.component import getUtility + +>>> from lp.services.compat import mock +>>> from lp.services.config import config >>> from lp.services.scripts.interfaces.scriptactivity import ( ... IScriptActivitySet) +>>> from lp.services.statsd.interfaces.statsd_client import IStatsdClient >>> from lp.testing.dbuser import switch_dbuser >>> UTC = pytz.timezone('UTC') >>> switch_dbuser('garbo_daily') # A script db user ->>> activity = getUtility(IScriptActivitySet).recordSuccess( -... name='script-name', -... date_started=datetime.datetime(2007,2,1,10,0,tzinfo=UTC), -... date_completed=datetime.datetime(2007,2,1,10,1,tzinfo=UTC), -... hostname='script-host') +>>> config.push('statsd_test', dedent(''' +... [statsd] +... environment: test +... ''')) +>>> statsd_client = getUtility(IStatsdClient) +>>> stats_client = mock.Mock() + +>>> with MockPatchObject(statsd_client, '_client', stats_client): +... activity = getUtility(IScriptActivitySet).recordSuccess( +... name='script-name', +... date_started=datetime.datetime(2007,2,1,10,0,tzinfo=UTC), +... date_completed=datetime.datetime(2007,2,1,10,1,tzinfo=UTC), +... hostname='script-host') + +>>> _ = config.pop('statsd_test') The activity object records the script name, the host name it ran on and the start and end timestamps: @@ -50,6 +67,15 @@ and the start and end timestamps: >>> print(activity.date_completed) 2007-02-01 10:01:00+00:00 +It sends a corresponding timing stat to statsd. + +>>> stats_client.timing.call_count +1 +>>> print(stats_client.timing.call_args[0][0]) +script_activity,name=script-name,env=test +>>> stats_client.timing.call_args[0][1] +6.0 + We can also query for the last activity for a particular script, which will match the activity we just created: diff --git a/lib/lp/services/scripts/model/scriptactivity.py b/lib/lp/services/scripts/model/scriptactivity.py index 7984696..0df3849 100644 --- a/lib/lp/services/scripts/model/scriptactivity.py +++ b/lib/lp/services/scripts/model/scriptactivity.py @@ -17,6 +17,7 @@ from storm.locals import ( Int, Unicode, ) +from zope.component import getUtility from zope.interface import implementer from lp.services.database.interfaces import IStore @@ -25,6 +26,7 @@ from lp.services.scripts.interfaces.scriptactivity import ( IScriptActivity, IScriptActivitySet, ) +from lp.services.statsd.interfaces.statsd_client import IStatsdClient @implementer(IScriptActivity) @@ -58,6 +60,11 @@ class ScriptActivitySet: name=six.ensure_text(name), hostname=six.ensure_text(hostname), date_started=date_started, date_completed=date_completed) IStore(ScriptActivity).add(activity) +# Pass equivalent information through to statsd as well. (Don't +# bother with the hostname, since telegraf adds that.) +getUtility(IStatsdClient).timing( +'script_activity,name={}'.format(name), +(date_completed - date_started).total_seconds() * 1000) return activity def getLastActivity(self, name): ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~cjwatson/launchpad:stormify-translations-queries into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:stormify-translations-queries into launchpad:master with ~cjwatson/launchpad:stormify-potranslation as a prerequisite. Commit message: Convert SQLObject-style queries in lp.translations to Storm Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/395062 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-translations-queries into launchpad:master. diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py index 2811a42..e83a7dc 100644 --- a/lib/lp/registry/model/distroseries.py +++ b/lib/lp/registry/model/distroseries.py @@ -178,7 +178,6 @@ from lp.translations.model.hastranslationtemplates import ( ) from lp.translations.model.languagepack import LanguagePack from lp.translations.model.pofile import POFile -from lp.translations.model.pofiletranslator import POFileTranslator from lp.translations.model.potemplate import ( POTemplate, TranslationTemplatesCollection, @@ -1362,6 +1361,9 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin, def getPOFileContributorsByLanguage(self, language): """See `IDistroSeries`.""" +# Circular import. +from lp.translations.model.pofiletranslator import POFileTranslator + contributors = IStore(Person).find( Person, POFileTranslator.personID == Person.id, diff --git a/lib/lp/translations/doc/poexport-request-productseries.txt b/lib/lp/translations/doc/poexport-request-productseries.txt index 1978e3e..53303a2 100644 --- a/lib/lp/translations/doc/poexport-request-productseries.txt +++ b/lib/lp/translations/doc/poexport-request-productseries.txt @@ -7,9 +7,9 @@ This is a dummy logger class to capture the export's log messages. ->>> from lp.registry.model.person import Person +>>> from lp.registry.interfaces.person import IPersonSet >>> from lp.services.log.logger import FakeLogger ->>> person = Person.selectOneBy(name='name12') +>>> person = getUtility(IPersonSet).getByName('name12') An arbitrary logged-in user requests an export of all translations for Evolution series trunk. @@ -18,16 +18,15 @@ At the UI level, this is easy. At the level we are looking at now, this consists of a series of requests for all templates and translations attached to the product series. ->>> from lp.registry.model.product import Product ->>> from lp.registry.model.productseries import ProductSeries ->>> from lp.translations.model.potemplate import POTemplate ->>> evolution_product = Product.selectOneBy(name='evolution') ->>> evolution_trunk = ProductSeries.selectOneBy( -... product=evolution_product, name='trunk') ->>> potemplates = list(POTemplate.selectBy(productseries=evolution_trunk)) +>>> from lp.registry.interfaces.product import IProductSet +>>> from lp.translations.interfaces.potemplate import IPOTemplateSet +>>> evolution_product = getUtility(IProductSet).getByName('evolution') +>>> evolution_trunk = evolution_product.getSeries('trunk') +>>> potemplates = list(getUtility(IPOTemplateSet).getSubset( +... productseries=evolution_trunk)) >>> pofiles = [] >>> for template in potemplates: -... pofiles += template.pofiles +... pofiles.extend(template.pofiles) >>> request_set = getUtility(IPOExportRequestSet) >>> request_set.addRequest(person, potemplates, pofiles) diff --git a/lib/lp/translations/doc/poexport-request.txt b/lib/lp/translations/doc/poexport-request.txt index cf6d13f..8e87314 100644 --- a/lib/lp/translations/doc/poexport-request.txt +++ b/lib/lp/translations/doc/poexport-request.txt @@ -233,9 +233,11 @@ just PO files. >>> product_template.productseries is None False >>> request_set.addRequest(person, product_template) ->>> alsa_template = POTemplate.selectOneBy(path='po/alsa-utils.pot') +>>> alsa_template = IStore(POTemplate).find( +... POTemplate, path='po/alsa-utils.pot').one() >>> alsa_es = alsa_template.getPOFileByLang('es') ->>> netapplet_template = POTemplate.selectOneBy(path='po/netapplet.pot') +>>> netapplet_template = IStore(POTemplate).find( +... POTemplate, path='po/netapplet.pot').one() >>> request_set.addRequest( ... person, [alsa_template, netapplet_template], [alsa_es]) >>> transaction.commit() diff --git a/lib/lp/translations/doc/pofile.txt b/lib/lp/translations/doc/pofile.txt index 9caf91d..286080b 100644 --- a/lib/lp/translations/doc/pofile.txt +++ b/lib/lp/translations/doc/pofile.txt @@ -611,10 +611,8 @@ If you have a distroseries and want to know all the people who contributed translations on a given language for that distroseries, you can use the getPOFileContributorsByLanguage() method of IDistroSeries.