Recent attempts at actual locking
This commit is contained in:
parent
4f3c0fe8cd
commit
8d9771a715
110
main.py
110
main.py
@ -18,10 +18,9 @@ from colorama import Fore, Back, Style, init as colorama_init
|
|||||||
import contentapi
|
import contentapi
|
||||||
import myutils
|
import myutils
|
||||||
|
|
||||||
VERSION="0.1.0" # Arbitrary but whatever
|
VERSION="0.1.1" # Arbitrary but whatever
|
||||||
CONFIGFILE="config.toml"
|
CONFIGFILE="config.toml"
|
||||||
MAXTITLE=25
|
MAXTITLE=25
|
||||||
MAXMESSAGEWIDTH=80 # May instead check the console window
|
|
||||||
MSGPREFIX=Back.GREEN + " " + Back.RESET + " "
|
MSGPREFIX=Back.GREEN + " " + Back.RESET + " "
|
||||||
|
|
||||||
# The entire config object with all defaults
|
# The entire config object with all defaults
|
||||||
@ -34,6 +33,8 @@ config = {
|
|||||||
"expire_seconds" : 31536000, # 365 days in seconds, expiration for token
|
"expire_seconds" : 31536000, # 365 days in seconds, expiration for token
|
||||||
"appear_in_global" : False,
|
"appear_in_global" : False,
|
||||||
"print_status_after_insert" : True,
|
"print_status_after_insert" : True,
|
||||||
|
"output_buffer_timeout" : 0.05, # 50 milliseconds
|
||||||
|
"fixed_width" : 78, # Need room for the pre-message decoration
|
||||||
"tokenfile" : ".qcstoken"
|
"tokenfile" : ".qcstoken"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ def main():
|
|||||||
# Might as well reuse the websocket object for my websocket context data (oops, is that bad?)
|
# Might as well reuse the websocket object for my websocket context data (oops, is that bad?)
|
||||||
ws.context = context
|
ws.context = context
|
||||||
ws.user_info = context.user_me()
|
ws.user_info = context.user_me()
|
||||||
ws.pause_output = False # Whether all output from the websocket should be paused (including status updates)
|
ws.output_lock = threading.Lock()
|
||||||
ws.output_buffer = [] # Individual print statements buffered from output.
|
ws.output_buffer = [] # Individual print statements buffered from output.
|
||||||
ws.main_config = config
|
ws.main_config = config
|
||||||
ws.current_room = 0
|
ws.current_room = 0
|
||||||
@ -109,20 +110,20 @@ def ws_onopen(ws):
|
|||||||
# The infinite input loop! Or something!
|
# The infinite input loop! Or something!
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
ws.pause_output = False # Allow arbitrary output again. Do this BEFORE other stuff for race conditions
|
# Dump the buffer, if there is any, since we're outside of user input
|
||||||
|
with ws.output_lock:
|
||||||
# We can be certain that at this point, there is no user input (because this loop is all there is)
|
for output in ws.output_buffer:
|
||||||
# As such, just dump the buffer
|
printr(output)
|
||||||
for output in ws.output_buffer:
|
|
||||||
printr(output)
|
|
||||||
|
|
||||||
ws.output_buffer = []
|
ws.output_buffer = []
|
||||||
|
|
||||||
if printstatus:
|
if printstatus:
|
||||||
print_statusline(ws)
|
print_statusline(ws)
|
||||||
|
|
||||||
printstatus = False # Assume we are not printing the status every time (it's kinda annoying)
|
printstatus = False # Assume we are not printing the status every time (it's kinda annoying)
|
||||||
|
|
||||||
|
# Listen for a key. The implementation of 'readkey()' on this version of python and windows makes the CPU spike
|
||||||
|
# to 100%, so we switch to getch() if we detect windows.
|
||||||
if platform.system().startswith("Windows"):
|
if platform.system().startswith("Windows"):
|
||||||
import msvcrt
|
import msvcrt
|
||||||
logging.debug("on windows, using msvcrt.getch")
|
logging.debug("on windows, using msvcrt.getch")
|
||||||
@ -130,42 +131,43 @@ def ws_onopen(ws):
|
|||||||
else:
|
else:
|
||||||
key = readchar.readkey()
|
key = readchar.readkey()
|
||||||
|
|
||||||
ws.pause_output = True # Disable output for the duration of input handling
|
# We get exclusive access to output while we're handling user input. This allows us to "pause/buffer" the
|
||||||
|
# output that might come from websocket events
|
||||||
if key == "h":
|
with ws.output_lock:
|
||||||
print(" -- Help menu / Controls --")
|
if key == "h":
|
||||||
for key, value in commands.items():
|
print(" -- Help menu / Controls --")
|
||||||
print(" " + Style.BRIGHT + key + Style.NORMAL + " - " + value)
|
for key, value in commands.items():
|
||||||
elif key == "s":
|
print(" " + Style.BRIGHT + key + Style.NORMAL + " - " + value)
|
||||||
search(ws)
|
elif key == "s":
|
||||||
printstatus = True
|
search(ws)
|
||||||
elif key == "g":
|
printstatus = True
|
||||||
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_global"))
|
elif key == "g":
|
||||||
elif key == "u":
|
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_global"))
|
||||||
if not ws.current_room:
|
elif key == "u":
|
||||||
print("You're not in a room! Can't check userlist!")
|
if not ws.current_room:
|
||||||
else:
|
print("You're not in a room! Can't check userlist!")
|
||||||
# Just send it out, we have to wait for the websocket handler to get the response
|
else:
|
||||||
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_room_%d" % ws.current_room))
|
# Just send it out, we have to wait for the websocket handler to get the response
|
||||||
elif key == "i":
|
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_room_%d" % ws.current_room))
|
||||||
if not ws.current_room:
|
elif key == "i":
|
||||||
print("You're not in a room! Can't send messages!")
|
if not ws.current_room:
|
||||||
else:
|
print("You're not in a room! Can't send messages!")
|
||||||
message = input("Post (empty = exit): ")
|
else:
|
||||||
if message:
|
message = input("Post (empty = exit): ")
|
||||||
ws.context.post_message(contentapi.comment_builder(message,
|
if message:
|
||||||
ws.current_room, ws.main_config["default_markup"], ws.user_info["avatar"]))
|
ws.context.post_message(contentapi.comment_builder(message,
|
||||||
printstatus = ws.main_config["print_status_after_insert"]
|
ws.current_room, ws.main_config["default_markup"], ws.user_info["avatar"]))
|
||||||
elif key == "t":
|
printstatus = ws.main_config["print_status_after_insert"]
|
||||||
print(" -- Ignored WS Data (normal) --")
|
elif key == "t":
|
||||||
for key,value in ws.ignored.items():
|
print(" -- Ignored WS Data (normal) --")
|
||||||
printr(Style.BRIGHT + ("%16s" % key) + (" : %d" % value))
|
for key,value in ws.ignored.items():
|
||||||
elif key == "q":
|
printr(Style.BRIGHT + ("%16s" % key) + (" : %d" % value))
|
||||||
print("Quitting (may take a bit for the websocket to close)")
|
elif key == "q":
|
||||||
ws.close()
|
print("Quitting (may take a bit for the websocket to close)")
|
||||||
break
|
ws.close()
|
||||||
elif key == " ":
|
break
|
||||||
printstatus = True
|
elif key == " ":
|
||||||
|
printstatus = True
|
||||||
|
|
||||||
# Set the main room; we want to wait until the websocket is open because this also sets your
|
# Set the main room; we want to wait until the websocket is open because this also sets your
|
||||||
# status in the userlist
|
# status in the userlist
|
||||||
@ -211,7 +213,7 @@ def ws_onmessage(ws, message):
|
|||||||
user = contentapi.get_user_or_default(objects["user"], message["createUserId"])
|
user = contentapi.get_user_or_default(objects["user"], message["createUserId"])
|
||||||
ws_print(ws, MSGPREFIX + Fore.CYAN + Style.BRIGHT + user["username"] + " " + Style.DIM + "#%d" % user["id"] +
|
ws_print(ws, MSGPREFIX + Fore.CYAN + Style.BRIGHT + user["username"] + " " + Style.DIM + "#%d" % user["id"] +
|
||||||
Fore.MAGENTA + " " + message["createDate"] + " [%d]" % message["id"])
|
Fore.MAGENTA + " " + message["createDate"] + " [%d]" % message["id"])
|
||||||
for t in textwrap.wrap(message["text"], width = MAXMESSAGEWIDTH):
|
for t in textwrap.wrap(message["text"], width = ws.main_config["fixed_width"]):
|
||||||
ws_print(ws, MSGPREFIX + t)
|
ws_print(ws, MSGPREFIX + t)
|
||||||
|
|
||||||
# Track ignored data
|
# Track ignored data
|
||||||
@ -223,10 +225,14 @@ def ws_onmessage(ws, message):
|
|||||||
# Printing websocket event output is tricky because we don't want to interrupt user input (we don't have
|
# Printing websocket event output is tricky because we don't want to interrupt user input (we don't have
|
||||||
# curses). As such, we must buffer our output IF we are asked to pause
|
# curses). As such, we must buffer our output IF we are asked to pause
|
||||||
def ws_print(ws, output):
|
def ws_print(ws, output):
|
||||||
if ws.pause_output:
|
# We can't block output for too long, so we need to only try to acquire the lock for a very short time
|
||||||
ws.output_buffer.append(output)
|
if ws.output_lock.acquire(timeout=ws.main_config["output_buffer_timeout"]):
|
||||||
|
try:
|
||||||
|
printr(output)
|
||||||
|
finally:
|
||||||
|
ws.output_lock.release()
|
||||||
else:
|
else:
|
||||||
printr(output)
|
ws.output_buffer.append(output)
|
||||||
|
|
||||||
|
|
||||||
# Loads the config from file into the global config var. If the file
|
# Loads the config from file into the global config var. If the file
|
||||||
|
Loading…
Reference in New Issue
Block a user