Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
6429477d
Commit
6429477d
authored
Nov 30, 2000
by
Evan Simpson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial checkin
parent
955f0de2
Changes
48
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
6085 additions
and
0 deletions
+6085
-0
lib/python/Products/PythonScripts/Bindings.py
lib/python/Products/PythonScripts/Bindings.py
+351
-0
lib/python/Products/PythonScripts/CHANGES.txt
lib/python/Products/PythonScripts/CHANGES.txt
+77
-0
lib/python/Products/PythonScripts/Extensions/RemotePS.py
lib/python/Products/PythonScripts/Extensions/RemotePS.py
+20
-0
lib/python/Products/PythonScripts/Guarded.py
lib/python/Products/PythonScripts/Guarded.py
+273
-0
lib/python/Products/PythonScripts/ModuleSecurity.py
lib/python/Products/PythonScripts/ModuleSecurity.py
+108
-0
lib/python/Products/PythonScripts/PythonScript.py
lib/python/Products/PythonScripts/PythonScript.py
+421
-0
lib/python/Products/PythonScripts/README.txt
lib/python/Products/PythonScripts/README.txt
+6
-0
lib/python/Products/PythonScripts/Script.py
lib/python/Products/PythonScripts/Script.py
+143
-0
lib/python/Products/PythonScripts/__init__.py
lib/python/Products/PythonScripts/__init__.py
+101
-0
lib/python/Products/PythonScripts/standard.py
lib/python/Products/PythonScripts/standard.py
+123
-0
lib/python/Products/PythonScripts/version.txt
lib/python/Products/PythonScripts/version.txt
+1
-0
lib/python/Products/PythonScripts/www/pyScriptAdd.dtml
lib/python/Products/PythonScripts/www/pyScriptAdd.dtml
+27
-0
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
+55
-0
lib/python/Products/PythonScripts/www/pyScriptProxy.dtml
lib/python/Products/PythonScripts/www/pyScriptProxy.dtml
+53
-0
lib/python/Products/PythonScripts/www/pyScriptUpload.dtml
lib/python/Products/PythonScripts/www/pyScriptUpload.dtml
+35
-0
lib/python/Products/PythonScripts/www/pyscript.gif
lib/python/Products/PythonScripts/www/pyscript.gif
+0
-0
lib/python/Products/PythonScripts/www/scriptBindings.dtml
lib/python/Products/PythonScripts/www/scriptBindings.dtml
+89
-0
lib/python/Products/PythonScripts/www/scriptTry.dtml
lib/python/Products/PythonScripts/www/scriptTry.dtml
+30
-0
lib/python/Products/PythonScripts/zbytecodehacks/ChangeLog
lib/python/Products/PythonScripts/zbytecodehacks/ChangeLog
+112
-0
lib/python/Products/PythonScripts/zbytecodehacks/Makefile
lib/python/Products/PythonScripts/zbytecodehacks/Makefile
+18
-0
lib/python/Products/PythonScripts/zbytecodehacks/README
lib/python/Products/PythonScripts/zbytecodehacks/README
+38
-0
lib/python/Products/PythonScripts/zbytecodehacks/TODO
lib/python/Products/PythonScripts/zbytecodehacks/TODO
+1
-0
lib/python/Products/PythonScripts/zbytecodehacks/VSExec.py
lib/python/Products/PythonScripts/zbytecodehacks/VSExec.py
+583
-0
lib/python/Products/PythonScripts/zbytecodehacks/__init__.py
lib/python/Products/PythonScripts/zbytecodehacks/__init__.py
+10
-0
lib/python/Products/PythonScripts/zbytecodehacks/attr_freeze.py
...thon/Products/PythonScripts/zbytecodehacks/attr_freeze.py
+58
-0
lib/python/Products/PythonScripts/zbytecodehacks/closure.py
lib/python/Products/PythonScripts/zbytecodehacks/closure.py
+139
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_editor.py
...thon/Products/PythonScripts/zbytecodehacks/code_editor.py
+385
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/Makefile
...n/Products/PythonScripts/zbytecodehacks/code_gen/Makefile
+3
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/__init__.py
...roducts/PythonScripts/zbytecodehacks/code_gen/__init__.py
+3
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/op_execute_methods
.../PythonScripts/zbytecodehacks/code_gen/op_execute_methods
+138
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/opexfuncread.py
...cts/PythonScripts/zbytecodehacks/code_gen/opexfuncread.py
+25
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/regen
...thon/Products/PythonScripts/zbytecodehacks/code_gen/regen
+4
-0
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/write_ops.py
...oducts/PythonScripts/zbytecodehacks/code_gen/write_ops.py
+122
-0
lib/python/Products/PythonScripts/zbytecodehacks/common.py
lib/python/Products/PythonScripts/zbytecodehacks/common.py
+54
-0
lib/python/Products/PythonScripts/zbytecodehacks/cyclehandle.py
...thon/Products/PythonScripts/zbytecodehacks/cyclehandle.py
+54
-0
lib/python/Products/PythonScripts/zbytecodehacks/dbc.py
lib/python/Products/PythonScripts/zbytecodehacks/dbc.py
+251
-0
lib/python/Products/PythonScripts/zbytecodehacks/find_function_call.py
...oducts/PythonScripts/zbytecodehacks/find_function_call.py
+67
-0
lib/python/Products/PythonScripts/zbytecodehacks/iif.py
lib/python/Products/PythonScripts/zbytecodehacks/iif.py
+29
-0
lib/python/Products/PythonScripts/zbytecodehacks/inline.py
lib/python/Products/PythonScripts/zbytecodehacks/inline.py
+129
-0
lib/python/Products/PythonScripts/zbytecodehacks/label.py
lib/python/Products/PythonScripts/zbytecodehacks/label.py
+40
-0
lib/python/Products/PythonScripts/zbytecodehacks/macro.py
lib/python/Products/PythonScripts/zbytecodehacks/macro.py
+211
-0
lib/python/Products/PythonScripts/zbytecodehacks/macros.py
lib/python/Products/PythonScripts/zbytecodehacks/macros.py
+68
-0
lib/python/Products/PythonScripts/zbytecodehacks/opbases.py
lib/python/Products/PythonScripts/zbytecodehacks/opbases.py
+94
-0
lib/python/Products/PythonScripts/zbytecodehacks/ops.py
lib/python/Products/PythonScripts/zbytecodehacks/ops.py
+1086
-0
lib/python/Products/PythonScripts/zbytecodehacks/rationalize.py
...thon/Products/PythonScripts/zbytecodehacks/rationalize.py
+281
-0
lib/python/Products/PythonScripts/zbytecodehacks/tailr.py
lib/python/Products/PythonScripts/zbytecodehacks/tailr.py
+75
-0
lib/python/Products/PythonScripts/zbytecodehacks/version
lib/python/Products/PythonScripts/zbytecodehacks/version
+1
-0
lib/python/Products/PythonScripts/zbytecodehacks/xapply.py
lib/python/Products/PythonScripts/zbytecodehacks/xapply.py
+93
-0
No files found.
lib/python/Products/PythonScripts/Bindings.py
0 → 100644
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/CHANGES.txt
0 → 100644
View file @
6429477d
1999-12-13 Evan Simpson <evan@4-am.com>
* Version 0.1.7
* Nested functions and lambdas are now supported, with full safety.
* You can access all of the dtml-var format functions through a builtin
dictionary called special_formats (eg: special_formats['html-quote']).
* Handing off to Digital Creations for inclusion in CVS.
* Packaged with packProduct script, which excludes parent directories
and .pyc files. Makes for a smaller package, and doesn't step on
ownership/permissions of lib/python/Products path elements.
1999-12-01 Evan Simpson <evan@4-am.com>
* Added COPYRIGHT.txt, making Wide Open Source licence (BSD-style)
explicit. (Mike Goldman provided the text, I provided the silly name).
* Jeff Rush donated a PrincipiaSearchSource method, so that
PythonMethod objects can be zcataloged to the same degree
as DTML Methods.
* Also from Jeff Rush, a document_src method, so that the source of
PythonMethods can be viewed via a "View Source" link if desired.
* If a PM has a 'traverse_subpath' parameter, you can now directly
traverse it. The elements of the subpath will then be put into a list
in 'traverse_subpath'. (thanks to Anthony Baxter)
1999-11-11 Evan Simpson <evan@4-am.com>
* Version 0.1.6
* Fix to builtins messed up DTML Methods, so I re-fixed it.
1999-11-05 Evan Simpson <evan@4-am.com>
* Version 0.1.5
* Killed *%#&$@ weird bug in which having 'add' documents in 'www'
subdirectory prevented rename, paste, or import of existing
PythonMethods! See use of '_www'.
* Range, test, and several other Zope 'builtins' had an unbound 'self'
argument unless called on _, but that's fixed.
* Safe multiplication was utterly broken (thanks to the guard); now
it works. Is anyone using the safe version??
1999-10-18 Evan Simpson <evan@4-am.com>
* Eliminated bug which delayed stringification of printed values.
1999-10-08 Evan Simpson <evan@4-am.com>
* Version 0.1.4
* Fixed mis-design noticed by Michel Pelletier, and refactored
MakeFunction. Now both kinds of Python Method have the bugfix
from 0.1.3, and shouldn't provoke a transaction when called.
1999-10-07 Evan Simpson <evan@4-am.com>
* Version 0.1.3
* Fixed parameter bug with 'self' and no defaults
1999-09-24 Evan Simpson <evan@4-am.com>
* Version 0.1.2
* Added WebDAV/FTP access code donated by Michel Pelletier
* Made parameters part of WebDAV/FTP text
* Eliminated initialization of globals to None
* Added 'global_exists' global function instead
* Killed bug with unused parameters
* Put switch in Guarded.py to allow both regular and
dangerous (XXX) PythonMethods to live side-by-side.
This means that people who patched version 0.1.1
will have to re-create any unsafe PMs they use (Sorry).
1999-09-10 Evan Simpson <evan@4-am.com>
* Version 0.1.1
* Incorporated DT_Util builtins and guards
* Fixed direct access via URL
* Fixed methodAdd.dtml
* rstrip function body
* Major changes to zbytecodehacks
lib/python/Products/PythonScripts/Extensions/RemotePS.py
0 → 100644
View file @
6429477d
''' RemotePS.py
External Method that allows you to remotely (via XML-RPC, for instance)
execute restricted Python code.
For example, create an External Method 'restricted_exec' in your Zope
root, and you can remotely call:
foobarsize = s.foo.bar.restricted_exec('len(context.objectIds())')
'''
from
Products.PythonScripts.PythonScript
import
PythonScript
from
string
import
join
def
restricted_exec
(
self
,
body
,
varmap
=
None
):
ps
=
PythonScript
(
'temp'
)
if
varmap
is
None
:
varmap
=
{}
ps
.
ZPythonScript_edit
(
join
(
varmap
.
keys
(),
','
),
body
)
return
apply
(
ps
.
__of__
(
self
),
varmap
.
values
())
lib/python/Products/PythonScripts/Guarded.py
0 → 100644
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/ModuleSecurity.py
0 → 100644
View file @
6429477d
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
"""Module Security module
"""
__version__
=
'$Revision: 1.1 $'
[
11
:
-
2
]
import
AccessControl
class
ModuleSecurityInfo
:
#(AccessControl.ClassSecurityInfo):
def
__init__
(
self
,
module_name
=
None
):
if
module_name
is
not
None
:
moduleSecurity
[
module_name
]
=
self
def
stub
(
self
,
*
args
,
**
kwargs
):
pass
def
__getattr__
(
self
,
name
):
return
self
.
stub
moduleSecurity
=
{}
def
getModuleSecurity
():
return
moduleSecurity
AccessControl
.
getModuleSecurity
=
getModuleSecurity
AccessControl
.
ModuleSecurityInfo
=
ModuleSecurityInfo
lib/python/Products/PythonScripts/PythonScript.py
0 → 100644
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/README.txt
0 → 100644
View file @
6429477d
Python Scripts
The Python Scripts product provides support for restricted execution of
Python scripts, exposing them as callable objects within the Zope
environment.
lib/python/Products/PythonScripts/Script.py
0 → 100644
View file @
6429477d
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
"""Script module
This provides generic script support
"""
__version__
=
'$Revision: 1.1 $'
[
11
:
-
2
]
import
os
from
Globals
import
package_home
,
HTMLFile
from
OFS.SimpleItem
import
SimpleItem
from
string
import
join
from
urllib
import
quote
from
Bindings
import
Bindings
class
FuncCode
:
def
__init__
(
self
,
varnames
,
argcount
):
self
.
co_varnames
=
varnames
self
.
co_argcount
=
argcount
def
__cmp__
(
self
,
other
):
if
other
is
None
:
return
1
try
:
return
cmp
((
self
.
co_argcount
,
self
.
co_varnames
),
(
other
.
co_argcount
,
other
.
co_varnames
))
except
:
return
1
_www
=
os
.
path
.
join
(
package_home
(
globals
()),
'www'
)
class
Script
(
SimpleItem
,
Bindings
):
"""Web-callable script mixin
"""
index_html
=
None
func_defaults
=
()
func_code
=
None
__ac_permissions__
=
(
(
'View management screens'
,
(
'ZScriptHTML_tryForm'
,)),
(
'View'
,
(
'__call__'
,
''
,
'ZPythonScriptHTML_tryAction'
)),
)
ZScriptHTML_tryForm
=
HTMLFile
(
'scriptTry'
,
_www
)
def
ZScriptHTML_tryAction
(
self
,
REQUEST
,
argvars
):
"""Apply the test parameters.
"""
vv
=
[]
for
argvar
in
argvars
:
vv
.
append
(
"%s=%s"
%
(
quote
(
argvar
.
name
),
quote
(
argvar
.
value
)))
raise
"Redirect"
,
"%s?%s"
%
(
REQUEST
[
'URL1'
],
join
(
vv
,
'&'
))
def
_setFuncSignature
(
self
,
defaults
,
varnames
,
argcount
):
# Generate a change only if we have to.
if
self
.
func_defaults
!=
defaults
:
self
.
func_defaults
=
defaults
code
=
FuncCode
(
varnames
,
argcount
)
if
self
.
func_code
!=
code
:
self
.
func_code
=
code
lib/python/Products/PythonScripts/__init__.py
0 → 100644
View file @
6429477d
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__
=
'''Python Scripts Product Initialization
$Id: __init__.py,v 1.1 2000/11/30 22:18:03 evan Exp $'''
__version__
=
'$Revision: 1.1 $'
[
11
:
-
2
]
import
ModuleSecurity
import
PythonScript
import
standard
__roles__
=
None
__allow_access_to_unprotected_subobjects__
=
1
def
initialize
(
context
):
context
.
registerClass
(
instance_class
=
PythonScript
.
PythonScript
,
constructors
=
(
PythonScript
.
manage_addPythonScriptForm
,
PythonScript
.
manage_addPythonScript
),
icon
=
'www/pyscript.gif'
)
lib/python/Products/PythonScripts/standard.py
0 → 100644
View file @
6429477d
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
"""Python Scripts standard utility module
This module provides helpful functions and classes for use in Python
Scripts. It can be accessed from Python with the statement
"import Products.PythonScripts.standard"
"""
__version__
=
'$Revision: 1.1 $'
[
11
:
-
2
]
from
AccessControl
import
ModuleSecurityInfo
security
=
ModuleSecurityInfo
()
security
.
public
(
'special_formats'
)
from
DocumentTemplate.DT_Var
import
special_formats
from
Globals
import
HTML
from
AccessControl
import
getSecurityManager
security
.
public
(
'DTML'
)
class
DTML
(
HTML
):
"""DTML objects are DocumentTemplate.HTML objects that allow
dynamic, temporary creation of restricted DTML."""
def
__call__
(
self
,
client
=
None
,
REQUEST
=
{},
RESPONSE
=
None
,
**
kw
):
"""Render the DTML given a client object, REQUEST mapping,
Response, and key word arguments."""
security
=
getSecurityManager
()
security
.
addContext
(
self
)
try
:
return
apply
(
HTML
.
__call__
,
(
self
,
client
,
REQUEST
),
kw
)
finally
:
security
.
removeContext
(
self
)
def
validate
(
self
,
inst
,
parent
,
name
,
value
,
md
):
return
getSecurityManager
().
validate
(
inst
,
parent
,
name
,
value
)
lib/python/Products/PythonScripts/version.txt
0 → 100644
View file @
6429477d
PythonScripts-1-0-0
lib/python/Products/PythonScripts/www/pyScriptAdd.dtml
0 → 100644
View file @
6429477d
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html
lang=
"en"
>
<head>
<title>
Add Python Script
</title>
</head>
<body
bgcolor=
"#FFFFFF"
link=
"#000099"
vlink=
"#555555"
alink=
"#77003B"
>
<h2>
Add Python Script
</h2>
<P>
Python Scripts allow you to add functionality to Zope by writing
scripts in the Python programming language
that are exposed as callable Zope objects.
</P>
<form
action=
"&dtml-URL1;"
method=
"POST"
>
<input
type=
"hidden"
name=
"manage_addPythonScript:default_method"
value=
""
>
<p>
<strong>
ID:
</strong>
<input
type=
"text"
name=
"id"
size=
"20"
>
</p>
<p>
<input
type=
"submit"
value=
"Add and Edit"
name=
"addedit"
>
<input
type=
"submit"
value=
"Cancel"
name=
"manage_workspace:method"
>
</p>
</form>
</body>
</html>
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
0 → 100644
View file @
6429477d
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html
lang=
"en"
>
<head>
<title>
Edit
<dtml-var
title_or_id
></title>
</head>
<body
bgcolor=
"#ffffff"
link=
"#000099"
vlink=
"#555555"
alink=
"#77003b"
>
<dtml-var
manage_tabs
>
<form
action=
"&dtml-URL1;"
method=
"POST"
>
<input
type=
"hidden"
name=
":default_method"
value=
"ZPythonScriptHTML_changePrefs"
>
<table
cellspacing=
"2"
>
<tr>
<th
align=
"left"
valign=
"top"
><em>
Title
</em></th>
<td
align=
"left"
valign=
"top"
>
<input
type=
"text"
name=
"title"
size=
"50"
value=
"&dtml-title;"
>
</td>
</tr>
<tr>
<th
align=
"left"
><em>
Parameter
list
</em></th>
<td
align=
"left"
><input
name=
"params"
size=
"30"
value=
"&dtml-params;"
>
</td></tr>
<dtml-with
getBindingAssignments
>
<dtml-if
getAssignedNamesInOrder
>
<tr>
<th
align=
"left"
><em>
Bound
names
</em></th>
<td
align=
"left"
>
<dtml-in
getAssignedNamesInOrder
>
<dtml-var
sequence-item
html_quote
><dtml-unless
sequence-end
>
,
</dtml-unless>
</dtml-in>
</td></tr>
</dtml-if>
</dtml-with>
<tr>
<th
align=
"left"
valign=
"top"
><em>
Last
modified
</em></th>
<td
align=
"left"
valign=
"top"
><dtml-var
bobobase_modification_time
></td>
</tr>
</table>
<!-- style="width: 2em" -->
<b>
Text area
</b>
<input
name=
"height"
type=
"submit"
value=
"Taller"
>
<input
name=
"height"
type=
"submit"
value=
"Shorter"
>
<input
name=
"width"
type=
"submit"
value=
"Wider"
>
<input
name=
"width"
type=
"submit"
value=
"Narrower"
>
<br>
<textarea
name=
"body:text"
wrap=
"off"
style=
"width: 100%"
cols=
<dtml-var
dtpref_cols
html_quote
missing=
"50"
>
rows=
<dtml-var
dtpref_rows
html_quote
missing=
"20"
>
>
&dtml-body;
</textarea><br>
<input
name=
"ZPythonScriptHTML_editAction:method"
type=
"submit"
value=
"Save Changes"
>
</form>
</body>
</html>
lib/python/Products/PythonScripts/www/pyScriptProxy.dtml
0 → 100644
View file @
6429477d
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML
lang=
"en"
>
<HEAD>
<TITLE>
Edit
</TITLE>
</HEAD>
<BODY
BGCOLOR=
"#FFFFFF"
LINK=
"#000099"
VLINK=
"#555555"
>
<dtml-var
manage_tabs
>
<P>
Proxy roles allow you to control the access that a
Script has. Proxy roles replace the roles of the user who is executing
the Script. This can be used to both expand and limit
access to resources.
</P>
<P>
Use the form below to select which roles this Script will have.
</P>
<FORM
ACTION=
"manage_proxy"
METHOD=
"POST"
>
<TABLE
CELLSPACING=
"2"
>
<TR>
<TH
ALIGN=
"LEFT"
VALIGN=
"TOP"
>
Id
</TH>
<TD
ALIGN=
"LEFT"
VALIGN=
"TOP"
><dtml-var
id
></TD>
</TR>
<TR>
<TH
ALIGN=
"LEFT"
VALIGN=
"TOP"
><EM>
Title
</EM></TH>
<TD
ALIGN=
"LEFT"
VALIGN=
"TOP"
><dtml-var
title
></TD>
</TR>
<TR>
<TH
ALIGN=
"LEFT"
VALIGN=
"TOP"
>
Proxy Roles
</TH>
<TD
VALIGN=
"TOP"
>
<SELECT
NAME=
"roles:list"
SIZE=
"7"
MULTIPLE
>
<dtml-in
valid_roles
>
<dtml-if
expr=
"_vars['sequence-item'] != 'Shared'"
>
<OPTION
<
dtml-if
expr=
"manage_haveProxy(_vars['sequence-item'])"
>
SELECTED
</dtml-if>
>
<dtml-var
sequence-item
></OPTION>
</dtml-if>
</dtml-in
valid_roles
>
</SELECT>
</TD>
</TR>
<TR>
<TD></TD>
<TD>
<INPUT
NAME=
SUBMIT
TYPE=
"SUBMIT"
VALUE=
"Change"
>
</TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
lib/python/Products/PythonScripts/www/pyScriptUpload.dtml
0 → 100644
View file @
6429477d
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML
lang=
"en"
>
<HEAD>
<TITLE>
Upload
</TITLE>
</HEAD>
<BODY
BGCOLOR=
"#FFFFFF"
LINK=
"#000099"
VLINK=
"#555555"
>
<dtml-var
manage_tabs
>
<P>
You may upload the source for
&dtml-title_and_id;
using the form below.
Choose an existing file from your local computer by pushing the
<I>
Browse
</I>
button. The contents of the file should be a
valid script with an optional
"
##data
"
block at the start.
You may click the following link to
<a
href=
"document_src"
>
view or
download
</a>
the current source.
<FORM
ACTION=
"ZPythonScriptHTML_upload"
METHOD=
"POST"
ENCTYPE=
"multipart/form-data"
>
<TABLE
CELLSPACING=
"2"
>
<TR>
<TH
ALIGN=
"LEFT"
VALIGN=
"TOP"
>
File
</TH>
<TD
ALIGN=
"LEFT"
VALIGN=
"TOP"
>
<INPUT
TYPE=
"file"
NAME=
"file"
SIZE=
"25"
VALUE=
""
>
</TD>
</TR>
<TR>
<TD></TD>
<TD><BR><INPUT
TYPE=
"SUBMIT"
VALUE=
"Change"
></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
lib/python/Products/PythonScripts/www/pyscript.gif
0 → 100644
View file @
6429477d
116 Bytes
lib/python/Products/PythonScripts/www/scriptBindings.dtml
0 → 100644
View file @
6429477d
<html>
<head>
<title>
Bindings -
&dtml-title_or_id;
</title>
</head>
<body
bgcolor=
"#ffffff"
link=
"#000099"
vlink=
"#555555"
alink=
"#77003b"
>
<dtml-var
manage_tabs
>
<h2>
Bindings -
&dtml-title_or_id;
</h2>
<form
action=
"ZBindingsHTML_editAction"
method=
"POST"
>
<dtml-with
getBindingAssignments
>
<p><em>
Each of the following items describes a piece of information about
this script's calling environment. If you supply a variable name for
an item, or accept the recommended name, the information will
automatically be provided under that name when the script is called.
</em></p>
<table
cellpadding=
"2"
>
<tr>
<th
align=
"left"
valign=
"top"
>
Container
</th>
<td
align=
"left"
valign=
"top"
nowrap
><input
type=
"text"
name=
"name_container"
value=
"<dtml-var expr="
getAssignedName
('
name_container
',
'')"
html_quote
>
">
<br>
Recommended:
<code>
self
</code>
</td><td
align=
"left"
valign=
"top"
>
This is the
<dtml-with
expr=
"aq_inner.aq_parent"
>
&dtml-meta_type;
"
&dtml.missing.html_quote-title_or_id;
"
</dtml-with>
, in which this
script is located. This doesn't change unless you move the script.
If the script is in a ZClass, the Container is the class instance.
</td>
</tr>
<tr><td>
</td></tr>
<tr>
<th
align=
"left"
valign=
"top"
>
Context
</th>
<td
align=
"left"
valign=
"top"
><input
type=
"text"
name=
"name_context"
value=
"<dtml-var expr="
getAssignedName
('
name_context
',
'')"
html_quote
>
">
<br>
Recommended:
<code>
context
</code>
</td><td
align=
"left"
valign=
"top"
>
This is the object on which the script is being called, also known as the
"acquisition parent" of the script. This
<em>
may
</em>
be the container, but
varies according to the path through which the script is accessed.
</td>
</tr>
<tr><td>
</td></tr>
<tr>
<th
align=
"left"
valign=
"top"
>
Script
</th>
<td
align=
"left"
valign=
"top"
><input
type=
"text"
name=
"name_m_self"
value=
"<dtml-var expr="
getAssignedName
('
name_m_self
',
'')"
html_quote
>
">
<br>
Recommended:
<code>
m_self
</code>
</td><td
align=
"left"
valign=
"top"
>
This is the object
"&dtml-title_or_id;"
itself.
</td>
</tr>
<tr><td>
</td></tr>
<tr>
<th
align=
"left"
valign=
"top"
>
Namespace
</th>
<td
align=
"left"
valign=
"top"
><input
type=
"text"
name=
"name_ns"
value=
"<dtml-var expr="
getAssignedName
('
name_ns
',
'')"
html_quote
>
">
<br>
Rec:
<code>
_
</code>
(an underscore)
</td><td
align=
"left"
valign=
"top"
>
When the script is called from DTML, this is the caller's DTML namespace,
otherwise it is an empty namespace.
</td>
</tr>
<tr><td>
</td></tr>
<tr>
<th
align=
"left"
valign=
"top"
>
Subpath
</th>
<td
align=
"left"
valign=
"top"
nowrap
><input
type=
"text"
name=
"name_subpath"
value=
"<dtml-var expr="
getAssignedName
('
name_subpath
',
'')"
html_quote
>
">
<br>
Rec:
<code>
traverse_subpath
</code>
</td><td
align=
"left"
valign=
"top"
>
When the script is published directly from a URL, this is the
portion of the URL path after the script's name, split at slash separators
into a list of strings. Otherwise, it is an empty list.
</td>
</tr>
<tr>
<td
align=
"left"
>
<input
name=
"submit"
type=
"submit"
value=
"Change"
>
</td>
</tr>
</table>
</dtml-with>
</form>
</body>
</html>
lib/python/Products/PythonScripts/www/scriptTry.dtml
0 → 100644
View file @
6429477d
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html
lang=
"en"
>
<head>
<title>
Try
<dtml-var
title_or_id
></title>
</head>
<body
bgcolor=
"#ffffff"
link=
"#000099"
vlink=
"#555555"
alink=
"#77003b"
>
<dtml-var
manage_tabs
>
<h2>
Try
<dtml-var
title_or_id
></h2>
<form
action=
"&dtml-URL1;/ZScriptHTML_tryAction"
method=
"POST"
>
<table
cellspacing=
"2"
>
<tr><th>
Variable
</th><th>
Value
</th></tr>
<dtml-in
ZScriptHTML_tryParams
>
<tr>
<td
align=
"left"
valign=
"top"
>
<input
name=
"argvars.name:records"
type=
"text"
value=
"&dtml-sequence-item;"
>
</td>
<td
align=
"left"
valign=
"top"
>
<input
name=
"argvars.value:records"
type=
"text"
>
</td>
</tr>
<dtml-else>
<dtml-raise
type=
"Redirect"
>
&dtml-URL1;
</dtml-raise>
</dtml-in>
</table>
<input
name=
"submit"
type=
"submit"
value=
"Go"
><br>
</form>
</body>
</html>
lib/python/Products/PythonScripts/zbytecodehacks/ChangeLog
0 → 100755
View file @
6429477d
1999-12-11 Evan Simpson <evan@4-am.com>
* Tupleizing and UntupleFunction now handle nested function definitions
* Subdirectories reverted to v0.5 bytecodehacks, since the only change
I've ever made was to accidentally change line endings in them to CRLF
1999-09-09 Evan Simpson <evan@4-am.com>
* Tupleizing a function now omits globals
* New UntupleFunction re-applies globals, with automatic initialization
of variables to None, since there's no way to check if they exist.
It also includes $functions, and checks __builtins__ handling.
* Moved all bytecode manipulation into Munge_window class, which uses
op.execute to maintain information about who did what to the stack.
* Added Munger which re-enables creation of dictionary literals.
* Made all Mungers load frequently used functions from the global dict
into the local instead of storing them in co_consts.
* Simplified GuardedOps and turned off test Guard.
* Wrote lots of docstring.
1999-08-28 Evan Simpson <evan@4-am.com>
* Ripped out Fleshy acquisition-style class and added
CycleHandle in an attempt to improve speed.
* code_editor.py: Added "as_tuple" to Function and EditableCode
to provide (hopefully) pickleable representations. Their __init__s
now accept these tuples.
* Added VSExec.py (the point of all this), which provides facilities
for compiling arbitrary blocks of code with heavy restrictions.
1999-06-11 Michael Hudson <mwh21@cam.ac.uk>
* a monumental amount has changed. I haven't been keeping the
ChangeLog up to date, sorry.
1999-05-16 Michael Hudson <mwh21@cam.ac.uk>
* doc/bch.tex: documented macro and macros.
* macros.py: added basic library of macros.
* setq2.py: does same job as setq.py, but uses the new macro
package.
* macro.py It's a macro packages of sorts. Needs documentation.
1999-05-15 Michael Hudson <mwh21@cam.ac.uk>
* inline.py: Substantially rewritten to use find_function_call,
and to support keyword arguments. No varags yet.
* setq.py Added changes written by Christian Tismer (now converts
globals to locals)
1999-05-13 Michael Hudson <mwh21@cam.ac.uk>
* Release 0.11 - cleaned up production of documentation following
advice from the documentation master, Fred L. Drake.
1999-05-12 Michael Hudson <mwh21@cam.ac.uk>
* Release 0.10.
* doc/ There's documentation (gasp)
1999-05-10 Michael Hudson <mwh21@cam.ac.uk>
* inline.py: Python now has inline functions! Bet you never
expected that.
* It's all changing again! Much polish, some docstrings,
everything rewritten to use code_editor that wasn't already, many
style fixes.
1999-05-06 Michael Hudson <mwh21@cam.ac.uk>
* attr_freeze.py: implement an attribute freezer that works.
* xapply2.py: implement xapply for functions (again!) using the
new code editing framework from code_editor.py.
* code_editor.py: That's more like it!
1999-05-04 Michael Hudson <mwh21@cam.ac.uk>
* attr_freeze.py: implements a (buggy) attempt at freezing
attribute references.
* read_code.py,opbases.py,ops.py,write_ops.py,
common.py,__init__.py: Much stuff added/changed. It not pretty or
internally consistent yet. I might bash on it some more some
time. I'm afraid I don't feel like explaining myself properly yet
either.
1999-05-02 Michael Hudson <mwh21@cam.ac.uk>
* README,ChangeLog: Added.
* xapply.py: Added, following prompting by Christian Tismer.
* closure.py: Made improvements suggested by Tim Peters.
lib/python/Products/PythonScripts/zbytecodehacks/Makefile
0 → 100755
View file @
6429477d
SUBDIRS
=
tests code_gen doc
clean
:
clean-local clean-recursive
release
:
version src-release doc-release
clean-local
:
$(RM)
*
.pyc
*
~
*
.pyo
clean-recursive
:
for
i
in
$(SUBDIRS)
;
do
\
(
cd
$$
i
&&
make clean
)
;
\
done
src-release
:
clean
cd
..
&&
./mkdist.sh
doc-release
:
clean
cd
doc
&&
make release
lib/python/Products/PythonScripts/zbytecodehacks/README
0 → 100755
View file @
6429477d
Welcome to the bytecodehacks!
There's docmentation in doc/; To build it you need an unpacked python
source distribution somewhere, and for html output you also need
latex2html.
Build docs like this:
$(path to Python source)/Doc/tools/mkhowto --$(format) (--a4) bch.tex
You can get built html docs at
ftp://starship.python.net/pub/crew/mwh/bytecodehacks-doc-$(VERSION).tar.gz.
The bytecodehacks rewrite the bytecode of functions to do unlikely
things in Python.
The package (and that's how it's distributed) splits into two parts -
the byte code editing routines and the "bytecodehacks" that are
usuable without a degree in python arcanery, although one might help
understand some of the consequences.
Some highlights:
bytecodehacks.closure - bind global references to constants
bytecodehacks.xapply - a sort-of lazy apply
bytecodehacks.setq - this one should interest people!
bytecodehacks.inline - Python gets inline functions
bytecodehacks.macro - Python gets semantic (hygenic) macros!
Please note that these modules are not really bullet-proof, more a
proof-of-concept than anything else.
The are also public domain; do what you like with them. If you find
bugs, or more imaginative uses for these techniques, I'd surely like
to know!
Thanks for taking an interest.
lib/python/Products/PythonScripts/zbytecodehacks/TODO
0 → 100755
View file @
6429477d
polish attr_freeze.
lib/python/Products/PythonScripts/zbytecodehacks/VSExec.py
0 → 100755
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/zbytecodehacks/__init__.py
0 → 100755
View file @
6429477d
__all__
=
[
'closure'
,
'xapply'
,
'common'
,
'inline'
,
'code_editor'
,
'opbases'
,
'ops'
,
'attr_freeze'
,
'code_gen'
]
lib/python/Products/PythonScripts/zbytecodehacks/attr_freeze.py
0 → 100755
View file @
6429477d
from
code_editor
import
Function
from
ops
import
LOAD_GLOBAL
,
LOAD_ATTR
,
LOAD_CONST
def
freeze_one_attr
(
cs
,
code
,
attr
,
value
):
looking_for
=
0
is_global
=
1
inserted
=
0
i
=
0
while
i
<
len
(
cs
):
op
=
cs
[
i
]
if
is_global
:
if
op
.
__class__
is
LOAD_GLOBAL
:
if
code
.
co_names
[
op
.
arg
]
==
attr
[
looking_for
]:
looking_for
=
looking_for
+
1
is_global
=
0
else
:
if
op
.
__class__
is
LOAD_ATTR
\
and
code
.
co_names
[
op
.
arg
]
==
attr
[
looking_for
]:
looking_for
=
looking_for
+
1
if
looking_for
==
len
(
attr
):
inserted
=
1
newop
=
LOAD_CONST
(
len
(
code
.
co_consts
))
cs
[
i
-
len
(
attr
)
+
1
:
i
+
1
]
=
[
newop
]
i
=
i
-
len
(
attr
)
looking_for
=
0
is_global
=
1
else
:
looking_for
=
0
is_global
=
1
i
=
i
+
1
if
inserted
:
code
.
co_consts
.
append
(
value
)
return
cs
class
Ref
:
def
__init__
(
self
,
name
=
()):
self
.
name
=
name
def
__getattr__
(
self
,
attr
):
return
Ref
(
self
.
name
+
(
attr
,))
def
__call__
(
self
):
return
self
.
name
def
__repr__
(
self
):
return
`self.name`
def
freeze_attrs
(
func
,
*
vars
):
func
=
Function
(
func
)
code
=
func
.
func_code
cs
=
code
.
co_code
if
len
(
vars
)
%
2
<>
0
:
raise
TypeError
,
"wrong number of arguments"
for
i
in
range
(
0
,
len
(
vars
),
2
):
freeze_one_attr
(
cs
,
code
,
vars
[
i
](),
vars
[
i
+
1
])
return
func
.
make_function
()
lib/python/Products/PythonScripts/zbytecodehacks/closure.py
0 → 100755
View file @
6429477d
"""
\
closure
implements a form of closures by abusing the co_consts field of a code
object.
exports: bind, bind_locals, bind_now
and contains two examples: make_adder, make_balance
"""
from
code_editor
import
Function
from
ops
import
*
def
scan_for_STORE
(
func
,
name
):
for
i
in
func
.
func_code
.
co_code
:
if
i
.
__class__
in
[
STORE_FAST
,
STORE_NAME
,
STORE_GLOBAL
]
\
and
i
.
name
==
name
:
return
1
return
0
def
bind
(
function
,
newname
=
None
,
**
vars
):
"""
\
bind(function[,newname],var1=value1,var2=value2,...) -> function
returns a new function (optionally renamed) where every reference to
one of var1, var2, etc is replaced by a reference to the respective
valueN."""
func
=
Function
(
function
)
code
=
func
.
func_code
cs
=
func
.
func_code
.
co_code
name2index
=
{}
mutated
=
{}
for
name
in
vars
.
keys
():
mutated
[
name
]
=
scan_for_STORE
(
func
,
name
)
if
0
in
code
.
co_consts
:
zeroIndex
=
code
.
co_consts
.
index
(
0
)
else
:
zeroIndex
=
len
(
code
.
co_consts
)
code
.
co_consts
.
append
(
0
)
i
=
0
while
i
<
len
(
cs
):
op
=
cs
[
i
]
i
=
i
+
1
# should LOAD_NAME be here??? tricky, I'd say
if
op
.
__class__
in
[
LOAD_GLOBAL
,
LOAD_NAME
,
LOAD_FAST
]:
if
not
vars
.
has_key
(
op
.
name
):
continue
if
mutated
[
name
]:
if
not
name2index
.
has_key
(
op
.
name
):
name2index
[
op
.
name
]
=
len
(
code
.
co_consts
)
code
.
co_consts
.
append
([
vars
[
op
.
name
]])
cs
[
i
-
1
:
i
]
=
[
LOAD_CONST
(
name2index
[
op
.
name
]),
LOAD_CONST
(
zeroIndex
),
BINARY_SUBSCR
()]
i
=
i
+
2
else
:
if
not
name2index
.
has_key
(
op
.
name
):
name2index
[
op
.
name
]
=
len
(
code
.
co_consts
)
code
.
co_consts
.
append
(
vars
[
op
.
name
])
cs
[
i
-
1
]
=
LOAD_CONST
(
name2index
[
op
.
name
])
elif
op
.
__class__
in
[
STORE_FAST
,
STORE_NAME
,
STORE_GLOBAL
]:
if
not
vars
.
has_key
(
op
.
name
):
continue
if
not
mutated
[
name
]:
continue
# shouldn't be reached
cs
[
i
-
1
:
i
]
=
[
LOAD_CONST
(
name2index
[
op
.
name
]),
LOAD_CONST
(
zeroIndex
),
STORE_SUBSCR
()]
i
=
i
+
2
if
newname
is
not
None
:
func
.
func_name
=
newname
return
func
.
make_function
()
bind
=
Function
(
bind
)
bind
.
func_code
.
co_varnames
[
0
]
=
'$function'
bind
.
func_code
.
co_varnames
[
1
]
=
'$newname'
bind
=
bind
.
make_function
()
def
bind_locals
(
func
):
"""bind_locals(func) -> function
returns a new function where every global variable reference in func
is replaced, if possible, by a reference to a local variable in the
callers context."""
try
:
raise
""
except
:
import
sys
frame
=
sys
.
exc_traceback
.
tb_frame
.
f_back
name
=
func
.
func_name
+
'+'
l
=
apply
(
bind
,(
func
,
name
),
frame
.
f_locals
)
frame
=
None
return
l
def
bind_now
(
func
):
"""bind_now(func) -> function
returns a new function where every global variable reference in func
is replaced, if possible, by a reference to a variable in the callers
context."""
try
:
raise
""
except
:
import
sys
frame
=
sys
.
exc_traceback
.
tb_frame
.
f_back
l
=
apply
(
bind
,(
func
,),
frame
.
f_locals
)
g
=
apply
(
bind
,(
l
,),
frame
.
f_globals
)
frame
=
None
return
g
## examples
def
make_adder
(
n
):
"""make_adder(n) -> function
return a monadic function that adds n to its argument."""
def
adder
(
x
):
return
x
+
n
return
bind_locals
(
adder
)
def
make_balance
(
initial_amount
):
"""make_balance(initial_amount) -> function
demonstrates an object with state, sicp style."""
def
withdraw
(
amount
):
if
current
[
0
]
<
amount
:
raise
"debt!"
else
:
current
[
0
]
=
current
[
0
]
-
amount
return
current
[
0
]
return
bind
(
withdraw
,
current
=
[
initial_amount
])
lib/python/Products/PythonScripts/zbytecodehacks/code_editor.py
0 → 100755
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/Makefile
0 → 100644
View file @
6429477d
clean
:
$(RM)
*
~
*
.pyc
*
.pyo
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/__init__.py
0 → 100644
View file @
6429477d
__all__
=
[
'write_ops'
,
'opexecfuncread'
]
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/op_execute_methods
0 → 100644
View file @
6429477d
# -*- python -*-
STOP_CODE
:
pass
POP_TOP
:
stack
.
pop
()
ROT_TWO
:
stack
[
-
2
:]
=
[
stack
[
-
1
],
stack
[
-
2
]]
ROT_THREE
:
stack
[
-
3
:]
=
[
stack
[
-
1
],
stack
[
-
3
],
stack
[
-
2
]]
DUP_TOP
:
stack
.
append
(
stack
[
-
1
])
UNARY_POSITIVE
:
UNARY_NEGATIVE
:
UNARY_NOT
:
UNARY_CONVERT
:
UNARY_INVERT
:
stack
[
-
1
:]
=
[
self
]
BINARY_POWER
:
BINARY_MULTIPLY
:
BINARY_DIVIDE
:
BINARY_MODULO
:
BINARY_ADD
:
BINARY_SUBTRACT
:
BINARY_SUBSCR
:
BINARY_LSHIFT
:
BINARY_RSHIFT
:
BINARY_AND
:
BINARY_XOR
:
BINARY_OR
:
stack
[
-
2
:]
=
[
self
]
SLICE_0
:
stack
[
-
1
:]
=
[
self
]
SLICE_1
:
SLICE_2
:
stack
[
-
2
:]
=
[
self
]
SLICE_3
:
stack
[
-
3
:]
=
[
self
]
STORE_SLICE_0
:
del
stack
[
-
2
:]
STORE_SLICE_1
:
STORE_SLICE_2
:
del
stack
[
-
3
:]
STORE_SLICE_3
:
del
stack
[
-
4
:]
DELETE_SLICE_0
:
del
stack
[
-
1
:]
DELETE_SLICE_1
:
DELETE_SLICE_2
:
del
stack
[
-
2
:]
DELETE_SLICE_3
:
del
stack
[
-
3
:]
STORE_SUBSCR
:
del
stack
[
-
3
:]
DELETE_SUBSCR
:
del
stack
[
-
2
:]
PRINT_EXPR
:
PRINT_ITEM
:
stack
.
pop
()
PRINT_NEWLINE
:
pass
BREAK_LOOP
:
raise
"No jumps here!"
LOAD_LOCALS
:
stack
.
append
(
self
)
RETURN_VALUE
:
stack
[:]
=
[]
EXEC_STMT
:
pass
POP_BLOCK
:
pass
END_FINALLY
:
pass
BUILD_CLASS
:
stack
[
-
3
:]
=
[
self
]
STORE_NAME
:
DELETE_NAME
:
stack
.
pop
()
UNPACK_TUPLE
:
UNPACK_LIST
:
stack
.
append
([
self
]
*
self
.
arg
)
STORE_ATTR
:
DELETE_ATTR
:
STORE_GLOBAL
:
DELETE_GLOBAL
:
stack
.
pop
()
LOAD_CONST
:
LOAD_NAME
:
stack
.
append
(
self
)
BUILD_TUPLE
:
BUILD_LIST
:
if
self
.
arg
>
0
:
stack
[
-
self
.
arg
:]
=
[
self
]
else
:
stack
.
append
(
self
)
BUILD_MAP
:
stack
.
append
(
self
)
LOAD_ATTR
:
stack
[
-
1
]
=
self
COMPARE_OP
:
stack
[
-
2
:]
=
[
self
]
# ????
IMPORT_NAME
:
stack
.
append
(
self
)
IMPORT_FROM
:
pass
JUMP_FORWARD
:
JUMP_IF_TRUE
:
JUMP_IF_FALSE
:
JUMP_ABSOLUTE
:
raise
"jumps not handled here!"
FOR_LOOP
:
raise
"loop alert"
LOAD_GLOBAL
:
stack
.
append
(
self
)
SETUP_LOOP
:
raise
"loop alert!"
SETUP_EXCEPT
:
SETUP_FINALLY
:
pass
# ??
LOAD_FAST
:
stack
.
append
(
self
)
STORE_FAST
:
DELETE_FAST
:
stack
.
pop
()
SET_LINENO
:
pass
RAISE_VARARGS
:
raise
"Exception!"
CALL_FUNCTION
:
num_keyword_args
=
self
.
arg
>>
8
num_regular_args
=
self
.
arg
&
0xFF
stack
[
-
2
*
num_keyword_args
-
num_regular_args
-
1
:]
=
[
self
]
MAKE_FUNCTION
:
stack
[
-
self
.
arg
-
1
:]
=
[
self
]
BUILD_SLICE
:
stack
[
-
self
.
arg
:]
=
[
self
]
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/opexfuncread.py
0 → 100644
View file @
6429477d
import
os
,
string
file
=
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'op_execute_methods'
),
'r'
)
lines
=
string
.
split
(
file
.
read
(),
'
\
n
'
)[
1
:]
exec_funcs
=
{}
n
=
len
(
lines
)
for
i
in
range
(
n
):
if
(
not
lines
[
i
])
or
lines
[
i
][
0
]
==
' '
:
continue
j
=
i
body
=
[]
while
j
<
n
:
if
lines
[
j
][
0
]
==
' '
:
while
lines
[
j
]
and
lines
[
j
][
0
]
==
' '
:
body
.
append
(
lines
[
j
])
j
=
j
+
1
break
j
=
j
+
1
body
=
' '
+
string
.
join
(
body
,
'
\
n
'
)
exec_funcs
[
lines
[
i
][:
-
1
]]
=
body
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/regen
0 → 100755
View file @
6429477d
#!/usr/local/bin/python
from
bytecodehacks.code_gen
import
write_ops
write_ops
.
Main
()
lib/python/Products/PythonScripts/zbytecodehacks/code_gen/write_ops.py
0 → 100644
View file @
6429477d
import
dis
,
re
,
sys
,
os
,
string
from
bytecodehacks.code_gen
import
opexfuncread
temphead
=
"""
\
# this file is autogenerated by running
# from bytecodehacks.code_gen import write_ops
# write_ops.Main()
from bytecodehacks import opbases
from bytecodehacks.label import Label
_opbases = opbases
_Label = Label
del Label
del opbases
_bytecodes={}
"""
noargtemplate
=
"""
\
class %(name)s(_opbases.%(base)s):
op = %(index)d
opc = '
\
\
%(index)03o'
def __init__(self,cs=None,code=None):
if cs is not None:
_opbases.%(base)s.__init__(self,cs,code)
def execute(self,stack):
%(exec_body)s
_bytecodes[%(name)s.opc]=%(name)s
"""
argtemplate
=
"""
\
class %(name)s(_opbases.%(base)s):
op = %(index)d
opc = '
\
\
%(index)03o'
def __init__(self,csorarg,code=None):
if code is not None:
_opbases.%(base)s.__init__(self,csorarg,code)
else:
self.user_init(csorarg)
def execute(self,stack):
%(exec_body)s
_bytecodes[%(name)s.opc]=%(name)s
"""
jumptemplate
=
"""
\
class %(name)s(_opbases.%(base)s):
op = %(index)d
opc = '
\
\
%(index)03o'
def __init__(self,csorarg=None,code=None):
if csorarg is not None:
if code is not None:
_opbases.%(base)s.__init__(self,csorarg,code)
else:
self.label = _Label()
self.user_init(csorarg)
else:
self.label = _Label()
def execute(self,stack):
%(exec_body)s
_bytecodes[%(name)s.opc]=%(name)s
"""
idprog
=
re
.
compile
(
'^[_a-zA-Z][_a-zA-Z0-9]*$'
)
notopprog
=
re
.
compile
(
'^<[0-9]+>$'
)
def
main
(
file
=
sys
.
stdout
):
file
.
write
(
temphead
)
trans
=
string
.
maketrans
(
'+'
,
'_'
)
for
index
in
range
(
len
(
dis
.
opname
)):
name
=
string
.
translate
(
dis
.
opname
[
index
],
trans
)
if
notopprog
.
match
(
name
):
continue
if
not
idprog
.
match
(
name
):
name
=
"Opcode_%d"
%
index
s
=
"generating %s ..."
%
name
pad
=
" "
*
(
30
-
len
(
s
))
print
s
,
pad
,
base
=
"GenericOneByteCode"
if
index
<
dis
.
HAVE_ARGUMENT
:
template
=
noargtemplate
base
=
"GenericOneByteCode"
elif
index
in
dis
.
hasjrel
:
template
=
jumptemplate
base
=
"JRel"
elif
index
in
dis
.
hasjabs
:
template
=
jumptemplate
base
=
"JAbs"
elif
index
in
dis
.
hasname
:
template
=
argtemplate
base
=
"NameOpcode"
elif
index
in
dis
.
haslocal
:
template
=
argtemplate
base
=
"LocalOpcode"
else
:
template
=
argtemplate
base
=
"GenericThreeByteCode"
exec_body
=
opexfuncread
.
exec_funcs
[
name
]
file
.
write
(
template
%
locals
())
print
"done"
def
Main
():
from
bytecodehacks
import
__init__
main
(
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__init__
.
__file__
),
'ops.py'
),
'w'
))
lib/python/Products/PythonScripts/zbytecodehacks/common.py
0 → 100755
View file @
6429477d
import
new
def
copy_code_with_changes
(
codeobject
,
argcount
=
None
,
nlocals
=
None
,
stacksize
=
None
,
flags
=
None
,
code
=
None
,
consts
=
None
,
names
=
None
,
varnames
=
None
,
filename
=
None
,
name
=
None
,
firstlineno
=
None
,
lnotab
=
None
):
if
argcount
is
None
:
argcount
=
codeobject
.
co_argcount
if
nlocals
is
None
:
nlocals
=
codeobject
.
co_nlocals
if
stacksize
is
None
:
stacksize
=
codeobject
.
co_stacksize
if
flags
is
None
:
flags
=
codeobject
.
co_flags
if
code
is
None
:
code
=
codeobject
.
co_code
if
consts
is
None
:
consts
=
codeobject
.
co_consts
if
names
is
None
:
names
=
codeobject
.
co_names
if
varnames
is
None
:
varnames
=
codeobject
.
co_varnames
if
filename
is
None
:
filename
=
codeobject
.
co_filename
if
name
is
None
:
name
=
codeobject
.
co_name
if
firstlineno
is
None
:
firstlineno
=
codeobject
.
co_firstlineno
if
lnotab
is
None
:
lnotab
=
codeobject
.
co_lnotab
return
new
.
code
(
argcount
,
nlocals
,
stacksize
,
flags
,
code
,
consts
,
names
,
varnames
,
filename
,
name
,
firstlineno
,
lnotab
)
code_attrs
=
[
'argcount'
,
'nlocals'
,
'stacksize'
,
'flags'
,
'code'
,
'consts'
,
'names'
,
'varnames'
,
'filename'
,
'name'
,
'firstlineno'
,
'lnotab'
]
lib/python/Products/PythonScripts/zbytecodehacks/cyclehandle.py
0 → 100755
View file @
6429477d
class
CycleHandle
:
'''CycleHandles are proxies for cycle roots
A CycleHandle subclass should create one or more workers, and pass them
to _set_workers. These workers can then participate in cycles, as long
as deleting all of the worker's attributes will break the cycle. When a
CycleHandle instance goes away, it deletes all attributes of all of
its workers. You could also explicitly call drop_workers.
For example,
>>> class Ham:
... def __del__(self):
... print 'A ham has died!'
...
>>> ct = CycleHandle()
>>> ct._set_workers(Ham(), Ham())
>>> ct._workers[0].ham2 = ct._workers[1]
>>> ct._workers[1].ham1 = ct._workers[0]
>>> del ct
A ham has died!
A ham has died!
'''
_workers
=
()
def
_set_workers
(
self
,
*
workers
):
self
.
__dict__
[
'_workers'
]
=
workers
def
_not_mutable
(
self
,
*
x
):
raise
TypeError
,
'CycleHandle is not mutable'
__delattr__
=
_not_mutable
def
__setattr__
(
self
,
attr
,
val
):
for
worker
in
self
.
_workers
:
if
hasattr
(
worker
,
'__setattr__'
):
return
getattr
(
worker
,
'__setattr__'
)(
attr
,
val
)
_not_mutable_defs
=
(
'__delslice__'
,
'__setslice__'
,
'__delitem__'
,
'__setitem__'
)
def
__getattr__
(
self
,
attr
):
for
worker
in
self
.
_workers
:
if
hasattr
(
worker
,
attr
):
return
getattr
(
worker
,
attr
)
if
attr
in
self
.
_not_mutable_defs
:
return
self
.
_not_mutable
raise
AttributeError
,
attr
def
_drop_workers
(
self
):
for
worker
in
self
.
_workers
:
worker
.
__dict__
.
clear
()
self
.
__dict__
[
'_workers'
]
=
()
def
__del__
(
self
,
drop_workers
=
_drop_workers
):
drop_workers
(
self
)
def
_test
():
import
doctest
,
cyclehandle
return
doctest
.
testmod
(
cyclehandle
)
if
__name__
==
"__main__"
:
_test
()
lib/python/Products/PythonScripts/zbytecodehacks/dbc.py
0 → 100755
View file @
6429477d
from
code_editor
import
Function
from
ops
import
*
import
dis
,
new
,
string
PRECONDITIONS
=
1
POSTCONDITIONS
=
2
INVARIANTS
=
4
EVERYTHING
=
PRECONDITIONS
|
POSTCONDITIONS
|
INVARIANTS
if
__debug__
:
__strength__
=
PRECONDITIONS
|
POSTCONDITIONS
else
:
__strength__
=
0
# TODO: docs, sort out inheritance.
if
__debug__
:
def
add_contracts
(
target_class
,
contract_class
,
strength
=
None
):
if
strength
is
None
:
strength
=
__strength__
newmethods
=
{}
contractmethods
=
contract_class
.
__dict__
if
strength
&
INVARIANTS
:
inv
=
contractmethods
.
get
(
"class_invariants"
,
None
)
for
name
,
meth
in
target_class
.
__dict__
.
items
():
if
strength
&
PRECONDITIONS
:
pre
=
contractmethods
.
get
(
"pre_"
+
name
,
None
)
if
pre
is
not
None
:
meth
=
add_precondition
(
meth
,
pre
)
if
strength
&
POSTCONDITIONS
:
post
=
contractmethods
.
get
(
"post_"
+
name
,
None
)
if
post
is
not
None
:
meth
=
add_postcondition
(
meth
,
post
)
if
(
strength
&
INVARIANTS
)
and
inv
\
and
type
(
meth
)
is
type
(
add_contracts
):
if
name
<>
'__init__'
:
meth
=
add_precondition
(
meth
,
inv
)
meth
=
add_postcondition
(
meth
,
inv
)
newmethods
[
name
]
=
meth
return
new
.
classobj
(
target_class
.
__name__
,
target_class
.
__bases__
,
newmethods
)
def
add_precondition
(
meth
,
cond
):
meth
=
Function
(
meth
)
cond
=
Function
(
cond
)
mcs
=
meth
.
func_code
.
co_code
ccs
=
cond
.
func_code
.
co_code
nlocals
=
len
(
meth
.
func_code
.
co_varnames
)
nconsts
=
len
(
meth
.
func_code
.
co_consts
)
nnames
=
len
(
meth
.
func_code
.
co_names
)
nargs
=
meth
.
func_code
.
co_argcount
retops
=
[]
for
op
in
ccs
:
if
op
.
__class__
is
RETURN_VALUE
:
# RETURN_VALUEs have to be replaced by JUMP_FORWARDs
newop
=
JUMP_FORWARD
()
ccs
[
ccs
.
index
(
op
)]
=
newop
retops
.
append
(
newop
)
elif
op
.
op
in
dis
.
hasname
:
op
.
arg
=
op
.
arg
+
nnames
elif
op
.
op
in
dis
.
haslocal
:
if
op
.
arg
>=
nargs
:
op
.
arg
=
op
.
arg
+
nlocals
elif
op
.
op
in
dis
.
hasconst
:
op
.
arg
=
op
.
arg
+
nconsts
new
=
POP_TOP
()
mcs
.
insert
(
0
,
new
)
mcs
[
0
:
0
]
=
ccs
.
opcodes
for
op
in
retops
:
op
.
label
.
op
=
new
meth
.
func_code
.
co_consts
.
extend
(
cond
.
func_code
.
co_consts
)
meth
.
func_code
.
co_varnames
.
extend
(
cond
.
func_code
.
co_varnames
)
meth
.
func_code
.
co_names
.
extend
(
cond
.
func_code
.
co_names
)
return
meth
.
make_function
()
def
add_postcondition
(
meth
,
cond
):
""" a bit of a monster! """
meth
=
Function
(
meth
)
cond
=
Function
(
cond
)
mcode
=
meth
.
func_code
ccode
=
cond
.
func_code
mcs
=
mcode
.
co_code
ccs
=
ccode
.
co_code
nlocals
=
len
(
mcode
.
co_varnames
)
nconsts
=
len
(
mcode
.
co_consts
)
nnames
=
len
(
mcode
.
co_names
)
nargs
=
ccode
.
co_argcount
cretops
=
[]
Result_index
=
len
(
meth
.
func_code
.
co_varnames
)
mcode
.
co_varnames
.
append
(
'Result'
)
old_refs
=
find_old_refs
(
cond
)
for
op
in
ccs
:
if
op
.
__class__
is
RETURN_VALUE
:
newop
=
JUMP_FORWARD
()
ccs
[
ccs
.
index
(
op
)]
=
newop
cretops
.
append
(
newop
)
elif
op
.
op
in
dis
.
hasname
:
if
cond
.
func_code
.
co_names
[
op
.
arg
]
==
'Result'
\
and
op
.
__class__
is
LOAD_GLOBAL
:
ccs
[
ccs
.
index
(
op
)]
=
LOAD_FAST
(
Result_index
)
else
:
op
.
arg
=
op
.
arg
+
nnames
elif
op
.
op
in
dis
.
haslocal
:
if
op
.
arg
>=
nargs
:
op
.
arg
=
op
.
arg
+
nlocals
+
1
# + 1 for Result
elif
op
.
op
in
dis
.
hasconst
:
op
.
arg
=
op
.
arg
+
nconsts
# lets generate the prologue code to save values for `Old'
# references and point the LOAD_FASTs inserted by
# find_old_refs to the right locations.
prologue
=
[]
for
ref
,
load_op
in
old_refs
:
if
ref
[
0
]
in
mcode
.
co_varnames
:
prologue
.
append
(
LOAD_FAST
(
mcode
.
co_varnames
.
index
(
ref
[
0
])))
else
:
prologue
.
append
(
LOAD_GLOBAL
(
mcode
.
name_index
(
ref
[
0
])))
for
name
in
ref
[
1
:]:
prologue
.
append
(
LOAD_ATTR
(
mcode
.
name_index
(
name
)))
lname
=
string
.
join
(
ref
,
'.'
)
lindex
=
len
(
mcode
.
co_varnames
)
mcode
.
co_varnames
.
append
(
lname
)
prologue
.
append
(
STORE_FAST
(
lindex
))
load_op
.
arg
=
lindex
mcs
[
0
:
0
]
=
prologue
mretops
=
[]
for
op
in
mcs
:
if
op
.
__class__
is
RETURN_VALUE
:
newop
=
JUMP_FORWARD
()
mcs
[
mcs
.
index
(
op
)]
=
newop
mretops
.
append
(
newop
)
n
=
len
(
mcs
)
# insert the condition code
mcs
[
n
:
n
]
=
ccs
.
opcodes
# store the returned value in Result
store_result
=
STORE_FAST
(
Result_index
)
mcs
.
insert
(
n
,
store_result
)
# target the returns in the method to this store
for
op
in
mretops
:
op
.
label
.
op
=
store_result
# the post condition will leave a value on the stack; lose it.
# could just strip off the LOAD_CONST & RETURN_VALLUE at the
# end of the function and scan for RETURN_VALUES in the
# postcondition as a postcondition shouldn't be returning
# things (certainly not other than None).
new
=
POP_TOP
()
mcs
.
append
(
new
)
# redirect returns in the condition to the POP_TOP just
# inserted...
for
op
in
cretops
:
op
.
label
.
op
=
new
# actually return Result...
mcs
.
append
(
LOAD_FAST
(
Result_index
))
mcs
.
append
(
RETURN_VALUE
())
# and add the new constants and names (to avoid core dumps!)
mcode
.
co_consts
.
extend
(
ccode
.
co_consts
)
mcode
.
co_varnames
.
extend
(
ccode
.
co_varnames
)
mcode
.
co_names
.
extend
(
ccode
.
co_names
)
return
meth
.
make_function
()
def
find_old_refs
(
func
):
chaining
=
0
refs
=
[]
ref
=
[]
code
=
func
.
func_code
cs
=
code
.
co_code
i
=
0
while
i
<
len
(
cs
):
op
=
cs
[
i
]
if
not
chaining
:
if
op
.
__class__
is
LOAD_GLOBAL
:
if
code
.
co_names
[
op
.
arg
]
==
'Old'
:
chaining
=
1
else
:
if
op
.
__class__
is
LOAD_ATTR
:
ref
.
append
(
code
.
co_names
[
op
.
arg
])
else
:
newop
=
LOAD_FAST
(
0
)
cs
[
i
-
len
(
ref
)
-
1
:
i
]
=
[
newop
]
i
=
i
-
len
(
ref
)
refs
.
append
((
ref
,
newop
))
ref
=
[]
chaining
=
0
i
=
i
+
1
return
refs
else
:
# if not __debug__
def
add_contracts
(
target_class
,
contracts_class
):
return
target_class
# example
class
Uncontracted
:
def
__init__
(
self
,
x
,
y
):
self
.
x
=
x
self
.
y
=
y
def
do
(
self
):
# self.x = self.x + 1 # sneaky!
return
self
.
x
/
self
.
y
class
Contracts
:
def
pre___init__
(
self
,
x
,
y
):
assert
y
<>
0
def
post_do
(
self
):
assert
Old
.
self
.
x
==
self
.
x
assert
Old
.
self
.
y
==
self
.
y
assert
Result
>
0
,
"Result was %s"
%
`Result`
def
class_invariants
(
self
):
assert
self
.
x
>
0
Contracted
=
add_contracts
(
Uncontracted
,
Contracts
)
lib/python/Products/PythonScripts/zbytecodehacks/find_function_call.py
0 → 100755
View file @
6429477d
from
code_editor
import
Function
from
ops
import
*
def
find_function_call
(
infunc
,
calledfuncname
,
allowkeywords
=
0
,
startindex
=
0
):
i
=
startindex
code
=
infunc
.
func_code
cs
=
code
.
co_code
def
match
(
op
,
name
=
calledfuncname
):
return
getattr
(
op
,
'name'
,
None
)
==
name
while
i
<
len
(
cs
):
op
=
code
.
co_code
[
i
]
if
match
(
op
):
try
:
if
allowkeywords
:
return
simulate_stack_with_keywords
(
code
,
i
)
else
:
return
simulate_stack
(
code
,
i
)
except
:
i
=
i
+
1
i
=
i
+
1
if
allowkeywords
:
return
None
,
0
else
:
return
None
def
call_stack_length_usage
(
arg
):
num_keyword_args
=
arg
>>
8
num_regular_args
=
arg
&
0xFF
return
2
*
num_keyword_args
+
num_regular_args
def
simulate_stack
(
code
,
index_start
):
stack
=
[]
cs
=
code
.
co_code
i
,
n
=
index_start
,
len
(
cs
)
while
i
<
n
:
op
=
cs
[
i
]
if
op
.
__class__
is
CALL_FUNCTION
and
op
.
arg
+
1
==
len
(
stack
):
stack
.
append
(
op
)
return
stack
elif
op
.
is_jump
():
i
=
cs
.
index
(
op
.
label
.
op
)
+
1
else
:
op
.
execute
(
stack
)
i
=
i
+
1
raise
"no call found!"
def
simulate_stack_with_keywords
(
code
,
index_start
):
stack
=
[]
cs
=
code
.
co_code
i
,
n
=
index_start
,
len
(
cs
)
while
i
<
n
:
op
=
cs
[
i
]
if
op
.
__class__
is
CALL_FUNCTION
\
and
call_stack_length_usage
(
op
.
arg
)
+
1
==
len
(
stack
):
stack
.
append
(
op
)
return
stack
,
op
.
arg
>>
8
elif
op
.
is_jump
():
i
=
cs
.
index
(
op
.
label
.
op
)
+
1
else
:
op
.
execute
(
stack
)
i
=
i
+
1
raise
"no call found!"
lib/python/Products/PythonScripts/zbytecodehacks/iif.py
0 → 100755
View file @
6429477d
from
code_editor
import
Function
from
ops
import
*
from
find_function_call
import
find_function_call
def
iifize
(
func
):
func
=
Function
(
func
)
cs
=
func
.
func_code
.
co_code
while
1
:
stack
=
find_function_call
(
func
,
"iif"
)
if
stack
is
None
:
break
load
,
test
,
consequent
,
alternative
,
call
=
stack
cs
.
remove
(
load
)
jump1
=
JUMP_IF_FALSE
(
alternative
)
cs
.
insert
(
cs
.
index
(
test
)
+
1
,
jump1
)
jump2
=
JUMP_FORWARD
(
call
)
cs
.
insert
(
cs
.
index
(
consequent
)
+
1
,
jump2
)
cs
.
remove
(
call
)
cs
=
None
return
func
.
make_function
()
lib/python/Products/PythonScripts/zbytecodehacks/inline.py
0 → 100755
View file @
6429477d
import
dis
from
code_editor
import
Function
from
find_function_call
import
find_function_call
from
ops
import
\
LOAD_GLOBAL
,
RETURN_VALUE
,
SET_LINENO
,
CALL_FUNCTION
,
\
JUMP_FORWARD
,
STORE_FAST
INLINE_MAX_DEPTH
=
100
def
inline
(
func
,
**
funcs
):
func
=
Function
(
func
)
code
=
func
.
func_code
for
name
,
function
in
funcs
.
items
():
count
=
inline1
(
func
,
name
,
function
)
if
count
<>
0
:
fcode
=
function
.
func_code
code
.
co_consts
=
code
.
co_consts
+
list
(
fcode
.
co_consts
)
code
.
co_varnames
=
code
.
co_varnames
+
list
(
fcode
.
co_varnames
)
code
.
co_names
=
code
.
co_names
+
list
(
fcode
.
co_names
)
code
.
co_stacksize
=
code
.
co_stacksize
+
fcode
.
co_stacksize
return
func
.
make_function
()
def
munge_code
(
function
,
code
):
f
=
Function
(
function
)
fcs
=
f
.
func_code
.
co_code
i
,
n
=
0
,
len
(
fcs
)
retops
=
[]
while
i
<
n
:
op
=
fcs
[
i
]
if
op
.
__class__
is
RETURN_VALUE
:
# RETURN_VALUEs have to be replaced by JUMP_FORWARDs
newop
=
JUMP_FORWARD
()
fcs
[
i
]
=
newop
retops
.
append
(
newop
)
elif
op
.
op
in
dis
.
hasname
:
op
.
arg
=
op
.
arg
+
len
(
code
.
co_names
)
elif
op
.
op
in
dis
.
haslocal
:
op
.
arg
=
op
.
arg
+
len
(
code
.
co_varnames
)
elif
op
.
op
in
dis
.
hasconst
:
op
.
arg
=
op
.
arg
+
len
(
code
.
co_consts
)
# should we hack out SET_LINENOs? doesn't seem worth it.
i
=
i
+
1
return
fcs
.
opcodes
,
retops
def
inline1
(
func
,
funcname
,
function
):
code
=
func
.
func_code
cs
=
code
.
co_code
count
=
0
defaults_added
=
0
while
count
<
INLINE_MAX_DEPTH
:
stack
,
numkeywords
=
find_function_call
(
func
,
funcname
,
allowkeywords
=
1
)
if
stack
is
None
:
return
count
count
=
count
+
1
load_func
,
posargs
,
kwargs
,
function_call
=
\
stack
[
0
],
stack
[
1
:
-
2
*
numkeywords
-
1
],
stack
[
-
2
*
numkeywords
-
1
:
-
1
],
stack
[
-
1
]
kw
=
{}
for
i
in
range
(
0
,
len
(
kwargs
),
2
):
name
=
code
.
co_consts
[
kwargs
[
i
].
arg
]
valuesrc
=
kwargs
[
i
+
1
]
kw
[
name
]
=
valuesrc
varnames
=
list
(
function
.
func_code
.
co_varnames
)
for
i
in
kw
.
keys
():
if
i
in
varnames
:
if
varnames
.
index
(
i
)
<
len
(
posargs
):
raise
TypeError
,
"keyword parameter redefined"
else
:
raise
TypeError
,
"unexpected keyword argument: %s"
%
i
# no varargs yet!
# flags = function.func_code.co_flags
# varargs = flags & (1<<2)
# varkeys = flags & (1<<3)
args_got
=
len
(
kw
)
+
len
(
posargs
)
args_expected
=
function
.
func_code
.
co_argcount
if
args_got
>
args_expected
:
raise
TypeError
,
"too many arguments; expected %d, got %d"
%
(
ac
,
len
(
lf
)
+
len
(
posargs
))
elif
args_got
<
args_expected
:
# default args?
raise
TypeError
,
"not enough arguments; expected %d, got %d"
%
(
ac
,
len
(
lf
)
+
len
(
posargs
))
cs
.
remove
(
load_func
)
local_index
=
len
(
code
.
co_varnames
)
for
insn
in
posargs
:
new
=
STORE_FAST
(
local_index
)
cs
.
insert
(
cs
.
index
(
insn
)
+
1
,
new
)
labels
=
cs
.
find_labels
(
cs
.
index
(
new
)
+
1
)
for
label
in
labels
:
label
.
op
=
new
local_index
=
local_index
+
1
for
name
,
insn
in
kw
.
items
():
new
=
STORE_FAST
(
varnames
.
index
(
name
)
+
len
(
code
.
co_varnames
))
cs
.
insert
(
cs
.
index
(
insn
)
+
1
,
new
)
labels
=
cs
.
find_labels
(
cs
.
index
(
new
)
+
1
)
for
label
in
labels
:
label
.
op
=
new
newops
,
retops
=
munge_code
(
function
,
code
)
call_index
=
cs
.
index
(
function_call
)
nextop
=
cs
[
call_index
+
1
]
cs
[
call_index
:
call_index
+
1
]
=
newops
for
op
in
retops
:
op
.
label
.
op
=
nextop
raise
RuntimeError
,
"are we trying to inline a recursive function here?"
lib/python/Products/PythonScripts/zbytecodehacks/label.py
0 → 100755
View file @
6429477d
import
struct
class
Label
:
def
__init__
(
self
,
byte
=
None
):
self
.
byte
=
byte
self
.
__op
=
None
self
.
absrefs
=
[]
self
.
relrefs
=
[]
def
resolve
(
self
,
code
):
self
.
__op
=
code
.
opcodes
[
code
.
byte2op
[
self
.
byte
]]
def
add_absref
(
self
,
byte
):
# request that the absolute address of self.op be written to
# the argument of the opcode starting at byte in the
# codestring
self
.
absrefs
.
append
(
byte
)
def
add_relref
(
self
,
byte
):
# request that the relative address of self.op be written to
# the argument of the opcode starting at byte in the
# codestring
self
.
relrefs
.
append
(
byte
)
def
__setattr__
(
self
,
attr
,
value
):
if
attr
==
'op'
:
self
.
__op
=
value
else
:
self
.
__dict__
[
attr
]
=
value
def
__getattr__
(
self
,
attr
):
if
attr
==
'op'
:
return
self
.
__op
else
:
raise
AttributeError
,
attr
def
write_refs
(
self
,
cs
):
address
=
self
.
__op
.
byte
for
byte
in
self
.
absrefs
:
cs
.
seek
(
byte
+
1
)
cs
.
write
(
struct
.
pack
(
'<h'
,
address
))
for
byte
in
self
.
relrefs
:
offset
=
address
-
byte
-
3
cs
.
seek
(
byte
+
1
)
cs
.
write
(
struct
.
pack
(
'<h'
,
offset
))
lib/python/Products/PythonScripts/zbytecodehacks/macro.py
0 → 100755
View file @
6429477d
import
dis
from
code_editor
import
Function
from
find_function_call
import
find_function_call
from
ops
import
*
MAX_MACRO_DEPTH
=
100
_macros
=
{}
def
add_macro
(
arg1
,
arg2
=
None
):
if
arg2
is
None
:
_macros
[
arg1
.
func_name
]
=
arg1
else
:
_macros
[
arg1
]
=
arg2
def
expand
(
func
,
macros
=
None
):
func
=
Function
(
func
)
code
=
func
.
func_code
if
macros
is
None
:
macros
=
_macros
insertions
=
{}
trips
=
0
while
trips
<
MAX_MACRO_DEPTH
:
outercount
=
0
for
name
,
macro
in
macros
.
items
():
count
=
expand1
(
func
,
name
,
macro
)
outercount
=
outercount
+
count
if
count
<>
0
and
not
insertions
.
has_key
(
macro
):
fcode
=
macro
.
func_code
code
.
co_consts
=
code
.
co_consts
+
list
(
fcode
.
co_consts
)
code
.
co_varnames
=
code
.
co_varnames
+
list
(
fcode
.
co_varnames
)
code
.
co_names
=
code
.
co_names
+
list
(
fcode
.
co_names
)
code
.
co_stacksize
=
code
.
co_stacksize
+
fcode
.
co_stacksize
insertions
[
macro
]
=
0
if
not
outercount
:
return
func
.
make_function
()
trips
=
trips
+
1
raise
RuntimeError
,
"unbounded recursion?!"
def
expand_these
(
func
,
**
macros
):
return
expand
(
func
,
macros
)
def
remove_epilogue
(
cs
):
try
:
last
,
butone
,
buttwo
=
cs
[
-
3
:]
except
:
return
if
last
.
__class__
is
buttwo
.
__class__
is
RETURN_VALUE
:
if
butone
.
__class__
is
LOAD_CONST
:
if
cs
.
code
.
co_consts
[
butone
.
arg
]
is
None
:
if
not
(
cs
.
find_labels
(
-
1
)
or
cs
.
find_labels
(
-
2
)):
del
cs
[
-
2
:]
def
munge_code
(
function
,
code
,
imported_locals
):
f
=
Function
(
function
)
fcs
=
f
.
func_code
.
co_code
if
fcs
[
0
].
__class__
is
SET_LINENO
:
del
fcs
[
1
:
1
+
2
*
len
(
imported_locals
)]
else
:
del
fcs
[
0
:
2
*
len
(
imported_locals
)]
# a nicety: let's see if the last couple of opcodes are necessary
# (Python _always_ adds a LOAD_CONST None, RETURN_VALUE to the end
# of a function, and I'd like to get rid of that if we can).
remove_epilogue
(
fcs
)
i
,
n
=
0
,
len
(
fcs
)
retops
=
[]
while
i
<
n
:
op
=
fcs
[
i
]
if
op
.
__class__
is
RETURN_VALUE
:
# RETURN_VALUEs have to be replaced by JUMP_FORWARDs
newop
=
JUMP_FORWARD
()
fcs
[
i
]
=
newop
retops
.
append
(
newop
)
elif
op
.
op
in
dis
.
hasname
:
op
.
arg
=
op
.
arg
+
len
(
code
.
co_names
)
elif
op
.
op
in
dis
.
haslocal
:
localname
=
f
.
func_code
.
co_varnames
[
op
.
arg
]
op
.
arg
=
imported_locals
.
get
(
localname
,
op
.
arg
+
len
(
code
.
co_varnames
))
elif
op
.
op
in
dis
.
hasconst
:
op
.
arg
=
op
.
arg
+
len
(
code
.
co_consts
)
# should we hack out SET_LINENOs? doesn't seem worth it.
i
=
i
+
1
return
fcs
.
opcodes
,
retops
def
expand1
(
func
,
name
,
macro
):
code
=
func
.
func_code
cs
=
code
.
co_code
count
=
0
macrocode
=
macro
.
func_code
while
count
<
MAX_MACRO_DEPTH
:
stack
=
find_function_call
(
func
,
name
)
if
stack
is
None
:
return
count
count
=
count
+
1
load_func
,
args
,
function_call
=
\
stack
[
0
],
stack
[
1
:
-
1
],
stack
[
-
1
]
args_got
=
len
(
args
)
args_expected
=
macrocode
.
co_argcount
if
args_got
>
args_expected
:
raise
TypeError
,
"too many arguments; expected %d, got %d"
%
(
args_expected
,
args_got
)
elif
args_got
<
args_expected
:
# default args?
raise
TypeError
,
"not enough arguments; expected %d, got %d"
%
(
args_expected
,
args_got
)
cs
.
remove
(
load_func
)
arg_names
=
macrocode
.
co_varnames
[:
macrocode
.
co_argcount
]
import_args
=
[]
normal_args
=
[]
for
i
in
range
(
len
(
arg_names
)):
if
arg_names
[
i
][
0
]
==
'.'
:
import_args
.
append
(
args
[
i
])
else
:
normal_args
.
append
(
args
[
i
])
imported_locals
=
{}
for
insn
in
import_args
:
cs
.
remove
(
insn
)
if
insn
.
__class__
is
LOAD_GLOBAL
:
name
=
code
.
co_names
[
insn
.
arg
]
var
=
global_to_local
(
code
,
name
)
elif
insn
.
__class__
is
not
LOAD_FAST
:
raise
TypeError
,
"imported arg must be local"
else
:
var
=
insn
.
arg
argindex
=
macrocode
.
co_argcount
+
import_args
.
index
(
insn
)
argname
=
macrocode
.
co_varnames
[
argindex
]
imported_locals
[
argname
]
=
var
local_index
=
len
(
code
.
co_varnames
)
for
insn
in
normal_args
:
new
=
STORE_FAST
(
local_index
+
args
.
index
(
insn
))
cs
.
insert
(
cs
.
index
(
insn
)
+
1
,
new
)
labels
=
cs
.
find_labels
(
cs
.
index
(
new
)
+
1
)
for
label
in
labels
:
label
.
op
=
new
newops
,
retops
=
munge_code
(
macro
,
code
,
imported_locals
)
call_index
=
cs
.
index
(
function_call
)
nextop
=
cs
[
call_index
+
1
]
cs
[
call_index
:
call_index
+
1
]
=
newops
for
op
in
retops
:
if
cs
.
index
(
nextop
)
-
cs
.
index
(
op
)
==
1
:
cs
.
remove
(
op
)
else
:
op
.
label
.
op
=
nextop
raise
RuntimeError
,
"are we trying to expand a recursive macro here?"
def
global_to_local
(
code
,
name
):
"""
\
internal function to make a global variable into
a local one, for the case that setq is the first
reference to a variable.
Modifies a code object in-place.
Return value is index into variable table
"""
cs
=
code
.
co_code
index
=
len
(
code
.
co_varnames
)
code
.
co_varnames
.
append
(
name
)
for
i
in
range
(
len
(
cs
)):
op
=
cs
[
i
]
if
op
.
__class__
not
in
[
LOAD_GLOBAL
,
STORE_GLOBAL
]:
continue
thisname
=
code
.
co_names
[
op
.
arg
]
if
thisname
<>
name
:
continue
if
op
.
__class__
is
LOAD_GLOBAL
:
cs
[
i
]
=
LOAD_FAST
(
index
)
else
:
cs
[
i
]
=
STORE_FAST
(
index
)
return
index
lib/python/Products/PythonScripts/zbytecodehacks/macros.py
0 → 100755
View file @
6429477d
from
macro
import
add_macro
def
main
():
def
setq
((
x
),
v
):
x
=
v
return
v
add_macro
(
setq
)
def
pre_incr
((
x
)):
x
=
x
+
1
return
x
add_macro
(
pre_incr
)
def
post_incr
((
x
)):
t
=
x
x
=
x
+
1
return
t
add_macro
(
post_incr
)
def
pre_decr
((
x
)):
x
=
x
-
1
return
x
add_macro
(
pre_decr
)
def
post_decr
((
x
)):
t
=
x
x
=
x
+
1
return
t
add_macro
(
post_decr
)
def
add_set
((
x
),
v
):
x
=
x
+
v
return
x
add_macro
(
add_set
)
def
sub_set
((
x
),
v
):
x
=
x
-
v
return
x
add_macro
(
sub_set
)
def
mul_set
((
x
),
v
):
x
=
x
*
v
return
x
add_macro
(
mul_set
)
def
div_set
((
x
),
v
):
x
=
x
/
v
return
x
add_macro
(
div_set
)
def
mod_set
((
x
),
v
):
x
=
x
%
v
return
x
add_macro
(
mod_set
)
main
()
def
test
():
from
macro
import
expand
def
f
(
x
):
i
=
0
while
pre_incr
(
i
)
<
len
(
x
):
if
setq
(
c
,
x
[
i
])
==
3
:
print
c
,
42
x
=
expand
(
f
)
return
x
x
(
range
(
10
))
lib/python/Products/PythonScripts/zbytecodehacks/opbases.py
0 → 100755
View file @
6429477d
import
struct
,
dis
,
new
from
label
import
Label
class
ByteCode
:
pass
class
GenericOneByteCode
(
ByteCode
):
def
__init__
(
self
,
cs
,
code
):
pass
def
__repr__
(
self
):
return
self
.
__class__
.
__name__
def
assemble
(
self
,
code
):
return
self
.
opc
def
is_jump
(
self
):
return
0
def
has_name
(
self
):
return
0
def
has_name_or_local
(
self
):
return
self
.
has_name
()
or
self
.
has_local
()
def
has_local
(
self
):
return
0
class
GenericThreeByteCode
(
GenericOneByteCode
):
def
__init__
(
self
,
cs
,
code
):
GenericOneByteCode
.
__init__
(
self
,
cs
,
code
)
arg
=
cs
.
read
(
2
)
self
.
arg
=
struct
.
unpack
(
'<h'
,
arg
)[
0
]
def
__repr__
(
self
):
return
"%s %d"
%
(
self
.
__class__
.
__name__
,
self
.
arg
)
def
assemble
(
self
,
code
):
return
self
.
opc
+
struct
.
pack
(
'<h'
,
self
.
arg
)
def
user_init
(
self
,
arg
):
self
.
arg
=
arg
class
Jump
(
GenericThreeByteCode
):
def
__repr__
(
self
):
return
"%s %s"
%
(
self
.
__class__
.
__name__
,
`self.label`
)
def
is_jump
(
self
):
return
1
def
user_init
(
self
,
arg
):
self
.
label
.
op
=
arg
class
JRel
(
Jump
):
def
__init__
(
self
,
cs
,
code
):
GenericThreeByteCode
.
__init__
(
self
,
cs
,
code
)
self
.
label
=
Label
(
cs
.
tell
()
+
self
.
arg
)
code
.
add_label
(
self
.
label
)
def
assemble
(
self
,
code
):
self
.
label
.
add_relref
(
self
.
byte
)
return
self
.
opc
+
'
\
000
\
000
'
class
JAbs
(
Jump
):
def
__init__
(
self
,
cs
,
code
):
GenericThreeByteCode
.
__init__
(
self
,
cs
,
code
)
self
.
label
=
Label
(
self
.
arg
)
code
.
add_label
(
self
.
label
)
def
assemble
(
self
,
code
):
self
.
label
.
add_absref
(
self
.
byte
)
return
self
.
opc
+
'
\
000
\
000
'
class
_NamedOpcode
(
GenericThreeByteCode
):
def
user_init
(
self
,
arg
):
if
type
(
arg
)
==
type
(
1
):
self
.
arg
=
arg
else
:
self
.
name
=
arg
def
__repr__
(
self
):
if
hasattr
(
self
,
"name"
):
return
"%s : %s"
%
(
self
.
__class__
.
__name__
,
self
.
name
)
else
:
return
"%s : %d"
%
(
self
.
__class__
.
__name__
,
self
.
arg
)
class
NameOpcode
(
_NamedOpcode
):
def
__init__
(
self
,
cs
,
code
):
GenericThreeByteCode
.
__init__
(
self
,
cs
,
code
)
self
.
name
=
code
.
code
.
co_names
[
self
.
arg
]
def
has_name
(
self
):
return
1
def
assemble
(
self
,
code
):
if
hasattr
(
self
,
"name"
)
and
not
hasattr
(
self
,
"arg"
):
self
.
arg
=
code
.
code
.
name_index
(
self
.
name
)
return
GenericThreeByteCode
.
assemble
(
self
,
code
)
class
LocalOpcode
(
_NamedOpcode
):
def
__init__
(
self
,
cs
,
code
):
GenericThreeByteCode
.
__init__
(
self
,
cs
,
code
)
self
.
name
=
code
.
code
.
co_varnames
[
self
.
arg
]
def
has_local
(
self
):
return
1
def
assemble
(
self
,
code
):
if
hasattr
(
self
,
"name"
)
and
not
hasattr
(
self
,
"arg"
):
self
.
arg
=
code
.
code
.
local_index
(
self
.
name
)
return
GenericThreeByteCode
.
assemble
(
self
,
code
)
lib/python/Products/PythonScripts/zbytecodehacks/ops.py
0 → 100755
View file @
6429477d
This diff is collapsed.
Click to expand it.
lib/python/Products/PythonScripts/zbytecodehacks/rationalize.py
0 → 100755
View file @
6429477d
import
code_editor
from
ops
import
*
import
operator
CONDJUMP
=
[
JUMP_IF_TRUE
,
JUMP_IF_FALSE
]
UNCONDJUMP
=
[
JUMP_FORWARD
,
JUMP_ABSOLUTE
]
UNCOND
=
UNCONDJUMP
+
[
BREAK_LOOP
,
STOP_CODE
,
RETURN_VALUE
,
\
RAISE_VARARGS
]
PYBLOCK
=
[
SETUP_LOOP
,
SETUP_EXCEPT
,
SETUP_FINALLY
]
PYENDBLOCK
=
[
POP_BLOCK
]
binaryops
=
{
'BINARY_ADD'
:
operator
.
add
,
'BINARY_SUBTRACT'
:
operator
.
sub
,
'BINARY_MULTIPLY'
:
operator
.
mul
,
'BINARY_DIVIDE'
:
operator
.
div
,
'BINARY_MODULO'
:
operator
.
mod
,
'BINARY_POWER'
:
pow
,
'BINARY_LSHIFT'
:
operator
.
lshift
,
'BINARY_RSHIFT'
:
operator
.
rshift
,
'BINARY_AND'
:
operator
.
and_
,
'BINARY_OR'
:
operator
.
or_
,
'BINARY_XOR'
:
operator
.
xor
}
unaryops
=
{
'UNARY_POS'
:
operator
.
pos
,
'UNARY_NEG'
:
operator
.
neg
,
'UNARY_NOT'
:
operator
.
not_
}
def
rationalize
(
code
):
calculateConstants
(
code
)
strip_setlineno
(
code
)
simplifyjumps
(
code
)
removeconstjump
(
code
)
simplifyjumps
(
code
)
eliminateUnusedNames
(
code
)
eliminateUnusedLocals
(
code
)
def
calculateConstants
(
co
):
"""Precalculate results of operations involving constants."""
cs
=
co
.
co_code
cc
=
co
.
co_consts
stack
=
[]
i
=
0
while
i
<
len
(
cs
):
op
=
cs
[
i
]
if
binaryops
.
has_key
(
op
.
__class__
.
__name__
):
if
stack
[
-
1
].
__class__
is
stack
[
-
2
].
__class__
is
LOAD_CONST
:
arg1
=
cc
[
stack
[
-
2
].
arg
]
arg2
=
cc
[
stack
[
-
1
].
arg
]
result
=
binaryops
[
op
.
__class__
.
__name__
](
arg1
,
arg2
)
if
result
in
cc
:
arg
=
cc
.
index
(
result
)
else
:
arg
=
len
(
cc
)
cc
.
append
(
result
)
cs
.
remove
(
stack
[
-
2
])
cs
.
remove
(
stack
[
-
1
])
i
=
i
-
2
cs
[
i
]
=
LOAD_CONST
(
arg
)
stack
.
pop
()
stack
.
pop
()
stack
.
append
(
cs
[
i
])
else
:
op
.
execute
(
stack
)
elif
unaryops
.
has_key
(
op
.
__class__
.
__name__
):
if
stack
[
-
1
].
__class__
is
LOAD_CONST
:
arg1
=
cc
[
stack
[
-
1
].
arg
]
result
=
unaryops
[
op
.
__class__
.
__name__
](
arg1
)
if
result
in
cc
:
arg
=
cc
.
index
(
result
)
else
:
arg
=
len
(
cc
)
cc
.
append
(
result
)
cs
.
remove
(
stack
[
-
1
])
i
=
i
-
1
cs
[
i
]
=
LOAD_CONST
(
arg
)
stack
.
pop
()
stack
.
append
(
cs
[
i
])
else
:
op
.
execute
(
stack
)
else
:
# this is almost certainly wrong
try
:
op
.
execute
(
stack
)
except
:
pass
i
=
i
+
1
def
strip_setlineno
(
co
):
"""Take in an EditableCode object and strip the SET_LINENO bytecodes"""
i
=
0
while
i
<
len
(
co
.
co_code
):
op
=
co
.
co_code
[
i
]
if
op
.
__class__
is
SET_LINENO
:
co
.
co_code
.
remove
(
op
)
else
:
i
=
i
+
1
def
simplifyjumps
(
co
):
cs
=
co
.
co_code
i
=
0
pyblockstack
=
[
None
]
loopstack
=
[
None
]
trystack
=
[
None
]
firstlook
=
1
while
i
<
len
(
cs
):
op
=
cs
[
i
]
# new pyblock?
if
firstlook
:
if
op
.
__class__
in
PYBLOCK
:
pyblockstack
.
append
(
op
)
if
op
.
__class__
is
SETUP_LOOP
:
loopstack
.
append
(
op
.
label
.
op
)
else
:
trystack
.
append
(
op
.
label
.
op
)
# end of pyblock?
elif
op
.
__class__
==
POP_BLOCK
:
op2
=
pyblockstack
.
pop
()
if
op2
.
__class__
==
SETUP_LOOP
:
loopstack
.
pop
()
else
:
trystack
.
pop
()
# Is the code inaccessible
if
i
>=
1
:
if
cs
[
i
-
1
].
__class__
in
UNCOND
and
not
(
cs
.
find_labels
(
i
)
or
\
op
.
__class__
in
PYENDBLOCK
):
cs
.
remove
(
op
)
firstlook
=
1
continue
# are we jumping from the statement before?
if
cs
[
i
-
1
].
__class__
in
UNCONDJUMP
:
if
cs
[
i
-
1
].
label
.
op
==
op
:
cs
.
remove
(
cs
[
i
-
1
])
firstlook
=
1
continue
# break before end of loop?
elif
cs
[
i
-
1
].
__class__
==
BREAK_LOOP
:
if
op
.
__class__
==
POP_BLOCK
:
cs
.
remove
(
cs
[
i
-
1
])
firstlook
=
1
continue
# Do we have an unconditional jump to an unconditional jump?
if
op
.
__class__
in
UNCONDJUMP
:
if
op
.
label
.
op
.
__class__
in
UNCONDJUMP
:
refop
=
op
.
label
.
op
if
op
.
__class__
==
JUMP_FORWARD
:
newop
=
JUMP_ABSOLUTE
()
newop
.
label
.
op
=
refop
.
label
.
op
cs
[
i
]
=
newop
else
:
op
.
label
.
op
=
refop
.
label
.
op
firstlook
=
0
continue
# Do we have a conditional jump to a break?
if
op
.
__class__
in
CONDJUMP
and
loopstack
[
-
1
]:
destindex
=
cs
.
index
(
op
.
label
.
op
)
preendindex
=
cs
.
index
(
loopstack
[
-
1
])
-
2
if
cs
[
i
+
2
].
__class__
==
BREAK_LOOP
and
cs
[
preendindex
].
__class__
\
==
POP_TOP
:
if
op
.
__class__
==
JUMP_IF_FALSE
:
newop
=
JUMP_IF_TRUE
()
else
:
newop
=
JUMP_IF_FALSE
()
newop
.
label
.
op
=
cs
[
preendindex
]
cs
[
i
]
=
newop
cs
.
remove
(
cs
[
i
+
1
])
cs
.
remove
(
cs
[
i
+
1
])
cs
.
remove
(
cs
[
i
+
1
])
firstlook
=
0
continue
elif
cs
[
destindex
+
1
].
__class__
==
BREAK_LOOP
and
\
cs
[
preendindex
].
__class__
==
POP_TOP
:
op
.
label
.
op
=
cs
[
preendindex
]
cs
.
remove
(
cs
[
destindex
])
cs
.
remove
(
cs
[
destindex
])
cs
.
remove
(
cs
[
destindex
])
firstlook
=
0
continue
firstlook
=
1
i
=
i
+
1
def
removeconstjump
(
co
):
cs
=
co
.
co_code
cc
=
co
.
co_consts
i
=
0
while
i
<
len
(
cs
):
op
=
cs
[
i
]
if
op
.
__class__
in
CONDJUMP
and
cs
[
i
-
1
].
__class__
==
LOAD_CONST
:
if
(
op
.
__class__
==
JUMP_IF_FALSE
and
cc
[
cs
[
i
-
1
].
arg
])
or
\
(
op
.
__class__
==
JUMP_IF_TRUE
and
not
cc
[
cs
[
i
-
1
].
arg
]):
cs
.
remove
(
cs
[
i
-
1
])
cs
.
remove
(
cs
[
i
-
1
])
cs
.
remove
(
cs
[
i
-
1
])
i
=
i
-
2
else
:
cs
.
remove
(
cs
[
i
-
1
])
cs
.
remove
(
cs
[
i
])
newop
=
JUMP_FORWARD
()
newop
.
label
.
op
=
cs
[
cs
.
index
(
op
.
label
.
op
)
+
1
]
cs
[
i
-
1
]
=
newop
i
=
i
-
1
i
=
i
+
1
def
eliminateUnusedNames
(
code
):
used_names
=
{}
for
op
in
code
.
co_code
:
if
op
.
has_name
():
if
hasattr
(
op
,
"arg"
):
arg
=
op
.
arg
else
:
arg
=
op
.
arg
=
code
.
name_index
(
op
.
name
)
used_names
[
arg
]
=
1
used_names
=
used_names
.
keys
()
used_names
.
sort
()
name_mapping
=
{}
for
i
in
range
(
len
(
used_names
)):
name_mapping
[
used_names
[
i
]]
=
i
newnames
=
[]
for
i
in
range
(
len
(
code
.
co_names
)):
if
i
in
used_names
:
newnames
.
append
(
code
.
co_names
[
i
])
code
.
co_names
=
newnames
for
op
in
code
.
co_code
:
if
op
.
has_name
():
op
.
arg
=
name_mapping
[
op
.
arg
]
def
eliminateUnusedLocals
(
code
):
used_names
=
{}
for
op
in
code
.
co_code
:
if
op
.
has_local
():
if
hasattr
(
op
,
"arg"
):
arg
=
op
.
arg
else
:
arg
=
op
.
arg
=
code
.
local_index
(
op
.
name
)
used_names
[
arg
]
=
1
used_names
=
used_names
.
keys
()
used_names
.
sort
()
name_mapping
=
{}
for
i
in
range
(
len
(
used_names
)):
name_mapping
[
used_names
[
i
]]
=
i
newnames
=
[]
for
i
in
range
(
len
(
code
.
co_varnames
)):
if
i
in
used_names
:
newnames
.
append
(
code
.
co_varnames
[
i
])
code
.
co_varnames
=
newnames
for
op
in
code
.
co_code
:
if
op
.
has_local
():
op
.
arg
=
name_mapping
[
op
.
arg
]
lib/python/Products/PythonScripts/zbytecodehacks/tailr.py
0 → 100755
View file @
6429477d
from
code_editor
import
Function
from
find_function_call
import
find_function_call
from
ops
import
*
def
make_tail_recursive
(
func
):
func
=
Function
(
func
)
code
=
func
.
func_code
cs
=
code
.
co_code
index
=
0
while
1
:
stack
=
find_function_call
(
func
,
func
.
func_name
,
startindex
=
index
)
if
stack
is
None
:
break
index
=
cs
.
index
(
stack
[
-
1
])
if
cs
[
index
+
1
].
__class__
is
RETURN_VALUE
:
cs
.
remove
(
stack
[
0
])
newop
=
JUMP_ABSOLUTE
()
cs
[
index
-
1
:
index
]
=
[
newop
]
newop
.
label
.
op
=
cs
[
0
]
del
stack
[
0
],
stack
[
-
1
]
nlocals
=
len
(
code
.
co_varnames
)
code
.
co_varnames
=
code
.
co_varnames
+
code
.
co_varnames
for
op
in
stack
:
cs
.
insert
(
cs
.
index
(
op
)
+
1
,
STORE_FAST
(
stack
.
index
(
op
)
+
nlocals
))
iindex
=
cs
.
index
(
newop
)
for
i
in
range
(
len
(
stack
)):
cs
.
insert
(
iindex
,
STORE_FAST
(
i
))
cs
.
insert
(
iindex
,
LOAD_FAST
(
i
+
nlocals
))
index
=
iindex
return
func
.
make_function
()
def
_facr
(
n
,
c
,
p
):
if
c
<=
n
:
return
_facr
(
n
,
c
+
1
,
c
*
p
)
return
p
def
facr
(
n
,
_facr
=
_facr
):
return
_facr
(
n
,
1
,
1
l
)
_factr
=
make_tail_recursive
(
_facr
)
def
factr
(
n
,
_factr
=
_factr
):
return
_factr
(
n
,
1
,
1
l
)
def
faci
(
n
):
p
=
1
l
;
c
=
1
;
while
c
<=
n
:
p
=
c
*
p
c
=
c
+
1
return
p
import
time
def
suite
(
n
,
c
=
10
,
T
=
time
.
time
):
r
=
[
0
,
0
,
0
]
for
i
in
range
(
c
):
t
=
T
();
facr
(
n
);
r
[
0
]
=
T
()
-
t
+
r
[
0
]
t
=
T
();
factr
(
n
);
r
[
1
]
=
T
()
-
t
+
r
[
1
]
t
=
T
();
faci
(
n
);
r
[
2
]
=
T
()
-
t
+
r
[
2
]
print
" recursive: 1.000000000000 (arbitrarily)"
print
"tail recursive:"
,
r
[
1
]
/
r
[
0
]
print
" iterative:"
,
r
[
2
]
/
r
[
0
]
lib/python/Products/PythonScripts/zbytecodehacks/version
0 → 100755
View file @
6429477d
0.52z
lib/python/Products/PythonScripts/zbytecodehacks/xapply.py
0 → 100755
View file @
6429477d
"""
\
xapply
Inspired by Don Beaudry's functor module.
xapply exports one public function, the eponymous xapply. xapply can
be thought of as `lazy apply' or `partial argument resolution'.
It takes a function and part of it's argument list, and returns a
function with the first parameters filled in. An example:
def f(x,y):
return x+y
add1 = xapply(f,1)
add1(2) => 3
This xapply is not yet as general as that from the functor module, but
the functions return are as fast as normal function, i.e. twice as
fast as functors.
This may be generalised at some point in the future.
"""
import
new
,
string
,
re
,
types
from
ops
import
LOAD_FAST
,
LOAD_CONST
from
code_editor
import
Function
,
InstanceMethod
def
xapply_munge
(
code
,
args
,
except0
=
0
):
nconsts
=
len
(
code
.
co_consts
)
nvars
=
len
(
args
)
code
.
co_consts
.
extend
(
list
(
args
))
if
except0
:
var2constlim
=
nvars
+
1
var2constoff
=
nconsts
-
1
else
:
var2constlim
=
nvars
var2constoff
=
nconsts
cs
=
code
.
co_code
for
i
in
range
(
len
(
cs
)):
op
=
cs
[
i
]
if
op
.
__class__
is
LOAD_FAST
:
if
op
.
arg
==
0
and
except0
:
continue
if
op
.
arg
<
var2constlim
:
cs
[
i
]
=
LOAD_CONST
(
op
.
arg
+
var2constoff
)
else
:
op
.
arg
=
op
.
arg
-
nvars
code
.
co_varnames
=
code
.
co_varnames
[
nvars
:]
code
.
co_argcount
=
code
.
co_argcount
-
nvars
def
xapply_func
(
func
,
args
):
f
=
Function
(
func
)
xapply_munge
(
f
.
func_code
,
args
,
0
)
return
f
.
make_function
()
def
xapply_meth
(
meth
,
args
):
im
=
InstanceMethod
(
meth
)
xapply_munge
(
im
.
im_func
.
func_code
,
args
,
1
)
return
im
.
make_instance_method
()
def
xapply
(
callable
,
*
args
):
""" xapply(callable,arg1,arg2,...) -> callable
if
f=xapply(callable,arg1,arg2,...,argn)
then
f(arg<n+1>,....argm)
is equivalent to
callable(arg1,...,argn,arg<n+1>,..argm)
callable currently must be a function or instance method, and keyword
arguments are currently not allowed.
"""
callable_type
=
type
(
callable
)
if
callable_type
is
types
.
FunctionType
:
return
xapply_func
(
callable
,
args
)
elif
callable_type
is
types
.
UnboundMethodType
:
return
xapply_meth
(
callable
,
args
)
else
:
raise
"nope"
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