• 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

76.76
/src/Products/CMFCore/FSPythonScript.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 Python scripts that come from the filesystem.
1✔
14
"""
15

16
from difflib import unified_diff
1✔
17

18
from six import get_unbound_function
1✔
19

20
from AccessControl.class_init import InitializeClass
1✔
21
from AccessControl.SecurityInfo import ClassSecurityInfo
1✔
22
from App.special_dtml import DTMLFile
1✔
23
from ComputedAttribute import ComputedAttribute
1✔
24
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
1✔
25
from Shared.DC.Scripts.Script import Script
1✔
26

27
from Products.PythonScripts.PythonScript import PythonScript
1✔
28

29
from .DirectoryView import registerFileExtension
1✔
30
from .DirectoryView import registerMetaType
1✔
31
from .FSObject import FSObject
1✔
32
from .permissions import FTPAccess
1✔
33
from .permissions import View
1✔
34
from .permissions import ViewManagementScreens
1✔
35
from .utils import _dtmldir
1✔
36

37

38
_marker = object()
1✔
39

40

41
class CustomizedPythonScript(PythonScript):
1✔
42

43
    """ Subclass which captures the "source" version's text.
44
    """
45

46
    # meta_type = 'Customized Python Script'  #(need permissions here)
47

48
    security = ClassSecurityInfo()
1✔
49

50
    def __init__(self, id, text):
1✔
51
        super(CustomizedPythonScript, self).__init__(id)
1✔
52
        self.write(text)
1✔
53
        self.original_source = text
1✔
54

55
    @security.protected(ViewManagementScreens)
1✔
56
    def getDiff(self):
1✔
57
        """ Return a diff of the current source with the original source.
58
        """
59
        return unified_diff(self.original_source.splitlines(),
1✔
60
                            self.read().splitlines(),
61
                            'original',
62
                            'modified',
63
                            '',
64
                            '',
65
                            lineterm='')
66

67
    security.declareProtected(ViewManagementScreens,  # NOQA: flake8: D001
1✔
68
                              'manage_showDiff')
69
    manage_showDiff = PageTemplateFile('www/cpsDiff.pt', globals())
1✔
70

71
    manage_options = (
1✔
72
        PythonScript.manage_options[:1] +
73
        ({'label': 'Diff', 'action': 'manage_showDiff'},) +
74
        PythonScript.manage_options[1:])
75

76

77
InitializeClass(CustomizedPythonScript)
1✔
78

79

80
class FSPythonScript(FSObject, Script):
1✔
81

82
    """FSPythonScripts act like Python Scripts but are not directly
83
    modifiable from the management interface."""
84

85
    meta_type = 'Filesystem Script (Python)'
1✔
86
    zmi_icon = 'fa fa-terminal'
1✔
87
    _params = _body = ''
1✔
88
    _proxy_roles = ()
1✔
89
    _owner = None  # Unowned
1✔
90

91
    manage_options = (
1✔
92
        {'label': 'Customize', 'action': 'manage_main'},)
93

94
    security = ClassSecurityInfo()
1✔
95
    security.declareObjectProtected(View)
1✔
96

97
    security.declareProtected(ViewManagementScreens,  # NOQA: flake8: D001
1✔
98
                              'manage_main')
99
    manage_main = DTMLFile('custpy', _dtmldir)
1✔
100

101
    security.declareProtected(View, 'index_html')  # NOQA: flake8: D001
1✔
102
    # Prevent the bindings from being edited TTW
103
    security.declarePrivate('ZBindings_edit',  # NOQA: flake8: D001
1✔
104
                            'ZBindingsHTML_editForm',
105
                            'ZBindingsHTML_editAction')
106

107
    def _createZODBClone(self):
1✔
108
        """Create a ZODB (editable) equivalent of this object."""
109
        return CustomizedPythonScript(self.getId(), self.read())
1✔
110

111
    def _readFile(self, reparse):
1✔
112
        """Read the data from the filesystem.
113
        """
114
        file = open(self._filepath, 'r')
1✔
115
        try:
1✔
116
            data = file.read()
1✔
117
        finally:
118
            file.close()
1✔
119

120
        if reparse:
1✔
121
            self._write(data, reparse)
1✔
122

123
    def _validateProxy(self, roles=None):
1✔
124
        pass
×
125

126
    def __render_with_namespace__(self, namespace):
1✔
127
        """Calls the script."""
128
        self._updateFromFS()
×
129
        return Script.__render_with_namespace__(self, namespace)
×
130

131
    def __call__(self, *args, **kw):
1✔
132
        """Calls the script."""
133
        self._updateFromFS()
1✔
134
        return Script.__call__(self, *args, **kw)
1✔
135

136
    _exec = get_unbound_function(PythonScript._exec)
1✔
137

138
    security.declareProtected(ViewManagementScreens,  # NOQA: flake8: D001
1✔
139
                              'getModTime')
140
    # getModTime defined in FSObject
141

142
    def ZScriptHTML_tryParams(self):
1✔
143
        """Parameters to test the script with."""
144
        param_names = []
×
145
        for name in self._params.split(','):
×
146
            name = name.strip()
×
147
            if name and name[0] != '*':
×
148
                param_names.append(name.split('=', 1)[0])
×
149
        return param_names
×
150

151
    @security.protected(ViewManagementScreens)
1✔
152
    def read(self):
1✔
153
        self._updateFromFS()
1✔
154
        return self._source
1✔
155

156
    @security.protected(ViewManagementScreens)
1✔
157
    def document_src(self, REQUEST=None, RESPONSE=None):
1✔
158
        """Return unprocessed document source."""
159

160
        if RESPONSE is not None:
×
161
            RESPONSE.setHeader('Content-Type', 'text/plain')
×
162
        return self._source
×
163

164
    @security.protected(ViewManagementScreens)
1✔
165
    def PrincipiaSearchSource(self):
1✔
166
        """Support for searching - the document's contents are searched."""
167
        return '%s\n%s' % (self._params, self._body)
×
168

169
    @security.protected(ViewManagementScreens)
1✔
170
    def params(self):
1✔
171
        return self._params
×
172

173
    security.declareProtected(ViewManagementScreens,  # NOQA: flake8: D001
1✔
174
                              'manage_haveProxy')
175
    manage_haveProxy = get_unbound_function(PythonScript.manage_haveProxy)
1✔
176

177
    @security.protected(ViewManagementScreens)
1✔
178
    def body(self):
1✔
179
        return self._body
×
180

181
    @security.protected(ViewManagementScreens)
1✔
182
    def get_size(self):
1✔
183
        return len(self.read())
1✔
184

185
    @security.protected(FTPAccess)
1✔
186
    def manage_FTPget(self):
1✔
187
        """Get source for FTP download"""
188
        self.REQUEST.RESPONSE.setHeader('Content-Type', 'text/plain')
×
189
        return self.read()
×
190

191
    def _write(self, text, compile):
1✔
192
        """
193
        Parses the source, storing the body, params, title, bindings,
194
        and source in self.  If compile is set, compiles the
195
        function.
196
        """
197
        ps = PythonScript(self.id)
1✔
198
        ps.write(text)
1✔
199
        if compile:
1!
200
            ps._makeFunction()
1✔
201
            self._v_ft = ps._v_ft
1✔
202
            self.__code__ = ps.__code__
1✔
203
            self.__defaults__ = ps.__defaults__
1✔
204
        self._body = ps._body
1✔
205
        self._params = ps._params
1✔
206
        self.title = ps.title
1✔
207
        self._setupBindings(ps.getBindingAssignments().getAssignedNames())
1✔
208
        self._source = ps.read()  # Find out what the script sees.
1✔
209

210
    def _func_defaults(self):
1✔
211
        # This ensures __code__ and __defaults__ are
212
        # set when the code hasn't been compiled yet,
213
        # just in time for mapply().  Truly odd, but so is mapply(). :P
214
        self._updateFromFS()
×
215
        return self.__dict__.get('__defaults__', None)
×
216
    __defaults__ = ComputedAttribute(_func_defaults, 1)
1✔
217

218
    def _func_code(self):
1✔
219
        # See func_defaults.
220
        self._updateFromFS()
×
221
        return self.__dict__.get('__code__', None)
×
222
    __code__ = ComputedAttribute(_func_code, 1)
1✔
223

224
    def title(self):
1✔
225
        # See func_defaults.
226
        self._updateFromFS()
×
227
        return self.__dict__.get('title', None)
×
228
    title = ComputedAttribute(title, 1)
1✔
229

230
    def getBindingAssignments(self):
1✔
231
        # Override of the version in Bindings.py.
232
        # This version ensures that bindings get loaded on demand.
233
        if not hasattr(self, '_bind_names'):
1!
234
            # Set a default first to avoid recursion
235
            self._setupBindings()
×
236
            # Now do it for real
237
            self._updateFromFS()
×
238
        return self._bind_names
1✔
239

240

241
InitializeClass(FSPythonScript)
1✔
242

243
registerFileExtension('py', FSPythonScript)
1✔
244
registerMetaType('Script (Python)', FSPythonScript)
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