Skip to content

examples/web_app.py announces a URL it has not yet bound, reading FISHE_WEB_PORT a third time to do it #178

Description

@dmccoystephenson

Summary

examples/web_app.py:34-38 prints the address before anything is listening on it, and builds that address from its own copy of the two environment variables rather than from the server:

host = os.environ.get("FISHE_WEB_HOST", "127.0.0.1")
port = os.environ.get("FISHE_WEB_PORT", "8000")
print(f"FishE web app is starting at http://{host}:{port}")
print("Open that URL in your browser to play. Press Ctrl+C here to stop.")
game = FishE(interfaceType=UIType.WEB)

Two consequences follow, both verified against source:

  • A URL that was never served is printed first. FISHE_WEB_PORT=80801x python3 examples/web_app.py prints FishE web app is starting at http://127.0.0.1:80801x and only then raises, because the value is not converted here at all — UserInterfaceFactory's WEB branch (src/ui/userInterfaceFactory.py:44-50) does the converting, after the print. The same ordering applies to a port that is already taken, which WebUserInterface now reports from _bindServer (src/ui/webUserInterface.py:148-169) — again after the URL has been announced. web/serve.py was given the opposite ordering in Name FISHE_WEB_PORT when a web port is busy or misspelled #177 (web/serve.py:128-133: bound first, announced second), so the two web entry points now disagree about this.
  • The defaults are copied. "8000" is written here and again at src/ui/userInterfaceFactory.py:44. Should the factory's default ever move, this file would keep printing the old one, with nothing failing to say so.

The ordering cannot simply be swapped: FishE.__init__ builds the front-end and then blocks in _selectSaveFile() (src/fishE.py:52-60), so control does not come back to main() after construction, and WebUserInterface.address — which would be the authoritative answer — cannot be read from there. Some other arrangement is required, which is why this is filed rather than folded into #177.

Why it matters

This is the entry point the README points a player at for the server-backed front-end (README.md:34). Of the two ordinary startup failures — a misspelled port and a busy one — both are now explained well by the exception, but both are still preceded by a confident sentence naming an address that will never answer.

Suggested fix

The port could be validated in main() before FishE is constructed (sharing the check the factory already performs), and the announcement could be deferred until the server is known to be bound — for example by having the factory or WebUserInterface report the bound address, or by binding in main() and handing the result in. Whichever shape is chosen, the "8000" default should be stated in one place rather than two. A test alongside tests/ui/test_userInterfaceFactory.py:116-128 would cover it.

Filed by Claude during an automated triage pass; every claim above was verified against source. This issue was filed during a Gardener session (https://github.com/Stephenson-Software/gardener).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions