• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Zope / 3956162881

pending completion
3956162881

push

github

Michael Howitz
Update to deprecation warning free releases.

4401 of 7036 branches covered (62.55%)

Branch coverage included in aggregate %.

27161 of 31488 relevant lines covered (86.26%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.26
/src/Products/Five/browser/resource.py
1
##############################################################################
2
#
3
# Copyright (c) 2004, 2005 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14
"""Provide basic resource functionality
1✔
15
"""
16

17
import os
1✔
18
from urllib.parse import unquote
1✔
19

20
import zope.browserresource.directory
1✔
21
import zope.browserresource.file
1✔
22
from Products.Five.browser import BrowserView
1✔
23
from zope.browserresource.file import File
1✔
24
from zope.interface import implementer
1✔
25
from zope.ptresource.ptresource import PageTemplate
1✔
26
from zope.publisher.interfaces import NotFound
1✔
27
from zope.publisher.interfaces.browser import IBrowserPublisher
1✔
28
from zope.traversing.browser import absoluteURL
1✔
29

30

31
_marker = object()
1✔
32

33

34
class Resource:
1✔
35
    """A mixin that changes the URL-rendering of resources (__call__).
36

37
    In zope.browserresource, resource URLs are of the form
38
    nearest_site/@@/resource_name.  Since Zope 2 didn't have support
39
    for sites from the beginning of the Five integration, resource
40
    URLs in Zope 2 are of the form context/++resource++resource_name.
41

42
    TODO It would be good if that could be changed in the long term,
43
    thus making this mixin (and probably the other classes in this
44
    module) obsolete.
45
    """
46
    def __call__(self):
1✔
47
        name = self.__name__
1✔
48
        container = self.__parent__
1✔
49

50
        url = unquote(absoluteURL(container, self.request))
1✔
51
        if not isinstance(container, DirectoryResource):
1✔
52
            name = '++resource++%s' % name
1✔
53
        return f"{url}/{name}"
1✔
54

55

56
@implementer(IBrowserPublisher)
1✔
57
class PageTemplateResource(Resource, BrowserView):
1✔
58

59
    def browserDefault(self, request):
1✔
60
        return self.render, ()
1✔
61

62
    def publishTraverse(self, request, name):
1✔
63
        raise NotFound(self, name, request)
1✔
64

65
    def render(self):
1✔
66
        """Rendered content"""
67
        # ZPublisher might have called setBody with an incorrect URL
68
        # we definitely don't want that if we are plain html
69
        self.request.response.setBase(None)
1✔
70
        pt = self.context
1✔
71
        return pt(self.request)
1✔
72

73

74
class FileResource(Resource, zope.browserresource.file.FileResource):
1✔
75
    pass
1✔
76

77

78
class ResourceFactory:
1✔
79

80
    factory = None
1✔
81
    resource = None
1✔
82

83
    def __init__(self, name, path, resource_factory=None):
1✔
84
        self.__name = name
1✔
85
        self.__rsrc = self.factory(path, name)
1✔
86
        if resource_factory is not None:
1✔
87
            self.resource = resource_factory
1✔
88

89
    def __call__(self, request):
1✔
90
        resource = self.resource(self.__rsrc, request)
1✔
91
        return resource
1✔
92

93

94
def _PageTemplate(self, path, name):
1✔
95
    # PageTemplate doesn't take a name parameter,
96
    # which makes it different from FileResource.
97
    # This is probably an error.
98
    template = PageTemplate(path)
1✔
99
    template.__name__ = name
1✔
100
    return template
1✔
101

102

103
class PageTemplateResourceFactory(ResourceFactory):
1✔
104
    """A factory for Page Template resources"""
105

106
    factory = _PageTemplate
1✔
107
    resource = PageTemplateResource
1✔
108

109

110
class FileResourceFactory(ResourceFactory):
1✔
111
    """A factory for File resources"""
112

113
    factory = File
1✔
114
    resource = FileResource
1✔
115

116

117
class ImageResourceFactory(ResourceFactory):
1✔
118
    """A factory for Image resources"""
119

120
    factory = File
1✔
121
    resource = FileResource
1✔
122

123

124
# we only need this class a context for DirectoryResource
125
class Directory:
1✔
126

127
    def __init__(self, path, name):
1✔
128
        self.path = path
1✔
129
        self.__name__ = name
1✔
130

131

132
class DirectoryResource(Resource,
1✔
133
                        zope.browserresource.directory.DirectoryResource):
134

135
    resource_factories = {
1✔
136
        'gif': ImageResourceFactory,
137
        'png': ImageResourceFactory,
138
        'jpg': ImageResourceFactory,
139
        'pt': PageTemplateResourceFactory,
140
        'zpt': PageTemplateResourceFactory,
141
        'html': PageTemplateResourceFactory,
142
        'htm': PageTemplateResourceFactory,
143
    }
144

145
    default_factory = FileResourceFactory
1✔
146

147
    def getId(self):
1✔
148
        name = self.__name__
1✔
149
        if not name.startswith('++resource++'):
1!
150
            name = '++resource++%s' % self.__name__
1✔
151
        return name
1✔
152

153
    def get(self, name, default=_marker):
1✔
154
        path = self.context.path
1✔
155
        filename = os.path.join(path, name)
1✔
156
        isfile = os.path.isfile(filename)
1✔
157
        isdir = os.path.isdir(filename)
1✔
158

159
        if not (isfile or isdir):
1✔
160
            if default is _marker:
1!
161
                raise KeyError(name)
1✔
162
            return default
×
163

164
        if isfile:
1✔
165
            ext = name.split('.')[-1]
1✔
166
            factory = self.resource_factories.get(ext, self.default_factory)
1✔
167
        else:
168
            factory = DirectoryResourceFactory
1✔
169

170
        resource = factory(name, filename)(self.request)
1✔
171
        resource.__name__ = name
1✔
172
        resource.__parent__ = self
1✔
173

174
        # We need to propagate security so that restrictedTraverse() will
175
        # work
176
        if hasattr(self, '__roles__'):
1!
177
            resource.__roles__ = self.__roles__
1✔
178

179
        return resource
1✔
180

181

182
class DirectoryResourceFactory(ResourceFactory):
1✔
183

184
    factory = Directory
1✔
185
    resource = DirectoryResource
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc