feat: Introduce pyproject.toml for build configuration

Migrated project dependencies and metadata into a newly added `pyproject.toml`, aligning with modern Python packaging practices. Removed `requirements.txt` as dependencies are now specified in the unified project configuration. Restructured the project by moving Python code, static assets, and templates into a `src/structables` directory to encapsulate project components better and facilitate packaging. Moreover, refactor `main.py` to read environment variables earlier, streamline argument parsing, and ensure configurations are correctly applied before the Flask app initialization. This reorganization supports better project scalability, simplifies the build process, and enhances maintainability by consolidating project configurations and dependencies.

Note: The usage of `pyproject.toml` requires tools that support PEP 518 and might necessitate updates to CI/CD pipelines or developer workflows.
This commit is contained in:
Kumi 2024-05-23 08:06:36 +02:00
parent 25a07d797b
commit 85d5c88294
Signed by: kumi
GPG key ID: ECBCC9082395383F
34 changed files with 108 additions and 60 deletions

31
pyproject.toml Normal file
View file

@ -0,0 +1,31 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "structables"
version = "0.2.0"
authors = [
{ name="Private.coffee Team", email="support@private.coffee" },
]
description = "A simple frontend for Instructables"
readme = "README.md"
license = { file="LICENSE" }
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
]
dependencies = [
"flask",
"bs4",
]
[project.scripts]
structables = "structables.main:main"
[project.urls]
"Homepage" = "https://git.private.coffee/privatecoffee/structables"
"Bug Tracker" = "https://git.private.coffee/privatecoffee/structables/issues"
"Source Code" = "https://git.private.coffee/privatecoffee/structables"

View file

@ -1,2 +0,0 @@
bs4
flask

View file

View file

@ -54,6 +54,10 @@ def get_typesense_api_key():
TYPESENSE_API_KEY = get_typesense_api_key() TYPESENSE_API_KEY = get_typesense_api_key()
debugmode = False
invidious = None
unsafe = False
def projects_search( def projects_search(
query="*", query="*",
@ -156,64 +160,8 @@ def update_data():
) )
debugmode = os.environ.get("FLASK_DEBUG", os.environ.get("STRUCTABLES_DEBUG", False))
invidious = os.environ.get("STRUCTABLES_INVIDIOUS")
unsafe = os.environ.get("STRUCTABLES_UNSAFE", False)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"-p",
"--port",
default=8002,
type=int,
help="Port to listen on",
)
parser.add_argument(
"-d",
"--debug",
action="store_true",
help="Enable debug mode",
)
parser.add_argument(
"-l",
"--listen-host",
default="127.0.0.1",
help="Host to listen on",
)
parser.add_argument(
"-I",
"--invidious",
help="URL to Invidious instance, e.g. https://invidious.private.coffee/",
)
parser.add_argument(
"-u",
"--unsafe",
action="store_true",
help="Display iframes regardless of origin",
)
args = parser.parse_args()
if args.debug:
debugmode = True
if args.invidious:
invidious = args.invidious
if args.unsafe:
unsafe = True
print("Loading initial data...")
update_data()
print("Started!")
app = Flask(__name__, template_folder="templates", static_folder="static") app = Flask(__name__, template_folder="templates", static_folder="static")
if debugmode:
app.logger.setLevel(logging.DEBUG)
@app.route("/cron/") @app.route("/cron/")
def cron(): def cron():
@ -1187,6 +1135,7 @@ def route_proxy():
if url.startswith("https://cdn.instructables.com/") or url.startswith( if url.startswith("https://cdn.instructables.com/") or url.startswith(
"https://content.instructables.com/" "https://content.instructables.com/"
): ):
def generate(): def generate():
# Subfunction to allow streaming the data instead of # Subfunction to allow streaming the data instead of
# downloading all of it at once # downloading all of it at once
@ -1199,6 +1148,7 @@ def route_proxy():
yield chunk yield chunk
except HTTPError as e: except HTTPError as e:
abort(e.code) abort(e.code)
try: try:
with urlopen(unquote(url)) as data: with urlopen(unquote(url)) as data:
content_type = data.headers["content-type"] content_type = data.headers["content-type"]
@ -1259,5 +1209,74 @@ def internal_server_error(e):
return render_template("500.html") return render_template("500.html")
if __name__ == "__main__": def main():
global debugmode, invidious, unsafe
parser = ArgumentParser()
parser.add_argument(
"-p",
"--port",
default=8002,
type=int,
help="Port to listen on",
)
parser.add_argument(
"-d",
"--debug",
action="store_true",
help="Enable debug mode",
)
parser.add_argument(
"-l",
"--listen-host",
default="127.0.0.1",
help="Host to listen on",
)
parser.add_argument(
"-I",
"--invidious",
help="URL to Invidious instance, e.g. https://invidious.private.coffee/",
)
parser.add_argument(
"-u",
"--unsafe",
action="store_true",
help="Display iframes regardless of origin",
)
parser.add_argument(
"-P",
"--privacy-file",
default="privacy.txt",
help="File to read privacy policy from",
)
args = parser.parse_args()
debugmode = os.environ.get(
"FLASK_DEBUG", os.environ.get("STRUCTABLES_DEBUG", False)
)
invidious = os.environ.get("STRUCTABLES_INVIDIOUS")
unsafe = os.environ.get("STRUCTABLES_UNSAFE", False)
if args.debug:
debugmode = True
if args.invidious:
invidious = args.invidious
if args.unsafe:
unsafe = True
print("Loading initial data...")
update_data()
print("Started!")
if debugmode:
app.logger.setLevel(logging.DEBUG)
app.run(port=args.port, host=args.listen_host, debug=debugmode) app.run(port=args.port, host=args.listen_host, debug=debugmode)
if __name__ == "__main__":
main()

View file

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

Before

Width:  |  Height:  |  Size: 891 KiB

After

Width:  |  Height:  |  Size: 891 KiB

View file

Before

Width:  |  Height:  |  Size: 494 B

After

Width:  |  Height:  |  Size: 494 B