-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.py
117 lines (90 loc) · 3.6 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from http.server import HTTPServer, SimpleHTTPRequestHandler
import sys
import os
from build.inject import injectAllComponents
from build.utils import locateAll, logStatus, output
watch = True
watcher = None
directory = ""
geosmart = r"""
_____ _____ __ __ _____ _______
/ ____| / ____| \/ | /\ | __ \__ __|
| | __ ___ ___| (___ | \ / | / \ | |__) | | |
| | |_ |/ _ \/ _ \\___ \| |\/| | / /\ \ | _ / | |
| |__| | __/ (_) |___) | | | |/ ____ \| | \ \ | |
\_____|\___|\___/_____/|_| |_/_/ \_\_| \_\ |_|
"""
# Found this funky little function on stack overflow:
# https://stackoverflow.com/questions/40419276/python-how-to-print-text-to-console-as-hyperlink
def link(uri, label=None):
if label is None:
label = uri
parameters = ""
# OSC 8 ; params ; URI ST <name> OSC 8 ;; ST
escape_mask = "\033]8;{};{}\033\\{}\033]8;;\033\\"
return escape_mask.format(parameters, uri, label)
def prepare(message: str):
global watcher
os.system("cls" if os.name=="nt" else "clear")
output(geosmart)
output(message)
if watch:
output("Searching for components to watch for changes...")
components = locateAll("components/", "_*.html")
watcher = FileWatcher(components)
else:
output("Note that components will not be watched for changes!")
output("Server ready and waiting at " + link("http://localhost:8000/"), logStatus.GOOD, newLine=True)
# ============== #
# *** SERVER *** #
def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
server_address = ("", 8000)
httpd = server_class(server_address, handler_class)
try:
httpd.serve_forever()
except:
output("Recieved keyboard interrupt, exiting...\n", logStatus.WARN)
class NoExtensionHandler(SimpleHTTPRequestHandler):
def do_GET(self):
print("\nUnmodified path: " + self.path)
output("\nUnmodified path: " + self.path)
self.path = directory + self.path
output("With directory: " + self.path)
home_paths = ["/", "/docs/"]
# The exclusion of paths with a period excludes image, js and other file types
if self.path not in home_paths and not "." in self.path:
self.path += ".html"
output("Extension added: " + self.path)
if watch and watcher.check():
output("Component file modified, injecting updated component(s)...")
injectAllComponents()
SimpleHTTPRequestHandler.do_GET(self)
class FileWatcher(object):
def __init__(self, paths: list[str]):
self._cachedStamps = [None] * len(paths)
self.watchPaths = paths
def check(self):
for index in range(len(self.watchPaths)):
file = self.watchPaths[index]
stamp = os.stat(file).st_mtime
output(f"Checking {file} modified time: {stamp}, {self._cachedStamps[index]}", newLine=True)
if stamp != self._cachedStamps[index]:
self._cachedStamps[index] = stamp
return True # file changed
return False # file unchanged
# ============ #
# *** MAIN *** #
if len(sys.argv) == 1:
prepare("Serving from root directory...")
run(HTTPServer, NoExtensionHandler)
elif len(sys.argv) == 2:
dir_flags = ["--docs", "-d"]
if sys.argv[1] in dir_flags:
watch = False # We can serve from the docs folder or watch for head changes, but it doesn't make sense to do both.
directory = "/docs"
prepare(f"Recieved '{sys.argv[1]}' flag, serving from /docs/ directory...")
run(HTTPServer, NoExtensionHandler)
else:
output(f"Invalid flag provided. Expected one of {str(dir_flags)}, got '{sys.argv[1]}'")
else:
output(f"Invalid number of arguments. Expected at most 1, got {len(sys.argv) - 1}")