launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03598
[Merge] lp:~rvb/launchpad/multi-parent-diff-pages2 into lp:launchpad/db-devel
Raphaël Victor Badin has proposed merging lp:~rvb/launchpad/multi-parent-diff-pages2 into lp:launchpad/db-devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #778371 in Launchpad itself: "The differences pages (i.e. pages showing DSDs) should be updated to account for the case where a series has multiple parents."
https://bugs.launchpad.net/launchpad/+bug/778371
For more details, see:
https://code.launchpad.net/~rvb/launchpad/multi-parent-diff-pages2/+merge/60799
This branch fixes the differences pages (+localpackagediff, etc.) to account for the case where a series has multiple parents.
This involves:
- fixing DSD pages to:
- modify the button, explanatory paragraph.
- add a column to the table to display the DSD's parent name.
- fixing the uri for a DSD (from https://.../distro/series/+difference/sourcename to https://.../distro/series/+source/sourcename/+difference/parentdistro/parentseries)
= Tests =
./bin/test -cvv test_distroseries test_differences_portlet_all_differences_multiple_parents
./bin/test -cvv test_distroseries test_queries_single_parent
./bin/test -cvv test_distroseries test_queries_multiple_parents
./bin/test -cvv test_distroseries test_label_multiple_parents
./bin/test -cvv test_distroseries test_multiple_parents_display
./bin/test -cvv test_distroseries test_higher_radio_mentions_parents
= Q/A =
On DF: create a series with multiple parents:
- check the series homepage displays the right number of parents: https://dogfood.launchpad.net/distro/series/
- check the differences pages:
https://dogfood.launchpad.net/distro/series/+localpackagediffs
https://dogfood.launchpad.net/distro/series/+uniquepackages
https://dogfood.launchpad.net/distro/series/+missingpackages
Check:
- sync button name
- page title
- page explanation paragraph
- package filtering options
Check having 2 packages with the same source package name from 2 difference parents.
- check opening up a row on
https://dogfood.launchpad.net/distro/series/+localpackagediffs
make sure the url for the html ragment is:
https://dogfood.launchpad.net/distro/series/+source/sourcename/+difference/parentdistro/parentseries
--
https://code.launchpad.net/~rvb/launchpad/multi-parent-diff-pages2/+merge/60799
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/launchpad/multi-parent-diff-pages2 into lp:launchpad/db-devel.
=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-04-27 15:12:08 +0000
+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-05-12 14:59:29 +0000
@@ -490,6 +490,8 @@
IDistroSeries, 'deriveDistroSeries', 'distribution', IDistribution)
patch_collection_return_type(
IDistroSeries, 'getDerivedSeries', IDistroSeries)
+patch_collection_return_type(
+ IDistroSeries, 'getParentSeries', IDistroSeries)
patch_plain_parameter_type(
IDistroSeries, 'getDifferencesTo', 'parent_series', IDistroSeries)
patch_choice_parameter_type(
@@ -856,8 +858,8 @@
patch_entry_explicit_version(IDistroSeries, 'beta')
patch_operations_explicit_version(
IDistroSeries, 'beta', "deriveDistroSeries", "getDerivedSeries",
- "getDistroArchSeries", "getPackageUploads", "getSourcePackage",
- "newMilestone")
+ "getParentSeries", "getDistroArchSeries", "getPackageUploads",
+ "getSourcePackage", "newMilestone")
# IDistroSeriesDifference
patch_entry_explicit_version(IDistroSeriesDifference, 'beta')
=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2011-04-17 18:00:45 +0000
+++ lib/lp/registry/browser/configure.zcml 2011-05-12 14:59:29 +0000
@@ -177,7 +177,7 @@
permission="zope.Public"/>
<browser:url
for="lp.registry.interfaces.distroseriesdifference.IDistroSeriesDifference"
- path_expression="string:+difference/${source_package_name/name}"
+ path_expression="string:+source/${source_package_name/name}/+difference/${parent_series/parent/name}/${parent_series/name}"
rootsite="mainsite"
attribute_to_parent="derived_series"/>
<browser:page
=== modified file 'lib/lp/registry/browser/distroseries.py'
--- lib/lp/registry/browser/distroseries.py 2011-05-12 00:09:30 +0000
+++ lib/lp/registry/browser/distroseries.py 2011-05-12 14:59:29 +0000
@@ -95,7 +95,6 @@
from lp.registry.interfaces.distroseriesdifference import (
IDistroSeriesDifferenceSource,
)
-from lp.registry.interfaces.distroseriesparent import IDistroSeriesParentSet
from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.registry.interfaces.series import SeriesStatus
from lp.services.features import getFeatureFlag
@@ -181,11 +180,6 @@
def traverse_queue(self, id):
return getUtility(IPackageUploadSet).get(id)
- @stepthrough('+difference')
- def traverse_difference(self, name):
- dsd_source = getUtility(IDistroSeriesDifferenceSource)
- return dsd_source.getByDistroSeriesAndName(self.context, name)
-
class DistroSeriesBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `IDistroSeries`."""
@@ -359,7 +353,35 @@
self.context.datereleased = UTC_NOW
-class DistroSeriesView(LaunchpadView, MilestoneOverlayMixin):
+class DerivedDistroSeriesMixin():
+
+ @cachedproperty
+ def has_unique_parent(self):
+ return len(self.context.getParentSeries()) == 1
+
+ @cachedproperty
+ def unique_parent(self):
+ if self.has_unique_parent:
+ return self.context.getParentSeries()[0]
+ else:
+ None
+
+ @cachedproperty
+ def number_of_parents(self):
+ return len(self.context.getParentSeries())
+
+ @cachedproperty
+ def parent_name(self):
+ if self.has_unique_parent:
+ parent_name = ("parent series '%s'" %
+ self.unique_parent.displayname)
+ else:
+ parent_name = 'a parent series'
+ return parent_name
+
+
+class DistroSeriesView(LaunchpadView, MilestoneOverlayMixin,
+ DerivedDistroSeriesMixin):
def initialize(self):
super(DistroSeriesView, self).initialize()
@@ -444,15 +466,6 @@
return self._num_differences(
DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES)
- @cachedproperty
- def parent_series(self):
- # XXX StevenK: This will currently throw NotOneError up the
- # callstack if the child has more than one parent. This is okay
- # *for now*, so we can get away with no UI changes.
- dsp = getUtility(IDistroSeriesParentSet).getByDerivedSeries(
- self.context).one()
- return dsp.parent_series
-
class DistroSeriesEditView(LaunchpadEditFormView, SeriesStatusMixin):
"""View class that lets you edit a DistroSeries object.
@@ -682,7 +695,7 @@
higher_term = SimpleTerm(
HIGHER_VERSION_THAN_PARENT,
HIGHER_VERSION_THAN_PARENT,
- "Blacklisted packages with a higher version than in '%s'"
+ "Blacklisted packages with a higher version than in %s"
% parent_name)
voc.insert(2, higher_term)
return SimpleVocabulary(tuple(voc))
@@ -715,7 +728,8 @@
class DistroSeriesDifferenceBaseView(LaunchpadFormView,
- PackageCopyingMixin):
+ PackageCopyingMixin,
+ DerivedDistroSeriesMixin):
"""Base class for all pages presenting differences between
a derived series and its parent."""
schema = IDifferencesFormSchema
@@ -750,10 +764,14 @@
return NotImplementedError()
def setupPackageFilterRadio(self):
+ if self.has_unique_parent:
+ parent_name = "'%s'" % self.unique_parent.displayname
+ else:
+ parent_name = 'parent'
return form.Fields(Choice(
__name__='package_type',
vocabulary=make_package_type_vocabulary(
- self.parent_series.displayname,
+ parent_name,
self.search_higher_parent_option),
default=DEFAULT_PACKAGE_TYPE,
required=True))
@@ -770,9 +788,8 @@
self.form_fields)
check_permission('launchpad.Edit', self.context)
terms = [
- SimpleTerm(diff, diff.source_package_name.name,
- diff.source_package_name.name)
- for diff in self.cached_differences.batch]
+ SimpleTerm(diff, diff.id)
+ for diff in self.cached_differences.batch]
diffs_vocabulary = SimpleVocabulary(terms)
choice = self.form_fields['selected_differences'].field.value_type
choice.vocabulary = diffs_vocabulary
@@ -905,15 +922,6 @@
DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT))
return not differences.is_empty()
- @cachedproperty
- def parent_series(self):
- # XXX StevenK: This will currently throw NotOneError up the
- # callstack if the child has more than one parent. This is okay
- # *for now*, so we can get away with no UI changes.
- dsp = getUtility(IDistroSeriesParentSet).getByDerivedSeries(
- self.context).one()
- return dsp.parent_series
-
class DistroSeriesLocalDifferencesView(DistroSeriesDifferenceBaseView,
LaunchpadFormView):
@@ -927,9 +935,13 @@
def initialize(self):
# Update the label for sync action.
+ if self.has_unique_parent:
+ parent_name = "'%s'" % self.unique_parent.displayname
+ else:
+ parent_name = 'Parent'
self.initialize_sync_label(
"Sync Selected %s Versions into %s" % (
- self.parent_series.displayname,
+ parent_name,
self.context.displayname,
))
super(DistroSeriesLocalDifferencesView, self).initialize()
@@ -938,23 +950,26 @@
def explanation(self):
return structured(
"Source packages shown here are present in both %s "
- "and the parent series, %s, but are different somehow. "
+ "and %s, but are different somehow. "
"Changes could be in either or both series so check the "
- "versions (and the diff if necessary) before syncing the %s "
+ "versions (and the diff if necessary) before syncing the parent "
'version (<a href="/+help/soyuz/derived-series-syncing.html" '
- 'target="help">Read more about syncing from the parent series'
+ 'target="help">Read more about syncing from a parent series'
'</a>).',
self.context.displayname,
- self.parent_series.fullseriesname,
- self.parent_series.displayname)
+ self.parent_name)
@property
def label(self):
+ if self.has_unique_parent:
+ parent_name = self.parent_name
+ else:
+ parent_name = 'parent series'
return (
- "Source package differences between '%s' and "
- "parent series '%s'" % (
+ "Source package differences between '%s' and"
+ " %s" % (
self.context.displayname,
- self.parent_series.displayname,
+ parent_name,
))
@action(_("Update"), name="update")
@@ -1034,7 +1049,7 @@
def initialize(self):
# Update the label for sync action.
self.initialize_sync_label(
- "Include Selected packages into into %s" % (
+ "Include Selected packages into %s" % (
self.context.displayname,
))
super(DistroSeriesMissingPackagesView, self).initialize()
@@ -1043,17 +1058,17 @@
def explanation(self):
return structured(
"Packages that are listed here are those that have been added to "
- "the specific packages %s that were used to create %s. They are "
- "listed here so you can consider including them in %s.",
- self.parent_series.displayname,
+ "the specific set of packages in %s that were used to create %s. "
+ "They are listed here so you can consider including them in %s.",
+ self.parent_name,
self.context.displayname,
self.context.displayname)
@property
def label(self):
return (
- "Packages in parent series '%s' but not in '%s'" % (
- self.parent_series.displayname,
+ "Packages in %s but not in '%s'" % (
+ self.parent_name,
self.context.displayname,
))
@@ -1086,16 +1101,16 @@
def explanation(self):
return structured(
"Packages that are listed here are those that have been added to "
- "%s but are not yet part of the parent series %s.",
+ "%s but are not yet part of %s.",
self.context.displayname,
- self.parent_series.displayname)
+ self.parent_name)
@property
def label(self):
return (
- "Packages in '%s' but not in parent series '%s'" % (
+ "Packages in '%s' but not in %s" % (
self.context.displayname,
- self.parent_series.displayname,
+ self.parent_name,
))
@action(_("Update"), name="update")
=== modified file 'lib/lp/registry/browser/tests/test_distroseries.py'
--- lib/lp/registry/browser/tests/test_distroseries.py 2011-05-12 00:09:30 +0000
+++ lib/lp/registry/browser/tests/test_distroseries.py 2011-05-12 14:59:29 +0000
@@ -142,29 +142,42 @@
layer = DatabaseFunctionalLayer
- def _setupDifferences(self, name, parent_name, nb_diff_versions,
+ def _setupDifferences(self, name, parent_names, nb_diff_versions,
nb_diff_child, nb_diff_parent):
- # Helper to create DSD of the different types.
+ # Helper to create DSDs of the different types.
derived_series = self.factory.makeDistroSeries(name=name)
- parent_series = self.factory.makeDistroSeries(name=parent_name)
- self.factory.makeDistroSeriesParent(
- derived_series=derived_series, parent_series=parent_series)
self.simple_user = self.factory.makePerson()
+ # parent_names can be a list of parent names or a single name
+ # for a single parent (e.g. ['parent1_name', 'parent2_name'] or
+ # 'parent_name').
+ # If multiple parents are created, the DSDs will be created with
+ # the first one.
+ if type(parent_names) == str:
+ parent_names = [parent_names]
+ dsps = []
+ for parent_name in parent_names:
+ parent_series = self.factory.makeDistroSeries(name=parent_name)
+ dsps.append(self.factory.makeDistroSeriesParent(
+ derived_series=derived_series, parent_series=parent_series))
+ first_parent_series = dsps[0].parent_series
for i in range(nb_diff_versions):
diff_type = DistroSeriesDifferenceType.DIFFERENT_VERSIONS
self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
- difference_type=diff_type)
+ difference_type=diff_type,
+ parent_series=first_parent_series)
for i in range(nb_diff_child):
diff_type = DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES
self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
- difference_type=diff_type)
+ difference_type=diff_type,
+ parent_series=first_parent_series)
for i in range(nb_diff_parent):
diff_type = DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES
self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
- difference_type=diff_type)
+ difference_type=diff_type,
+ parent_series=first_parent_series)
return derived_series
def test_differences_no_flag_no_portlet(self):
@@ -221,6 +234,33 @@
self.assertThat(html_content, portlet_display)
+ def test_differences_portlet_all_differences_multiple_parents(self):
+ # The difference portlet shows the differences with the multiple
+ # parent series.
+ set_derived_series_ui_feature_flag(self)
+ derived_series = self._setupDifferences(
+ 'deri', ['sid1', 'sid2'], 0, 1, 0)
+ portlet_display = soupmatchers.HTMLContains(
+ soupmatchers.Tag(
+ 'Derivation portlet header', 'h2',
+ text='Derived from 2 parents'),
+ soupmatchers.Tag(
+ 'Parent diffs link', 'a',
+ text=re.compile('\s*1 package only in a parent series\s*'),
+ attrs={'href': re.compile('.*/\+missingpackages')}))
+
+ with person_logged_in(self.simple_user):
+ view = create_initialized_view(
+ derived_series,
+ '+index',
+ principal=self.simple_user)
+ # XXX rvb 2011-04-12 bug=758649: LaunchpadTestRequest overrides
+ # self.features to NullFeatureController.
+ view.request.features = get_relevant_feature_controller()
+ html_text = view()
+
+ self.assertThat(html_text, portlet_display)
+
def test_differences_portlet_no_differences(self):
# The difference portlet displays 'No differences' if there is no
# differences with the parent.
@@ -419,13 +459,19 @@
self.assertThat(html_content, parent_packagesets)
- def _create_child_and_parent(self):
+ def _createChildAndParent(self):
derived_series = self.factory.makeDistroSeries(name='derilucid')
parent_series = self.factory.makeDistroSeries(name='lucid')
self.factory.makeDistroSeriesParent(
derived_series=derived_series, parent_series=parent_series)
return (derived_series, parent_series)
+ def _createChildAndParents(self, other_parent_series=None):
+ derived_series, parent_series = self._createChildAndParent()
+ self.factory.makeDistroSeriesParent(
+ derived_series=derived_series, parent_series=other_parent_series)
+ return (derived_series, parent_series)
+
class TestDistroSeriesLocalDifferences(
DistroSeriesDifferenceMixin, TestCaseWithFactory):
@@ -443,7 +489,7 @@
# Test that the page includes the filter form if differences
# are present
login_person(self.simple_user)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
self.factory.makeDistroSeriesDifference(
derived_series=derived_series)
@@ -459,7 +505,7 @@
# Test that the page doesn't includes the filter form if no
# differences are present
login_person(self.simple_user)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
view = create_initialized_view(
derived_series, '+localpackagediffs', principal=self.simple_user)
@@ -513,13 +559,24 @@
html_content, packageset_text, 'parent-packagesets',
'Parent packagesets')
- def test_queries(self):
+
+class TestDistroSeriesLocalDifferencesPerformance(DistroSeriesDifferenceMixin,
+ TestCaseWithFactory):
+ """Test the distroseries +localpackagediffs page's performance."""
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestDistroSeriesLocalDifferencesPerformance,
+ self).setUp('foo.bar@xxxxxxxxxxxxx')
+ set_derived_series_ui_feature_flag(self)
+ self.simple_user = self.factory.makePerson()
+
+ def _assertQueryCount(self, derived_series):
# With no DistroSeriesDifferences the query count should be low and
# fairly static. However, with some DistroSeriesDifferences the query
# count will be higher, but it should remain the same no matter how
# many differences there are.
- dsp = self.factory.makeDistroSeriesParent()
- derived_series = dsp.derived_series
ArchivePermission(
archive=derived_series.main_archive, person=self.simple_user,
component=getUtility(IComponentSet)["main"],
@@ -627,8 +684,28 @@
recorder3, HasQueryCount(
LessThan(compromise_statement_count + 1)))
-
-class TestDistroSeriesLocalDifferencesZopeless(TestCaseWithFactory):
+ def test_queries_single_parent(self):
+ dsp = self.factory.makeDistroSeriesParent()
+ derived_series = dsp.derived_series
+ self._assertQueryCount(derived_series)
+
+ def test_queries_multiple_parents(self):
+ dsp = self.factory.makeDistroSeriesParent()
+ derived_series = dsp.derived_series
+ self.factory.makeDistroSeriesParent(
+ derived_series=derived_series)
+ self._assertQueryCount(derived_series)
+
+ def test_queries_multiple_parents(self):
+ dsp = self.factory.makeDistroSeriesParent()
+ derived_series = dsp.derived_series
+ self.factory.makeDistroSeriesParent(
+ derived_series=derived_series)
+ self._assertQueryCount(derived_series)
+
+
+class TestDistroSeriesLocalDifferencesZopeless(DistroSeriesDifferenceMixin,
+ TestCaseWithFactory):
"""Test the distroseries +localpackagediffs view."""
layer = LaunchpadFunctionalLayer
@@ -658,7 +735,7 @@
principal=get_current_principal(),
current_request=True)
- def _create_child_and_parent(self):
+ def _createChildAndParent(self):
parent_series = self.factory.makeDistroSeries(name='lucid')
derived_series = self.factory.makeDistroSeries(name='derilucid')
self.factory.makeDistroSeriesParent(
@@ -668,7 +745,7 @@
def test_view_redirects_without_feature_flag(self):
# If the feature flag soyuz.derived-series-ui.enabled is not set the
# view simply redirects to the derived series.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
self.assertIs(
None, getFeatureFlag('soyuz.derived-series-ui.enabled'))
@@ -681,7 +758,7 @@
def test_label(self):
# The view label includes the names of both series.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
view = self.makeView(derived_series)
@@ -690,10 +767,36 @@
"parent series 'Lucid'",
view.label)
+ def test_label_multiple_parents(self):
+ # If the series has multiple parents, the view label mentions
+ # the generic term 'parent series'.
+ derived_series, parent_series = self._createChildAndParents()
+
+ view = create_initialized_view(
+ derived_series, '+localpackagediffs')
+
+ self.assertEqual(
+ "Source package differences between 'Derilucid' and "
+ "parent series",
+ view.label)
+
+ def test_label_multiple_parents(self):
+ # If the series has multiple parents, the view label mentions
+ # the generic term 'parent series'.
+ derived_series, parent_series = self._createChildAndParents()
+
+ view = create_initialized_view(
+ derived_series, '+localpackagediffs')
+
+ self.assertEqual(
+ "Source package differences between 'Derilucid' and "
+ "parent series",
+ view.label)
+
def test_batch_includes_needing_attention_only(self):
# The differences attribute includes differences needing
# attention only.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
current_difference = self.factory.makeDistroSeriesDifference(
derived_series=derived_series)
self.factory.makeDistroSeriesDifference(
@@ -707,7 +810,7 @@
def test_batch_includes_different_versions_only(self):
# The view contains differences of type DIFFERENT_VERSIONS only.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
different_versions_diff = self.factory.makeDistroSeriesDifference(
derived_series=derived_series)
self.factory.makeDistroSeriesDifference(
@@ -722,7 +825,7 @@
def test_template_includes_help_link(self):
# The help link for popup help is included.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
set_derived_series_ui_feature_flag(self)
view = self.makeView(derived_series)
@@ -733,7 +836,7 @@
def test_diff_row_includes_last_comment_only(self):
# The most recent comment is rendered for each difference.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
difference = self.factory.makeDistroSeriesDifference(
derived_series=derived_series)
with person_logged_in(derived_series.owner):
@@ -755,7 +858,7 @@
def test_diff_row_links_to_extra_details(self):
# The source package name links to the difference details.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
difference = self.factory.makeDistroSeriesDifference(
derived_series=derived_series)
@@ -769,11 +872,49 @@
self.assertEqual(1, len(links))
self.assertEqual(difference.source_package_name.name, links[0].string)
+ def test_multiple_parents_display(self):
+ package_name = 'package-1'
+ other_parent_series = self.factory.makeDistroSeries(name='other')
+ derived_series, parent_series = self._createChildAndParents(
+ other_parent_series=other_parent_series)
+ versions = {
+ 'base': u'1.0',
+ 'derived': u'1.0derived1',
+ 'parent': u'1.0-1',
+ }
+
+ self.factory.makeDistroSeriesDifference(
+ versions=versions,
+ parent_series=other_parent_series,
+ source_package_name_str=package_name,
+ derived_series=derived_series)
+ self.factory.makeDistroSeriesDifference(
+ versions=versions,
+ parent_series=parent_series,
+ source_package_name_str=package_name,
+ derived_series=derived_series)
+ set_derived_series_ui_feature_flag(self)
+ view = create_initialized_view(
+ derived_series, '+localpackagediffs')
+ multiple_parents_matches = soupmatchers.HTMLContains(
+ soupmatchers.Tag(
+ "Parent table header", 'th',
+ text=re.compile("\s*Parent\s")),
+ soupmatchers.Tag(
+ "Parent version table header", 'th',
+ text=re.compile("\s*Parent version\s*")),
+ soupmatchers.Tag(
+ "Parent name", 'a',
+ attrs={'class': 'parent-name'},
+ text=re.compile("\s*Other\s*")),
+ )
+ self.assertThat(view.render(), multiple_parents_matches)
+
def test_diff_row_shows_version_attached(self):
# The +localpackagediffs page shows the version attached to the
# DSD and not the last published version (bug=745776).
package_name = 'package-1'
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
versions = {
'base': u'1.0',
'derived': u'1.0derived1',
@@ -817,7 +958,7 @@
# The +localpackagediffs page shows only the version (no link)
# if we fail to fetch the published version.
package_name = 'package-1'
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
versions = {
'base': u'1.0',
'derived': u'1.0derived1',
@@ -965,7 +1106,7 @@
# A single web request may need to schedule large numbers of
# package upgrades. It must do so without issuing large numbers
# of database queries.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
# Take a baseline measure of queries.
self.makePackageUpgrade(derived_series=derived_series)
flush_database_caches()
@@ -981,11 +1122,12 @@
self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
-class TestDistroSeriesLocalDifferencesFunctional(TestCaseWithFactory):
+class TestDistroSeriesLocalDifferencesFunctional(DistroSeriesDifferenceMixin,
+ TestCaseWithFactory):
layer = LaunchpadFunctionalLayer
- def _create_child_and_parent(self):
+ def _createChildAndParent(self):
parent_series = self.factory.makeDistroSeries(name='lucid')
derived_series = self.factory.makeDistroSeries(name='derilucid')
self.factory.makeDistroSeriesParent(
@@ -993,8 +1135,10 @@
return (derived_series, parent_series)
def test_higher_radio_mentions_parent(self):
+ # The user is shown an option to display only the blacklisted
+ # package with a higer version than in the parent.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
source_package_name_str="my-src-package")
@@ -1011,6 +1155,25 @@
)
self.assertThat(view.render(), radio_option_matches)
+ def test_higher_radio_mentions_parents(self):
+ set_derived_series_ui_feature_flag(self)
+ derived_series, parent_series = self._createChildAndParents()
+ self.factory.makeDistroSeriesDifference(
+ derived_series=derived_series,
+ source_package_name_str="my-src-package")
+ view = create_initialized_view(
+ derived_series,
+ '+localpackagediffs')
+
+ radio_title = \
+ " Blacklisted packages with a higher version than in parent"
+ radio_option_matches = soupmatchers.HTMLContains(
+ soupmatchers.Tag(
+ "radio displays parent's name", 'label',
+ text=radio_title),
+ )
+ self.assertThat(view.render(), radio_option_matches)
+
def _set_source_selection(self, series):
# Set up source package format selection so that copying will
# work with the default dsc_format used in
@@ -1021,7 +1184,7 @@
def test_batch_filtered(self):
# The name_filter parameter allows filtering of packages by name.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
diff1 = self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
source_package_name_str="my-src-package")
@@ -1045,7 +1208,7 @@
def test_batch_non_blacklisted(self):
# The default filter is all non blacklisted differences.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
diff1 = self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
source_package_name_str="my-src-package")
@@ -1073,7 +1236,7 @@
# field.package_type parameter allows to list only
# blacklisted differences.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
blacklisted_diff = self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
status=DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT)
@@ -1095,7 +1258,7 @@
# field.package_type parameter allows to list only
# blacklisted differences with a child's version higher than parent's.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
blacklisted_diff_higher = self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
status=DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT,
@@ -1123,7 +1286,7 @@
# Test that we can search for differences that we marked
# resolved.
set_derived_series_ui_feature_flag(self)
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
self.factory.makeDistroSeriesDifference(
derived_series=derived_series,
@@ -1156,14 +1319,14 @@
self.factory.makeDistroSeriesParent(
derived_series=derived_series, parent_series=parent_series)
self._set_source_selection(derived_series)
- self.factory.makeDistroSeriesDifference(
+ diff = self.factory.makeDistroSeriesDifference(
source_package_name_str=src_name,
derived_series=derived_series, versions=versions,
difference_type=difference_type)
sourcepackagename = self.factory.getOrMakeSourcePackageName(
src_name)
set_derived_series_ui_feature_flag(self)
- return derived_series, parent_series, sourcepackagename
+ return derived_series, parent_series, sourcepackagename, str(diff.id)
def test_canPerformSync_anon(self):
# Anonymous users cannot sync packages.
@@ -1246,11 +1409,13 @@
def test_sync_error_invalid_selection(self):
# An error is raised when an invalid difference is selected.
- derived_series = self._setUpDSD('my-src-name')[0]
+ derived_series, unused, unused2, diff_id = self._setUpDSD(
+ 'my-src-name')
person = self._setUpPersonWithPerm(derived_series)
+ another_id = str(int(diff_id) + 1)
set_derived_series_sync_feature_flag(self)
view = self._syncAndGetView(
- derived_series, person, ['some-other-name'])
+ derived_series, person, [another_id])
self.assertEqual(2, len(view.errors))
self.assertEqual(
@@ -1261,11 +1426,12 @@
def test_sync_error_no_perm_dest_archive(self):
# A user without upload rights on the destination archive cannot
# sync packages.
- derived_series = self._setUpDSD('my-src-name')[0]
+ derived_series, unused, unused2, diff_id = self._setUpDSD(
+ 'my-src-name')
person = self._setUpPersonWithPerm(derived_series)
set_derived_series_sync_feature_flag(self)
view = self._syncAndGetView(
- derived_series, person, ['my-src-name'])
+ derived_series, person, [diff_id])
self.assertEqual(1, len(view.errors))
self.assertTrue(
@@ -1283,27 +1449,27 @@
def test_sync_success_perm_component(self):
# A user with upload rights on the destination component
# can sync packages.
- derived_series, parent_series, sourcepackagename = self._setUpDSD(
+ derived_series, parent_series, sp_name, diff_id = self._setUpDSD(
'my-src-name')
person, _ = self.makePersonWithComponentPermission(
derived_series.main_archive,
derived_series.getSourcePackage(
- sourcepackagename).latest_published_component)
+ sp_name).latest_published_component)
view = self._syncAndGetView(
- derived_series, person, ['my-src-name'])
+ derived_series, person, [diff_id])
self.assertEqual(0, len(view.errors))
def test_sync_error_no_perm_component(self):
# A user without upload rights on the destination component
# will get an error when he syncs packages to this component.
- derived_series, parent_series, sourcepackagename = self._setUpDSD(
+ derived_series, parent_series, unused, diff_id = self._setUpDSD(
'my-src-name')
person, another_component = self.makePersonWithComponentPermission(
derived_series.main_archive)
set_derived_series_sync_feature_flag(self)
view = self._syncAndGetView(
- derived_series, person, ['my-src-name'])
+ derived_series, person, [diff_id])
self.assertEqual(1, len(view.errors))
self.assertTrue(
@@ -1343,13 +1509,13 @@
'derived': '1.0derived1',
'parent': '1.0-1',
}
- derived_series, parent_series, sourcepackagename = self._setUpDSD(
+ derived_series, parent_series, sp_name, diff_id = self._setUpDSD(
'my-src-name', versions=versions)
# Setup a user with upload rights.
person = self.factory.makePerson()
removeSecurityProxy(derived_series.main_archive).newPackageUploader(
- person, sourcepackagename)
+ person, sp_name)
# The inital state is that 1.0-1 is not in the derived series.
pubs = derived_series.main_archive.getPublishedSources(
@@ -1360,7 +1526,7 @@
# Now, sync the source from the parent using the form.
set_derived_series_sync_feature_flag(self)
view = self._syncAndGetView(
- derived_series, person, ['my-src-name'])
+ derived_series, person, [diff_id])
# The parent's version should now be in the derived series and
# the notifications displayed:
@@ -1375,13 +1541,13 @@
'parent': '1.0-1',
}
missing = DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES
- derived_series, parent_series, sourcepackagename = self._setUpDSD(
+ derived_series, parent_series, unused, diff_id = self._setUpDSD(
'my-src-name', difference_type=missing, versions=versions)
person, another_component = self.makePersonWithComponentPermission(
derived_series.main_archive)
set_derived_series_sync_feature_flag(self)
view = self._syncAndGetView(
- derived_series, person, ['my-src-name'],
+ derived_series, person, [diff_id],
view_name='+missingpackages')
self.assertPackageCopied(
@@ -1393,7 +1559,7 @@
versions = {
'parent': '1.0-1',
}
- derived_series, parent_series, sourcepackagename = self._setUpDSD(
+ derived_series, parent_series, sp_name, diff_id = self._setUpDSD(
'my-src-name', versions=versions)
# Update destination series status to current and update
# daterelease.
@@ -1404,9 +1570,9 @@
set_derived_series_sync_feature_flag(self)
person = self.factory.makePerson()
removeSecurityProxy(derived_series.main_archive).newPackageUploader(
- person, sourcepackagename)
+ person, sp_name)
self._syncAndGetView(
- derived_series, person, ['my-src-name'])
+ derived_series, person, [diff_id])
parent_pub = parent_series.main_archive.getPublishedSources(
name='my-src-name', version=versions['parent'],
distroseries=parent_series).one()
@@ -1519,12 +1685,13 @@
'Parent packagesets')
-class DistroSerieUniquePackageDiffsTestCase(TestCaseWithFactory):
+class DistroSerieUniquePackageDiffsTestCase(DistroSeriesDifferenceMixin,
+ TestCaseWithFactory):
"""Test the distroseries +uniquepackages view."""
layer = LaunchpadZopelessLayer
- def _create_child_and_parent(self):
+ def _createChildAndParent(self):
derived_series = self.factory.makeDistroSeries(name='derilucid')
parent_series = self.factory.makeDistroSeries(name='lucid')
self.factory.makeDistroSeriesParent(
@@ -1534,7 +1701,7 @@
def test_uniquepackages_differences(self):
# The view fetches the differences with type
# UNIQUE_TO_DERIVED_SERIES.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
missing_type = DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES
# Missing blacklisted diff.
@@ -1557,7 +1724,7 @@
def test_uniquepackages_differences_empty(self):
# The view is empty if there is no differences with type
# UNIQUE_TO_DERIVED_SERIES.
- derived_series, parent_series = self._create_child_and_parent()
+ derived_series, parent_series = self._createChildAndParent()
not_missing_type = DistroSeriesDifferenceType.DIFFERENT_VERSIONS
=== modified file 'lib/lp/registry/browser/tests/test_distroseriesdifference_views.py'
--- lib/lp/registry/browser/tests/test_distroseriesdifference_views.py 2011-04-18 14:47:14 +0000
+++ lib/lp/registry/browser/tests/test_distroseriesdifference_views.py 2011-05-12 14:59:29 +0000
@@ -74,6 +74,7 @@
# Avoid circular import.
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
distro_series = distro_series_difference.derived_series
+ parent_series = distro_series_difference.parent_series
source_package_name_str = (
distro_series_difference.source_package_name.name)
stp = SoyuzTestPublisher()
@@ -90,8 +91,8 @@
# updateDistroSeriesPackageCache reconnects the db, so the
# objects need to be reloaded.
dsd_source = getUtility(IDistroSeriesDifferenceSource)
- ds_diff = dsd_source.getByDistroSeriesAndName(
- distro_series, source_package_name_str)
+ ds_diff = dsd_source.getByDistroSeriesNameAndParentSeries(
+ distro_series, source_package_name_str, parent_series)
return ds_diff
def test_binary_summaries_for_source_pub(self):
@@ -187,7 +188,8 @@
self.assertEqual('0.1-1', ds_diff.base_version)
with person_logged_in(self.factory.makePerson()):
- view = create_initialized_view(ds_diff, '+listing-distroseries-extra')
+ view = create_initialized_view(
+ ds_diff, '+listing-distroseries-extra')
soup = BeautifulSoup(view())
tags = soup.find('ul', 'package-diff-status').findAll('span')
self.assertEqual(2, len(tags))
@@ -208,7 +210,8 @@
self.assertEqual('0.30-1', ds_diff.base_version)
with person_logged_in(self.factory.makePerson()):
- view = create_initialized_view(ds_diff, '+listing-distroseries-extra')
+ view = create_initialized_view(
+ ds_diff, '+listing-distroseries-extra')
soup = BeautifulSoup(view())
tags = soup.find('ul', 'package-diff-status').findAll('span')
self.assertEqual(1, len(tags))
@@ -229,7 +232,8 @@
self.assertEqual('0.30-1', ds_diff.base_version)
with person_logged_in(self.factory.makePerson()):
- view = create_initialized_view(ds_diff, '+listing-distroseries-extra')
+ view = create_initialized_view(
+ ds_diff, '+listing-distroseries-extra')
soup = BeautifulSoup(view())
tags = soup.find('ul', 'package-diff-status').findAll('span')
self.assertEqual(1, len(tags))
=== modified file 'lib/lp/registry/browser/tests/test_distroseriesdifference_webservice.py'
--- lib/lp/registry/browser/tests/test_distroseriesdifference_webservice.py 2011-04-20 13:07:24 +0000
+++ lib/lp/registry/browser/tests/test_distroseriesdifference_webservice.py 2011-05-12 14:59:29 +0000
@@ -46,8 +46,9 @@
transaction.commit()
utility = getUtility(IDistroSeriesDifferenceSource)
- ds_diff = utility.getByDistroSeriesAndName(
- ds_diff.derived_series, ds_diff.source_package_name.name)
+ ds_diff = utility.getByDistroSeriesNameAndParentSeries(
+ ds_diff.derived_series, ds_diff.source_package_name.name,
+ ds_diff.parent_series)
self.assertEqual(
DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT,
ds_diff.status)
@@ -63,8 +64,9 @@
transaction.commit()
utility = getUtility(IDistroSeriesDifferenceSource)
- ds_diff = utility.getByDistroSeriesAndName(
- ds_diff.derived_series, ds_diff.source_package_name.name)
+ ds_diff = utility.getByDistroSeriesNameAndParentSeries(
+ ds_diff.derived_series, ds_diff.source_package_name.name,
+ ds_diff.parent_series)
self.assertEqual(
DistroSeriesDifferenceStatus.NEEDS_ATTENTION,
ds_diff.status)
@@ -106,8 +108,9 @@
# Reload and check that the package diffs are there.
utility = getUtility(IDistroSeriesDifferenceSource)
- ds_diff = utility.getByDistroSeriesAndName(
- ds_diff.derived_series, ds_diff.source_package_name.name)
+ ds_diff = utility.getByDistroSeriesNameAndParentSeries(
+ ds_diff.derived_series, ds_diff.source_package_name.name,
+ ds_diff.parent_series)
self.assertIsNot(None, ds_diff.package_diff)
self.assertIsNot(None, ds_diff.parent_package_diff)
=== modified file 'lib/lp/registry/interfaces/distroseries.py'
--- lib/lp/registry/interfaces/distroseries.py 2011-05-11 13:11:13 +0000
+++ lib/lp/registry/interfaces/distroseries.py 2011-05-12 14:59:29 +0000
@@ -173,6 +173,16 @@
"'%s': %s" % (version, error))
+class IDistroSeriesEditRestricted(Interface):
+ """IDistroSeries properties which require launchpad.Edit."""
+
+ @rename_parameters_as(dateexpected='date_targeted')
+ @export_factory_operation(
+ IMilestone, ['name', 'dateexpected', 'summary', 'code_name'])
+ def newMilestone(name, dateexpected=None, summary=None, code_name=None):
+ """Create a new milestone for this DistroSeries."""
+
+
class IDistroSeriesPublic(
ISeriesMixin, IHasAppointedDriver, IHasOwner, IBugTarget,
ISpecificationGoal, IHasMilestones, IHasOfficialBugTags,
@@ -828,6 +838,11 @@
def getDerivedSeries():
"""Get all `DistroSeries` derived from this one."""
+ @operation_returns_collection_of(Interface)
+ @export_read_operation()
+ def getParentSeries():
+ """Get all parent `DistroSeries`."""
+
@operation_parameters(
parent_series=Reference(
schema=Interface, # IDistroSeries
=== modified file 'lib/lp/registry/interfaces/distroseriesdifference.py'
--- lib/lp/registry/interfaces/distroseriesdifference.py 2011-05-06 15:15:23 +0000
+++ lib/lp/registry/interfaces/distroseriesdifference.py 2011-05-12 14:59:29 +0000
@@ -308,14 +308,20 @@
:return: A result set of `IDistroSeriesDifference`.
"""
- def getByDistroSeriesAndName(distro_series, source_package_name):
- """Returns a single difference matching the series and name.
+ def getByDistroSeriesNameAndParentSeries(distro_series,
+ source_package_name,
+ parent_series):
+ """Returns a single difference matching the series, name and parent
+ series.
:param distro_series: The derived distribution series which is to be
searched for differences.
:type distro_series: `IDistroSeries`.
:param source_package_name: The name of the package difference.
:type source_package_name: unicode.
+ :param parent_series: The parent distribution series of the package
+ difference.
+ :type distro_series: `IDistroSeries`.
"""
def getSimpleUpgrades(distro_series):
=== modified file 'lib/lp/registry/javascript/distroseriesdifferences_details.js'
--- lib/lp/registry/javascript/distroseriesdifferences_details.js 2011-04-08 15:11:19 +0000
+++ lib/lp/registry/javascript/distroseriesdifferences_details.js 2011-05-12 14:59:29 +0000
@@ -215,7 +215,9 @@
* class 'diff-extra-container' into which the results
* are inserted.
*/
- var get_extra_diff_info = function(uri, container, source_name) {
+ var get_extra_diff_info = function(uri, container, source_name,
+ parent_distro_name,
+ parent_series_name) {
var in_progress_message = Y.lp.soyuz.base.makeInProgressNode(
'Fetching difference details ...');
container.one('div.diff-extra-container').insert(
@@ -225,8 +227,11 @@
response.responseText, 'replace');
var api_uri = [
LP.cache.context.self_link,
+ '+source',
+ source_name,
'+difference',
- source_name
+ parent_distro_name,
+ parent_series_name
].join('/');
blacklist_slot = args.container.one('div.blacklist-options');
// The blacklist slot can be null if the user's not allowed
@@ -244,7 +249,8 @@
var retry_handler = function(e) {
e.preventDefault();
get_extra_diff_info(
- args.uri, args.container, args.source_name);
+ args.uri, args.container, args.source_name,
+ args.parent_distro_name, args.parent_series_name);
};
var failure_message = Y.lp.soyuz.base.makeFailureNode(
'Failed to fetch difference details.', retry_handler);
@@ -283,6 +289,10 @@
var details_row;
if (next_row == null || !next_row.hasClass('diff-extra')) {
var source_name = row.one('a.toggle-extra').get('text');
+ var rev_link = row
+ .one('a.toggle-extra').get('href').split('/').reverse();
+ var parent_series_name = rev_link[0];
+ var parent_distro_name = rev_link[1];
var nb_columns = row.all('td').size();
details_row = Y.Node.create([
'<table><tr class="diff-extra unseen ' + source_name + '">',
@@ -292,7 +302,9 @@
].join('')).one('tr');
row.insert(details_row, 'after');
var uri = toggle.get('href');
- get_extra_diff_info(uri, details_row.one('td'), source_name);
+ get_extra_diff_info(
+ uri, details_row.one('td'), source_name, parent_distro_name,
+ parent_series_name);
} else {
details_row = next_row;
}
=== modified file 'lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.html'
--- lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.html 2011-03-31 14:41:30 +0000
+++ lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.html 2011-05-12 14:59:29 +0000
@@ -38,7 +38,7 @@
<div class="diff-extra-container">
<input name="field.selected_differences" type="checkbox" />
<a class="toggle-extra"
- href="/deribuntu/deriwarty/+difference/evolution">
+ href="/deribuntu/deriwarty/+source/evolution/+difference/ubuntu/warty">
evolution</a>
<span class="package-diff-button"></span>
<dt class="package-diff-placeholder">
=== modified file 'lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js'
--- lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js 2011-04-05 12:10:01 +0000
+++ lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js 2011-05-12 14:59:29 +0000
@@ -16,7 +16,7 @@
var ArrayAssert = Y.ArrayAssert;
var suite = new Y.Test.Suite("Distroseries differences Tests");
var dsd_details = Y.lp.registry.distroseriesdifferences_details;
-var dsd_uri = '/deribuntu/deriwarty/+difference/evolution';
+var dsd_uri = '/duntu/dwarty/+source/evolution/+difference/ubuntu/warty';
var placeholder_content = Y.one('#placeholder_base').get('innerHTML');
@@ -46,7 +46,7 @@
placeholder.set('innerHTML', placeholder_content);
var msg_txt = 'Exemple text';
var msg_node = Y.Node.create(msg_txt);
- var placeholder = Y.one('#placeholder');
+ placeholder = Y.one('#placeholder');
dsd_details.add_msg_node(placeholder, msg_node);
Assert.areEqual(
placeholder.one('.package-diff-placeholder').get('innerHTML'),
=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py 2011-05-11 05:39:36 +0000
+++ lib/lp/registry/model/distroseries.py 2011-05-12 14:59:29 +0000
@@ -754,7 +754,6 @@
clauseTables=['SourcePackageRelease',
'SourcePackagePublishingHistory']).count()
-
# next update the binary count
clauseTables = ['DistroArchSeries', 'BinaryPackagePublishingHistory',
'BinaryPackageRelease']
@@ -791,12 +790,7 @@
@property
def is_derived_series(self):
"""See `IDistroSeries`."""
- # Circular imports.
- from lp.registry.interfaces.distroseriesparent import (
- IDistroSeriesParentSet,
- )
- dsps = getUtility(IDistroSeriesParentSet).getByDerivedSeries(self)
- return not dsps.is_empty()
+ return not self.getParentSeries() == []
@property
def is_initialising(self):
@@ -2001,6 +1995,15 @@
getUtility(IInitialiseDistroSeriesJobSource).create(
self, child, architectures, packagesets, rebuild)
+ def getParentSeries(self):
+ """See `IDistroSeriesPublic`."""
+ # Circular imports.
+ from lp.registry.interfaces.distroseriesparent import (
+ IDistroSeriesParentSet,
+ )
+ dsps = getUtility(IDistroSeriesParentSet).getByDerivedSeries(self)
+ return [dsp.parent_series for dsp in dsps]
+
def getDerivedSeries(self):
"""See `IDistroSeriesPublic`."""
# Circular imports.
=== modified file 'lib/lp/registry/model/distroseriesdifference.py'
--- lib/lp/registry/model/distroseriesdifference.py 2011-05-06 18:10:36 +0000
+++ lib/lp/registry/model/distroseriesdifference.py 2011-05-12 14:59:29 +0000
@@ -385,11 +385,15 @@
differences, pre_iter_hook=eager_load)
@staticmethod
- def getByDistroSeriesAndName(distro_series, source_package_name):
+ def getByDistroSeriesNameAndParentSeries(distro_series,
+ source_package_name,
+ parent_series):
"""See `IDistroSeriesDifferenceSource`."""
+
return IStore(DistroSeriesDifference).find(
DistroSeriesDifference,
DistroSeriesDifference.derived_series == distro_series,
+ DistroSeriesDifference.parent_series == parent_series,
DistroSeriesDifference.source_package_name == (
SourcePackageName.id),
SourcePackageName.name == source_package_name).one()
=== modified file 'lib/lp/registry/templates/distroseries-index.pt'
--- lib/lp/registry/templates/distroseries-index.pt 2011-04-15 15:08:20 +0000
+++ lib/lp/registry/templates/distroseries-index.pt 2011-05-12 14:59:29 +0000
@@ -65,10 +65,13 @@
<div
tal:replace="structure context/@@+portlet-details"/>
</div>
- <div class="yui-u"
- tal:condition="request/features/soyuz.derived-series-ui.enabled">
- <div tal:replace="structure context/@@+portlet-derivation" />
- </div>
+ <tal:derivation
+ tal:condition="request/features/soyuz.derived-series-ui.enabled">
+ <div class="yui-u"
+ tal:condition="python:context.is_derived_series or context.is_initialising">
+ <div tal:replace="structure context/@@+portlet-derivation" />
+ </div>
+ </tal:derivation>
<div class="yui-u">
<div tal:replace="structure context/@@+portlet-package-summary" />
=== modified file 'lib/lp/registry/templates/distroseries-localdifferences.pt'
--- lib/lp/registry/templates/distroseries-localdifferences.pt 2011-05-06 10:45:50 +0000
+++ lib/lp/registry/templates/distroseries-localdifferences.pt 2011-05-12 14:59:29 +0000
@@ -23,7 +23,6 @@
<div class="top-portlet" metal:fill-slot="main"
tal:define="differences view/cached_differences;
series_name context/displayname;
- parent_name view/parent_series/displayname;
can_perform_sync view/canPerformSync;">
<p><tal:replace replace="structure view/explanation/escapedtext" /></p>
@@ -43,8 +42,17 @@
<thead>
<tr>
<th>Source</th>
+ <th tal:condition="python: not(view.has_unique_parent) and view.show_parent_version">
+ Parent
+ </th>
<th tal:condition="view/show_parent_version">
- <tal:replace replace="parent_name" /> version</th>
+ <tal:one_parent condition="view/has_unique_parent">
+ <tal:replace replace="view/unique_parent/displayname" /> version
+ </tal:one_parent>
+ <tal:multiple_parents condition="not: view/has_unique_parent">
+ Parent version
+ </tal:multiple_parents>
+ </th>
<th tal:condition="view/show_derived_version">
<tal:replace replace="series_name" /> version</th>
<th tal:condition="view/show_parent_packagesets">
@@ -61,6 +69,7 @@
<tal:difference repeat="difference differences/batch">
<tr tal:define="parent_source_pub difference/parent_source_pub;
source_pub difference/source_pub;
+ diff_id difference/id;
src_name difference/source_package_name/name;"
tal:attributes="class src_name">
@@ -68,13 +77,17 @@
<input tal:condition="can_perform_sync"
name="field.selected_differences" type="checkbox"
tal:attributes="
- value src_name;
- id string:field.selected_differences.${src_name}"/>
+ value diff_id;
+ id string:field.selected_differences.${diff_id}"/>
<a tal:attributes="href difference/fmt:url" class="toggle-extra"
tal:content="src_name">Foo</a>
</td>
-
+ <td tal:condition="python: not(view.has_unique_parent) and view.show_parent_version">
+ <a tal:attributes="href difference/parent_series/fmt:url"
+ tal:content="difference/parent_series/displayname"
+ class="parent-name">Warty</a>
+ </td>
<td tal:condition="view/show_parent_version">
<a tal:condition="difference/parent_source_package_release"
tal:attributes="href difference/parent_source_package_release/fmt:url"
=== modified file 'lib/lp/registry/templates/distroseries-portlet-derivation.pt'
--- lib/lp/registry/templates/distroseries-portlet-derivation.pt 2011-05-05 04:52:36 +0000
+++ lib/lp/registry/templates/distroseries-portlet-derivation.pt 2011-05-12 14:59:29 +0000
@@ -6,7 +6,12 @@
tal:define="overview_menu context/menu:overview">
<tal:is_derived condition="context/is_derived_series">
<tal:is_initialised condition="not: context/is_initialising">
- <h2>Derived from <tal:name replace="view/parent_series/displayname"/></h2>
+ <tal:one_parent condition="view/has_unique_parent">
+ <h2>Derived from <tal:name replace="view/unique_parent/displayname"/></h2>
+ </tal:one_parent>
+ <tal:multiple_parents condition="not: view/has_unique_parent">
+ <h2>Derived from <tal:name replace="view/number_of_parents"/> parents</h2>
+ </tal:multiple_parents>
<tal:diffs define="nb_diffs view/num_differences;
nb_diffs_in_parent view/num_differences_in_parent;
@@ -15,7 +20,7 @@
<li tal:condition="nb_diffs">
<a tal:attributes="href string:${context/fmt:url}/+localpackagediffs"
class="sprite info"
- title="Source package differences between this series and his parent">
+ title="Source package differences between this series and his parent(s)">
<tal:nb_diffs replace="nb_diffs"/> package<tal:plural
content="string:s"
condition="python:nb_diffs!=1"/> with differences
@@ -25,10 +30,17 @@
<a tal:attributes="href string:${context/fmt:url}/+missingpackages"
class="sprite info"
title="Source packages only in parent series">
- <tal:nb_diffs replace="nb_diffs_in_parent"/> package<tal:plural
- content="string:s"
- condition="python:nb_diffs_in_parent!=1"/> only in <tal:replace
- replace="view/parent_series/displayname">Sid</tal:replace>
+ <tal:one_parent condition="view/has_unique_parent">
+ <tal:nb_diffs replace="nb_diffs_in_parent"/> package<tal:plural
+ content="string:s"
+ condition="python:nb_diffs_in_parent!=1"/> only in <tal:replace
+ replace="view/unique_parent/displayname">Sid</tal:replace>
+ </tal:one_parent>
+ <tal:multiple_parents condition="not: view/has_unique_parent">
+ <tal:nb_diffs replace="nb_diffs_in_parent"/> package<tal:plural
+ content="string:s"
+ condition="python:nb_diffs_in_parent!=1"/> only in a parent series
+ </tal:multiple_parents>
</a>
</li>
<li tal:condition="nb_diffs_in_child">
=== modified file 'lib/lp/registry/tests/test_distroseriesdifference.py'
--- lib/lp/registry/tests/test_distroseriesdifference.py 2011-05-11 16:15:35 +0000
+++ lib/lp/registry/tests/test_distroseriesdifference.py 2011-05-12 14:59:29 +0000
@@ -1027,14 +1027,14 @@
self.assertContentEqual(diffs['normal'], results)
self.assertContentEqual(diffs2['normal'], results2)
- def test_getByDistroSeriesAndName(self):
+ def test_getByDistroSeriesNameAndParentSeries(self):
# An individual difference is obtained using the name.
ds_diff = self.factory.makeDistroSeriesDifference(
source_package_name_str='fooname')
dsd_source = getUtility(IDistroSeriesDifferenceSource)
- result = dsd_source.getByDistroSeriesAndName(
- ds_diff.derived_series, 'fooname')
+ result = dsd_source.getByDistroSeriesNameAndParentSeries(
+ ds_diff.derived_series, 'fooname', ds_diff.parent_series)
self.assertEqual(ds_diff, result)
=== modified file 'lib/lp/soyuz/browser/configure.zcml'
--- lib/lp/soyuz/browser/configure.zcml 2011-01-28 04:08:32 +0000
+++ lib/lp/soyuz/browser/configure.zcml 2011-05-12 14:59:29 +0000
@@ -723,6 +723,12 @@
<browser:page
for="lp.registry.interfaces.sourcepackage.ISourcePackage"
class=
+ "lp.soyuz.browser.sourcepackage.SourcePackageDifferenceView"
+ permission="zope.Public"
+ name="+difference"/>
+ <browser:page
+ for="lp.registry.interfaces.sourcepackage.ISourcePackage"
+ class=
"lp.soyuz.browser.sourcepackage.SourcePackageChangelogView"
permission="zope.Public"
name="+changelog"
=== modified file 'lib/lp/soyuz/browser/sourcepackage.py'
--- lib/lp/soyuz/browser/sourcepackage.py 2010-07-02 20:32:58 +0000
+++ lib/lp/soyuz/browser/sourcepackage.py 2011-05-12 14:59:29 +0000
@@ -10,7 +10,15 @@
'SourcePackageCopyrightView',
]
+from zope.component import getUtility
+
+from canonical.launchpad.webapp import Navigation
from canonical.lazr.utils import smartquote
+from lp.registry.interfaces.distribution import IDistributionSet
+from lp.registry.interfaces.distroseries import IDistroSeriesSet
+from lp.registry.interfaces.distroseriesdifference import (
+ IDistroSeriesDifferenceSource,
+ )
class SourcePackageChangelogView:
@@ -33,3 +41,18 @@
def label(self):
"""Page heading."""
return smartquote("Copyright for " + self.context.title)
+
+
+class SourcePackageDifferenceView(Navigation):
+ """A view to traverse to a DistroSeriesDifference.
+ """
+
+ def traverse(self, parent_distro_name):
+ parent_distro = getUtility(
+ IDistributionSet).getByName(parent_distro_name)
+ parent_series = getUtility(
+ IDistroSeriesSet).queryByName(
+ parent_distro, self.request.stepstogo.consume())
+ dsd_source = getUtility(IDistroSeriesDifferenceSource)
+ return dsd_source.getByDistroSeriesNameAndParentSeries(
+ self.context.distroseries, self.context.name, parent_series)