AIM-PIbd-32-Kurbanova-A-A/aimenv/Lib/site-packages/isapi/samples/test.py

196 lines
6.2 KiB
Python
Raw Normal View History

2024-10-02 22:15:59 +04:00
# This extension is used mainly for testing purposes - it is not
# designed to be a simple sample, but instead is a hotch-potch of things
# that attempts to exercise the framework.
import os
import stat
import sys
from isapi import isapicon
from isapi.simple import SimpleExtension
if hasattr(sys, "isapidllhandle"):
import win32traceutil
# We use the same reload support as 'advanced.py' demonstrates.
import threading
import win32con
import win32event
import win32file
import winerror
from isapi import InternalReloadException
# A watcher thread that checks for __file__ changing.
# When it detects it, it simply sets "change_detected" to true.
class ReloadWatcherThread(threading.Thread):
def __init__(self):
self.change_detected = False
self.filename = __file__
if self.filename.endswith("c") or self.filename.endswith("o"):
self.filename = self.filename[:-1]
self.handle = win32file.FindFirstChangeNotification(
os.path.dirname(self.filename),
False, # watch tree?
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
)
threading.Thread.__init__(self)
def run(self):
last_time = os.stat(self.filename)[stat.ST_MTIME]
while 1:
try:
rc = win32event.WaitForSingleObject(self.handle, win32event.INFINITE)
win32file.FindNextChangeNotification(self.handle)
except win32event.error as details:
# handle closed - thread should terminate.
if details.winerror != winerror.ERROR_INVALID_HANDLE:
raise
break
this_time = os.stat(self.filename)[stat.ST_MTIME]
if this_time != last_time:
print("Detected file change - flagging for reload.")
self.change_detected = True
last_time = this_time
def stop(self):
win32file.FindCloseChangeNotification(self.handle)
def TransmitFileCallback(ecb, hFile, cbIO, errCode):
print("Transmit complete!")
ecb.close()
# The ISAPI extension - handles requests in our virtual dir, and sends the
# response to the client.
class Extension(SimpleExtension):
"Python test Extension"
def __init__(self):
self.reload_watcher = ReloadWatcherThread()
self.reload_watcher.start()
def HttpExtensionProc(self, ecb):
# NOTE: If you use a ThreadPoolExtension, you must still perform
# this check in HttpExtensionProc - raising the exception from
# The "Dispatch" method will just cause the exception to be
# rendered to the browser.
if self.reload_watcher.change_detected:
print("Doing reload")
raise InternalReloadException
if ecb.GetServerVariable("UNICODE_URL").endswith("test.py"):
file_flags = (
win32con.FILE_FLAG_SEQUENTIAL_SCAN | win32con.FILE_FLAG_OVERLAPPED
)
hfile = win32file.CreateFile(
__file__,
win32con.GENERIC_READ,
0,
None,
win32con.OPEN_EXISTING,
file_flags,
None,
)
flags = (
isapicon.HSE_IO_ASYNC
| isapicon.HSE_IO_DISCONNECT_AFTER_SEND
| isapicon.HSE_IO_SEND_HEADERS
)
# We pass hFile to the callback simply as a way of keeping it alive
# for the duration of the transmission
try:
ecb.TransmitFile(
TransmitFileCallback,
hfile,
int(hfile),
"200 OK",
0,
0,
None,
None,
flags,
)
except:
# Errors keep this source file open!
hfile.Close()
raise
else:
# default response
ecb.SendResponseHeaders("200 OK", "Content-Type: text/html\r\n\r\n", 0)
print("<HTML><BODY>", file=ecb)
print("The root of this site is at", ecb.MapURLToPath("/"), file=ecb)
print("</BODY></HTML>", file=ecb)
ecb.close()
return isapicon.HSE_STATUS_SUCCESS
def TerminateExtension(self, status):
self.reload_watcher.stop()
# The entry points for the ISAPI extension.
def __ExtensionFactory__():
return Extension()
# Our special command line customization.
# Pre-install hook for our virtual directory.
def PreInstallDirectory(params, options):
# If the user used our special '--description' option,
# then we override our default.
if options.description:
params.Description = options.description
# Post install hook for our entire script
def PostInstall(params, options):
print()
print("The sample has been installed.")
print("Point your browser to /PyISAPITest")
# Handler for our custom 'status' argument.
def status_handler(options, log, arg):
"Query the status of something"
print("Everything seems to be fine!")
custom_arg_handlers = {"status": status_handler}
if __name__ == "__main__":
# If run from the command-line, install ourselves.
from isapi.install import *
params = ISAPIParameters(PostInstall=PostInstall)
# Setup the virtual directories - this is a list of directories our
# extension uses - in this case only 1.
# Each extension has a "script map" - this is the mapping of ISAPI
# extensions.
sm = [ScriptMapParams(Extension="*", Flags=0)]
vd = VirtualDirParameters(
Name="PyISAPITest",
Description=Extension.__doc__,
ScriptMaps=sm,
ScriptMapUpdate="replace",
# specify the pre-install hook.
PreInstall=PreInstallDirectory,
)
params.VirtualDirs = [vd]
# Setup our custom option parser.
from optparse import OptionParser
parser = OptionParser("") # blank usage, so isapi sets it.
parser.add_option(
"",
"--description",
action="store",
help="custom description to use for the virtual directory",
)
HandleCommandLine(
params, opt_parser=parser, custom_arg_handlers=custom_arg_handlers
)