Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
OneDotNet/srcs/private/app/OxfordWordlistExtractor/*.html linguist-vendored
OneDotNet/tests/OxfordDictExtractor.Tests/examples/*.html linguist-vendored
src/private/app/supermemo-mcp/references/*.ahk linguist-vendored
src/private/app/factorio-cycle-calculator/src/factorio_cycle_calculator/generated/* linguist-generated
8 changes: 8 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
experimental_monorepo_root = true

[settings]
experimental = true

[monorepo]
config_roots = ["src/private/app/factorio-cycle-calculator"]

[tools]
# Runtimes
dotnet = "10"
Expand Down
35 changes: 35 additions & 0 deletions src/private/app/factorio-cycle-calculator/.mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[tasks."schema:generate"]
description = "Generate Python models from the JSON schema."
run = [
"""
uv run \
--project src/private/app/factorio-cycle-calculator \
--package factorio-cycle-calculator \
--group dev \
datamodel-codegen \
--url https://raw.githubusercontent.com/jacquev6/factorio-data-raw-json-schema/refs/heads/main/factorio-data-raw-json-schema.full.json \
--output src/factorio_cycle_calculator/generated/data_raw_models.py \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve schema task paths against project directory

Running the documented command mise //src/private/app/factorio-cycle-calculator:schema:generate from the repo root executes this task with no task dir, but the generated-file path here is relative (src/factorio_cycle_calculator/...) and therefore points outside the package directory; this makes codegen/ruff operate on the wrong location (or fail if the path does not exist), so the intended src/private/app/factorio-cycle-calculator/src/factorio_cycle_calculator/generated/data_raw_models.py is not reliably updated.

Useful? React with 👍 / 👎.

--input-file-type jsonschema \
--output-model-type dataclasses.dataclass \
--target-python-version 3.12 \
--formatters ruff-format""",
"""
uv run \
--project src/private/app/factorio-cycle-calculator \
--package factorio-cycle-calculator \
--group dev \
ruff check \
--fix \
--exit-zero \
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ruff check --exit-zero will make the generation task succeed even if Ruff still reports unfixable issues in the generated file, which can mask real regressions in the codegen output. Prefer removing --exit-zero and instead adjusting per-file ignores (or a targeted --select/--ignore) so the task fails when new, unexpected Ruff issues appear.

Suggested change
--exit-zero \

Copilot uses AI. Check for mistakes.
--quiet \
src/factorio_cycle_calculator/generated/data_raw_models.py""",
"""
uv run \
--project src/private/app/factorio-cycle-calculator \
--package factorio-cycle-calculator \
--group dev \
ruff format \
--quiet \
src/factorio_cycle_calculator/generated/data_raw_models.py""",
]
outputs = ["src/factorio_cycle_calculator/generated/data_raw_models.py"]
16 changes: 14 additions & 2 deletions src/private/app/factorio-cycle-calculator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ An initial Streamlit prototype is available in `app.py`. It focuses on the
advanced oil processing chain and uses Google OR-Tools to compute machine
counts given a petroleum gas demand and the chosen machine/effect settings.

Run the app with:
Run the app after installation with the script entry point:

- `uv run --project src/private/app/factorio-cycle-calculator streamlit run app.py`
- `uv run --project src/private/app/factorio-cycle-calculator factorio-cycle-calculator`

## Schema and generated models

The generated models live in
`src/factorio_cycle_calculator/generated/data_raw_models.py`.

Model generation is driven entirely by a mise task that pulls the schema from
the upstream URL and does not store a local JSON schema file.

Generate models:

- `mise //src/private/app/factorio-cycle-calculator:schema:generate`
25 changes: 24 additions & 1 deletion src/private/app/factorio-cycle-calculator/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[build-system]
requires = ["hatchling>=1.24.2"]
build-backend = "hatchling.build"

[project]
name = "factorio-cycle-calculator"
version = "0.0.0-dev"
Expand All @@ -9,5 +13,24 @@ license = "GPL-3.0-or-later"
classifiers = ["Private :: Do Not Upload"]
dependencies = ["ortools>=9.11.4210", "pillow>=10.3.0", "streamlit>=1.42.0"]

[project.scripts]
factorio-cycle-calculator = "factorio_cycle_calculator.__main__:main"

[dependency-groups]
dev = ["datamodel-code-generator[ruff]>=0.53.0"]
dev = ["datamodel-code-generator[debug,ruff,http]>=0.53.0"]

[tool.hatch.build.targets.wheel]
packages = ["src/factorio_cycle_calculator"]

[tool.datamodel-codegen]
input = "https://raw.githubusercontent.com/jacquev6/factorio-data-raw-json-schema/refs/heads/main/factorio-data-raw-json-schema.full.json"
input-file-type = "jsonschema"
output = "src/factorio_cycle_calculator/generated/data_raw_models.py"
output-model-type = "dataclasses.dataclass"
target-python-version = "3.12"

[tool.ruff]
extend = "../../../../pyproject.toml"

[tool.ruff.lint.per-file-ignores]
"src/factorio_cycle_calculator/generated/data_raw_models.py" = ["D", "N815"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Run the Streamlit app via the package entry point."""

from __future__ import annotations

import sys
from importlib import import_module
from pathlib import Path

from streamlit.web.cli import main as streamlit_main


def main(argv: list[str] | None = None) -> None:
"""Launch the Streamlit application."""
module = import_module("factorio_cycle_calculator.app")
app_path = Path(module.__file__).resolve()
new_argv = ["streamlit", "run", str(app_path)]
if argv is not None:
new_argv.extend(argv)
Comment on lines +17 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Forward CLI arguments to Streamlit entrypoint

The console script entry point invokes main() without parameters, and this code only appends extra args when argv is explicitly passed, so user-supplied flags on factorio-cycle-calculator (for example --help or --server.port) are silently dropped and never reach Streamlit; defaulting to sys.argv[1:] is needed to preserve CLI behavior.

Useful? React with 👍 / 👎.


Comment on lines +12 to +19
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The console script entry point ignores user-provided CLI args when argv is left as None. Since main() is invoked by console_scripts without arguments, flags like --server.port passed to factorio-cycle-calculator will be dropped. Consider defaulting argv to sys.argv[1:] so options are forwarded to streamlit run.

Copilot uses AI. Check for mistakes.
old_argv = sys.argv
try:
sys.argv = new_argv
streamlit_main()
finally:
sys.argv = old_argv


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

from __future__ import annotations

import importlib
import io
import json
import os
import re
import sys
from collections.abc import Mapping, Sequence
from dataclasses import MISSING, dataclass, fields, is_dataclass
from pathlib import Path
Expand Down Expand Up @@ -58,20 +56,14 @@ class ModulePrototype(_GeneratedModel):
class RecipePrototype(_GeneratedModel):
"""Type-checking stub for recipes."""
else:
_generated_path = (
Path(__file__).resolve().parent / "generated" / "data_raw_models.py"
)
if not _generated_path.exists():
raise GeneratedModelsImportError(
_generated_path,
reason="Generated models not found",
)
_generated_root = _generated_path.parent.parent
if str(_generated_root) not in sys.path:
sys.path.insert(0, str(_generated_root))
try:
_module = importlib.import_module("generated.data_raw_models")
from factorio_cycle_calculator.generated import (
data_raw_models as _module,
)
except Exception as exc:
_generated_path = (
Path(__file__).resolve().parent / "generated" / "data_raw_models.py"
)
raise GeneratedModelsImportError(
_generated_path,
reason="Failed to import generated models",
Expand Down
Loading
Loading