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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
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
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Titouan Soulard
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
...
@@ -32,6 +32,8 @@ from copy import copy
import
warnings
import
warnings
import
types
import
types
import
thread
,
threading
import
thread
,
threading
import
os
from
lib2to3.pgen2.parse
import
ParseError
from
BTrees.OOBTree
import
OOBTree
from
BTrees.OOBTree
import
OOBTree
from
Products.ERP5Type.Globals
import
InitializeClass
,
DTMLFile
from
Products.ERP5Type.Globals
import
InitializeClass
,
DTMLFile
...
@@ -42,6 +44,7 @@ from AccessControl.SecurityManagement import getSecurityManager
...
@@ -42,6 +44,7 @@ from AccessControl.SecurityManagement import getSecurityManager
from
AccessControl.ZopeGuards
import
guarded_getattr
from
AccessControl.ZopeGuards
import
guarded_getattr
from
Acquisition
import
aq_base
,
aq_inner
,
aq_acquire
,
aq_chain
from
Acquisition
import
aq_base
,
aq_inner
,
aq_acquire
,
aq_chain
from
DateTime
import
DateTime
from
DateTime
import
DateTime
from
my2to3.trace
import
apply_fixers
import
OFS.History
import
OFS.History
from
OFS.SimpleItem
import
SimpleItem
from
OFS.SimpleItem
import
SimpleItem
from
OFS.PropertyManager
import
PropertyManager
from
OFS.PropertyManager
import
PropertyManager
...
@@ -855,6 +858,27 @@ class Base(
...
@@ -855,6 +858,27 @@ class Base(
self
.
uid
=
uid
# Else it will be generated when we need it
self
.
uid
=
uid
# Else it will be generated when we need it
self
.
sid
=
sid
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.
# XXX This is necessary to override getId which is also defined in SimpleItem.
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getId'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getId'
)
getId
=
BaseAccessor
.
Getter
(
'getId'
,
'id'
,
'string'
)
getId
=
BaseAccessor
.
Getter
(
'getId'
,
'id'
,
'string'
)
...
...
product/ERP5Type/ZopePatch.py
View file @
a0e79027
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
##############################################################################
##############################################################################
# Load all monkey patches
# Load all monkey patches
from
Products.ERP5Type.patches
import
my2to3_patch
from
Products.ERP5Type.patches
import
WSGIPublisher
from
Products.ERP5Type.patches
import
WSGIPublisher
from
Products.ERP5Type.patches
import
HTTPRequest
from
Products.ERP5Type.patches
import
HTTPRequest
from
Products.ERP5Type.patches
import
AccessControl_patch
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