Products.PythonScripts 4.15__tar.gz → 5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. Products.PythonScripts-5.1/.pre-commit-config.yaml +28 -0
  2. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/CHANGES.rst +19 -0
  3. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/MANIFEST.in +1 -1
  4. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/PKG-INFO +32 -9
  5. Products.PythonScripts-5.1/pyproject.toml +21 -0
  6. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/setup.cfg +1 -4
  7. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/setup.py +7 -11
  8. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/PythonScript.py +34 -30
  9. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/standard.py +1 -1
  10. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/testBindings.py +1 -1
  11. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/testPythonScript.py +57 -93
  12. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/www/pyScriptEdit.dtml +1 -1
  13. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/PKG-INFO +32 -9
  14. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/SOURCES.txt +3 -4
  15. Products.PythonScripts-5.1/tox.ini +77 -0
  16. Products.PythonScripts-4.15/buildout4.cfg +0 -7
  17. Products.PythonScripts-4.15/src/Products/PythonScripts/tests/tscripts/complex_print_py2.ps +0 -9
  18. Products.PythonScripts-4.15/src/Products/PythonScripts/tests/tscripts/ps_2.13.2.pkl +0 -0
  19. Products.PythonScripts-4.15/tox.ini +0 -90
  20. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/CONTRIBUTING.md +0 -0
  21. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/COPYRIGHT.txt +0 -0
  22. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/LICENSE.txt +0 -0
  23. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/README.rst +0 -0
  24. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/buildout.cfg +0 -0
  25. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/Extensions/RemotePS.py +0 -0
  26. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/Utility.py +0 -0
  27. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/__init__.py +0 -0
  28. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/configure.zcml +0 -0
  29. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/__init__.py +0 -0
  30. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/big_boolean.ps +0 -0
  31. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/boolean_map.ps +0 -0
  32. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/class.__name__.ps +0 -0
  33. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/complete.ps +0 -0
  34. /Products.PythonScripts-4.15/src/Products/PythonScripts/tests/tscripts/complex_print_py3.ps → /Products.PythonScripts-5.1/src/Products/PythonScripts/tests/tscripts/complex_print.ps +0 -0
  35. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/fibonacci.ps +0 -0
  36. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/filepath.ps +0 -0
  37. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/for_loop.ps +0 -0
  38. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/global_is_declaration.ps +0 -0
  39. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/mutate_literals.ps +0 -0
  40. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/ns_bind.ps +0 -0
  41. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/ns_bind_invalid.ps +0 -0
  42. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/simple_print.ps +0 -0
  43. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/subversive_except.ps +0 -0
  44. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/try_except.ps +0 -0
  45. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/tuple_unpack_assignment.ps +0 -0
  46. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/tests/tscripts/while_loop.ps +0 -0
  47. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/www/default_content +0 -0
  48. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/www/pyScriptAdd.dtml +0 -0
  49. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/PythonScripts/www/pyScriptProxy.dtml +0 -0
  50. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products/__init__.py +0 -0
  51. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/dependency_links.txt +0 -0
  52. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/entry_points.txt +0 -0
  53. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/namespace_packages.txt +0 -0
  54. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/not-zip-safe +0 -0
  55. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/requires.txt +0 -0
  56. {Products.PythonScripts-4.15 → Products.PythonScripts-5.1}/src/Products.PythonScripts.egg-info/top_level.txt +0 -0
@@ -0,0 +1,28 @@
1
+ # Generated from:
2
+ # https://github.com/zopefoundation/meta/tree/master/config/zope-product
3
+ minimum_pre_commit_version: '3.6'
4
+ repos:
5
+ - repo: https://github.com/pycqa/isort
6
+ rev: "5.13.2"
7
+ hooks:
8
+ - id: isort
9
+ - repo: https://github.com/hhatto/autopep8
10
+ rev: "v2.3.1"
11
+ hooks:
12
+ - id: autopep8
13
+ args: [--in-place, --aggressive, --aggressive]
14
+ - repo: https://github.com/asottile/pyupgrade
15
+ rev: v3.17.0
16
+ hooks:
17
+ - id: pyupgrade
18
+ args: [--py38-plus]
19
+ - repo: https://github.com/isidentical/teyit
20
+ rev: 0.4.3
21
+ hooks:
22
+ - id: teyit
23
+ - repo: https://github.com/PyCQA/flake8
24
+ rev: "7.1.1"
25
+ hooks:
26
+ - id: flake8
27
+ additional_dependencies:
28
+ - flake8-debugger == 4.1.2
@@ -1,6 +1,25 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 5.1 (2024-10-16)
5
+ ----------------
6
+
7
+ - Fix behavior when uploading no file in ``Zope >= 5.8.1``.
8
+
9
+ - Add support for Python 3.12 and 3.13
10
+
11
+ - Drop support for Python 3.7.
12
+
13
+ - Show Python Scripts source code in tracebacks.
14
+ `#64 <https://github.com/zopefoundation/Products.PythonScripts/issues/64>`_
15
+
16
+
17
+ 5.0 (2023-02-01)
18
+ ----------------
19
+
20
+ - Drop support for Python 2.7, 3.5, 3.6.
21
+
22
+
4
23
  4.15 (2022-12-16)
5
24
  -----------------
6
25
 
@@ -5,9 +5,9 @@ include *.rst
5
5
  include *.txt
6
6
  include buildout.cfg
7
7
  include tox.ini
8
+ include .pre-commit-config.yaml
8
9
 
9
10
  recursive-include src *.py
10
- include buildout4.cfg
11
11
  include src/Products/PythonScripts/www/default_content
12
12
  recursive-include src *.dtml
13
13
  recursive-include src *.pkl
@@ -1,34 +1,38 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Products.PythonScripts
3
- Version: 4.15
3
+ Version: 5.1
4
4
  Summary: Provides support for restricted execution of Python scripts in Zope.
5
5
  Home-page: https://github.com/zopefoundation/Products.PythonScripts
6
6
  Author: Zope Foundation and Contributors
7
- Author-email: zope-dev@zope.org
7
+ Author-email: zope-dev@zope.dev
8
8
  License: ZPL 2.1
9
9
  Project-URL: Issue Tracker, https://github.com/zopefoundation/Products.PythonScripts/issues
10
10
  Project-URL: Sources, https://github.com/zopefoundation/Products.PythonScripts
11
11
  Classifier: Development Status :: 6 - Mature
12
12
  Classifier: Environment :: Web Environment
13
13
  Classifier: Framework :: Zope
14
- Classifier: Framework :: Zope :: 4
15
14
  Classifier: Framework :: Zope :: 5
16
15
  Classifier: License :: OSI Approved :: Zope Public License
17
16
  Classifier: Operating System :: OS Independent
18
17
  Classifier: Programming Language :: Python
19
- Classifier: Programming Language :: Python :: 2
20
- Classifier: Programming Language :: Python :: 2.7
21
18
  Classifier: Programming Language :: Python :: 3
22
- Classifier: Programming Language :: Python :: 3.5
23
- Classifier: Programming Language :: Python :: 3.6
24
- Classifier: Programming Language :: Python :: 3.7
25
19
  Classifier: Programming Language :: Python :: 3.8
26
20
  Classifier: Programming Language :: Python :: 3.9
27
21
  Classifier: Programming Language :: Python :: 3.10
28
22
  Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
29
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
30
- Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*
26
+ Requires-Python: >=3.8
31
27
  License-File: LICENSE.txt
28
+ Requires-Dist: setuptools
29
+ Requires-Dist: AccessControl
30
+ Requires-Dist: Acquisition
31
+ Requires-Dist: DateTime
32
+ Requires-Dist: DocumentTemplate
33
+ Requires-Dist: RestrictedPython>=4.0b5
34
+ Requires-Dist: zExceptions
35
+ Requires-Dist: Zope>=4.1.2
32
36
 
33
37
  .. image:: https://github.com/zopefoundation/Products.PythonScripts/actions/workflows/tests.yml/badge.svg
34
38
  :target: https://github.com/zopefoundation/Products.PythonScripts/actions/workflows/tests.yml
@@ -122,6 +126,25 @@ in the Products directory.
122
126
  Changelog
123
127
  =========
124
128
 
129
+ 5.1 (2024-10-16)
130
+ ----------------
131
+
132
+ - Fix behavior when uploading no file in ``Zope >= 5.8.1``.
133
+
134
+ - Add support for Python 3.12 and 3.13
135
+
136
+ - Drop support for Python 3.7.
137
+
138
+ - Show Python Scripts source code in tracebacks.
139
+ `#64 <https://github.com/zopefoundation/Products.PythonScripts/issues/64>`_
140
+
141
+
142
+ 5.0 (2023-02-01)
143
+ ----------------
144
+
145
+ - Drop support for Python 2.7, 3.5, 3.6.
146
+
147
+
125
148
  4.15 (2022-12-16)
126
149
  -----------------
127
150
 
@@ -0,0 +1,21 @@
1
+ #
2
+ # Generated from:
3
+ # https://github.com/zopefoundation/meta/tree/master/config/zope-product
4
+
5
+ [build-system]
6
+ requires = ["setuptools < 74"]
7
+ build-backend = "setuptools.build_meta"
8
+
9
+ [tool.coverage.run]
10
+ branch = true
11
+ source = ["Products.PythonScripts"]
12
+
13
+ [tool.coverage.report]
14
+ fail_under = 83
15
+ precision = 2
16
+ ignore_errors = true
17
+ show_missing = true
18
+ exclude_lines = ["pragma: no cover", "pragma: nocover", "except ImportError:", "raise NotImplementedError", "if __name__ == '__main__':", "self.fail", "raise AssertionError", "raise unittest.Skip"]
19
+
20
+ [tool.coverage.html]
21
+ directory = "parts/htmlcov"
@@ -1,6 +1,3 @@
1
- [bdist_wheel]
2
- universal = 1
3
-
4
1
  [flake8]
5
2
  doctests = 1
6
3
  no-accept-encodings = True
@@ -15,7 +12,7 @@ ignore =
15
12
  force_single_line = True
16
13
  combine_as_imports = True
17
14
  sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER
18
- known_third_party = six, docutils, pkg_resources
15
+ known_third_party = docutils, pkg_resources, pytz
19
16
  known_zope =
20
17
  known_first_party =
21
18
  default_section = ZOPE
@@ -17,7 +17,7 @@ from setuptools import setup
17
17
 
18
18
 
19
19
  setup(name='Products.PythonScripts',
20
- version='4.15',
20
+ version='5.1',
21
21
  url='https://github.com/zopefoundation/Products.PythonScripts',
22
22
  project_urls={
23
23
  'Issue Tracker': ('https://github.com/zopefoundation/'
@@ -29,9 +29,9 @@ setup(name='Products.PythonScripts',
29
29
  description='Provides support for restricted execution of Python '
30
30
  'scripts in Zope.',
31
31
  author='Zope Foundation and Contributors',
32
- author_email='zope-dev@zope.org',
33
- long_description=('%s\n%s' % (open('README.rst').read(),
34
- open('CHANGES.rst').read())),
32
+ author_email='zope-dev@zope.dev',
33
+ long_description=('{}\n{}'.format(open('README.rst').read(),
34
+ open('CHANGES.rst').read())),
35
35
  packages=find_packages('src'),
36
36
  namespace_packages=['Products'],
37
37
  package_dir={'': 'src'},
@@ -39,24 +39,20 @@ setup(name='Products.PythonScripts',
39
39
  'Development Status :: 6 - Mature',
40
40
  'Environment :: Web Environment',
41
41
  'Framework :: Zope',
42
- 'Framework :: Zope :: 4',
43
42
  'Framework :: Zope :: 5',
44
43
  'License :: OSI Approved :: Zope Public License',
45
44
  'Operating System :: OS Independent',
46
45
  'Programming Language :: Python',
47
- 'Programming Language :: Python :: 2',
48
- 'Programming Language :: Python :: 2.7',
49
46
  'Programming Language :: Python :: 3',
50
- 'Programming Language :: Python :: 3.5',
51
- 'Programming Language :: Python :: 3.6',
52
- 'Programming Language :: Python :: 3.7',
53
47
  'Programming Language :: Python :: 3.8',
54
48
  'Programming Language :: Python :: 3.9',
55
49
  'Programming Language :: Python :: 3.10',
56
50
  'Programming Language :: Python :: 3.11',
51
+ 'Programming Language :: Python :: 3.12',
52
+ 'Programming Language :: Python :: 3.13',
57
53
  'Programming Language :: Python :: Implementation :: CPython',
58
54
  ],
59
- python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*',
55
+ python_requires='>=3.8',
60
56
  install_requires=[
61
57
  'setuptools',
62
58
  'AccessControl',
@@ -16,15 +16,16 @@ This product provides support for Script objects containing restricted
16
16
  Python code.
17
17
  """
18
18
 
19
+ import importlib.abc
20
+ import importlib.util
21
+ import linecache
19
22
  import marshal
20
23
  import os
21
24
  import re
22
25
  import sys
23
26
  import types
24
27
  from logging import getLogger
25
-
26
- import six
27
- from six.moves.urllib.parse import quote
28
+ from urllib.parse import quote
28
29
 
29
30
  from AccessControl.class_init import InitializeClass
30
31
  from AccessControl.Permissions import change_proxy_roles
@@ -47,27 +48,17 @@ from Shared.DC.Scripts.Script import BindingsUI
47
48
  from Shared.DC.Scripts.Script import Script
48
49
  from Shared.DC.Scripts.Script import defaultBindings
49
50
  from zExceptions import Forbidden
51
+ from zExceptions import ResourceLockedError
50
52
  from ZPublisher.HTTPRequest import default_encoding
51
53
 
52
54
 
53
- try:
54
- from zExceptions import ResourceLockedError
55
- except ImportError:
56
- from webdav.Lockable import ResourceLockedError
57
-
58
55
  LOG = getLogger('PythonScripts')
59
56
 
60
57
  # Track the Python bytecode version
61
- try:
62
- import importlib.util
63
- Python_magic = importlib.util.MAGIC_NUMBER
64
- except ImportError: # Python 2
65
- import imp
66
- Python_magic = imp.get_magic()
67
- del imp
58
+ Python_magic = importlib.util.MAGIC_NUMBER
68
59
 
69
60
  # This should only be incremented to force recompilation.
70
- Script_magic = 4
61
+ Script_magic = 5
71
62
  _log_complaint = (
72
63
  'Some of your Scripts have stale code cached. Since Zope cannot'
73
64
  ' use this code, startup will be slightly slower until these Scripts'
@@ -103,11 +94,22 @@ def manage_addPythonScript(self, id, title='', file=None, REQUEST=None,
103
94
  except Exception:
104
95
  u = REQUEST['URL1']
105
96
  if submit == 'Add and Edit':
106
- u = '%s/%s' % (u, quote(id))
97
+ u = f'{u}/{quote(id)}'
107
98
  REQUEST.RESPONSE.redirect(u + '/manage_main')
108
99
  return ''
109
100
 
110
101
 
102
+ class PythonScriptLoader(importlib.abc.Loader):
103
+ """PEP302 loader to display source code in tracebacks
104
+ """
105
+
106
+ def __init__(self, source):
107
+ self._source = source
108
+
109
+ def get_source(self, name):
110
+ return self._source
111
+
112
+
111
113
  class PythonScript(Script, Historical, Cacheable):
112
114
  """Web-callable scripts written in a safe subset of Python.
113
115
 
@@ -190,12 +192,12 @@ class PythonScript(Script, Historical, Cacheable):
190
192
  if self.wl_isLocked():
191
193
  raise ResourceLockedError('The script is locked via WebDAV.')
192
194
 
195
+ if not file:
196
+ return self.ZPythonScriptHTML_editForm(
197
+ self, REQUEST,
198
+ manage_tabs_message='No file specified',
199
+ manage_tabs_type='warning')
193
200
  if not isinstance(file, str):
194
- if not file:
195
- return self.ZPythonScriptHTML_editForm(
196
- self, REQUEST,
197
- manage_tabs_message='No file specified',
198
- manage_tabs_type='warning')
199
201
  file = file.read()
200
202
 
201
203
  self.write(file)
@@ -245,7 +247,7 @@ class PythonScript(Script, Historical, Cacheable):
245
247
  self._params,
246
248
  body=self._body or 'pass',
247
249
  name=self.id,
248
- filename=self.meta_type,
250
+ filename=getattr(self, '_filepath', None) or self.get_filepath(),
249
251
  globalize=bind_names)
250
252
 
251
253
  code = compile_result.code
@@ -272,6 +274,7 @@ class PythonScript(Script, Historical, Cacheable):
272
274
  fc.co_argcount)
273
275
  self.Python_magic = Python_magic
274
276
  self.Script_magic = Script_magic
277
+ linecache.clearcache()
275
278
  self._v_change = 0
276
279
 
277
280
  def _newfun(self, code):
@@ -288,7 +291,7 @@ class PythonScript(Script, Historical, Cacheable):
288
291
  safe_globals['__name__'] = 'script'
289
292
 
290
293
  safe_locals = {}
291
- six.exec_(code, safe_globals, safe_locals)
294
+ exec(code, safe_globals, safe_locals)
292
295
  func = list(safe_locals.values())[0]
293
296
  self._v_ft = (func.__code__, safe_globals, func.__defaults__ or ())
294
297
  return func
@@ -332,7 +335,7 @@ class PythonScript(Script, Historical, Cacheable):
332
335
  if ft is None:
333
336
  __traceback_supplement__ = (
334
337
  PythonScriptTracebackSupplement, self)
335
- raise RuntimeError('%s %s has errors.' % (self.meta_type, self.id))
338
+ raise RuntimeError(f'{self.meta_type} {self.id} has errors.')
336
339
 
337
340
  function_code, safe_globals, function_argument_definitions = ft
338
341
  safe_globals = safe_globals.copy()
@@ -342,6 +345,8 @@ class PythonScript(Script, Historical, Cacheable):
342
345
  PythonScriptTracebackSupplement, self, -1)
343
346
  safe_globals['__file__'] = getattr(
344
347
  self, '_filepath', None) or self.get_filepath()
348
+ safe_globals['__loader__'] = PythonScriptLoader(self._body)
349
+
345
350
  function = types.FunctionType(
346
351
  function_code, safe_globals, None, function_argument_definitions)
347
352
 
@@ -433,10 +438,8 @@ class PythonScript(Script, Historical, Cacheable):
433
438
  bindmap = self.getBindingAssignments().getAssignedNames()
434
439
  bup = 0
435
440
 
436
- if six.PY3 and isinstance(text, bytes):
441
+ if isinstance(text, bytes):
437
442
  text = text.decode(default_encoding)
438
- elif six.PY2 and not isinstance(text, bytes):
439
- text = text.encode(default_encoding)
440
443
 
441
444
  st = 0
442
445
  try:
@@ -520,7 +523,7 @@ class PythonScript(Script, Historical, Cacheable):
520
523
  else:
521
524
  prefix = '##'
522
525
 
523
- hlines = ['%s %s "%s"' % (prefix, self.meta_type, self.id)]
526
+ hlines = [f'{prefix} {self.meta_type} "{self.id}"']
524
527
  mm = sorted(self._metadata_map().items())
525
528
  for kv in mm:
526
529
  hlines.append('%s=%s' % kv)
@@ -553,7 +556,7 @@ class PythonScript(Script, Historical, Cacheable):
553
556
  @security.protected(view_management_screens)
554
557
  def PrincipiaSearchSource(self):
555
558
  """Support for searching - the document's contents are searched."""
556
- return '%s\n%s' % (self._params, self._body)
559
+ return f'{self._params}\n{self._body}'
557
560
 
558
561
  @security.protected(view_management_screens)
559
562
  def document_src(self, REQUEST=None, RESPONSE=None):
@@ -569,6 +572,7 @@ InitializeClass(PythonScript)
569
572
 
570
573
  class PythonScriptTracebackSupplement:
571
574
  """Implementation of ITracebackSupplement"""
575
+
572
576
  def __init__(self, script, line=0):
573
577
  self.object = script
574
578
  # If line is set to -1, it means to use tb_lineno.
@@ -18,7 +18,7 @@ Scripts. It can be accessed from Python with the statement
18
18
  "import Products.PythonScripts.standard"
19
19
  """
20
20
 
21
- from six.moves.urllib.parse import urlencode # NOQA
21
+ from urllib.parse import urlencode # NOQA
22
22
 
23
23
  from AccessControl.SecurityInfo import ModuleSecurityInfo
24
24
  from AccessControl.SecurityManagement import getSecurityManager
@@ -21,7 +21,7 @@ from OFS.Folder import Folder
21
21
  from OFS.ObjectManager import ObjectManager
22
22
 
23
23
 
24
- class UnderprivilegedUser(object):
24
+ class UnderprivilegedUser:
25
25
 
26
26
  def getId(self):
27
27
  return 'underprivileged'
@@ -14,13 +14,11 @@ import codecs
14
14
  import contextlib
15
15
  import io
16
16
  import os
17
- import pickle
18
17
  import sys
18
+ import traceback
19
19
  import unittest
20
20
  import warnings
21
-
22
- import six
23
- from six.moves.urllib.error import HTTPError
21
+ from urllib.error import HTTPError
24
22
 
25
23
  import zExceptions
26
24
  import Zope2
@@ -41,7 +39,7 @@ HERE = os.path.dirname(__file__)
41
39
  @contextlib.contextmanager
42
40
  def warning_interceptor():
43
41
  old_stderr = sys.stderr
44
- sys.stderr = stream = six.StringIO()
42
+ sys.stderr = stream = io.StringIO()
45
43
  try:
46
44
  yield stream
47
45
  finally:
@@ -53,7 +51,7 @@ def warning_interceptor():
53
51
 
54
52
  def readf(name):
55
53
  path = os.path.join(HERE, 'tscripts', '%s.ps' % name)
56
- with open(path, 'r') as f:
54
+ with open(path) as f:
57
55
  return f.read()
58
56
 
59
57
 
@@ -137,7 +135,7 @@ class TestPythonScriptNoAq(PythonScriptTestBase):
137
135
  import string
138
136
  params = string.ascii_letters[:26]
139
137
  sparams = ','.join(params)
140
- ps = self._newPS('##parameters=%s\nreturn %s' % (sparams, sparams))
138
+ ps = self._newPS(f'##parameters={sparams}\nreturn {sparams}')
141
139
  res = ps(*params)
142
140
  self.assertEqual(res, tuple(params))
143
141
 
@@ -203,8 +201,7 @@ class TestPythonScriptNoAq(PythonScriptTestBase):
203
201
  self.assertEqual(res, 'a\n')
204
202
 
205
203
  def testComplexPrint(self):
206
- script = 'complex_print_py%s' % sys.version_info.major
207
- res = self._filePS(script)()
204
+ res = self._filePS('complex_print')()
208
205
  self.assertEqual(res, 'double\ndouble\nx: 1\ny: 0 1 2\n\n')
209
206
 
210
207
  def testNSBind(self):
@@ -220,19 +217,13 @@ class TestPythonScriptNoAq(PythonScriptTestBase):
220
217
  self.assertTrue(res)
221
218
 
222
219
  def testGetSize(self):
223
- script = 'complex_print_py%s' % sys.version_info.major
224
- f = self._filePS(script)
220
+ f = self._filePS('complex_print')
225
221
  self.assertEqual(f.get_size(), len(f.read()))
226
222
 
227
223
  def testBuiltinSet(self):
228
224
  res = self._newPS('return len(set([1, 2, 3, 1]))')()
229
225
  self.assertEqual(res, 3)
230
226
 
231
- @unittest.skipIf(six.PY3, 'sets module does not exist in python3')
232
- def testSetModule(self):
233
- res = self._newPS('from sets import Set; return len(Set([1,2,3]))')()
234
- self.assertEqual(res, 3)
235
-
236
227
  def testDateTime(self):
237
228
  res = self._newPS(
238
229
  "return DateTime('2007/12/10').strftime('%d.%m.%Y')")()
@@ -251,11 +242,12 @@ class TestPythonScriptNoAq(PythonScriptTestBase):
251
242
  self.assertEqual(ps.read(), ps.manage_DAVget())
252
243
 
253
244
  def test_PUT_native_string(self):
254
- ps = makerequest(self._filePS('complete'))
245
+ container = DummyFolder('container')
246
+ ps = makerequest(self._filePS('complete').__of__(container))
255
247
  self.assertEqual(ps.title, 'This is a title')
256
248
  self.assertEqual(ps.body(), 'print(foo+bar+baz)\nreturn printed\n')
257
249
  self.assertEqual(ps.params(), 'foo, bar, baz=1')
258
- new_body = u"""\
250
+ new_body = """\
259
251
  ## Script (Python) "complete"
260
252
  ##bind container=container
261
253
  ##bind context=context
@@ -271,16 +263,12 @@ return \xe4\xe9\xee\xf6\xfc
271
263
  ps._filepath = 'fake'
272
264
  ps.PUT(ps.REQUEST, ps.REQUEST.RESPONSE)
273
265
  self.assertEqual(ps.title, 'New Title')
274
- if six.PY3:
275
- self.assertEqual(ps.body(), 'return \xe4\xe9\xee\xf6\xfc\n')
276
- else:
277
- self.assertEqual(
278
- ps.body(),
279
- 'return \xc3\xa4\xc3\xa9\xc3\xae\xc3\xb6\xc3\xbc\n')
266
+ self.assertEqual(ps.body(), 'return \xe4\xe9\xee\xf6\xfc\n')
280
267
  self.assertEqual(ps.params(), 'oops')
281
268
 
282
269
  def test_PUT_bytes(self):
283
- ps = makerequest(self._filePS('complete'))
270
+ container = DummyFolder('container')
271
+ ps = makerequest(self._filePS('complete').__of__(container))
284
272
  self.assertEqual(ps.title, 'This is a title')
285
273
  self.assertEqual(ps.body(), 'print(foo+bar+baz)\nreturn printed\n')
286
274
  self.assertEqual(ps.params(), 'foo, bar, baz=1')
@@ -300,12 +288,7 @@ return \xc3\xa4\xc3\xa9\xc3\xae\xc3\xb6\xc3\xbc
300
288
  ps._filepath = 'fake'
301
289
  ps.PUT(ps.REQUEST, ps.REQUEST.RESPONSE)
302
290
  self.assertEqual(ps.title, 'New Title')
303
- if six.PY3:
304
- self.assertEqual(ps.body(), 'return \xe4\xe9\xee\xf6\xfc\n')
305
- else:
306
- self.assertEqual(
307
- ps.body(),
308
- 'return \xc3\xa4\xc3\xa9\xc3\xae\xc3\xb6\xc3\xbc\n')
291
+ self.assertEqual(ps.body(), 'return \xe4\xe9\xee\xf6\xfc\n')
309
292
  self.assertEqual(ps.params(), 'oops')
310
293
 
311
294
  def test_write(self):
@@ -314,7 +297,7 @@ return \xc3\xa4\xc3\xa9\xc3\xae\xc3\xb6\xc3\xbc
314
297
  ps.write(b'return 1')
315
298
  self.assertEqual(ps.body(), 'return 1\n')
316
299
 
317
- ps.write(u'return 1')
300
+ ps.write('return 1')
318
301
  self.assertEqual(ps.body(), 'return 1\n')
319
302
 
320
303
  def test_factory(self):
@@ -391,15 +374,7 @@ return \xc3\xa4\xc3\xa9\xc3\xae\xc3\xb6\xc3\xbc
391
374
  self.assertEqual(
392
375
  script.__code__.co_varnames,
393
376
  ('a',))
394
- if six.PY2:
395
- self.assertEqual(script.func_code.co_argcount, 1)
396
- self.assertEqual(
397
- script.func_code.co_varnames,
398
- ('a',))
399
-
400
377
  self.assertEqual(script.__defaults__, ('b',))
401
- if six.PY2:
402
- self.assertEqual(script.func_defaults, ('b',))
403
378
 
404
379
 
405
380
  class TestPythonScriptErrors(PythonScriptTestBase):
@@ -479,10 +454,7 @@ class TestPythonScriptGlobals(PythonScriptTestBase):
479
454
 
480
455
  def test__name__(self):
481
456
  f = self._filePS('class.__name__')
482
- if six.PY3:
483
- class_name = "'script.class.__name__.<locals>.foo'>"
484
- else:
485
- class_name = "'script.foo'>"
457
+ class_name = "'script.class.__name__.<locals>.foo'>"
486
458
 
487
459
  self.assertEqual(f(), (class_name, "'string'"))
488
460
 
@@ -504,11 +476,8 @@ class TestPythonScriptGlobals(PythonScriptTestBase):
504
476
  class PythonScriptInterfaceConformanceTests(unittest.TestCase):
505
477
 
506
478
  def test_class_conforms_to_IWriteLock(self):
479
+ from OFS.interfaces import IWriteLock
507
480
  from zope.interface.verify import verifyClass
508
- try:
509
- from OFS.interfaces import IWriteLock
510
- except ImportError:
511
- from webdav.interfaces import IWriteLock
512
481
  verifyClass(IWriteLock, PythonScript)
513
482
 
514
483
 
@@ -517,7 +486,7 @@ class PythonScriptBrowserTests(FunctionalTestCase):
517
486
 
518
487
  def setUp(self):
519
488
  from Products.PythonScripts.PythonScript import manage_addPythonScript
520
- super(PythonScriptBrowserTests, self).setUp()
489
+ super().setUp()
521
490
 
522
491
  Zope2.App.zcml.load_site(force=True)
523
492
 
@@ -526,10 +495,8 @@ class PythonScriptBrowserTests(FunctionalTestCase):
526
495
  manage_addPythonScript(self.app, 'py_script')
527
496
 
528
497
  self.browser = Browser()
529
- self.browser.addHeader(
530
- 'Authorization',
531
- 'basic {}'.format(codecs.encode( # noqa: P101
532
- b'manager:manager_pass', 'base64').decode()))
498
+ pw = codecs.encode(b'manager:manager_pass', 'base64').decode()
499
+ self.browser.addHeader('Authorization', f'basic {pw}')
533
500
  self.browser.open('http://localhost/py_script/manage_main')
534
501
 
535
502
  def test_ZPythonScriptHTML_upload__no_file(self):
@@ -626,47 +593,44 @@ class PythonScriptBrowserTests(FunctionalTestCase):
626
593
  noSecurityManager()
627
594
 
628
595
 
629
- class PythonScriptPickle(unittest.TestCase):
596
+ class TestTraceback(FunctionalTestCase, PythonScriptTestBase):
630
597
 
631
- @unittest.skipIf(
632
- six.PY3,
633
- 'Pickles from python2 can not be loaded on python3')
634
- def test_load_old_zope_2_pickle_recompiles(self):
635
- with open(os.path.join(HERE, 'tscripts', 'ps_2.13.2.pkl'), 'rb') as f:
636
- script = pickle.load(f)
637
- self.assertIsInstance(script, PythonScript)
598
+ def _format_exception(self):
599
+ return "".join(traceback.format_exception(*sys.exc_info()))
638
600
 
639
- self.assertEqual(
640
- script.document_src(),
641
- '## Script (Python) "test"\n'
642
- '##bind container=container\n'
643
- '##bind context=context\n'
644
- '##bind namespace=\n'
645
- '##bind script=script\n'
646
- '##bind subpath=traverse_subpath\n'
647
- '##parameters=Products_PythonScripts_version=\'2.13.2\'\n'
648
- '##title=\n'
649
- '##\n'
650
- 'return """This is an old script created with\n'
651
- 'Products.PythonScripts version %s\n'
652
- 'and Zope version 2.13.30 (on python 2.7)\n'
653
- '""" % Products_PythonScripts_version\n')
601
+ def test_source_code_in_traceback(self):
602
+ ps = self._newPS("1 / 0")
603
+ try:
604
+ ps()
605
+ except ZeroDivisionError:
606
+ formatted_exception = self._format_exception()
607
+ self.assertIn("1 / 0", formatted_exception)
654
608
 
655
- self.assertEqual(script.__code__.co_argcount, 1)
656
- self.assertEqual(
657
- script.__code__.co_varnames,
658
- ('Products_PythonScripts_version',))
659
- self.assertEqual(script.func_code.co_argcount, 1)
660
- self.assertEqual(
661
- script.func_code.co_varnames,
662
- ('Products_PythonScripts_version',))
663
- self.assertEqual(script.__defaults__, ('2.13.2',))
664
- self.assertEqual(script.func_defaults, ('2.13.2',))
609
+ ps.write("2 / 0")
610
+ try:
611
+ ps()
612
+ except ZeroDivisionError:
613
+ formatted_exception = self._format_exception()
614
+ self.assertIn("2 / 0", formatted_exception)
665
615
 
666
- container = makerequest(DummyFolder('container'))
667
- container.REQUEST.form = {}
668
- self.assertEqual(
669
- script.__of__(container)(),
670
- 'This is an old script created with\n'
671
- 'Products.PythonScripts version 2.13.2\n'
672
- 'and Zope version 2.13.30 (on python 2.7)\n')
616
+ def test_multiple_scripts_in_traceback(self):
617
+ from Products.PythonScripts.PythonScript import manage_addPythonScript
618
+
619
+ script1_body = "container.script2()"
620
+ manage_addPythonScript(
621
+ self.folder,
622
+ "script1",
623
+ file=script1_body,
624
+ )
625
+ script2_body = "1 / 0"
626
+ manage_addPythonScript(
627
+ self.folder,
628
+ "script2",
629
+ file=script2_body,
630
+ )
631
+ try:
632
+ self.folder.script1()
633
+ except ZeroDivisionError:
634
+ formatted_exception = self._format_exception()
635
+ self.assertIn(script1_body, formatted_exception)
636
+ self.assertIn(script2_body, formatted_exception)
@@ -16,7 +16,7 @@
16
16
  <div class="form-group row ">
17
17
  <label for="params" class="form-label col-sm-3 col-md-2">Parameter List</label>
18
18
  <div class="col-sm-9 col-md-10">
19
- <input id="params" class="form-control" type="text" name="params" value="&dtml-params;" />
19
+ <input id="params" class="form-control code" type="text" name="params" value="&dtml-params;" />
20
20
  </div>
21
21
  </div>
22
22
  </dtml-with>
@@ -1,34 +1,38 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Products.PythonScripts
3
- Version: 4.15
3
+ Version: 5.1
4
4
  Summary: Provides support for restricted execution of Python scripts in Zope.
5
5
  Home-page: https://github.com/zopefoundation/Products.PythonScripts
6
6
  Author: Zope Foundation and Contributors
7
- Author-email: zope-dev@zope.org
7
+ Author-email: zope-dev@zope.dev
8
8
  License: ZPL 2.1
9
9
  Project-URL: Issue Tracker, https://github.com/zopefoundation/Products.PythonScripts/issues
10
10
  Project-URL: Sources, https://github.com/zopefoundation/Products.PythonScripts
11
11
  Classifier: Development Status :: 6 - Mature
12
12
  Classifier: Environment :: Web Environment
13
13
  Classifier: Framework :: Zope
14
- Classifier: Framework :: Zope :: 4
15
14
  Classifier: Framework :: Zope :: 5
16
15
  Classifier: License :: OSI Approved :: Zope Public License
17
16
  Classifier: Operating System :: OS Independent
18
17
  Classifier: Programming Language :: Python
19
- Classifier: Programming Language :: Python :: 2
20
- Classifier: Programming Language :: Python :: 2.7
21
18
  Classifier: Programming Language :: Python :: 3
22
- Classifier: Programming Language :: Python :: 3.5
23
- Classifier: Programming Language :: Python :: 3.6
24
- Classifier: Programming Language :: Python :: 3.7
25
19
  Classifier: Programming Language :: Python :: 3.8
26
20
  Classifier: Programming Language :: Python :: 3.9
27
21
  Classifier: Programming Language :: Python :: 3.10
28
22
  Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
29
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
30
- Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*
26
+ Requires-Python: >=3.8
31
27
  License-File: LICENSE.txt
28
+ Requires-Dist: setuptools
29
+ Requires-Dist: AccessControl
30
+ Requires-Dist: Acquisition
31
+ Requires-Dist: DateTime
32
+ Requires-Dist: DocumentTemplate
33
+ Requires-Dist: RestrictedPython>=4.0b5
34
+ Requires-Dist: zExceptions
35
+ Requires-Dist: Zope>=4.1.2
32
36
 
33
37
  .. image:: https://github.com/zopefoundation/Products.PythonScripts/actions/workflows/tests.yml/badge.svg
34
38
  :target: https://github.com/zopefoundation/Products.PythonScripts/actions/workflows/tests.yml
@@ -122,6 +126,25 @@ in the Products directory.
122
126
  Changelog
123
127
  =========
124
128
 
129
+ 5.1 (2024-10-16)
130
+ ----------------
131
+
132
+ - Fix behavior when uploading no file in ``Zope >= 5.8.1``.
133
+
134
+ - Add support for Python 3.12 and 3.13
135
+
136
+ - Drop support for Python 3.7.
137
+
138
+ - Show Python Scripts source code in tracebacks.
139
+ `#64 <https://github.com/zopefoundation/Products.PythonScripts/issues/64>`_
140
+
141
+
142
+ 5.0 (2023-02-01)
143
+ ----------------
144
+
145
+ - Drop support for Python 2.7, 3.5, 3.6.
146
+
147
+
125
148
  4.15 (2022-12-16)
126
149
  -----------------
127
150
 
@@ -1,3 +1,4 @@
1
+ .pre-commit-config.yaml
1
2
  CHANGES.rst
2
3
  CONTRIBUTING.md
3
4
  COPYRIGHT.txt
@@ -5,7 +6,7 @@ LICENSE.txt
5
6
  MANIFEST.in
6
7
  README.rst
7
8
  buildout.cfg
8
- buildout4.cfg
9
+ pyproject.toml
9
10
  setup.cfg
10
11
  setup.py
11
12
  tox.ini
@@ -31,8 +32,7 @@ src/Products/PythonScripts/tests/tscripts/big_boolean.ps
31
32
  src/Products/PythonScripts/tests/tscripts/boolean_map.ps
32
33
  src/Products/PythonScripts/tests/tscripts/class.__name__.ps
33
34
  src/Products/PythonScripts/tests/tscripts/complete.ps
34
- src/Products/PythonScripts/tests/tscripts/complex_print_py2.ps
35
- src/Products/PythonScripts/tests/tscripts/complex_print_py3.ps
35
+ src/Products/PythonScripts/tests/tscripts/complex_print.ps
36
36
  src/Products/PythonScripts/tests/tscripts/fibonacci.ps
37
37
  src/Products/PythonScripts/tests/tscripts/filepath.ps
38
38
  src/Products/PythonScripts/tests/tscripts/for_loop.ps
@@ -40,7 +40,6 @@ src/Products/PythonScripts/tests/tscripts/global_is_declaration.ps
40
40
  src/Products/PythonScripts/tests/tscripts/mutate_literals.ps
41
41
  src/Products/PythonScripts/tests/tscripts/ns_bind.ps
42
42
  src/Products/PythonScripts/tests/tscripts/ns_bind_invalid.ps
43
- src/Products/PythonScripts/tests/tscripts/ps_2.13.2.pkl
44
43
  src/Products/PythonScripts/tests/tscripts/simple_print.ps
45
44
  src/Products/PythonScripts/tests/tscripts/subversive_except.ps
46
45
  src/Products/PythonScripts/tests/tscripts/try_except.ps
@@ -0,0 +1,77 @@
1
+ # Generated from:
2
+ # https://github.com/zopefoundation/meta/tree/master/config/zope-product
3
+ [tox]
4
+ minversion = 3.18
5
+ envlist =
6
+ release-check
7
+ lint
8
+ py38
9
+ py39
10
+ py310
11
+ py311
12
+ py312
13
+ py313
14
+ coverage
15
+
16
+ [testenv]
17
+ skip_install = true
18
+ deps =
19
+ setuptools < 74
20
+ zc.buildout >= 3.1
21
+ wheel > 0.37
22
+ setenv =
23
+ commands_pre =
24
+ {envbindir}/buildout -nc {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test
25
+ commands =
26
+ {envbindir}/test {posargs:-cv}
27
+
28
+ [testenv:setuptools-latest]
29
+ basepython = python3
30
+ deps =
31
+ git+https://github.com/pypa/setuptools.git\#egg=setuptools
32
+ zc.buildout >= 3.1
33
+ wheel > 0.37
34
+
35
+
36
+ [testenv:release-check]
37
+ description = ensure that the distribution is ready to release
38
+ basepython = python3
39
+ skip_install = true
40
+ deps =
41
+ setuptools < 74
42
+ twine
43
+ build
44
+ check-manifest
45
+ check-python-versions >= 0.20.0
46
+ wheel
47
+ commands_pre =
48
+ commands =
49
+ check-manifest
50
+ check-python-versions --only setup.py,tox.ini,.github/workflows/tests.yml
51
+ python -m build --sdist --no-isolation
52
+ twine check dist/*
53
+
54
+ [testenv:lint]
55
+ description = This env runs all linters configured in .pre-commit-config.yaml
56
+ basepython = python3
57
+ skip_install = true
58
+ deps =
59
+ pre-commit
60
+ commands_pre =
61
+ commands =
62
+ pre-commit run --all-files --show-diff-on-failure
63
+
64
+ [testenv:coverage]
65
+ basepython = python3
66
+ skip_install = true
67
+ allowlist_externals =
68
+ {[testenv]allowlist_externals}
69
+ mkdir
70
+ deps =
71
+ {[testenv]deps}
72
+ coverage[toml]
73
+ commands =
74
+ mkdir -p {toxinidir}/parts/htmlcov
75
+ coverage run {envbindir}/test {posargs:-cv}
76
+ coverage html
77
+ coverage report
@@ -1,7 +0,0 @@
1
- [buildout]
2
- extends =
3
- buildout.cfg
4
- http://zopefoundation.github.io/Zope/releases/4.x/versions.cfg
5
-
6
- [versions]
7
- Products.PythonScripts =
@@ -1,9 +0,0 @@
1
- x = {'x': 1}
2
- y = range(3)
3
-
4
- print 'double'
5
- print printed,
6
- print 'x:', x['x']
7
- print 'y:', y[0], y[1], y[2]
8
- print
9
- return printed
@@ -1,90 +0,0 @@
1
- # Generated from:
2
- # https://github.com/zopefoundation/meta/tree/master/config/zope-product
3
- [tox]
4
- minversion = 3.18
5
- envlist =
6
- lint
7
- py27
8
- py35
9
- py36
10
- py37
11
- py38
12
- py39
13
- py310
14
- py311
15
- coverage
16
-
17
- [testenv]
18
- skip_install = true
19
- deps =
20
- zc.buildout >= 3.0.1
21
- wheel > 0.37
22
- commands_pre =
23
- py27,py35: {envbindir}/buildout -nc {toxinidir}/buildout4.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test
24
- !py27-!py35: {envbindir}/buildout -nc {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test
25
- commands =
26
- {envdir}/bin/test {posargs:-cv}
27
-
28
- [testenv:lint]
29
- basepython = python3
30
- commands_pre =
31
- mkdir -p {toxinidir}/parts/flake8
32
- allowlist_externals =
33
- mkdir
34
- commands =
35
- isort --check-only --diff {toxinidir}/src {toxinidir}/setup.py
36
- - flake8 {toxinidir}/src {toxinidir}/setup.py
37
- flake8 {toxinidir}/src {toxinidir}/setup.py
38
- check-manifest
39
- check-python-versions
40
- deps =
41
- check-manifest
42
- check-python-versions
43
- flake8
44
- isort
45
- # Useful flake8 plugins that are Python and Plone specific:
46
- flake8-coding
47
- flake8-debugger
48
- mccabe
49
-
50
- [testenv:isort-apply]
51
- basepython = python3
52
- commands_pre =
53
- deps =
54
- isort
55
- commands =
56
- isort {toxinidir}/src {toxinidir}/setup.py []
57
-
58
- [testenv:coverage]
59
- basepython = python3
60
- skip_install = true
61
- allowlist_externals =
62
- mkdir
63
- deps =
64
- {[testenv]deps}
65
- coverage
66
- coverage-python-version
67
- commands =
68
- mkdir -p {toxinidir}/parts/htmlcov
69
- coverage run {envdir}/bin/test {posargs:-cv}
70
- coverage html
71
- coverage report -m --fail-under=83
72
-
73
- [coverage:run]
74
- branch = True
75
- plugins = coverage_python_version
76
- source = Products.PythonScripts
77
-
78
- [coverage:report]
79
- precision = 2
80
- exclude_lines =
81
- pragma: no cover
82
- pragma: nocover
83
- except ImportError:
84
- raise NotImplementedError
85
- if __name__ == '__main__':
86
- self.fail
87
- raise AssertionError
88
-
89
- [coverage:html]
90
- directory = parts/htmlcov