Issue with WaitressServer.py and --wsgi-script argument

Will Sadkin via Webware-discuss <webware-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> Sun, 15 May 2022 21:08:28 +0000
Newsgroups gmane.comp.python.webware
Message-ID <SA1PR15MB4854B06BAA1558289B0CAC98D0CC9@SA1PR15MB4854.namprd15.prod.outlook.com>
--===============3159674113910432539==
Content-Language: en-US
Content-Type: multipart/alternative;
	boundary="_000_SA1PR15MB4854B06BAA1558289B0CAC98D0CC9SA1PR15MB4854namp_"

--_000_SA1PR15MB4854B06BAA1558289B0CAC98D0CC9SA1PR15MB4854namp_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

To whom it may concern,

We are finally porting our old webware application for Windows to w4py3, an=
d I ran into a bit of ugliness that I wanted to report.

As a test, I had made the HelloWorld app in a subfolder to our main app, an=
d verified my w4py3 install.  I then wanted to just run it initially from t=
he WindowsService wrapper I wrote around webware's WaitressServer.py script=
 as a first step before tackling the port of the rest of our application.

Now, webware's default template WSGIScript.py file has the logic:

workDir =3D None

if workDir is None:
    workDir =3D os.path.dirname(os.path.dirname(__file__))

if workDir:
    os.chdir(workDir)

if '.' in libDirs:
    sys.path.insert(0, workDir)


And the WaitressServer.py, among its many nifty options, has a -wsgi-script=
 argument, so I provided the HelloWorld/Scripts/WSGIScript.py as the -wsgi-=
script argument to the WaitressServer main() function, expecting this to ju=
st work as written above.  But the workDir did not change to the subfolder,=
 and I spent hours trying to figure out why.  What I finally discovered was=
 the cause was the following unexpected code modification in WaitressServer=
.py:

        # do not change working directory in the script
        script =3D script.replace('workDir =3D', "workDir =3D '' #")
        scriptVars =3D {}
        exec(script, scriptVars)


Now, I suspect the reason that this hack above to was done because, given t=
he way this script is "invoked" (via exec), if you didn't do this, when you=
 tried to exec the WSGIScript.py content, you'd get:

NameError: name '__file__' is not defined

but then why have all that logic in the WSGIScript.py determining workDir i=
n the first place?  Is the WSGIScript.py file used in some other context?
And what was the point of adding -wsgi-script as an argument to WaitressSer=
ver.py if it didn't allow you to specify app location other than the defaul=
t?

For what it's worth, I've hacked around this temporarily, by replacing the =
above line in WaitressServer.py with slightly different code modification l=
ogic, i.e.:
Import os
[...]
fullpath =3D "r'" + os.path.abspath(args.wsgi_script) + "'"
script =3D script.replace('__file__', fullpath)

But I'm not convinced this is the best solution, because I'm not sure what =
the intent was for the -wsgi-script argument if not to allow you to specify=
 where the app you want to serve lives... Is there a better way to do that?

Regards,
/Will Sadkin

--_000_SA1PR15MB4854B06BAA1558289B0CAC98D0CC9SA1PR15MB4854namp_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
>
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
	{font-family:Consolas;
	panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0in;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
span.EmailStyle17
	{mso-style-type:personal-compose;
	font-family:"Calibri",sans-serif;
	color:windowtext;}
.MsoChpDefault
	{mso-style-type:export-only;
	font-family:"Calibri",sans-serif;}
@page WordSection1
	{size:8.5in 11.0in;
	margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72" style=3D"word-wrap:=
break-word">
<div class=3D"WordSection1">
<p class=3D"MsoNormal">To whom it may concern,<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">We are finally porting our old webware application f=
or Windows to w4py3, and I ran into a bit of ugliness that I wanted to repo=
rt.<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">As a test, I had made the HelloWorld app in a subfol=
der to our main app, and verified my w4py3 install.&nbsp; I then wanted to =
just run it initially from the WindowsService wrapper I wrote around webwar=
e&#8217;s WaitressServer.py script as a first
 step before tackling the port of the rest of our application.<o:p></o:p></=
p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">Now, webware&#8217;s default template WSGIScript.py =
file has the logic:<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">workDir =3D None<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas"><o:p>&nbsp;</o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">if workDir is None:<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">&nbsp;&nbsp;&nbsp; workDir =3D os.path.dirname=
(os.path.dirname(__file__))<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas"><o:p>&nbsp;</o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">if workDir:<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">&nbsp;&nbsp;&nbsp; os.chdir(workDir)<o:p></o:p=
></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas"><o:p>&nbsp;</o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">if '.' in libDirs:<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">&nbsp;&nbsp;&nbsp; sys.path.insert(0, workDir)=
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:10.0pt"><o:p>&nbsp;</o:p></=
span></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">And the WaitressServer.py, among its many nifty opti=
ons, has a &#8211;wsgi-script argument, so I provided the HelloWorld/Script=
s/WSGIScript.py as the &#8211;wsgi-script argument to the WaitressServer ma=
in() function, expecting this to just work as
 written above.&nbsp; But the workDir did not change to the subfolder, and =
I spent hours trying to figure out why.&nbsp; What I finally discovered was=
 the cause was the following unexpected code modification in WaitressServer=
.py:<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-family:Consolas">&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style=3D"font-size:10.0pt;font-fam=
ily:Consolas"># do not change working directory in the script<o:p></o:p></s=
pan></p>
<p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:Consolas=
">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; script =3D script.replace('wor=
kDir =3D', &quot;workDir =3D '' #&quot;)<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:Consolas=
">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scriptVars =3D {}<o:p></o:p></=
span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:Consolas=
">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec(script, scriptVars)<o:p><=
/o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:Consolas=
"><o:p>&nbsp;</o:p></span></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">Now, I <i>suspect</i> the reason that this hack abov=
e to was done because, given the way this script is &#8220;invoked&#8221; (=
via exec), if you didn&#8217;t do this, when you tried to exec the WSGIScri=
pt.py content, you&#8217;d get:
<br>
<br>
<o:p></o:p></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">NameError: name '__file__' is not defined
<br>
<br>
<o:p></o:p></span></p>
<p class=3D"MsoNormal">but then why have all that logic in the WSGIScript.p=
y determining workDir in the first place?&nbsp; Is the WSGIScript.py file u=
sed in some other context?<o:p></o:p></p>
<p class=3D"MsoNormal">And what was the point of adding &#8211;wsgi-script =
as an argument to WaitressServer.py if it didn&#8217;t allow you to specify=
 app location other than the default?&nbsp;
<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">For what it&#8217;s worth, I&#8217;ve hacked around =
this temporarily, by replacing the above line in WaitressServer.py with sli=
ghtly different code modification logic, i.e.:<o:p></o:p></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in">Import os<o:p></o:p></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in">[&#8230;]<br>
<span style=3D"font-size:10.0pt;font-family:Consolas">fullpath =3D &quot;r'=
&quot; + os.path.abspath(args.wsgi_script) + &quot;'&quot;<o:p></o:p></span=
></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas">script =3D script.replace('__file__', fullpath=
)<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-left:.5in"><span style=3D"font-size:=
10.0pt;font-family:Consolas"><o:p>&nbsp;</o:p></span></p>
<p class=3D"MsoNormal">But I&#8217;m not convinced this is the best solutio=
n, because I&#8217;m not sure what the intent was for the &#8211;wsgi-scrip=
t argument if not to allow you to specify where the app you want to serve l=
ives&#8230; Is there a better way to do that?<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p>&nbsp;</o:p></p>
<p class=3D"MsoNormal">Regards,<o:p></o:p></p>
<p class=3D"MsoNormal">/Will Sadkin<o:p></o:p></p>
</div>
</body>
</html>

--_000_SA1PR15MB4854B06BAA1558289B0CAC98D0CC9SA1PR15MB4854namp_--


--===============3159674113910432539==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


--===============3159674113910432539==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Webware-discuss mailing list
Webware-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/webware-discuss

--===============3159674113910432539==--