Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
138
Merge Requests
138
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
erp5
Commits
a0e79027
Commit
a0e79027
authored
Jun 10, 2020
by
Bryton Lacquement
🚪
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Monkey-patch to apply my2to3 fixers
parent
7eed3ba6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
0 deletions
+155
-0
product/ERP5Type/Base.py
product/ERP5Type/Base.py
+24
-0
product/ERP5Type/ZopePatch.py
product/ERP5Type/ZopePatch.py
+1
-0
product/ERP5Type/patches/my2to3_patch.py
product/ERP5Type/patches/my2to3_patch.py
+130
-0
No files found.
product/ERP5Type/Base.py
View file @
a0e79027
...
...
@@ -32,6 +32,8 @@ from copy import copy
import
warnings
import
types
import
thread
,
threading
import
os
from
lib2to3.pgen2.parse
import
ParseError
from
BTrees.OOBTree
import
OOBTree
from
Products.ERP5Type.Globals
import
InitializeClass
,
DTMLFile
...
...
@@ -42,6 +44,7 @@ from AccessControl.SecurityManagement import getSecurityManager
from
AccessControl.ZopeGuards
import
guarded_getattr
from
Acquisition
import
aq_base
,
aq_inner
,
aq_acquire
,
aq_chain
from
DateTime
import
DateTime
from
my2to3.trace
import
apply_fixers
import
OFS.History
from
OFS.SimpleItem
import
SimpleItem
from
OFS.PropertyManager
import
PropertyManager
...
...
@@ -855,6 +858,27 @@ class Base(
self
.
uid
=
uid
# Else it will be generated when we need it
self
.
sid
=
sid
def
__setstate__
(
self
,
state
):
if
os
.
environ
.
get
(
"MY2TO3_ACTION"
)
==
"trace"
and
\
self
.
getPortalType
()
in
[
"Document Component"
,
"Extension Component"
,
"Interface Component"
,
"Mixin Component"
,
"Module Component"
,
"Test Component"
,
"Tool Component"
,
]:
# See Products.ERP5Type.patches.my2to3_patch
# Apply "trace" fixers on the fly
# Note: The modifications are not saved (unless it is done explicitly,
# e.g. the user saves manually).
text_content
=
state
.
get
(
'text_content'
)
if
text_content
:
try
:
state
[
'text_content'
]
=
apply_fixers
(
text_content
,
state
[
'id'
])
except
ParseError
:
# text_content is not valid code
pass
super
(
Base
,
self
).
__setstate__
(
state
)
# XXX This is necessary to override getId which is also defined in SimpleItem.
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getId'
)
getId
=
BaseAccessor
.
Getter
(
'getId'
,
'id'
,
'string'
)
...
...
product/ERP5Type/ZopePatch.py
View file @
a0e79027
...
...
@@ -21,6 +21,7 @@
##############################################################################
# Load all monkey patches
from
Products.ERP5Type.patches
import
my2to3_patch
from
Products.ERP5Type.patches
import
WSGIPublisher
from
Products.ERP5Type.patches
import
HTTPRequest
from
Products.ERP5Type.patches
import
AccessControl_patch
...
...
product/ERP5Type/patches/my2to3_patch.py
0 → 100644
View file @
a0e79027
import
new
,
os
from
Acquisition
import
aq_parent
from
my2to3.trace
import
apply_fixers
,
patch_imports
,
tracing_functions
from
Products.PageTemplates.ZRPythonExpr
import
PythonExpr
from
Products.PythonScripts.PythonScript
import
_marker
,
PythonScript
,
PythonScriptTracebackSupplement
from
RestrictedPython
import
compile_restricted_eval
from
.
import
PatchClass
erp5_products_path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'..'
,
'..'
)
erp5_products
=
[
'Products.'
+
p
for
p
in
os
.
listdir
(
erp5_products_path
)
if
os
.
path
.
isdir
(
os
.
path
.
join
(
erp5_products_path
,
p
))]
# Apply "trace" fixers on the fly
if
os
.
environ
.
get
(
"MY2TO3_ACTION"
)
==
"trace"
:
def
is_whitelisted
(
fullname
,
path
):
return
any
(
fullname
.
startswith
(
p
)
for
p
in
erp5_products
)
# Apply "trace" fixers on the fly, when importing modules
patch_imports
(
is_whitelisted
)
# Apply "trace" fixers on the fly, on PythonScript bodies
# Note: The modifications are not saved (unless it is done explicitly, e.g.
# the user saves manually).
class
_
(
PatchClass
(
PythonScript
)):
___setstate__
=
PythonScript
.
__setstate__
def
__setstate__
(
self
,
state
):
self
.
___setstate__
(
state
)
if
'_body'
in
state
:
# Note that self.___setstate__ is called unconditionally a first time,
# before. The reason is:
# We need the file path (i.e. self.get_filepath()). This information
# is contained in state['_filepath'], but it is not always the case.
# Calling ___setstate__ before makes this information available.
new_body
=
apply_fixers
(
state
[
'_body'
],
self
.
get_filepath
())
if
new_body
!=
state
[
'_body'
]:
state
[
'_body'
]
=
new_body
# This time, it's called to update the body.
self
.
___setstate__
(
state
)
self
.
_compile
()
# Add new "builtins" which the script can access
def
_exec
(
self
,
bound_names
,
args
,
kw
):
"""Call a Python Script
Calling a Python Script is an actual function invocation.
"""
# Retrieve the value from the cache.
keyset
=
None
if
self
.
ZCacheable_isCachingEnabled
():
# Prepare a cache key.
keyset
=
kw
.
copy
()
asgns
=
self
.
getBindingAssignments
()
name_context
=
asgns
.
getAssignedName
(
'name_context'
,
None
)
if
name_context
:
keyset
[
name_context
]
=
aq_parent
(
self
).
getPhysicalPath
()
name_subpath
=
asgns
.
getAssignedName
(
'name_subpath'
,
None
)
if
name_subpath
:
keyset
[
name_subpath
]
=
self
.
_getTraverseSubpath
()
# Note: perhaps we should cache based on name_ns also.
keyset
[
'*'
]
=
args
result
=
self
.
ZCacheable_get
(
keywords
=
keyset
,
default
=
_marker
)
if
result
is
not
_marker
:
# Got a cached value.
return
result
#__traceback_info__ = bound_names, args, kw, self.func_defaults
ft
=
self
.
_v_ft
if
ft
is
None
:
__traceback_supplement__
=
(
PythonScriptTracebackSupplement
,
self
)
raise
RuntimeError
,
'%s %s has errors.'
%
(
self
.
meta_type
,
self
.
id
)
fcode
,
g
,
fadefs
=
ft
g
=
g
.
copy
()
if
bound_names
is
not
None
:
g
.
update
(
bound_names
)
g
[
'__traceback_supplement__'
]
=
(
PythonScriptTracebackSupplement
,
self
,
-
1
)
g
[
'__file__'
]
=
getattr
(
self
,
'_filepath'
,
None
)
or
self
.
get_filepath
()
# <patch>
g
.
update
({
f
.
__name__
:
f
for
f
in
tracing_functions
})
# </patch>
f
=
new
.
function
(
fcode
,
g
,
None
,
fadefs
)
try
:
result
=
f
(
*
args
,
**
kw
)
except
SystemExit
:
raise
ValueError
(
'SystemExit cannot be raised within a PythonScript'
)
if
keyset
is
not
None
:
# Store the result in the cache.
self
.
ZCacheable_set
(
result
,
keywords
=
keyset
)
return
result
# Apply "trace" fixers on the fly, on TALES PythonExpr
class
__
(
PatchClass
(
PythonExpr
)):
def
__init__
(
self
,
name
,
expr
,
engine
):
self
.
text
=
self
.
expr
=
text
=
expr
.
strip
().
replace
(
'
\
n
'
,
' '
)
# Unicode expression are not handled properly by RestrictedPython
# We convert the expression to UTF-8 (ajung)
if
isinstance
(
text
,
unicode
):
text
=
text
.
encode
(
'utf-8'
)
code
,
err
,
warn
,
use
=
compile_restricted_eval
(
text
,
self
.
__class__
.
__name__
)
if
err
:
raise
engine
.
getCompilerError
()(
'Python expression error:
\
n
%s'
%
'
\
n
'
.
join
(
err
))
# <patch>
# `compile_restricted_eval` is called a first time before (the original
# code), mainly to handle errors related to the content of `text`. If it
# succeeds, we know that `text` contains valid code, on which we can
# safely apply fixers.
# XXX: "'PythonExpr:' + text" is used as the name for now. Let's try to
# find something better.
code
,
err
,
warn
,
use
=
compile_restricted_eval
(
apply_fixers
(
text
,
'PythonExpr:'
+
text
),
self
.
__class__
.
__name__
)
# </patch>
self
.
_varnames
=
use
.
keys
()
self
.
_code
=
code
# Add new "builtins" which the script can access
PythonExpr
.
_globals
.
update
({
f
.
__name__
:
f
for
f
in
tracing_functions
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment