Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • branch/default
  • topic/default/defarch
  • v1.0.0
  • v1.1.0
  • v1.1.10
  • v1.1.11
  • v1.1.2
  • v1.1.3
  • v1.1.4
  • v1.1.6
  • v1.1.7
  • v2.0.0
  • v3.0.0
13 results

Target

Select target project
  • openvms/wasd/pyrte
1 result
Select Git revision
  • branch/default
  • topic/default/defarch
  • v1.0.0
  • v1.1.0
  • v1.1.10
  • v1.1.11
  • v1.1.2
  • v1.1.3
  • v1.1.4
  • v1.1.6
  • v1.1.7
  • v2.0.0
  • v3.0.0
13 results
Show changes
Commits on Source (2)
......@@ -9,3 +9,5 @@
fd3282a48af92ab896c871604ab1de697f9f2cae v1.1.11
bdd8cb18f7176c99a537d760568ae9717df424b3 v2.0.0
aff157d9025310d1eee56d29d81fd9d7ee58a922 v3.0.0
aff157d9025310d1eee56d29d81fd9d7ee58a922 v3.0.0
94b50ed5112d3ddd883fdb94aed679a9b447d403 v3.0.0
......@@ -353,7 +353,7 @@
VERSION HISTORY (update SOFTWAREVN as well!)
---------------
08-SEP-2020 MGD v3.0.0, Python 3 (via JFP Python 3.10.0a0)
10-SEP-2020 MGD v3.0.0, Python 3 (via JFP Python 3.10.0a0)
v2.0.0, Python 2 equivalent
Python 2.7.18 build kludge for
VSI C V7.4-001 on OpenVMS IA64 V8.4-2L1
......@@ -2246,8 +2246,6 @@
PyObject *args
)
{
int DataLength;
#if PY_MAJOR_VERSION >= 3
const char *DataPtr;
#else
int isuni,
DataLength;
char *DataPtr;
......@@ -2253,5 +2251,4 @@
char *DataPtr;
#endif
PyObject *pValue;
/*********/
......@@ -2274,4 +2271,5 @@
return (Py_None);
}
DEBUGPYOBJ("pValue",pValue)
#if PY_MAJOR_VERSION >= 3
......@@ -2277,7 +2275,7 @@
#if PY_MAJOR_VERSION >= 3
if (PyUnicode_Check (pValue))
if ((isuni = PyUnicode_Check (pValue)) || PyBytes_Check (pValue))
#else
if (PyString_Check (pValue))
#endif
{
#if PY_MAJOR_VERSION >= 3
......@@ -2279,9 +2277,12 @@
#else
if (PyString_Check (pValue))
#endif
{
#if PY_MAJOR_VERSION >= 3
DataPtr = PyUnicode_AsUTF8AndSize (pValue, &DataLength);
if (isuni)
DataPtr = (char*)PyUnicode_AsUTF8AndSize (pValue, &DataLength);
else
PyBytes_AsStringAndSize (pValue, &DataPtr, &DataLength);
#else
PyString_AsStringAndSize (pValue, &DataPtr, &DataLength);
#endif
......@@ -2300,4 +2301,7 @@
return (Py_None);
}
#if PY_MAJOR_VERSION >= 3
PyErr_SetString (PyExc_TypeError, "type must be Unicode, Bytes or None");
#else
PyErr_SetString (PyExc_TypeError, "type must be String or None");
......@@ -2303,4 +2307,5 @@
PyErr_SetString (PyExc_TypeError, "type must be String or None");
#endif
return (NULL);
}
......@@ -3016,7 +3021,7 @@
return (Py_None);
}
if (!PyArg_ParseTuple (args, "SO|O:start_response",
if (!PyArg_ParseTuple (args, "OO|O:start_response",
&pStatus, &pHeaders, &pWsgiExcInfo))
return (NULL);
......@@ -3079,4 +3084,7 @@
{
int cnt,
DataLength;
#if PY_MAJOR_VERSION >= 3
const char *DataPtr;
#else
char *DataPtr;
......@@ -3082,4 +3090,5 @@
char *DataPtr;
#endif
PyObject *pItem,
*pIter;
......@@ -3094,9 +3103,9 @@
DEBUGPYOBJ("pResponse",pResponse)
#if PY_MAJOR_VERSION >= 3
if (PyBytes_Check (pResponse))
if (PyUnicode_Check (pResponse))
#else
if (PyString_Check (pResponse))
#endif
{
#if PY_MAJOR_VERSION >= 3
......@@ -3098,9 +3107,9 @@
#else
if (PyString_Check (pResponse))
#endif
{
#if PY_MAJOR_VERSION >= 3
PyBytes_AsStringAndSize (pResponse, &DataPtr, &DataLength);
DataPtr = PyUnicode_AsUTF8AndSize (pResponse, &DataLength);
#else
PyString_AsStringAndSize (pResponse, &DataPtr, &DataLength);
#endif
......@@ -3117,8 +3126,8 @@
{
if (!WsgiHeadersSent) WsgiSendHeaders ();
#if PY_MAJOR_VERSION >= 3
if (PyBytes_Check (pItem))
if (PyUnicode_Check (pItem))
#else
if (PyString_Check (pItem))
#endif
#if PY_MAJOR_VERSION >= 3
......@@ -3121,8 +3130,8 @@
#else
if (PyString_Check (pItem))
#endif
#if PY_MAJOR_VERSION >= 3
if (!PyBytes_AsStringAndSize (pItem, &DataPtr, &DataLength))
if (DataPtr = PyUnicode_AsUTF8AndSize (pItem, &DataLength))
#else
if (!PyString_AsStringAndSize (pItem, &DataPtr, &DataLength))
#endif
......@@ -3152,5 +3161,6 @@
int WsgiSendHeaders ()
{
int StatusCode;
int StatusCode,
StatusLength;
char *NamePtr,
......@@ -3156,3 +3166,2 @@
char *NamePtr,
*StatusPtr,
*ValuePtr;
......@@ -3158,4 +3167,9 @@
*ValuePtr;
#if PY_MAJOR_VERSION >= 3
const char *StatusPtr;
#else
char *StatusPtr;
#endif
PyObject *pItem,
*pIter;
......@@ -3170,7 +3184,7 @@
if (!pWsgiHeaders || !pWsgiStatus) return (0);
#if PY_MAJOR_VERSION >= 3
if (!PyBytes_Check (pWsgiStatus))
if (!PyUnicode_Check (pWsgiStatus))
#else
if (!PyString_Check (pWsgiStatus))
#endif
......@@ -3181,7 +3195,7 @@
WsgiHeadersSent = 1;
#if PY_MAJOR_VERSION >= 3
StatusPtr = PyBytes_AsString (pWsgiStatus);
StatusPtr = PyUnicode_AsUTF8AndSize (pWsgiStatus, &StatusLength);
#else
StatusPtr = PyString_AsString (pWsgiStatus);
#endif
......
......@@ -60,6 +60,12 @@
padding-left:1em;
}
.indent
{
margin-left:2em;
margin-right:5em;
}
.quote {
border-style:dotted; border-color:#888888; border-width:1px;
font-size:90%;
......@@ -89,8 +95,8 @@
<h1>Python Run-Time Environment</h1>
<h3>~~~ PRE-RELEASE ~~~</h3>
<h3>Version 2.0.0, 8th September 2020
<br>Version 3.0.0, 8th September 2020</h3>
<h3>Version 2.0.0, 10th September 2020
<br>Version 3.0.0, 10th September 2020</h3>
<p><b>Copyright &copy; 2007-2020 Mark G. Daniel</b>
<br>This program, comes with ABSOLUTELY NO WARRANTY.
......@@ -335,6 +341,70 @@
after changing mapping rules.
<h3>Supporting Multiple Python Versions</h3>
<p> It is sometimes useful, sometimes necessary, to maintain multiple versions
of Python on a system, and also support multiple versions to web applications
(scripts). It is not difficult to have PyRTE activate a specific version by
wrapping the executable in a procedure that sets up the appropriate Python
environment in a process-local context.
<pre class="code">
$! CGI_BIN:PYRTE.COM
$! activate JFP Python 2.7
$ @disk$jfplib0020i:[000000]lib_logicals.com "/process"
$ @disk$jfppy1400i:[000000]python_logicals.com "/process"
$ @python_root:[vms]setup
$ pyrte == "$cgi_exe:pyrte.exe"
$ pyrte
</pre>
<pre class="code">
$! CGI_BIN:PYRTE3.COM
$! activate JFP Python 3.10
$ @disk$jfplib0020i:[000000]lib_logicals.com "/process"
$ @disk$jfppy3100i:[python3100.vms]logicals.com "/process"
$ @python3_root:[vms]setup
$ pyrte3 == "$cgi_exe:pyrte3.exe"
$ pyrte3
</pre>
<p> Each of these is mapped for independent activation based on the request
path.
<pre class="code">
# WASD_CONFIG_MAP
exec /py-bin/* (@cgi_bin:pyrte.com)/wasd_root/src/python/scripts/* \
script=syntax=unix map=once script=query=none ods=5
exec /py3-bin/* (@cgi_bin:pyrte3.com)/<i>volume<sup>**</sup></i>/wasd_root/src/python/scripts/* \
script=syntax=unix map=once script=query=none ods=5
</pre>
<table style="margin-left:2em;font-size:95%;">
<td style="vertical-align:top;"><sup>**</sup></td><td>
<b>Note</b> that the scripts activated are the same on-disk files, located in
the PyRTE source directory.
<br><b>Also note</b> that <tt>/py3-bin/</tt> mapping result is different to
that of the <tt>/py-bin/</tt> mapping. There is a /<i>volume</i>/ present.
<br> This is only required where the same on-disk files are being scripted.
<b> This is a kludge.</b> Due to the way WASD caches script information (on
the disk file path), <b>including any associated RTE</b>, it was necessary to
differentiate the two activations and the chosen solution was to include the
physical volume (on which <tt>[WASD_ROOT]</tt> resides) in the mapping.
Another solution might be to use an alternate concealed logical device name.
</td>
</table>
<p> This is one approach. A little creativity would yield others.
<h3>wasd.vsm.com.au</h3>
<p> At the time of writing the demonstration site uses this approach to
default the examples below to (JFP) Python 2.7, while optionally allowing them
to be activated under 3.10 &ndash; just modify the browser location field to
contain <tt>/py3-bin/</tt> rather than the default <tt>/py-bin/</tt>. Several
of the scripts display the underlying Python version confirming the activations.
<a name="example">
<h2>Example Scripts</h2>
</a>
......@@ -573,7 +643,7 @@
<dl>
<dt>v3.0.0&nbsp; 08-SEP-2020 ~~~ PRE-RELEASE ~~~</dt>
<dt>v3.0.0&nbsp; 10-SEP-2020 ~~~ PRE-RELEASE ~~~</dt>
<dd>&bull;&nbsp; Python version 3.10.0a0</dd>
</dd>
......@@ -577,7 +647,7 @@
<dd>&bull;&nbsp; Python version 3.10.0a0</dd>
</dd>
<dt>v2.0.0&nbsp; 08-SEP-2020 ~~~ PRE-RELEASE ~~~</dt>
<dt>v2.0.0&nbsp; 10-SEP-2020 ~~~ PRE-RELEASE ~~~</dt>
<dd>&bull;&nbsp; Python version 2.7.18</dd>
</dd>
......
def application(environ, start_response):
import cgi
import html
import platform
write_fn = start_response('200 OK', [('Content-Type', 'text/html')])
yield '<html><head><title>os.environment</title></head>\n' \
'<body bgcolor="#ffffff" color="#000000">\n' \
'<p><b><u>os.environment</b></u></p>\n' \
'<table cellspacing="0" cellpadding="2" border="1">'
names = environ.keys()
......@@ -3,9 +5,9 @@
write_fn = start_response('200 OK', [('Content-Type', 'text/html')])
yield '<html><head><title>os.environment</title></head>\n' \
'<body bgcolor="#ffffff" color="#000000">\n' \
'<p><b><u>os.environment</b></u></p>\n' \
'<table cellspacing="0" cellpadding="2" border="1">'
names = environ.keys()
names.sort()
sorted(names)
for name in names:
yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
......@@ -10,6 +12,6 @@
for name in names:
yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
name, cgi.escape(`environ[name]`))
name, escape(str(environ[name])))
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ,
keep_blank_values=1)
......@@ -20,8 +22,9 @@
yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
field.name, field.value)
write_fn('<tr><td>This has been write()n</td><td>:-)</td></tr>\n');
write_fn('<tr><td>This has been write()n :-)</td><td>Python ' +
platform.sys.version + '</td></tr>\n')
yield '</table>\n' \
'</body></html>\n'
......@@ -24,6 +27,17 @@
yield '</table>\n' \
'</body></html>\n'
def escape(s, quote=None):
'''Replace special characters "&", "<" and ">" to HTML-safe sequences.
If the optional flag quote is true, the quotation mark character (")
is also translated. (Python 2 and 3 neutral.)'''
s = s.replace("&", "&amp;") # Must be done first!
s = s.replace("<", "&lt;")
s = s.replace(">", "&gt;")
if quote:
s = s.replace('"', "&quot;")
return s
import wasd
wasd.wsgi_run(application)
def show_environ(environ, start_response):
start_response('200 OK',[('Content-type','text/html')])
sorted_keys = environ.keys()
sorted_keys.sort()
sorted(sorted_keys)
return [
'<html><body><h1>Keys in <tt>environ</tt></h1><p>',
'<br />'.join(sorted_keys),
......
......@@ -3,4 +3,9 @@
It can operate as a standard CGI or as a CGIplus script.
It accepts a GIF, JPEG or PNG file and displays it in the browser.
"""
# caters for Python 2 and 3
if hasattr(importlib,'reload'):
importlib.reload(cgi)
else:
reload(cgi)
if os.environ["REQUEST_METHOD"] == "POST":
......@@ -6,5 +11,5 @@
if os.environ["REQUEST_METHOD"] == "POST":
display_uploaded_file (start_response, "image_file")
display_uploaded_file (start_response)
else:
print_html_form (start_response)
return ('')
......@@ -29,8 +34,8 @@
wsgi_write = start_response('200 OK',[('Content-type','text/html')])
wsgi_write (HTML_TEMPLATE % {'SCRIPT_NAME':os.environ['SCRIPT_NAME']})
def display_uploaded_file (start_response, form_field):
def display_uploaded_file (start_response):
"""This display an image file uploaded by an HTML form.
"""
form = cgi.FieldStorage()
......@@ -33,9 +38,9 @@
"""This display an image file uploaded by an HTML form.
"""
form = cgi.FieldStorage()
if not form.has_key(form_field): return
fileitem = form[form_field]
if not 'image_file' in form: return
fileitem = form['image_file']
if not fileitem.file: return
if not fileitem.filename: return
filename = fileitem.filename.lower()
......@@ -47,7 +52,7 @@
elif filename.rfind(".png") != -1:
response_headers = [('Content-type','image/png')]
else:
wsgi_write = start_response('200 OK',[('Content-type','text/html')])
wsgi_write = start_response(status,[('Content-type','text/html')])
wsgi_write ("Only GIFs, JPEGs and PNGs handled by this test.")
return
......@@ -61,6 +66,7 @@
del fileitem
import wasd;
import importlib
import cgi
import cgitb; cgitb.enable()
import os, sys
......