#11648 closed enhancement (fixed)
Model classes should have a resource property
| Reported by: | Ryan J Ollos | Owned by: | Ryan J Ollos |
|---|---|---|---|
| Priority: | normal | Milestone: | 1.1.3 |
| Component: | general | Version: | |
| Severity: | normal | Keywords: | model |
| Cc: | Branch: | ||
| Release Notes: | |||
| API Changes: |
Every model class has a |
||
| Internal Changes: | |||
Description (last modified by )
The Changeset, Milestone and Node classes have a resource read-only property while the Attachment, Ticket, Repository and WikiPage classes create the resource attribute in their __init__ method.
Having resource as a read-only property seems simpler since we don't have to worry about updating the resource attribute as the object changes. For example: tags/trac-1.0.1/trac/ticket/model.py@:252#L236. As a read-only property, resource will be implicitly updated as the object changes. This change prevent defects like the one we saw in #11138.
With this change and the one in #11609, if we ever find it worthwhile to create a ModelBase class it will be clear that resource and realm should be abstract properties (decorated with abc.abstractproperty). I also wanted to make this change ahead of modifying the Component and Version classes in #1233 so that the pattern to follow is clear.
Attachments (1)
Change History (20)
comment:1 by , 11 years ago
| Description: | modified (diff) |
|---|---|
| Owner: | set to |
| Status: | new → assigned |
follow-up: 14 comment:2 by , 11 years ago
| Milestone: | 1.1.2 → 1.1.3 |
|---|
follow-ups: 11 12 15 comment:3 by , 11 years ago
The WikiPage class has some unique behavior that presents a complication for these changes. When the version is not specified when creating the object (e.g. page = WikiPage(self.env, name)), page.version will contain the latest version of the page, but page.resource.version will be None.
The behavior is utilized when rendering the wiki page to determine whether a versioned page or just the standard HEAD view of the page should be rendered: trunk/trac/wiki/web_ui.py@13003:582,630#L581. For example, if there are 3 versions of WikiStart the page displayed when the URL is /wiki/WikiStart?version=3 will differ slightly from the page displayed when the URL is /wiki/WikiStart. Specifically, the following is displayed at the top of the versioned page:
| Version 3 (modified by , 5 weeks ago) (diff) |
|---|
The behavior is subtle, but could be considered rather confusing. We could preserve the existing behavior by storing the version when creating the object. Maybe there is a better way though, such as changing the behavior.
There is a relevant comment in this unit test: trunk/trac/wiki/tests/model.py@12751:88#L77.
Minor refactoring on the trunk in [13009].
follow-up: 6 comment:4 by , 11 years ago
Is there any reason to keep this statements, since conversion_href is immediately overwritten?:
trunk/trac/wiki/web_ui.py@13009:587-588#L580.
comment:5 by , 11 years ago
One additional change added this evening added to log:rjollos.git:t11648.1, raising a question about the TracFineGrainedPermissions implementation. Descriptive log message in [ca3b43b8/rjollos.git].
follow-up: 7 comment:6 by , 11 years ago
Replying to rjollos:
Is there any reason to keep this statements, since
conversion_hrefis immediately overwritten?: trunk/trac/wiki/web_ui.py@13009:587-588#L580.
I don't see a reason to keep this either. (Looks like it was first overwritten in [6055], maybe as an side-by-side example of the new Resource API?) I guess instead of removing the first assignment, it would also be possible to remove the second (now longer) assignment?
follow-up: 16 comment:7 by , 11 years ago
Replying to psuter:
I don't see a reason to keep this either. (Looks like it was first overwritten in [6055], maybe as an side-by-side example of the new Resource API?) I guess instead of removing the first assignment, it would also be possible to remove the second (now longer) assignment?
I'm glad you mentioned. The second assignment looks like the right one to remove since the changes suggested in this ticket so far could result in page.resource.version no longer being None when version parsed from the URL is None. However, the conversion_href should only contain the version when version is contained in the page URL.
So the following change is proposed on 1.0-stable:
-
trac/wiki/web_ui.py
diff --git a/trac/wiki/web_ui.py b/trac/wiki/web_ui.py index 48fc618..94e8bfc 100644
a b class WikiModule(Component): 608 608 .get_supported_conversions('text/x-trac-wiki'): 609 609 conversion_href = req.href.wiki(page.name, version=version, 610 610 format=conversion[0]) 611 # or...612 conversion_href = get_resource_url(self.env, page.resource,613 req.href,614 format=conversion[0])615 611 add_link(req, 'alternate', conversion_href, conversion[1], 616 612 conversion[3]) 617 613
Unrelated, we could probably refactor the code on the trunk to use a NamedTuple in Mimeview.get_supported_conversions, in order to make the code above more readable: trunk/trac/mimeview/api.py@12999:663#L654 (as suggested in TracDev/ApiChanges/1.1.1).
comment:8 by , 11 years ago
follow-up: 13 comment:9 by , 11 years ago
Would it be clearer if the following change was made: branches/1.0-stable/trac/perm.py@12644:462#L451?
- if not decision: + if decision is False
The two conditionals would seem to be equivalent since the outer conditional has already tested decision is not None. It seems that only True, False and None should be considered: branches/1.0-stable/trac/perm.py@12644:135-137#L122, which implies that decision must be True or False at this point in the code (assuming properly implemented IPermissionPolicy). See also [5867].
comment:10 by , 11 years ago
| Description: | modified (diff) |
|---|
comment:11 by , 11 years ago
Replying to rjollos:
The
WikiPageclass has some unique behavior that presents a complication for these changes. When the version is not specified when creating the object (e.g.page = WikiPage(self.env, name)),page.versionwill contain the latest version of the page, butpage.resource.versionwill beNone.The behavior is utilized when rendering the wiki page to determine whether a versioned page or just the standard HEAD view of the page should be rendered: trunk/trac/wiki/web_ui.py@13003:582,630#L581.
This may be related to the behavior reported in comment:3:ticket:11651. #8976 is a related ticket.
comment:12 by , 11 years ago
Replying to rjollos:
The
WikiPageclass has some unique behavior that presents a complication for these changes. When the version is not specified when creating the object (e.g.page = WikiPage(self.env, name)),page.versionwill contain the latest version of the page, butpage.resource.versionwill beNone.
The consequences of the change in #11544 should be looked at more closely when investigating how to modify the behavior of the WikiPage class.
comment:13 by , 11 years ago
Replying to rjollos:
Would it be clearer if the following change was made: branches/1.0-stable/trac/perm.py@12644:462#L451?
- if not decision: + if decision is False
Committed to 1.0-stable in [13168], merged to trunk in [13169].
by , 11 years ago
| Attachment: | profile_object_creation.py added |
|---|
comment:14 by , 11 years ago
Replying to rjollos:
The changes are more extensive than I initially suspected, so moving this forward. So far I've found that it simplifies the code quite a bit to have a readonly
resourceproperty. The downside could be that aResourceobject is constructed each time theresourceproperty is accessed. I'm assuming the overhead in this will be so small that it won't be an issue, but if it ever is an issue we can lazily-evaluateresourceand delete the value when it becomes invalid (similar to howEnvironment.database_versionis handled inupgrade_environment: [12989/branches/1.0-stable/trac/env.py]).
We only have to be concerned about this in places where many objects are being constructed. The only places in Trac where I can think this could be an issue are in the ReportModule and QueryModule. There we aren't working with Ticket objects though:
- QueryMacro: tags/trac-1.0.2/trac/ticket/query.py@:1419-1420#L1414.
Resourceobject will be constructed in tags/trac-1.0.2/trac/perm.py@:544#L520. - Query and Report views: tags/trac-1.0.2/trac/ticket/templates/query_results.html@:75-76#L54. Resource objects are constructed in the template
Profiling shows approximately 10x overhead to create Resource objects on every property access (profile_object_creation.py):
$ python profile_object_creation.py Profiling resource as a property: [0.22201299667358398, 0.2205369472503662, 0.2116711139678955] Profiling resource as a attribute: [0.0338740348815918, 0.03734707832336426, 0.0335540771484375]
comment:15 by , 11 years ago
| API Changes: | modified (diff) |
|---|
Replying to rjollos:
The
WikiPageclass has some unique behavior that presents a complication for these changes. When the version is not specified when creating the object (e.g.page = WikiPage(self.env, name)),page.versionwill contain the latest version of the page, butpage.resource.versionwill beNone.
The proposed changes in log:rjollos.git:t11648.2 document this behavior. The behavior appeared to be slightly inconsistent before. The behavior now is that page.resource.version is always None unless a specific version of the page has been requested when initializing the WikiPage object.
comment:16 by , 11 years ago
Replying to rjollos:
Unrelated, we could probably refactor the code on the trunk to use a
NamedTupleinMimeview.get_supported_conversions, in order to make the code above more readable: trunk/trac/mimeview/api.py@12999:663#L654 (as suggested in TracDev/ApiChanges/1.1.1).
⇒ #11873.
comment:17 by , 11 years ago
| Description: | modified (diff) |
|---|
comment:18 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Committed to trunk in [13487].



The changes are more extensive than I initially suspected, so moving this forward. So far I've found that it simplifies the code quite a bit to have a readonly
resourceproperty. The downside could be that aResourceobject is constructed each time theresourceproperty is accessed. I'm assuming the overhead in this will be so small that it won't be an issue, but if it ever is an issue we can lazily-evaluateresourceand delete the value when it becomes invalid (similar to howEnvironment.database_versionis handled inupgrade_environment: [12989/branches/1.0-stable/trac/env.py]).