From f7afb753c358fff7405f4e19eebb25d3c52c6adf Mon Sep 17 00:00:00 2001 From: Michael Lawrence Date: Mon, 6 Nov 2023 14:10:02 +0000 Subject: [PATCH] checking demos work after updates to event class. Ported the sanic ones to fast api --- domonic/dom.py | 7 ++ examples/events/.gitignore | 1 - examples/events/README.md | 3 + examples/games/hangman.py | 106 ++++++++++--------- examples/games/rockpaperscissors.py | 35 +++---- examples/grid.py | 54 ++++------ examples/ken/sf2.html | 2 +- examples/mindreader.py | 40 -------- examples/mixed.py | 1 - examples/parsing/README.md | 1 - examples/parsing/codemirror.py | 151 +++++++++------------------- requirements-dev.txt | 1 + 12 files changed, 148 insertions(+), 254 deletions(-) delete mode 100755 examples/events/.gitignore create mode 100644 examples/events/README.md delete mode 100644 examples/mindreader.py diff --git a/domonic/dom.py b/domonic/dom.py index 7e31efb2..b6c6884d 100644 --- a/domonic/dom.py +++ b/domonic/dom.py @@ -467,6 +467,13 @@ def __getattr__(self, attr): if retry in kwargs: return kwargs[retry] + # TODO - think of solution for other MIA attributes as when it would fail silently + # it was a nightmare. But having to catch the raised errors may also be sluggish + # maybe specific tags can override this method and provide default values when not present? + if self.__class__.__name__ == "a" and attr == "href": + print(" Warning: No 'href' attribute was defined for this 'a' tag.") + return "" + try: # return getattr(super(), attr) # return getattr(self, attr) diff --git a/examples/events/.gitignore b/examples/events/.gitignore deleted file mode 100755 index bf9e782d..00000000 --- a/examples/events/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.mp3 \ No newline at end of file diff --git a/examples/events/README.md b/examples/events/README.md new file mode 100644 index 00000000..6b0c28fd --- /dev/null +++ b/examples/events/README.md @@ -0,0 +1,3 @@ +cd to this dir. +run events.py then open the events.html file in a browser +click around to see the output from the socket \ No newline at end of file diff --git a/examples/games/hangman.py b/examples/games/hangman.py index 7a6f1e16..347b8d57 100644 --- a/examples/games/hangman.py +++ b/examples/games/hangman.py @@ -1,5 +1,4 @@ import sys - sys.path.insert(0, "../..") import os @@ -7,22 +6,15 @@ from dataclasses import asdict, dataclass, field from json import load -from sanic import Sanic, response -from sanic_session import InMemorySessionInterface, Session - from domonic.CDN import * from domonic.html import * -# TO run this : -# pip3 install sanic -# pip3 install sanic-session +from fastapi import FastAPI, Request, Response, Query +from starlette.middleware.sessions import SessionMiddleware -app = Sanic(name="Hangman") -app.static("/assets", "./assets") +app = FastAPI() +app.add_middleware(SessionMiddleware, secret_key="secret", session_cookie="session") -session = Session(app, interface=InMemorySessionInterface()) - -# create a template page_wrapper = lambda content: html( head( script(_src="https://code.jquery.com/jquery-3.5.1.min.js"), @@ -41,13 +33,11 @@ body(str(content)), ) - def get_word(): wordArray = "Adult Aeroplane Air Aircraft Carrier Airforce Airport Album Alphabet Apple Arm Army Baby Baby Backpack Balloon Banana Bank Barbecue Bathroom Bathtub Bed Bed Bee Bible Bible Bird Bomb Book Boss Bottle Bowl Box Boy Brain Bridge Butterfly Button Cappuccino Car Carpet Carrot Cave Chair Chess Board Chief Child Chisel Chocolates Church Church Circle Circus Circus Clock Clown Coffee Comet Compact Disc Compass Computer Crystal Cup Cycle Data Base Desk Diamond Dress Drill Drink Drum Dung Ears Earth Egg Electricity Elephant Eraser Explosive Eyes Family Fan Feather Festival Film Finger Fire Floodlight Flower Foot Fork Freeway Fruit Fungus Game Garden Gas Gate Gemstone Girl Gloves God Grapes Guitar Hammer Hat Hieroglyph Highway Horoscope Horse Hose Ice Insect Jet fighter Junk Kaleidoscope Kitchen Knife Leather jacket Leg Library Liquid Magnet Man Map Maze Meat Meteor Microscope Milk Milkshake Mist Money $$$$ Monster Mosquito Mouth Nail Navy Necklace Needle Onion PaintBrush Pants Parachute Passport Pebble Pendulum Pepper Perfume Pillow Plane Planet Pocket Potato Printer Prison Pyramid Radar Rainbow Record Restaurant Rifle Ring Robot Rock Rocket Roof Room Rope Saddle Salt Sandpaper Sandwich Satellite School Sex Ship Shoes Shop Shower Signature Skeleton Slave Snail Software Solid Space Shuttle Spectrum Sphere Spice Spiral Spoon Spot Light Square Staircase Star Stomach Sun Sunglasses Surveyor Swimming Pool Sword Table Tapestry Teeth Telescope Television Tennis racquet Thermometer Tiger Toilet Tongue Torch Torpedo Train Treadmill Triangle Tunnel Typewriter Umbrella Vacuum Vampire Videotape Vulture Water Weapon Web Wheelchair Window Woman Worm".lower().split() word = random.choice(wordArray) return word - def display_hangman(tries): stages = [ " +---+\n | |\n O |\n /|\ |\n / \ |\n |\n=========", @@ -69,42 +59,47 @@ class GameData: guessed_words: list = field(default_factory=list) tries: int = 6 - class Game: - """Hangman. The data is stored on a session""" + """Hangman. The data is stored in a session""" - def __init__(self, request=None): + def __init__(self, request: Request): self.state = GameData() - if request is not None: - if not request.ctx.session.get("game"): - request.ctx.session["game"] = asdict(self.state) - else: - data = request.ctx.session.get("game") - self.state.word = data["word"] - self.state.guessed = data["guessed"] - self.state.guessed_letters = data["guessed_letters"] - self.state.guessed_words = data["guessed_words"] - self.state.tries = data["tries"] - - -@app.route("/move") -async def move(request): + if not request.session.get("game"): + request.session["game"] = { + "word": self.state.word, + "guessed": self.state.guessed, + "guessed_letters": self.state.guessed_letters, + "guessed_words": self.state.guessed_words, + "tries": self.state.tries, + } + else: + data = request.session.get("game") + self.state.word = data["word"] + self.state.guessed = data["guessed"] + self.state.guessed_letters = data["guessed_letters"] + self.state.guessed_words = data["guessed_words"] + self.state.tries = data["tries"] + +@app.get("/move") +async def move(request: Request, letter: str = Query(...)): + game = Game(request) # recover the game from the session - guess = request.args["letter"][0] + word_completion = "_" * len(game.state.word) + board = [] - board = div() if not game.state.guessed and game.state.tries > 0: - if guess in game.state.guessed_letters: - board.appendChild(div("You already guessed the letter ", guess)) + + guess = str(letter) # Convert the query parameter to a string + if guess in game.state.guessed_letters: + board.append(f"You already guessed the letter {guess}") elif guess not in game.state.word: - board.appendChild(div(b(guess), " is not in the word.")) + board.append(p(f"{guess} is not in the word.")) game.state.tries -= 1 game.state.guessed_letters.append(guess) - else: - board.appendChild(div(f"You guessed the letter '{guess}' correctly!")) + board.append(p(f"You guessed the letter '{guess}' correctly!")) game.state.guessed_letters.append(guess) word_completion = list("_" * len(game.state.word)) @@ -115,10 +110,10 @@ async def move(request): if "_" not in word_completion: game.state.guessed = True - if game.state.guessed == True: - board.appendChild(div("Nice one!, you guessed it. You win.")) + if game.state.guessed: + board.append("Nice one! You guessed it. You win.") elif game.state.tries < 1: - board.appendChild(div(f"Out of tries. The word was {game.state.word}. Maybe next time!")) + board.append(p(f"Out of tries. The word was {game.state.word}. Maybe next time!")) page = div( div(f"Length of the word: {len(game.state.word)}"), @@ -134,25 +129,38 @@ async def move(request): # TODO - div('To Play Again Type (Y/N)') page.appendChild(" ".join(word_completion)) page.appendChild(board) - request.ctx.session["game"] = asdict(game.state) # update the session - return response.html(str(main(str(page), _id="game"))) + request.session["game"] = { + "word": game.state.word, + "guessed": game.state.guessed, + "guessed_letters": game.state.guessed_letters, + "guessed_words": game.state.guessed_words, + "tries": game.state.tries, + } + + return Response(content=str(main(str(page), _id="game")), media_type="text/html") @app.route("/") @app.route("/play") -async def play(request): - +async def play(request: Request): # create a new game based on this session - request.ctx.session["game"] = None + request.session["game"] = None game = Game(request) game.state.word = get_word() # get a random word to start playing with - request.ctx.session["game"] = asdict(game.state) + request.session["game"] = { + "word": game.state.word, + "guessed": game.state.guessed, + "guessed_letters": game.state.guessed_letters, + "guessed_words": game.state.guessed_words, + "tries": game.state.tries, + } intro = header( h1("HANGMAN!"), div("Can you guess the word? type a letter using the keyboard to guess."), main(_id="game") ) - return response.html(str(page_wrapper(intro))) + return Response(content=str(page_wrapper(intro)), media_type="text/html") if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=True) + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/examples/games/rockpaperscissors.py b/examples/games/rockpaperscissors.py index 140f7b19..d2bcfe5d 100644 --- a/examples/games/rockpaperscissors.py +++ b/examples/games/rockpaperscissors.py @@ -5,20 +5,16 @@ sys.path.insert(0, "../..") -import random - -from sanic import Sanic, response - from domonic.CDN import * from domonic.constants.entities import Char from domonic.html import * from domonic.utils import * -# To run this first: -# pip3 install sanic +from fastapi import FastAPI, Request, Query +from fastapi.responses import HTMLResponse +import random -app = Sanic(name="paper_scissors_rock") -app.static("/assets", "./assets") +app = FastAPI() # create a template page_wrapper = lambda content: html( @@ -49,18 +45,14 @@ body(str(content)), ) - choices = ["✊", "✋", "✌"] - def get_choice(): choice = random.choice(choices) return choice - -@app.route("/move") -async def move(request): - choice = Utils.escape(request.args["choice"][0]) +@app.get("/move", response_class=HTMLResponse) +async def move(request: Request, choice: str = Query(...)): computer = get_choice() page = div() @@ -95,20 +87,19 @@ async def move(request): result("✌", "✋", "I lose. You win!") page.appendChild(board) - return response.html(str(main(str(page), _id="game"))) + return str(main(str(page), _id="game")) - -@app.route("/") -@app.route("/play") -async def play(request): +@app.get("/", response_class=HTMLResponse) +@app.get("/play", response_class=HTMLResponse) +async def play(request: Request): intro = header( h1("✊✋✌!"), h2("Wanna play?"), div("type 'r' for Rock ✊", br(), "'p' for Paper ✋", br(), "Or 's' for Scissors ✌"), main(_id="game"), ) - return response.html(str(page_wrapper(intro))) - + return str(page_wrapper(intro)) if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=True) + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/examples/grid.py b/examples/grid.py index b5e1e936..eae3139c 100644 --- a/examples/grid.py +++ b/examples/grid.py @@ -1,50 +1,27 @@ import sys - sys.path.insert(0, "..") -import os - -from sanic import Sanic, response - -from domonic.CDN import * +from fastapi import FastAPI, Request, Response +from fastapi.responses import HTMLResponse from domonic.html import * +from domonic.CDN import CDN_CSS -# from app import * -# from app.components import * - -app = Sanic(name="Long_poll_grid_test") -app.static("/assets", "./assets") +app = FastAPI() MARGIN = 1 PADDING = 2 # create a template -cell = lambda x=None: div(_class=x if x else "", _style=f"display:inline;margin:{MARGIN}px;padding:{PADDING}px;").html( - # button(":)", _style="background-color:white;color:black;") -) +cell = lambda x=None: div(_class=x if x else "", _style=f"display:inline;margin:{MARGIN}px;padding:{PADDING}px;") row = lambda *x: div(*x, _class="row") -# TODO - random color gen is required. -# TODO - random face gen is required. - # world grid _grid = div( - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), - # row( cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d'),cell('d') ), row(cell("d") / 100) / 100, row(cell("d") / 100) / 100, - # _style="max-width:100px;", _class="container-fluid", ) -# print( str(cell()*10) ) -# cells = cell()*10 -# print(''.join([str(c) for c in cells])) - _materials = style( """ @@ -86,18 +63,21 @@ def __str__(self): return str(div(_materials, _scripts, _grid)) -@app.route("/") -@app.route("/world") -async def world(request): - # check the diffs against our diff map - return response.html( - str( +@app.get("/") +@app.get("/world", response_class=HTMLResponse) +async def world(request: Request): + return Response( + content=str( html( - head(), body(link(_rel="stylesheet", _type="text/css", _href=CDN_CSS.BOOTSTRAP_4), str(World(request))) + head(), + body( + link(rel="stylesheet", type="text/css", href=CDN_CSS.BOOTSTRAP_4), + str(World(request)), + ), ) ) ) - if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=True) + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/examples/ken/sf2.html b/examples/ken/sf2.html index 2c991204..b8b6c4cf 100644 --- a/examples/ken/sf2.html +++ b/examples/ken/sf2.html @@ -1,4 +1,4 @@ -