Skip to content

Commit

Permalink
Merge pull request #14 from Scrumplex/refactor/improve-poetry-packaging
Browse files Browse the repository at this point in the history
refactor: improve poetry packaging
  • Loading branch information
ShyAssassin authored Sep 10, 2024
2 parents c5597c7 + 6a05ef1 commit 42f79cc
Show file tree
Hide file tree
Showing 50 changed files with 471 additions and 198 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
- run: source $VENV

- name: Build Backend
run: poetry run pyinstaller --noconfirm ETVR.spec TrackingBackend/main.py
run: poetry run pyinstaller --noconfirm ETVR.spec eyetrackvr_backend/main.py

- name: Rename Linux Binary
if: ${{ matrix.os == 'ubuntu-latest' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ jobs:
run: poetry install
- name: Lint with Mypy
# Wish we could warn instead of erroring
run: poetry run mypy --ignore-missing-imports --check-untyped-defs --show-error-context --implicit-optional --disable-error-code union-attr TrackingBackend/
run: poetry run mypy --ignore-missing-imports --check-untyped-defs --show-error-context --implicit-optional --disable-error-code union-attr eyetrackvr_backend/
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ dist/
build/
tracker-config.json
TrackingBackend/tracker-config.json
**/.DS_Store
**/.DS_Store
# Nix
result
.envrc
.direnv/
9 changes: 3 additions & 6 deletions ETVR.spec
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ block_cipher = None


a = Analysis(
['TrackingBackend/main.py'],
["eyetrackvr_backend/__main__.py"],
pathex=[],
binaries=[],
# WTF, wildcard doesnt apply to sub folders???
datas=[
("TrackingBackend/assets/*", "assets/"),
("TrackingBackend/assets/models/*", "assets/models/"),
("TrackingBackend/assets/images/*", "assets/images/")
("eyetrackvr_backend/assets", "eyetrackvr_backend/assets")
],
hiddenimports=["cv2", "numpy"],
hookspath=[],
Expand Down Expand Up @@ -46,5 +43,5 @@ exe = EXE(
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon="TrackingBackend/assets/images/logo.ico"
icon="eyetrackvr_backend/assets/images/logo.ico"
)
24 changes: 12 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@
.DEFAULT_GOAL := run

stream1:
ffmpeg -stream_loop "-1" -i TrackingBackend/assets/ETVR_SAMPLE.mp4 -attempt_recovery 1 -http_persistent 1 -http_seekable 0 -listen 1 -f mp4 -movflags frag_keyframe+empty_moov http://localhost:8080
ffmpeg -stream_loop "-1" -i eyetrackvr_backend/assets/ETVR_SAMPLE.mp4 -attempt_recovery 1 -http_persistent 1 -http_seekable 0 -listen 1 -f mp4 -movflags frag_keyframe+empty_moov http://localhost:8080

stream2:
ffmpeg -stream_loop "-1" -i TrackingBackend/assets/ETVR_SAMPLE.mp4 -attempt_recovery 1 -http_persistent 1 -http_seekable 0 -listen 1 -f mp4 -movflags frag_keyframe+empty_moov http://localhost:8081
ffmpeg -stream_loop "-1" -i eyetrackvr_backend/assets/ETVR_SAMPLE.mp4 -attempt_recovery 1 -http_persistent 1 -http_seekable 0 -listen 1 -f mp4 -movflags frag_keyframe+empty_moov http://localhost:8081

install:
poetry install

run:
cd TrackingBackend/ && poetry run uvicorn --factory main:setup_app --reload --port 8000
poetry run uvicorn --factory eyetrackvr_backend:setup_app --reload --port 8000

black:
poetry run black TrackingBackend/
poetry run black eyetrackvr_backend/

ruff:
poetry run ruff TrackingBackend/
poetry run ruff eyetrackvr_backend/

mypy:
poetry run mypy --ignore-missing-imports --check-untyped-defs TrackingBackend/
poetry run mypy --ignore-missing-imports --check-untyped-defs eyetrackvr_backend/

pyinstaller:
poetry run pyinstaller ETVR.spec TrackingBackend/main.py
poetry run pyinstaller ETVR.spec

nuitka:
poetry run python -m nuitka --standalone --include-module=cv2 TrackingBackend/main.py
poetry run python -m nuitka --standalone --include-module=cv2 eyetrackvr_backend/__main__.py

clean:
rm -rf TrackingBackend/__pycache__/
rm -rf TrackingBackend/app/__pycache__/
rm -rf TrackingBackend/app/algorithms/__pycache__/
rm -rf eyetrackvr_backend/__pycache__/
rm -rf eyetrackvr_backend/app/__pycache__/
rm -rf eyetrackvr_backend/app/algorithms/__pycache__/
rm -rf build/
rm -rf dist/
rm -rf dist/
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ To start the local development server run either of the following commands.
python build.py run
```
```bash
cd TrackingBackend/ && poetry run uvicorn --factory main:setup_app --reload --port 8000
poetry run uvicorn --factory eyetrackvr_backend:setup_app --reload --port 8000
```

### The build script
Expand Down Expand Up @@ -115,7 +115,7 @@ python build.py build
```
If you want to build the backend manually you can do so with the following command.
```bash
poetry run pyinstaller ETVR.spec TrackingBackend/main.py
poetry run pyinstaller ETVR.spec
```

### Profiling
Expand All @@ -124,9 +124,9 @@ To start profiling run the following command, this will start the backend and ge
If you dont like viztracer you can use almost any other profiler (multi-processing and multi-threading support is required)\
*currently using the build script to start profiling is broken!*
```bash
cd TrackingBackend/ && poetry run viztracer main.py
poetry run viztracer -m eyetrackvr_backend:main
```


## License
Unless explicitly stated otherwise all code contained within this repository is under the [MIT License](./LICENSE-MIT)
Unless explicitly stated otherwise all code contained within this repository is under the [MIT License](./LICENSE-MIT)
4 changes: 0 additions & 4 deletions TrackingBackend/app/__init__.py

This file was deleted.

16 changes: 7 additions & 9 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ def install():

def lint():
print("Running black for code formatting...")
os.system(f"poetry run black TrackingBackend{os.path.sep}")
os.system(f"poetry run black eyetrackvr_backend{os.path.sep}")
print("-" * 80)

print("Running ruff for linting...")
os.system(f"poetry run ruff TrackingBackend{os.path.sep}")
os.system(f"poetry run ruff eyetrackvr_backend{os.path.sep}")
print("-" * 80)

print("Running mypy for type checking...")
os.system(f"poetry run mypy --ignore-missing-imports --check-untyped-defs TrackingBackend{os.path.sep}")
os.system(f"poetry run mypy --ignore-missing-imports --check-untyped-defs eyetrackvr_backend{os.path.sep}")
print("-" * 80)

print("Running pytest for unit testing...")
os.system(f"poetry run pytest TrackingBackend{os.path.sep}")
os.system(f"poetry run pytest eyetrackvr_backend{os.path.sep}")
print("-" * 80)


Expand All @@ -53,20 +53,18 @@ def clean():


def build():
os.system("poetry run pyinstaller ETVR.spec TrackingBackend/main.py")
os.system("poetry run pyinstaller ETVR.spec")


def profile():
os.chdir(f"{os.path.dirname(os.path.abspath(__file__))}{os.path.sep}TrackingBackend")
try:
os.system("poetry run viztracer main.py")
os.system("poetry run viztracer -m eyetrackvr_backend.__main__")
except KeyboardInterrupt:
exit(0)


def run():
os.chdir(f"{os.path.dirname(os.path.abspath(__file__))}{os.path.sep}TrackingBackend")
os.system("poetry run uvicorn --factory main:setup_app --reload --port 8000")
os.system("poetry run uvicorn --factory eyetrackvr_backend:setup_app --reload --port 8000")


def emulate():
Expand Down
127 changes: 55 additions & 72 deletions TrackingBackend/main.py → eyetrackvr_backend/__init__.py
Original file line number Diff line number Diff line change
@@ -1,72 +1,55 @@
import os

if os.pardir != os.path.dirname(__file__):
os.chdir(os.path.dirname(__file__))

from fastapi.staticfiles import StaticFiles
from app.logger import setup_logger
from fastapi import FastAPI
from app.etvr import ETVR


def setup_app():
setup_logger()
etvr_app = ETVR()
etvr_app.add_routes()
app = FastAPI()
app.include_router(etvr_app.router)
app.mount("/", StaticFiles(directory="assets/", html=True))
app.mount("/images", StaticFiles(directory="assets/images"))
return app


def main() -> int:
import uvicorn
import sys

port: int = 8000
host: str = "127.0.0.1"
args = sys.argv[1:]
for i, v in enumerate(args):
try:
match v:
case "--help" | "-h":
print("Usage: python main.py [OPTIONS]")
print("Options:")
print(f"--port [PORT] Set the port to listen on. Default: {port}")
print(f"--host [HOST] Set the host to listen on. Default: {host}")
print(f"--help, -h Show this help message and exit") # noqa: F541
return 0
case "--port":
if int(args[i + 1]) > 65535:
print("Port must be between 0 and 65535!")
return 1
port = int(args[i + 1])
case "--host":
host = args[i + 1]
case _:
if v.startswith("-"):
print("Unknown argument " + v)
except IndexError:
print("Missing value for argument " + v)
return 1
except ValueError:
print("Invalid value for argument " + v)
return 1

app = setup_app()
uvicorn.run(app=app, host=host, port=port, reload=False)
return 0


if __name__ == "__main__":
import multiprocessing
import sys

# check if we are running directly, if so, warn the user
if not (getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")):
print("WARNING: backend is being run directly but has not been compiled into an executable!")
print("It is recomended to start the backend using uvicorn CLI when not compiled as an executable.")
else:
multiprocessing.freeze_support()
raise SystemExit(main())
from fastapi.staticfiles import StaticFiles
from fastapi import FastAPI

from .assets import ASSETS_DIR, IMAGES_DIR
from .etvr import ETVR
from .logger import setup_logger

def setup_app():
setup_logger()
etvr_app = ETVR()
etvr_app.add_routes()
app = FastAPI()
app.include_router(etvr_app.router)
app.mount("/", StaticFiles(directory=ASSETS_DIR, html=True))
app.mount("/images", StaticFiles(directory=IMAGES_DIR))
return app


def main() -> int:
import uvicorn
import sys

port: int = 8000
host: str = "127.0.0.1"
args = sys.argv[1:]
for i, v in enumerate(args):
try:
match v:
case "--help" | "-h":
print(f"Usage: {sys.argv[0]} [OPTIONS]")
print("Options:")
print(f"--port [PORT] Set the port to listen on. Default: {port}")
print(f"--host [HOST] Set the host to listen on. Default: {host}")
print(f"--help, -h Show this help message and exit") # noqa: F541
return 0
case "--port":
if int(args[i + 1]) > 65535:
print("Port must be between 0 and 65535!")
return 1
port = int(args[i + 1])
case "--host":
host = args[i + 1]
case _:
if v.startswith("-"):
print("Unknown argument " + v)
except IndexError:
print("Missing value for argument " + v)
return 1
except ValueError:
print("Invalid value for argument " + v)
return 1

app = setup_app()
uvicorn.run(app=app, host=host, port=port, reload=False)
return 0
18 changes: 18 additions & 0 deletions eyetrackvr_backend/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This is the main script run by pyinstaller
from eyetrackvr_backend import main as real_main

import multiprocessing
import sys

def main():
# check if we are running directly, if so, warn the user
if not (getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")):
print("WARNING: backend is being run directly but has not been compiled into an executable!")
print("It is recommended to start the backend using uvicorn CLI when not compiled as an executable.")
else:
multiprocessing.freeze_support()
raise SystemExit(real_main())


if __name__ == "__main__":
main()
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
import numpy as np
from cv2.typing import MatLike
from functools import lru_cache
from app.utils import BaseAlgorithm
from app.processes import EyeProcessor
from app.types import EyeData, TrackerPosition, TRACKING_FAILED
from ..utils import BaseAlgorithm
from ..processes import EyeProcessor
from ..types import EyeData, TrackerPosition, TRACKING_FAILED

# cache param
lru_maxsize_vvs = 16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@

import cv2
from cv2.typing import MatLike
from app.utils import BaseAlgorithm
from app.processes import EyeProcessor
from app.types import EyeData, TrackerPosition, TRACKING_FAILED
from ..utils import BaseAlgorithm
from ..processes import EyeProcessor
from ..types import EyeData, TrackerPosition, TRACKING_FAILED


class Blob(BaseAlgorithm):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
from copy import deepcopy
from functools import lru_cache
from cv2.typing import MatLike, Point
from app.processes import EyeProcessor
from app.utils import BaseAlgorithm, safe_crop
from app.types import EyeData, TrackerPosition, TRACKING_FAILED
from ..processes import EyeProcessor
from ..utils import BaseAlgorithm, safe_crop
from ..types import EyeData, TrackerPosition, TRACKING_FAILED


# cache param
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from app.processes import EyeProcessor
from app.utils import BaseAlgorithm
from ..processes import EyeProcessor
from ..utils import BaseAlgorithm


class HSRAC(BaseAlgorithm):
Expand Down
Loading

0 comments on commit 42f79cc

Please sign in to comment.