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

zopefoundation / Products.CMFCore / 6246931310

20 Sep 2023 09:54AM UTC coverage: 86.008% (-0.3%) from 86.266%
6246931310

Pull #131

github

mauritsvanrees
gha: don't need setup-python on 27 as we use the 27 container.
Pull Request #131: Make decodeFolderFilter and encodeFolderFilter non-public.

2466 of 3689 branches covered (0.0%)

Branch coverage included in aggregate %.

6 of 6 new or added lines in 1 file covered. (100.0%)

17297 of 19289 relevant lines covered (89.67%)

0.9 hits per line

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

81.22
/src/Products/CMFCore/FSObject.py
1
##############################################################################
2
#
3
# Copyright (c) 2001 Zope Foundation and Contributors.
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE.
11
#
12
##############################################################################
13
""" Customizable objects that come from the filesystem (base class).
1✔
14
"""
15

16
import os
1✔
17

18
from AccessControl.class_init import InitializeClass
1✔
19
from AccessControl.Permission import Permission
1✔
20
from AccessControl.SecurityInfo import ClassSecurityInfo
1✔
21
from Acquisition import Implicit
1✔
22
from Acquisition import aq_base
1✔
23
from Acquisition import aq_inner
1✔
24
from Acquisition import aq_parent
1✔
25
from App.config import getConfiguration
1✔
26
from App.special_dtml import HTML
1✔
27
from DateTime.DateTime import DateTime
1✔
28
from OFS.Cache import Cacheable
1✔
29
from OFS.role import RoleManager
1✔
30
from OFS.SimpleItem import Item
1✔
31
from zope.component import getUtility
1✔
32

33
from Products.PythonScripts.standard import html_quote
1✔
34

35
from .interfaces import ISkinsTool
1✔
36
from .permissions import ManagePortal
1✔
37
from .permissions import View
1✔
38
from .permissions import ViewManagementScreens
1✔
39

40

41
class FSObject(Implicit, Item, RoleManager, Cacheable):
1✔
42

43
    """FSObject is a base class for all filesystem based look-alikes.
44

45
    Subclasses of this class mimic ZODB based objects like Image and
46
    DTMLMethod, but are not directly modifiable from the management
47
    interface. They provide means to create a TTW editable copy, however.
48
    """
49

50
    # Always empty for FS based, non-editable objects.
51
    title = ''
1✔
52
    _file_mod_time = 0
1✔
53
    _parsed = 0
1✔
54

55
    security = ClassSecurityInfo()
1✔
56
    security.declareObjectProtected(View)
1✔
57

58
    def __init__(self, id, filepath, fullname=None, properties=None):
1✔
59
        if properties:
1✔
60
            # Since props come from the filesystem, this should be
61
            # safe.
62
            self.__dict__.update(properties)
1✔
63
            if fullname and properties.get('keep_extension', 0):
1!
64
                id = fullname
×
65

66
            cache = properties.get('cache')
1✔
67
            if cache:
1✔
68
                self.ZCacheable_setManagerId(cache)
1✔
69

70
        self.id = id
1✔
71
        self.__name__ = id  # __name__ is used in traceback reporting
1✔
72
        self._filepath = filepath
1✔
73

74
        try:
1✔
75
            self._file_mod_time = os.stat(filepath).st_mtime
1✔
76
        except Exception:
×
77
            pass
×
78
        self._readFile(0)
1✔
79

80
    @security.protected(ViewManagementScreens)
1✔
81
    def manage_doCustomize(self, folder_path, RESPONSE=None, root=None,
1✔
82
                           obj=None):
83
        """Makes a ZODB Based clone with the same data.
84

85
        Calls _createZODBClone for the actual work.
86
        """
87

88
        if obj is None:
1✔
89
            obj = self._createZODBClone()
1✔
90
        parent = aq_parent(aq_inner(self))
1✔
91

92
        # Preserve cache manager associations
93
        cachemgr_id = self.ZCacheable_getManagerId()
1✔
94
        if cachemgr_id and \
1✔
95
                getattr(obj, 'ZCacheable_setManagerId', None) is not None:
96
            obj.ZCacheable_setManagerId(cachemgr_id)
1✔
97

98
        # If there are proxy roles we preserve them
99
        proxy_roles = getattr(aq_base(self), '_proxy_roles', None)
1✔
100
        if proxy_roles is not None and isinstance(proxy_roles, tuple):
1✔
101
            obj._proxy_roles = tuple(self._proxy_roles)
1✔
102

103
        # Also, preserve any permission settings that might have come
104
        # from a metadata file or from fiddling in the ZMI
105
        old_info = [x[:2] for x in self.ac_inherited_permissions(1)]
1✔
106
        for old_perm, value in old_info:
1✔
107
            p = Permission(old_perm, value, self)
1✔
108
            acquired = int(isinstance(p.getRoles(default=[]), list))
1✔
109
            rop_info = self.rolesOfPermission(old_perm)
1✔
110
            roles = [x['name'] for x in rop_info if x['selected'] != '']
1✔
111
            try:
1✔
112
                # if obj is based on OFS.ObjectManager an acquisition context
113
                # is required for _subobject_permissions()
114
                obj.__of__(parent).manage_permission(old_perm, roles=roles,
1✔
115
                                                     acquire=acquired)
116
            except ValueError:
1✔
117
                # The permission was invalid, never mind
118
                pass
1✔
119

120
        id = obj.getId()
1✔
121
        fpath = tuple(folder_path.split('/'))
1✔
122
        if root is None:
1✔
123
            portal_skins = getUtility(ISkinsTool)
1✔
124
        else:
125
            portal_skins = root
1✔
126
        if folder_path == '.':
1✔
127
            fpath = ()
1✔
128
        folder = portal_skins.restrictedTraverse(fpath)
1✔
129
        if id in folder.objectIds():
1!
130
            # we cant catch the badrequest so
131
            # we'll that to check before hand
132
            obj = folder._getOb(id)
×
133
            if RESPONSE is not None:
×
134
                RESPONSE.redirect('%s/manage_main?manage_tabs_message=%s' % (
×
135
                    obj.absolute_url(),
136
                    html_quote('An object with this id already exists')))
137
        else:
138
            folder._verifyObjectPaste(obj, validate_src=0)
1✔
139
            folder._setObject(id, obj)
1✔
140

141
            if RESPONSE is not None:
1!
142
                RESPONSE.redirect('%s/%s/manage_main' % (folder.absolute_url(),
×
143
                                                         id))
144

145
        if RESPONSE is not None:
1!
146
            RESPONSE.redirect('%s/%s/manage_main' % (
×
147
                folder.absolute_url(), id))
148

149
    def _createZODBClone(self):
1✔
150
        """Create a ZODB (editable) equivalent of this object."""
151
        raise NotImplementedError('This should be implemented in a subclass.')
152

153
    def _readFile(self, reparse):
1✔
154
        """Read the data from the filesystem.
155

156
        Read the file indicated by self._filepath, and parse the
157
        data if necessary.  'reparse' is set when reading the second
158
        time and beyond.
159
        """
160
        raise NotImplementedError('This should be implemented in a subclass.')
161

162
    # Refresh our contents from the filesystem if that is newer and we are
163
    # running in debug mode.
164
    def _updateFromFS(self):
1✔
165
        parsed = self._parsed
1✔
166
        if not parsed or getConfiguration().debug_mode:
1✔
167
            try:
1✔
168
                mtime = os.stat(self._filepath).st_mtime
1✔
169
            except Exception:
×
170
                mtime = 0.0
×
171
            if not parsed or mtime != self._file_mod_time:
1!
172
                self._readFile(1)
1✔
173
                if mtime != self._file_mod_time or mtime == 0.0:
1✔
174
                    self.ZCacheable_invalidate()
1✔
175
                    self._file_mod_time = mtime
1✔
176
                self._parsed = 1
1✔
177

178
    @security.protected(View)
1✔
179
    def get_size(self):
1✔
180
        """Get the size of the underlying file."""
181
        return os.path.getsize(self._filepath)
1✔
182

183
    @security.protected(View)
1✔
184
    def getModTime(self):
1✔
185
        """Return the last_modified date of the file we represent.
186

187
        Returns a DateTime instance.
188
        """
189
        self._updateFromFS()
1✔
190
        return DateTime(self._file_mod_time)
1✔
191

192
    @security.protected(View)
1✔
193
    def bobobase_modification_time(self):
1✔
194
        """Get the modification time the file did have last time it was read.
195
        """
196
        return DateTime(self._file_mod_time)
1✔
197

198
    @security.protected(ViewManagementScreens)
1✔
199
    def getObjectFSPath(self):
1✔
200
        """Return the path of the file we represent"""
201
        self._updateFromFS()
×
202
        return self._filepath
×
203

204

205
InitializeClass(FSObject)
1✔
206

207

208
class BadFile(FSObject):
1✔
209

210
    """
211
        Represent a file which was not readable or parseable
212
        as its intended type.
213
    """
214
    meta_type = 'Bad File'
1✔
215
    icon = 'p_/broken'
1✔
216

217
    BAD_FILE_VIEW = """\
1✔
218
<dtml-var manage_page_header>
219
<dtml-var manage_tabs>
220
<h2> Bad Filesystem Object: &dtml-getId; </h2>
221

222
<h3> File Contents </h3>
223
<pre>
224
<dtml-var getFileContents>
225
</pre>
226

227
<h3> Exception </h3>
228
<pre>
229
<dtml-var getExceptionText>
230
</pre>
231
<dtml-var manage_page_footer>
232
"""
233

234
    manage_options = ({'label': 'Error', 'action': 'manage_showError'},)
1✔
235

236
    def __init__(self, id, filepath, exc_str='', fullname=None,
1✔
237
                 properties=None):
238
        id = fullname or id  # Use the whole filename.
×
239
        self.exc_str = exc_str
×
240
        self.file_contents = ''
×
241
        FSObject.__init__(self, id, filepath, fullname, properties)
×
242

243
    security = ClassSecurityInfo()
1✔
244

245
    showError = HTML(BAD_FILE_VIEW)
1✔
246

247
    @security.protected(ManagePortal)
1✔
248
    def manage_showError(self, REQUEST):
1✔
249
        """
250
        """
251
        return self.showError(self, REQUEST)
×
252

253
    @security.private
1✔
254
    def _readFile(self, reparse):
1✔
255
        """Read the data from the filesystem.
256
        """
257
        try:
×
258
            file = open(self._filepath, 'rb')
×
259
            try:
×
260
                data = self.file_contents = file.read()
×
261
            finally:
262
                file.close()
×
263
        except Exception:  # No errors of any sort may propagate
×
264
            data = self.file_contents = None  # give up
×
265
        return data
×
266

267
    @security.public
1✔
268
    def getFileContents(self):
1✔
269
        """
270
            Return the contents of the file, if we could read it.
271
        """
272
        return self.file_contents
×
273

274
    @security.public
1✔
275
    def getExceptionText(self):
1✔
276
        """
277
            Return the exception thrown while reading or parsing
278
            the file.
279
        """
280
        return self.exc_str
×
281

282

283
InitializeClass(BadFile)
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