Merge lp:~cjwatson/launchpad/sprd-utilities into lp:launchpad
- sprd-utilities
- Merge into devel
Proposed by
Colin Watson
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 17887 | ||||
Proposed branch: | lp:~cjwatson/launchpad/sprd-utilities | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
302 lines (+78/-32) 6 files modified
lib/lp/code/browser/sourcepackagerecipe.py (+15/-14) lib/lp/code/configure.zcml (+10/-1) lib/lp/code/interfaces/sourcepackagerecipe.py (+25/-1) lib/lp/code/model/sourcepackagerecipe.py (+5/-3) lib/lp/code/model/sourcepackagerecipebuild.py (+9/-5) lib/lp/code/model/sourcepackagerecipedata.py (+14/-8) |
||||
To merge this branch: | bzr merge lp:~cjwatson/launchpad/sprd-utilities | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+282218@code.launchpad.net |
Commit message
Access recipe parsing via interfaces.
Description of the change
Access recipe parsing via interfaces.
This is a bit of refactoring before starting on Git recipe support; for that, we're going to want to push recipe text through a small amount of munging before passing it to RecipeParser, so it makes sense for it all to go through common code, and that ought to use an interface so that it can be used correctly from browser code.
To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote : | # |
Mainly because the method that returns a RecipeBranch can't reasonably be a securedutility (there's no Zope interface declared for that, so returning proxied objects is unhelpful), while the method that returns a SourcePackageRe
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/browser/sourcepackagerecipe.py' | |||
2 | --- lib/lp/code/browser/sourcepackagerecipe.py 2015-07-08 16:05:11 +0000 | |||
3 | +++ lib/lp/code/browser/sourcepackagerecipe.py 2016-01-11 19:38:23 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # Copyright 2010-2013 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2010-2016 Canonical Ltd. This software is licensed under the |
7 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | 3 | 3 | ||
9 | 4 | """SourcePackageRecipe views.""" | 4 | """SourcePackageRecipe views.""" |
10 | @@ -20,7 +20,6 @@ | |||
11 | 20 | from bzrlib.plugins.builder.recipe import ( | 20 | from bzrlib.plugins.builder.recipe import ( |
12 | 21 | ForbiddenInstructionError, | 21 | ForbiddenInstructionError, |
13 | 22 | RecipeParseError, | 22 | RecipeParseError, |
14 | 23 | RecipeParser, | ||
15 | 24 | ) | 23 | ) |
16 | 25 | from lazr.lifecycle.event import ObjectModifiedEvent | 24 | from lazr.lifecycle.event import ObjectModifiedEvent |
17 | 26 | from lazr.lifecycle.snapshot import Snapshot | 25 | from lazr.lifecycle.snapshot import Snapshot |
18 | @@ -92,6 +91,7 @@ | |||
19 | 92 | ) | 91 | ) |
20 | 93 | from lp.code.interfaces.branchtarget import IBranchTarget | 92 | from lp.code.interfaces.branchtarget import IBranchTarget |
21 | 94 | from lp.code.interfaces.sourcepackagerecipe import ( | 93 | from lp.code.interfaces.sourcepackagerecipe import ( |
22 | 94 | IRecipeBranchSource, | ||
23 | 95 | ISourcePackageRecipe, | 95 | ISourcePackageRecipe, |
24 | 96 | ISourcePackageRecipeSource, | 96 | ISourcePackageRecipeSource, |
25 | 97 | MINIMAL_RECIPE_TEXT, | 97 | MINIMAL_RECIPE_TEXT, |
26 | @@ -611,10 +611,11 @@ | |||
27 | 611 | 'distroseries', | 611 | 'distroseries', |
28 | 612 | 'You must specify at least one series for daily builds.') | 612 | 'You must specify at least one series for daily builds.') |
29 | 613 | try: | 613 | try: |
34 | 614 | parser = RecipeParser(data['recipe_text']) | 614 | self.error_handler( |
35 | 615 | parser.parse() | 615 | getUtility(IRecipeBranchSource).getParsedRecipe, |
36 | 616 | except RecipeParseError as error: | 616 | data['recipe_text']) |
37 | 617 | self.setFieldError('recipe_text', str(error)) | 617 | except ErrorHandled: |
38 | 618 | pass | ||
39 | 618 | 619 | ||
40 | 619 | def error_handler(self, callable, *args, **kwargs): | 620 | def error_handler(self, callable, *args, **kwargs): |
41 | 620 | try: | 621 | try: |
42 | @@ -631,7 +632,7 @@ | |||
43 | 631 | except NoSuchBranch as e: | 632 | except NoSuchBranch as e: |
44 | 632 | self.setFieldError( | 633 | self.setFieldError( |
45 | 633 | 'recipe_text', '%s is not a branch on Launchpad.' % e.name) | 634 | 'recipe_text', '%s is not a branch on Launchpad.' % e.name) |
47 | 634 | except PrivateBranchRecipe as e: | 635 | except (RecipeParseError, PrivateBranchRecipe) as e: |
48 | 635 | self.setFieldError('recipe_text', str(e)) | 636 | self.setFieldError('recipe_text', str(e)) |
49 | 636 | raise ErrorHandled() | 637 | raise ErrorHandled() |
50 | 637 | 638 | ||
51 | @@ -872,14 +873,14 @@ | |||
52 | 872 | self.context, providing=providedBy(self.context)) | 873 | self.context, providing=providedBy(self.context)) |
53 | 873 | 874 | ||
54 | 874 | recipe_text = data.pop('recipe_text') | 875 | recipe_text = data.pop('recipe_text') |
59 | 875 | parser = RecipeParser(recipe_text) | 876 | try: |
60 | 876 | recipe = parser.parse() | 877 | recipe = self.error_handler( |
61 | 877 | if self.context.builder_recipe != recipe: | 878 | getUtility(IRecipeBranchSource).getParsedRecipe, recipe_text) |
62 | 878 | try: | 879 | if self.context.builder_recipe != recipe: |
63 | 879 | self.error_handler(self.context.setRecipeText, recipe_text) | 880 | self.error_handler(self.context.setRecipeText, recipe_text) |
64 | 880 | changed = True | 881 | changed = True |
67 | 881 | except ErrorHandled: | 882 | except ErrorHandled: |
68 | 882 | return | 883 | return |
69 | 883 | 884 | ||
70 | 884 | distros = data.pop('distroseries') | 885 | distros = data.pop('distroseries') |
71 | 885 | if distros != self.context.distroseries: | 886 | if distros != self.context.distroseries: |
72 | @@ -927,7 +928,7 @@ | |||
73 | 927 | label = title | 928 | label = title |
74 | 928 | 929 | ||
75 | 929 | class schema(Interface): | 930 | class schema(Interface): |
77 | 930 | """Schema for deleting a branch.""" | 931 | """Schema for deleting a recipe.""" |
78 | 931 | 932 | ||
79 | 932 | @property | 933 | @property |
80 | 933 | def cancel_url(self): | 934 | def cancel_url(self): |
81 | 934 | 935 | ||
82 | === modified file 'lib/lp/code/configure.zcml' | |||
83 | --- lib/lp/code/configure.zcml 2015-10-09 16:56:45 +0000 | |||
84 | +++ lib/lp/code/configure.zcml 2016-01-11 19:38:23 +0000 | |||
85 | @@ -1,4 +1,4 @@ | |||
87 | 1 | <!-- Copyright 2009-2015 Canonical Ltd. This software is licensed under the | 1 | <!-- Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
88 | 2 | GNU Affero General Public License version 3 (see the file LICENSE). | 2 | GNU Affero General Public License version 3 (see the file LICENSE). |
89 | 3 | --> | 3 | --> |
90 | 4 | 4 | ||
91 | @@ -1053,6 +1053,15 @@ | |||
92 | 1053 | <require permission="launchpad.View" | 1053 | <require permission="launchpad.View" |
93 | 1054 | interface="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipeData"/> | 1054 | interface="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipeData"/> |
94 | 1055 | </class> | 1055 | </class> |
95 | 1056 | <utility | ||
96 | 1057 | component="lp.code.model.sourcepackagerecipedata.SourcePackageRecipeData" | ||
97 | 1058 | provides="lp.code.interfaces.sourcepackagerecipe.IRecipeBranchSource"> | ||
98 | 1059 | </utility> | ||
99 | 1060 | <securedutility | ||
100 | 1061 | component="lp.code.model.sourcepackagerecipedata.SourcePackageRecipeData" | ||
101 | 1062 | provides="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipeDataSource"> | ||
102 | 1063 | <allow interface="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipeDataSource"/> | ||
103 | 1064 | </securedutility> | ||
104 | 1056 | <!-- SourcePackageRecipe --> | 1065 | <!-- SourcePackageRecipe --> |
105 | 1057 | <class | 1066 | <class |
106 | 1058 | class="lp.code.model.sourcepackagerecipe.SourcePackageRecipe"> | 1067 | class="lp.code.model.sourcepackagerecipe.SourcePackageRecipe"> |
107 | 1059 | 1068 | ||
108 | === modified file 'lib/lp/code/interfaces/sourcepackagerecipe.py' | |||
109 | --- lib/lp/code/interfaces/sourcepackagerecipe.py 2015-04-30 01:45:30 +0000 | |||
110 | +++ lib/lp/code/interfaces/sourcepackagerecipe.py 2016-01-11 19:38:23 +0000 | |||
111 | @@ -1,4 +1,4 @@ | |||
113 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
114 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
115 | 3 | 3 | ||
116 | 4 | """Interface of the `SourcePackageRecipe` content type.""" | 4 | """Interface of the `SourcePackageRecipe` content type.""" |
117 | @@ -8,8 +8,10 @@ | |||
118 | 8 | 8 | ||
119 | 9 | 9 | ||
120 | 10 | __all__ = [ | 10 | __all__ = [ |
121 | 11 | 'IRecipeBranchSource', | ||
122 | 11 | 'ISourcePackageRecipe', | 12 | 'ISourcePackageRecipe', |
123 | 12 | 'ISourcePackageRecipeData', | 13 | 'ISourcePackageRecipeData', |
124 | 14 | 'ISourcePackageRecipeDataSource', | ||
125 | 13 | 'ISourcePackageRecipeSource', | 15 | 'ISourcePackageRecipeSource', |
126 | 14 | 'MINIMAL_RECIPE_TEXT', | 16 | 'MINIMAL_RECIPE_TEXT', |
127 | 15 | ] | 17 | ] |
128 | @@ -88,6 +90,28 @@ | |||
129 | 88 | """An iterator of the branches referenced by this recipe.""" | 90 | """An iterator of the branches referenced by this recipe.""" |
130 | 89 | 91 | ||
131 | 90 | 92 | ||
132 | 93 | class IRecipeBranchSource(Interface): | ||
133 | 94 | |||
134 | 95 | def getParsedRecipe(recipe_text): | ||
135 | 96 | """Parse recipe text into recipe data. | ||
136 | 97 | |||
137 | 98 | :param recipe_text: Recipe text as a string. | ||
138 | 99 | :return: a `RecipeBranch` representing the recipe. | ||
139 | 100 | """ | ||
140 | 101 | |||
141 | 102 | |||
142 | 103 | class ISourcePackageRecipeDataSource(Interface): | ||
143 | 104 | |||
144 | 105 | def createManifestFromText(text, sourcepackage_recipe_build): | ||
145 | 106 | """Create a manifest for the specified build. | ||
146 | 107 | |||
147 | 108 | :param text: The text of the recipe to create a manifest for. | ||
148 | 109 | :param sourcepackage_recipe_build: The build to associate the manifest | ||
149 | 110 | with. | ||
150 | 111 | :return: an instance of `SourcePackageRecipeData`. | ||
151 | 112 | """ | ||
152 | 113 | |||
153 | 114 | |||
154 | 91 | class ISourcePackageRecipeView(Interface): | 115 | class ISourcePackageRecipeView(Interface): |
155 | 92 | """IBranch attributes that require launchpad.View permission.""" | 116 | """IBranch attributes that require launchpad.View permission.""" |
156 | 93 | 117 | ||
157 | 94 | 118 | ||
158 | === modified file 'lib/lp/code/model/sourcepackagerecipe.py' | |||
159 | --- lib/lp/code/model/sourcepackagerecipe.py 2015-09-28 17:38:45 +0000 | |||
160 | +++ lib/lp/code/model/sourcepackagerecipe.py 2016-01-11 19:38:23 +0000 | |||
161 | @@ -1,4 +1,4 @@ | |||
163 | 1 | # Copyright 2009-2015 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
164 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
165 | 3 | 3 | ||
166 | 4 | """Implementation of the `SourcePackageRecipe` content type.""" | 4 | """Implementation of the `SourcePackageRecipe` content type.""" |
167 | @@ -42,6 +42,7 @@ | |||
168 | 42 | BuildNotAllowedForDistro, | 42 | BuildNotAllowedForDistro, |
169 | 43 | ) | 43 | ) |
170 | 44 | from lp.code.interfaces.sourcepackagerecipe import ( | 44 | from lp.code.interfaces.sourcepackagerecipe import ( |
171 | 45 | IRecipeBranchSource, | ||
172 | 45 | ISourcePackageRecipe, | 46 | ISourcePackageRecipe, |
173 | 46 | ISourcePackageRecipeData, | 47 | ISourcePackageRecipeData, |
174 | 47 | ISourcePackageRecipeSource, | 48 | ISourcePackageRecipeSource, |
175 | @@ -167,7 +168,7 @@ | |||
176 | 167 | owner_ids, need_validity=True)) | 168 | owner_ids, need_validity=True)) |
177 | 168 | 169 | ||
178 | 169 | def setRecipeText(self, recipe_text): | 170 | def setRecipeText(self, recipe_text): |
180 | 170 | parsed = SourcePackageRecipeData.getParsedRecipe(recipe_text) | 171 | parsed = getUtility(IRecipeBranchSource).getParsedRecipe(recipe_text) |
181 | 171 | self._recipe_data.setRecipe(parsed) | 172 | self._recipe_data.setRecipe(parsed) |
182 | 172 | 173 | ||
183 | 173 | @property | 174 | @property |
184 | @@ -187,7 +188,8 @@ | |||
185 | 187 | """See `ISourcePackageRecipeSource.new`.""" | 188 | """See `ISourcePackageRecipeSource.new`.""" |
186 | 188 | store = IMasterStore(SourcePackageRecipe) | 189 | store = IMasterStore(SourcePackageRecipe) |
187 | 189 | sprecipe = SourcePackageRecipe() | 190 | sprecipe = SourcePackageRecipe() |
189 | 190 | builder_recipe = SourcePackageRecipeData.getParsedRecipe(recipe) | 191 | builder_recipe = getUtility(IRecipeBranchSource).getParsedRecipe( |
190 | 192 | recipe) | ||
191 | 191 | SourcePackageRecipeData(builder_recipe, sprecipe) | 193 | SourcePackageRecipeData(builder_recipe, sprecipe) |
192 | 192 | sprecipe.registrant = registrant | 194 | sprecipe.registrant = registrant |
193 | 193 | sprecipe.owner = owner | 195 | sprecipe.owner = owner |
194 | 194 | 196 | ||
195 | === modified file 'lib/lp/code/model/sourcepackagerecipebuild.py' | |||
196 | --- lib/lp/code/model/sourcepackagerecipebuild.py 2015-09-11 15:11:34 +0000 | |||
197 | +++ lib/lp/code/model/sourcepackagerecipebuild.py 2016-01-11 19:38:23 +0000 | |||
198 | @@ -1,4 +1,4 @@ | |||
200 | 1 | # Copyright 2010-2013 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2010-2016 Canonical Ltd. This software is licensed under the |
201 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
202 | 3 | 3 | ||
203 | 4 | """Implementation code for source package builds.""" | 4 | """Implementation code for source package builds.""" |
204 | @@ -46,6 +46,10 @@ | |||
205 | 46 | BuildAlreadyPending, | 46 | BuildAlreadyPending, |
206 | 47 | BuildNotAllowedForDistro, | 47 | BuildNotAllowedForDistro, |
207 | 48 | ) | 48 | ) |
208 | 49 | from lp.code.interfaces.sourcepackagerecipe import ( | ||
209 | 50 | IRecipeBranchSource, | ||
210 | 51 | ISourcePackageRecipeDataSource, | ||
211 | 52 | ) | ||
212 | 49 | from lp.code.interfaces.sourcepackagerecipebuild import ( | 53 | from lp.code.interfaces.sourcepackagerecipebuild import ( |
213 | 50 | ISourcePackageRecipeBuild, | 54 | ISourcePackageRecipeBuild, |
214 | 51 | ISourcePackageRecipeBuildSource, | 55 | ISourcePackageRecipeBuildSource, |
215 | @@ -53,7 +57,6 @@ | |||
216 | 53 | from lp.code.mail.sourcepackagerecipebuild import ( | 57 | from lp.code.mail.sourcepackagerecipebuild import ( |
217 | 54 | SourcePackageRecipeBuildMailer, | 58 | SourcePackageRecipeBuildMailer, |
218 | 55 | ) | 59 | ) |
219 | 56 | from lp.code.model.sourcepackagerecipedata import SourcePackageRecipeData | ||
220 | 57 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 60 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
221 | 58 | from lp.registry.model.person import Person | 61 | from lp.registry.model.person import Person |
222 | 59 | from lp.services.database.bulk import load_related | 62 | from lp.services.database.bulk import load_related |
223 | @@ -158,10 +161,11 @@ | |||
224 | 158 | if self.manifest is not None: | 161 | if self.manifest is not None: |
225 | 159 | IStore(self.manifest).remove(self.manifest) | 162 | IStore(self.manifest).remove(self.manifest) |
226 | 160 | elif self.manifest is None: | 163 | elif self.manifest is None: |
228 | 161 | SourcePackageRecipeData.createManifestFromText(text, self) | 164 | getUtility(ISourcePackageRecipeDataSource).createManifestFromText( |
229 | 165 | text, self) | ||
230 | 162 | else: | 166 | else: |
233 | 163 | from bzrlib.plugins.builder.recipe import RecipeParser | 167 | self.manifest.setRecipe( |
234 | 164 | self.manifest.setRecipe(RecipeParser(text).parse()) | 168 | getUtility(IRecipeBranchSource).getParsedRecipe(text)) |
235 | 165 | 169 | ||
236 | 166 | def getManifestText(self): | 170 | def getManifestText(self): |
237 | 167 | if self.manifest is None: | 171 | if self.manifest is None: |
238 | 168 | 172 | ||
239 | === modified file 'lib/lp/code/model/sourcepackagerecipedata.py' | |||
240 | --- lib/lp/code/model/sourcepackagerecipedata.py 2015-02-25 11:21:43 +0000 | |||
241 | +++ lib/lp/code/model/sourcepackagerecipedata.py 2016-01-11 19:38:23 +0000 | |||
242 | @@ -1,4 +1,4 @@ | |||
244 | 1 | # Copyright 2009-2015 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
245 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
246 | 3 | 3 | ||
247 | 4 | """Implementation of the recipe storage. | 4 | """Implementation of the recipe storage. |
248 | @@ -38,6 +38,10 @@ | |||
249 | 38 | Unicode, | 38 | Unicode, |
250 | 39 | ) | 39 | ) |
251 | 40 | from zope.component import getUtility | 40 | from zope.component import getUtility |
252 | 41 | from zope.interface import ( | ||
253 | 42 | implementer, | ||
254 | 43 | provider, | ||
255 | 44 | ) | ||
256 | 41 | 45 | ||
257 | 42 | from lp.code.errors import ( | 46 | from lp.code.errors import ( |
258 | 43 | NoSuchBranch, | 47 | NoSuchBranch, |
259 | @@ -45,6 +49,11 @@ | |||
260 | 45 | TooNewRecipeFormat, | 49 | TooNewRecipeFormat, |
261 | 46 | ) | 50 | ) |
262 | 47 | from lp.code.interfaces.branchlookup import IBranchLookup | 51 | from lp.code.interfaces.branchlookup import IBranchLookup |
263 | 52 | from lp.code.interfaces.sourcepackagerecipe import ( | ||
264 | 53 | IRecipeBranchSource, | ||
265 | 54 | ISourcePackageRecipeData, | ||
266 | 55 | ISourcePackageRecipeDataSource, | ||
267 | 56 | ) | ||
268 | 48 | from lp.code.model.branch import Branch | 57 | from lp.code.model.branch import Branch |
269 | 49 | from lp.services.database.bulk import ( | 58 | from lp.services.database.bulk import ( |
270 | 50 | load_referencing, | 59 | load_referencing, |
271 | @@ -142,6 +151,8 @@ | |||
272 | 142 | MAX_RECIPE_FORMAT = 0.4 | 151 | MAX_RECIPE_FORMAT = 0.4 |
273 | 143 | 152 | ||
274 | 144 | 153 | ||
275 | 154 | @implementer(ISourcePackageRecipeData) | ||
276 | 155 | @provider(IRecipeBranchSource, ISourcePackageRecipeDataSource) | ||
277 | 145 | class SourcePackageRecipeData(Storm): | 156 | class SourcePackageRecipeData(Storm): |
278 | 146 | """The database representation of a BaseRecipeBranch from bzr-builder. | 157 | """The database representation of a BaseRecipeBranch from bzr-builder. |
279 | 147 | 158 | ||
280 | @@ -177,6 +188,7 @@ | |||
281 | 177 | 188 | ||
282 | 178 | @staticmethod | 189 | @staticmethod |
283 | 179 | def getParsedRecipe(recipe_text): | 190 | def getParsedRecipe(recipe_text): |
284 | 191 | """See `IRecipeBranchSource`.""" | ||
285 | 180 | parser = RecipeParser(recipe_text) | 192 | parser = RecipeParser(recipe_text) |
286 | 181 | return parser.parse(permitted_instructions=SAFE_INSTRUCTIONS) | 193 | return parser.parse(permitted_instructions=SAFE_INSTRUCTIONS) |
287 | 182 | 194 | ||
288 | @@ -202,13 +214,7 @@ | |||
289 | 202 | 214 | ||
290 | 203 | @classmethod | 215 | @classmethod |
291 | 204 | def createManifestFromText(cls, text, sourcepackage_recipe_build): | 216 | def createManifestFromText(cls, text, sourcepackage_recipe_build): |
299 | 205 | """Create a manifest for the specified build. | 217 | """See `ISourcePackageRecipeDataSource`.""" |
293 | 206 | |||
294 | 207 | :param text: The text of the recipe to create a manifest for. | ||
295 | 208 | :param sourcepackage_recipe_build: The build to associate the manifest | ||
296 | 209 | with. | ||
297 | 210 | :return: an instance of SourcePackageRecipeData. | ||
298 | 211 | """ | ||
300 | 212 | parsed = cls.getParsedRecipe(text) | 218 | parsed = cls.getParsedRecipe(text) |
301 | 213 | return cls( | 219 | return cls( |
302 | 214 | parsed, sourcepackage_recipe_build=sourcepackage_recipe_build) | 220 | parsed, sourcepackage_recipe_build=sourcepackage_recipe_build) |
I don't understand why there are two interfaces and utilities, but otherwise good.