gams-frog 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. gams_frog-0.3.0/.gitignore +15 -0
  2. gams_frog-0.3.0/.gitlab-ci.yml +57 -0
  3. gams_frog-0.3.0/CHANGELOG.md +27 -0
  4. gams_frog-0.3.0/LICENSE.md +21 -0
  5. gams_frog-0.3.0/Makefile +16 -0
  6. gams_frog-0.3.0/PKG-INFO +128 -0
  7. gams_frog-0.3.0/README.md +106 -0
  8. gams_frog-0.3.0/pyproject.toml +47 -0
  9. gams_frog-0.3.0/src/gams_frog/__init__.py +2 -0
  10. gams_frog-0.3.0/src/gams_frog/cli.py +229 -0
  11. gams_frog-0.3.0/src/gams_frog/deploy/AuthorizationService.py +80 -0
  12. gams_frog-0.3.0/src/gams_frog/deploy/DeployService.py +148 -0
  13. gams_frog-0.3.0/src/gams_frog/deploy/GamsAuthClient.py +75 -0
  14. gams_frog-0.3.0/src/gams_frog/deploy/LoginFormParser.py +39 -0
  15. gams_frog-0.3.0/src/gams_frog/deploy/__init__.py +0 -0
  16. gams_frog-0.3.0/src/gams_frog/ssr/__init__.py +0 -0
  17. gams_frog-0.3.0/src/gams_frog/ssr/init/AppInitializer.py +106 -0
  18. gams_frog-0.3.0/src/gams_frog/ssr/init/ApplicationContext.py +36 -0
  19. gams_frog-0.3.0/src/gams_frog/ssr/init/__init__.py +0 -0
  20. gams_frog-0.3.0/src/gams_frog/ssr/init/config/AppEnv.py +23 -0
  21. gams_frog-0.3.0/src/gams_frog/ssr/init/config/ApplicationCacheConfig.py +20 -0
  22. gams_frog-0.3.0/src/gams_frog/ssr/init/config/ApplicationConfiguration.py +147 -0
  23. gams_frog-0.3.0/src/gams_frog/ssr/init/config/ApplicationExternalConfig.py +226 -0
  24. gams_frog-0.3.0/src/gams_frog/ssr/init/config/ApplicationExternalConfigImporter.py +103 -0
  25. gams_frog-0.3.0/src/gams_frog/ssr/init/config/__init__.py +0 -0
  26. gams_frog-0.3.0/src/gams_frog/ssr/load/ApplicationDataLoader.py +102 -0
  27. gams_frog-0.3.0/src/gams_frog/ssr/load/ApplicationDatastore.py +85 -0
  28. gams_frog-0.3.0/src/gams_frog/ssr/load/DigitalObjectService.py +49 -0
  29. gams_frog-0.3.0/src/gams_frog/ssr/load/ProjectService.py +23 -0
  30. gams_frog-0.3.0/src/gams_frog/ssr/load/__init__.py +0 -0
  31. gams_frog-0.3.0/src/gams_frog/ssr/load/cache/DataCacheManager.py +248 -0
  32. gams_frog-0.3.0/src/gams_frog/ssr/load/cache/__init__.py +0 -0
  33. gams_frog-0.3.0/src/gams_frog/ssr/load/utils/Pyrilo.py +199 -0
  34. gams_frog-0.3.0/src/gams_frog/ssr/load/utils/__init__.py +0 -0
  35. gams_frog-0.3.0/src/gams_frog/ssr/watch/ApplicationViewFileEventController.py +74 -0
  36. gams_frog-0.3.0/src/gams_frog/ssr/watch/ApplicationViewFileWatcher.py +37 -0
  37. gams_frog-0.3.0/src/gams_frog/ssr/watch/ApplicationWebServer.py +66 -0
  38. gams_frog-0.3.0/src/gams_frog/ssr/watch/__init__.py +0 -0
  39. gams_frog-0.3.0/src/gams_frog/ssr/watch/render/ApplicationErrorHtmlBuilder.py +14 -0
  40. gams_frog-0.3.0/src/gams_frog/ssr/watch/render/ApplicationStaticFileRenderer.py +72 -0
  41. gams_frog-0.3.0/src/gams_frog/ssr/watch/render/ApplicationViewTemplateRenderer.py +111 -0
  42. gams_frog-0.3.0/src/gams_frog/ssr/watch/render/DigitalObjectViewRenderer.py +182 -0
  43. gams_frog-0.3.0/src/gams_frog/ssr/watch/render/__init__.py +0 -0
  44. gams_frog-0.3.0/src/gams_frog/ssr/watch/utils/RenderUtils.py +19 -0
  45. gams_frog-0.3.0/src/gams_frog/ssr/watch/utils/__init__.py +0 -0
  46. gams_frog-0.3.0/src/gams_frog/validation/HardcodedPathVisitor.py +69 -0
  47. gams_frog-0.3.0/src/gams_frog/validation/JinjaTemplateValidator.py +71 -0
  48. gams_frog-0.3.0/src/gams_frog/validation/StaticFileValidator.py +98 -0
  49. gams_frog-0.3.0/src/gams_frog/validation/ValidationStatics.py +14 -0
  50. gams_frog-0.3.0/src/gams_frog/validation/__init__.py +0 -0
  51. gams_frog-0.3.0/tests/__init__.py +0 -0
  52. gams_frog-0.3.0/tests/conftest.py +92 -0
  53. gams_frog-0.3.0/tests/integration_tests/__init__.py +0 -0
  54. gams_frog-0.3.0/tests/integration_tests/test_build_cmd.py +144 -0
  55. gams_frog-0.3.0/tests/integration_tests/test_deploy.py +109 -0
  56. gams_frog-0.3.0/tests/integration_tests/test_project_template.py +35 -0
  57. gams_frog-0.3.0/tests/integration_tests/test_static_files.py +27 -0
  58. gams_frog-0.3.0/tests/integration_tests/test_validation.py +134 -0
  59. gams_frog-0.3.0/tests/pytest.ini +4 -0
  60. gams_frog-0.3.0/tests/resources/readme.md +1 -0
  61. gams_frog-0.3.0/tests/resources/test/templates/object-list.j2 +3 -0
  62. gams_frog-0.3.0/tests/resources/test/templates/object.j2 +2 -0
  63. gams_frog-0.3.0/tests/resources/test/templates/project.j2 +3 -0
  64. gams_frog-0.3.0/tests/unittests/__init__.py +0 -0
  65. gams_frog-0.3.0/tests/unittests/test_config.py +97 -0
  66. gams_frog-0.3.0/tests/unittests/test_datastore.py +39 -0
  67. gams_frog-0.3.0/tests/unittests/test_rendering.py +35 -0
  68. gams_frog-0.3.0/tests/utils/TestDatastream.py +30 -0
  69. gams_frog-0.3.0/tests/utils/TestDigitalObject.py +37 -0
  70. gams_frog-0.3.0/tests/utils/TestDigitalObjectViewModel.py +17 -0
  71. gams_frog-0.3.0/tests/utils/TestGamsFrogProject.py +190 -0
  72. gams_frog-0.3.0/tests/utils/TestProject.py +15 -0
  73. gams_frog-0.3.0/tests/utils/__init__.py +0 -0
  74. gams_frog-0.3.0/uv.lock +840 -0
@@ -0,0 +1,15 @@
1
+ # python generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # venv
10
+ .venv
11
+
12
+ output/*
13
+ views/*
14
+ .idea/*
15
+ .python-version
@@ -0,0 +1,57 @@
1
+ variables:
2
+ UV_VERSION: 0.5
3
+ PYTHON_BASE_VERSION: 3.12
4
+ BASE_LAYER: bookworm-slim
5
+
6
+ stages:
7
+ - test
8
+ - lint
9
+ - build
10
+ - publish
11
+
12
+ # A hidden job template that can be used by different Python versions
13
+ .test-template:
14
+ stage: test
15
+ image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_BASE_VERSION-$BASE_LAYER
16
+ script:
17
+ - echo "uv environment version"
18
+ - uv --version
19
+ - echo "Pinning ${PYTHON_VERSION}"
20
+ - uv python pin ${PYTHON_VERSION}
21
+ - uv sync
22
+ - echo "Using python version:"
23
+ - python --version
24
+ - echo "Running tests with uv"
25
+ - uv run pytest tests
26
+
27
+ # Specific jobs for Python versions
28
+ test-py_3.12:
29
+ extends: .test-template
30
+ variables:
31
+ PYTHON_VERSION: "3.12"
32
+
33
+ lint:
34
+ stage: lint
35
+ image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_BASE_VERSION-$BASE_LAYER
36
+ script:
37
+ - echo "uv environment version"
38
+ - uv --version
39
+ - echo "Using python version:"
40
+ - python --version
41
+ - echo "Running uv check with ruff"
42
+ - uv run ruff check src
43
+
44
+ build:
45
+ stage: build
46
+ image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_BASE_VERSION-$BASE_LAYER
47
+ script:
48
+ uv build
49
+
50
+ publish-pypi:
51
+ stage: publish
52
+ image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_BASE_VERSION-$BASE_LAYER
53
+ script:
54
+ - uv build
55
+ - uv publish --token $PYPI_TOKEN
56
+ rules:
57
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.0.3]
9
+
10
+ ### Changed
11
+
12
+ - renamed tool to gams-frog (from pollin-tool)
13
+
14
+ ## [0.0.2] - 13.04.2026 [YANKED]
15
+
16
+ ### Added
17
+
18
+ - cli commands now default for gams-frog.toml to the current working directory of gams-frog
19
+ - added --version command
20
+ - corrected readme (for deployed tool)
21
+
22
+ ## [0.0.1] - 13.04.2026 [YANKED]
23
+
24
+ ### Added
25
+
26
+ - release of initial beta version of the software
27
+ - core features with SSR rendering with GAMS5
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sebastian David Schiller-Stoff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,16 @@
1
+ # make test, coverage, documentation, etc
2
+ SHELL := /bin/bash
3
+
4
+ .PHONY: all test clean build
5
+
6
+ all: test lint build
7
+
8
+ test:
9
+ @uv run pytest tests
10
+
11
+ lint:
12
+ @uv run ruff check src
13
+
14
+ build:
15
+ @uv build
16
+
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: gams-frog
3
+ Version: 0.3.0
4
+ Summary: CLI tool for frontend generation for GAMS5 projects
5
+ Project-URL: Repository, https://zimlab.uni-graz.at/gams5/production/postprocessing/gams-frog
6
+ Author-email: Sebastian David Schiller-Stoff <sebastian.stoff@uni-graz.at>
7
+ License: MIT
8
+ License-File: LICENSE.md
9
+ Keywords: digital-humanities,gams,jinja2,static-site-generator
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
15
+ Requires-Python: >=3.12
16
+ Requires-Dist: aiohttp>=3.13.3
17
+ Requires-Dist: click>=8.3.1
18
+ Requires-Dist: jinja2==3.1.6
19
+ Requires-Dist: requests>=2.32.4
20
+ Requires-Dist: watchdog>=6.0.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # gams-frog
24
+
25
+ CLI tool that generates frontends for GAMS5 projects.
26
+ Supplies a development workflow for GAMS5-based web projects.
27
+
28
+ Meant as replacement for the gams3 "gamsdev" development workflow.
29
+
30
+ ## Quickstart
31
+
32
+ 1. Setup project files for gams-frog
33
+
34
+ 2. Install gams-frog itself
35
+
36
+ ```sh
37
+
38
+ # 1. install uv
39
+ # mac might need brew to install uv
40
+
41
+ # 2. install gams_frog via
42
+ # optionally specifiy version tag
43
+ uv tool install gams_frog
44
+
45
+ # verify installation via
46
+ frog --version
47
+
48
+ # 3. use the gams_frog
49
+ cd ./my/working/directory
50
+ frog dev # will use the gams_frog.toml from the current working dir
51
+ # alternatively specifiy a path
52
+ frog dev "C:\path\to\project"
53
+ # check for basic commands
54
+ frog
55
+
56
+ ```
57
+
58
+ ## Basic usage
59
+
60
+ 1. Have a running GAM5-API (OR external)
61
+ 2. Clone or init project files
62
+ 3. UV setup (install via pypi or clone via git)
63
+
64
+
65
+ ```sh
66
+ # 01. Setup project files from templates: https://zimlab.uni-graz.at/gams5/projects/project_template/gams-www
67
+ # 01b. Install uv (python package)
68
+
69
+ # 02a. Install via pypi
70
+ # 02a. uv install / pip install
71
+
72
+ # 02b. Clone gams_frog
73
+ # 02b. uv sync (uv procedure)
74
+ # 02b. Start virtual environment (venv)
75
+
76
+ # 03. Configure gams_frog via config file (gams_frog.toml) in template project folder
77
+
78
+ # (point to project folder with config file)
79
+ frog dev "C:\path\to\project"
80
+
81
+ # for production use
82
+ frog build "C:\path\to\project"
83
+
84
+ ```
85
+
86
+ ### Staging
87
+
88
+ ```sh
89
+ frog stage "/path/to/project"
90
+
91
+ ```
92
+
93
+
94
+ ### Production
95
+
96
+ ```sh
97
+ # use build command to generate the production files
98
+ frog build "/path/to/project"
99
+
100
+ ```
101
+
102
+
103
+ ### Deployment
104
+
105
+ - use the -d flag to deploy to staging or production environment
106
+
107
+ ```sh
108
+ # staging deployment
109
+ frog stage "/path/to/project" -d
110
+
111
+ # production deployment
112
+ frog build "/path/to/project" -d
113
+
114
+
115
+ ```
116
+
117
+
118
+ ## Development
119
+
120
+ ### Release
121
+
122
+ 1. Increment version in pyproject.toml in feature branch (merging into develop):
123
+ - make sure version follow vd.d.d pattern
124
+ 2. Merge changes to develop -> main
125
+ 3. Create release on the gitlab webclient (from main branch) with new git tag that must be the same as in the pyproject.toml!
126
+ - e.g. v0.1.1
127
+ - create the release from the main branch!
128
+ - gitlab will autodeploy the new version to pypi
@@ -0,0 +1,106 @@
1
+ # gams-frog
2
+
3
+ CLI tool that generates frontends for GAMS5 projects.
4
+ Supplies a development workflow for GAMS5-based web projects.
5
+
6
+ Meant as replacement for the gams3 "gamsdev" development workflow.
7
+
8
+ ## Quickstart
9
+
10
+ 1. Setup project files for gams-frog
11
+
12
+ 2. Install gams-frog itself
13
+
14
+ ```sh
15
+
16
+ # 1. install uv
17
+ # mac might need brew to install uv
18
+
19
+ # 2. install gams_frog via
20
+ # optionally specifiy version tag
21
+ uv tool install gams_frog
22
+
23
+ # verify installation via
24
+ frog --version
25
+
26
+ # 3. use the gams_frog
27
+ cd ./my/working/directory
28
+ frog dev # will use the gams_frog.toml from the current working dir
29
+ # alternatively specifiy a path
30
+ frog dev "C:\path\to\project"
31
+ # check for basic commands
32
+ frog
33
+
34
+ ```
35
+
36
+ ## Basic usage
37
+
38
+ 1. Have a running GAM5-API (OR external)
39
+ 2. Clone or init project files
40
+ 3. UV setup (install via pypi or clone via git)
41
+
42
+
43
+ ```sh
44
+ # 01. Setup project files from templates: https://zimlab.uni-graz.at/gams5/projects/project_template/gams-www
45
+ # 01b. Install uv (python package)
46
+
47
+ # 02a. Install via pypi
48
+ # 02a. uv install / pip install
49
+
50
+ # 02b. Clone gams_frog
51
+ # 02b. uv sync (uv procedure)
52
+ # 02b. Start virtual environment (venv)
53
+
54
+ # 03. Configure gams_frog via config file (gams_frog.toml) in template project folder
55
+
56
+ # (point to project folder with config file)
57
+ frog dev "C:\path\to\project"
58
+
59
+ # for production use
60
+ frog build "C:\path\to\project"
61
+
62
+ ```
63
+
64
+ ### Staging
65
+
66
+ ```sh
67
+ frog stage "/path/to/project"
68
+
69
+ ```
70
+
71
+
72
+ ### Production
73
+
74
+ ```sh
75
+ # use build command to generate the production files
76
+ frog build "/path/to/project"
77
+
78
+ ```
79
+
80
+
81
+ ### Deployment
82
+
83
+ - use the -d flag to deploy to staging or production environment
84
+
85
+ ```sh
86
+ # staging deployment
87
+ frog stage "/path/to/project" -d
88
+
89
+ # production deployment
90
+ frog build "/path/to/project" -d
91
+
92
+
93
+ ```
94
+
95
+
96
+ ## Development
97
+
98
+ ### Release
99
+
100
+ 1. Increment version in pyproject.toml in feature branch (merging into develop):
101
+ - make sure version follow vd.d.d pattern
102
+ 2. Merge changes to develop -> main
103
+ 3. Create release on the gitlab webclient (from main branch) with new git tag that must be the same as in the pyproject.toml!
104
+ - e.g. v0.1.1
105
+ - create the release from the main branch!
106
+ - gitlab will autodeploy the new version to pypi
@@ -0,0 +1,47 @@
1
+ [project]
2
+ name = "gams-frog"
3
+ version = "v0.3.0"
4
+ description = "CLI tool for frontend generation for GAMS5 projects"
5
+ authors = [
6
+ { name = "Sebastian David Schiller-Stoff", email = "sebastian.stoff@uni-graz.at" }
7
+ ]
8
+ license = { text = "MIT" }
9
+ dependencies = [
10
+ "jinja2==3.1.6",
11
+ "click>=8.3.1",
12
+ "watchdog>=6.0.0",
13
+ "aiohttp>=3.13.3",
14
+ "requests>=2.32.4"
15
+ ]
16
+ readme = "README.md"
17
+ requires-python = ">= 3.12"
18
+ keywords = ["gams", "static-site-generator", "digital-humanities", "jinja2"]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Environment :: Console",
22
+ "Intended Audience :: Developers",
23
+ "Topic :: Internet :: WWW/HTTP :: Site Management",
24
+ "Programming Language :: Python :: 3.12",
25
+ ]
26
+
27
+ [project.urls]
28
+ Repository = "https://zimlab.uni-graz.at/gams5/production/postprocessing/gams-frog"
29
+
30
+ [build-system]
31
+ requires = ["hatchling"]
32
+ build-backend = "hatchling.build"
33
+
34
+ [tool.hatch.metadata]
35
+ allow-direct-references = true
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/gams_frog"]
39
+
40
+ [dependency-groups]
41
+ dev = [
42
+ "pytest>=8.4.1",
43
+ "ruff>=0.14.0"
44
+ ]
45
+
46
+ [project.scripts]
47
+ frog = "gams_frog.cli:cli"
@@ -0,0 +1,2 @@
1
+ def hello() -> str:
2
+ return "Hello from gams_frog!"
@@ -0,0 +1,229 @@
1
+ import logging
2
+ import sys
3
+
4
+ import click
5
+ import multiprocessing
6
+
7
+ from importlib.metadata import version, PackageNotFoundError
8
+ # makes sure that the version is set correctly
9
+ try:
10
+ __version__ = version("gams_frog-tool")
11
+ except PackageNotFoundError:
12
+ __version__ = "dev"
13
+
14
+ from gams_frog.deploy.GamsAuthClient import GamsAuthClient
15
+ from gams_frog.ssr.watch.ApplicationViewFileEventController import ApplicationViewFileEventController
16
+ from gams_frog.ssr.init.ApplicationContext import ApplicationContext
17
+ from gams_frog.ssr.load.ApplicationDataLoader import ApplicationDataLoader
18
+ from gams_frog.ssr.watch.ApplicationViewFileWatcher import ApplicationViewFileWatcher
19
+ from gams_frog.ssr.watch.ApplicationWebServer import ApplicationWebServer
20
+ from gams_frog.ssr.init.AppInitializer import AppInitializer
21
+ from gams_frog.validation.JinjaTemplateValidator import JinjaTemplateValidator
22
+ from gams_frog.validation.StaticFileValidator import StaticFileValidator
23
+
24
+ # global application context
25
+ app_context = ApplicationContext()
26
+
27
+ def run_validation_or_exit(context: ApplicationContext):
28
+ # 1. Validate Templates (AST)
29
+ template_validator = JinjaTemplateValidator(context)
30
+ templates_ok = template_validator.validate()
31
+
32
+ # 2. Validate Static Files (Regex)
33
+ static_validator = StaticFileValidator(context)
34
+ static_ok = static_validator.validate()
35
+
36
+ if not (templates_ok and static_ok):
37
+ logging.error("Build aborted due to quality gate violations.")
38
+ sys.exit(1)
39
+
40
+
41
+ def run_deploy(context: ApplicationContext, username: str | None, password: str | None):
42
+ """
43
+ Performs authentication and deployment to the GAMS5 API.
44
+
45
+ :param context: The application context
46
+ :param username: GAMS API username (prompted if not provided)
47
+ :param password: GAMS API password (prompted if not provided)
48
+ """
49
+ from gams_frog.deploy.DeployService import DeployService
50
+
51
+ mode = context.get_config().mode
52
+ target_host = context.get_config().gams_host
53
+
54
+ # Safety confirmation for production deployments
55
+ if mode == "build":
56
+ click.echo("\n*** PRODUCTION DEPLOYMENT ***")
57
+ click.echo(f"Target: {target_host}")
58
+ click.echo(f"Project: {context.get_config().project}")
59
+ if not click.confirm("Deploy to PRODUCTION environment?", default=False):
60
+ click.echo("Deployment cancelled.")
61
+ return
62
+
63
+ # Prompt for credentials if not provided via options
64
+ if not username:
65
+ username = click.prompt("GAMS API username")
66
+ if not password:
67
+ password = click.prompt("GAMS API password", hide_input=True)
68
+
69
+ # Authenticate
70
+ logging.info(f"Authenticating with GAMS API at {target_host}...")
71
+ auth_gams_client = GamsAuthClient(target_host)
72
+ try:
73
+ from gams_frog.deploy.AuthorizationService import AuthorizationService
74
+ # TODO using a separte client seems weird
75
+ auth_service = AuthorizationService(auth_gams_client)
76
+ auth_service.login(username=username, password=password)
77
+ except PermissionError as e:
78
+ logging.error(f"Authentication failed: {e}")
79
+ sys.exit(1)
80
+ except Exception as e:
81
+ logging.error(f"Authentication error: {e}")
82
+ sys.exit(1)
83
+
84
+ # Deploy
85
+ try:
86
+ deploy_service = DeployService(context, auth_gams_client)
87
+ result = deploy_service.deploy()
88
+ click.echo("\nDeployment successful!")
89
+ click.echo(f" Project: {result.get('projectAbbr', 'N/A')}")
90
+ click.echo(f" Files: {result.get('fileCount', 'N/A')}")
91
+ click.echo(f" Total size: {result.get('totalSize', 'N/A')} bytes")
92
+ click.echo(f" Deployed at: {result.get('deployedAt', 'N/A')}")
93
+ except (FileNotFoundError, ValueError) as e:
94
+ logging.error(f"Deployment failed: {e}")
95
+ sys.exit(1)
96
+ except (ConnectionError, PermissionError) as e:
97
+ logging.error(f"Deployment failed: {e}")
98
+ sys.exit(1)
99
+
100
+
101
+ @click.group()
102
+ @click.version_option(version=version("gams_frog"), prog_name="gams_frog")
103
+ @click.option("--log", "-l", default="INFO", help="log level, default is INFO")
104
+ def cli(log: str):
105
+ """
106
+ Init command / start routine of application
107
+ Sets up the application context for the entire application.
108
+ """
109
+ logging.basicConfig( encoding='utf-8', level=logging.getLevelName(log))
110
+
111
+ @cli.command(name="stage", help="Builds output files once with staging configuration.")
112
+ @click.argument("directory", default=".", required=False)
113
+ @click.option("--deploy", "-d", is_flag=True, default=False, help="Deploy the built files to the staging GAMS API after build.")
114
+ @click.option("--username", "-u", default=None, help="GAMS API username for deployment.")
115
+ @click.option("--password", "-p", default=None, help="GAMS API password for deployment.")
116
+ def stage(directory: str, deploy: bool, username: str, password: str):
117
+ """
118
+ Builds the static site generator output files with staging config.
119
+ Use --deploy to upload the result to the staging GAMS API.
120
+ """
121
+
122
+ # setting up the application context
123
+ (AppInitializer(app_context)
124
+ .configure(
125
+ directory=directory,
126
+ mode="stage"
127
+ )
128
+ .init_context_beans()
129
+ .setup()
130
+ )
131
+
132
+ # validate template files first
133
+ run_validation_or_exit(app_context)
134
+
135
+ # encapsulates loading of project data and digital objects
136
+ (ApplicationDataLoader(app_context)
137
+ .load())
138
+
139
+ # render all views (and handle related files etc.)
140
+ (ApplicationViewFileEventController(app_context)
141
+ .render_views())
142
+
143
+ # deploy if requested
144
+ if deploy:
145
+ run_deploy(app_context, username, password)
146
+
147
+
148
+ @cli.command(name="build", help="Builds production output files.")
149
+ @click.argument("directory", default=".", required=False)
150
+ @click.option("--deploy", "-d", is_flag=True, default=False, help="Deploy the built files to the production GAMS API after build.")
151
+ @click.option("--username", "-u", default=None, help="GAMS API username for deployment.")
152
+ @click.option("--password", "-p", default=None, help="GAMS API password for deployment.")
153
+ def build(directory: str, deploy: bool, username: str, password: str):
154
+ """
155
+ Builds the static site generator production output files.
156
+ Use --deploy to upload the result to the production GAMS API.
157
+ """
158
+
159
+ # setting up the application context
160
+ (AppInitializer(app_context)
161
+ .configure(
162
+ directory=directory,
163
+ mode="build"
164
+ )
165
+ .init_context_beans()
166
+ .setup()
167
+ )
168
+
169
+ # validate template files first
170
+ run_validation_or_exit(app_context)
171
+
172
+ # encapsulates loading of project data and digital objects
173
+ (ApplicationDataLoader(app_context)
174
+ .load())
175
+
176
+ # render all views (and handle related files etc.)
177
+ (ApplicationViewFileEventController(app_context)
178
+ .render_views())
179
+
180
+ # deploy if requested
181
+ if deploy:
182
+ run_deploy(app_context, username, password)
183
+
184
+
185
+ @cli.command(name="dev", help="Starts the development process of the gams_frog tool.")
186
+ @click.argument("directory", default=".", required=False)
187
+ @click.option("--port", "-p", default=18090, help="The port to run the development server on")
188
+ def dev(directory: str, port: int):
189
+ """
190
+ Starts the static site generator (web server with rendering of views and initial data loading etc.)
191
+ """
192
+
193
+ # setting up the application context
194
+ (AppInitializer(app_context)
195
+ .configure(
196
+ directory=directory,
197
+ mode="dev"
198
+ )
199
+ .init_context_beans()
200
+ .setup()
201
+ )
202
+
203
+ # first run validation
204
+ run_validation_or_exit(app_context)
205
+
206
+ # encapsulates loading of project data and digital objects
207
+ (ApplicationDataLoader(app_context)
208
+ .load())
209
+
210
+ web_dir = app_context.get_config().public_dir
211
+ dev_server_process = multiprocessing.Process(target=ApplicationWebServer.start, args=(web_dir, port,))
212
+
213
+ try:
214
+ logging.info(f"*** Starting web server at port {port}")
215
+ dev_server_process.start()
216
+ logging.info("*** Starting view file watcher now")
217
+ ApplicationViewFileWatcher.start(
218
+ app_context
219
+ )
220
+ dev_server_process.join()
221
+ except KeyboardInterrupt:
222
+ logging.info("Keyboard interrupt received. Stopping processes")
223
+ dev_server_process.terminate()
224
+ dev_server_process.join()
225
+
226
+
227
+ cli.add_command(dev)
228
+ cli.add_command(build)
229
+ cli.add_command(stage)