diff --git a/README.md b/README.md
index e69de29..b021765 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1 @@
+# Gallery
diff --git a/weather.code-workspace b/gallery.code-workspace
similarity index 86%
rename from weather.code-workspace
rename to gallery.code-workspace
index fde26b9..ffd578d 100644
--- a/weather.code-workspace
+++ b/gallery.code-workspace
@@ -19,15 +19,15 @@
"version": "0.2.1",
"configurations": [
{
- "name": "app",
+ "name": "gallery:app",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": [
- "weather.main:app",
+ "gallery.main:app",
"--reload",
"--log-config",
- "weather/logging.yaml"
+ "gallery/logging.yaml"
]
}
]
diff --git a/gismeteo/__init__.py b/gallery/__init__.py
similarity index 100%
rename from gismeteo/__init__.py
rename to gallery/__init__.py
diff --git a/weather/app/__init__.py b/gallery/easel/__init__.py
similarity index 88%
rename from weather/app/__init__.py
rename to gallery/easel/__init__.py
index debba70..28e5faf 100644
--- a/weather/app/__init__.py
+++ b/gallery/easel/__init__.py
@@ -2,7 +2,7 @@ import locale
from fastapi import FastAPI
-from weather.api import WeatherApi
+from gallery.sketch.weather.api import WeatherApi
from .route import api, doc, view
diff --git a/weather/__init__.py b/gallery/easel/route/__init__.py
similarity index 100%
rename from weather/__init__.py
rename to gallery/easel/route/__init__.py
diff --git a/weather/app/route/api.py b/gallery/easel/route/api.py
similarity index 86%
rename from weather/app/route/api.py
rename to gallery/easel/route/api.py
index 969b65f..b241cda 100644
--- a/weather/app/route/api.py
+++ b/gallery/easel/route/api.py
@@ -2,8 +2,8 @@ import datetime
from fastapi import FastAPI, Request
-from weather.api import WeatherApi
-from weather.model import WeatherResponse
+from gallery.sketch.weather.api import WeatherApi
+from gallery.sketch.weather.model import WeatherResponse
def mount(app: FastAPI):
diff --git a/weather/app/route/doc/__init__.py b/gallery/easel/route/doc/__init__.py
similarity index 100%
rename from weather/app/route/doc/__init__.py
rename to gallery/easel/route/doc/__init__.py
diff --git a/weather/app/route/doc/static/redoc.standalone.js b/gallery/easel/route/doc/static/redoc.standalone.js
similarity index 100%
rename from weather/app/route/doc/static/redoc.standalone.js
rename to gallery/easel/route/doc/static/redoc.standalone.js
diff --git a/weather/app/route/doc/static/swagger-ui-bundle.js b/gallery/easel/route/doc/static/swagger-ui-bundle.js
similarity index 100%
rename from weather/app/route/doc/static/swagger-ui-bundle.js
rename to gallery/easel/route/doc/static/swagger-ui-bundle.js
diff --git a/weather/app/route/doc/static/swagger-ui.css b/gallery/easel/route/doc/static/swagger-ui.css
similarity index 100%
rename from weather/app/route/doc/static/swagger-ui.css
rename to gallery/easel/route/doc/static/swagger-ui.css
diff --git a/weather/app/route/util.py b/gallery/easel/route/util.py
similarity index 97%
rename from weather/app/route/util.py
rename to gallery/easel/route/util.py
index f3308c1..cb149b7 100644
--- a/weather/app/route/util.py
+++ b/gallery/easel/route/util.py
@@ -1,6 +1,6 @@
import datetime
from enum import Enum
-from typing import NamedTuple, Optional
+from typing import NamedTuple
class TagType(str, Enum):
diff --git a/weather/app/route/view/__init__.py b/gallery/easel/route/view/__init__.py
similarity index 87%
rename from weather/app/route/view/__init__.py
rename to gallery/easel/route/view/__init__.py
index aa7f262..6d5b117 100644
--- a/weather/app/route/view/__init__.py
+++ b/gallery/easel/route/view/__init__.py
@@ -6,12 +6,11 @@ from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
-from gismeteo.location import LOCATION_BUNDLE
-from gismeteo.mock import MOCK_DATA
-from weather.api import WeatherApi
-from weather.app.route.util import TagType, TagUtil
-from weather.model import WeatherResponse
+from gallery.sketch.weather.api import WeatherApi
+from gallery.sketch.weather.mock import WEATHER_MOCK_DATA
+from gallery.sketch.weather.model import WeatherResponse
+from ..util import TagType, TagUtil
from .filters import cloudness_icon, wind_direction_icon
@@ -39,11 +38,13 @@ def mount(app: FastAPI):
@app.get("/weather", response_class=HTMLResponse)
async def get_weather_list(request: Request):
+ weather_api: WeatherApi = request.app.state.weather_api
+ locations = await weather_api.get_locations()
return templates.TemplateResponse(
request=request,
name="index.html",
context={
- "locations": LOCATION_BUNDLE._values,
+ "locations": locations,
},
)
@@ -53,12 +54,12 @@ def mount(app: FastAPI):
@app.get("/weather/{location}/day/mock", response_class=HTMLResponse)
async def get_weather_day_mock(request: Request):
- response = MOCK_DATA.get_response("day")
+ response = WEATHER_MOCK_DATA.get_response("day")
return build_weather_response(request, response)
@app.get("/weather/{location}/days/mock", response_class=HTMLResponse)
async def get_weather_days_mock(request: Request):
- response = MOCK_DATA.get_response("days")
+ response = WEATHER_MOCK_DATA.get_response("days")
return build_weather_response(request, response)
@app.get("/weather/{location}/day/{date}", response_class=HTMLResponse)
diff --git a/weather/app/route/view/filters.py b/gallery/easel/route/view/filters.py
similarity index 92%
rename from weather/app/route/view/filters.py
rename to gallery/easel/route/view/filters.py
index ebdd0f1..c24bda5 100644
--- a/weather/app/route/view/filters.py
+++ b/gallery/easel/route/view/filters.py
@@ -1,4 +1,4 @@
-from weather.model import Cloudness, Precipitation, Sky, WindDirection
+from gallery.sketch.weather.model import Cloudness, Precipitation, Sky, WindDirection
def wind_direction_icon(wind_direction: WindDirection) -> str:
diff --git a/weather/app/route/view/static/favicon.ico b/gallery/easel/route/view/static/favicon.ico
similarity index 100%
rename from weather/app/route/view/static/favicon.ico
rename to gallery/easel/route/view/static/favicon.ico
diff --git a/weather/app/route/view/static/index.js b/gallery/easel/route/view/static/index.js
similarity index 100%
rename from weather/app/route/view/static/index.js
rename to gallery/easel/route/view/static/index.js
diff --git a/weather/app/route/view/static/style.css b/gallery/easel/route/view/static/style.css
similarity index 100%
rename from weather/app/route/view/static/style.css
rename to gallery/easel/route/view/static/style.css
diff --git a/weather/app/route/view/templates/index.html b/gallery/easel/route/view/templates/index.html
similarity index 84%
rename from weather/app/route/view/templates/index.html
rename to gallery/easel/route/view/templates/index.html
index 5740528..ef84ef0 100644
--- a/weather/app/route/view/templates/index.html
+++ b/gallery/easel/route/view/templates/index.html
@@ -18,7 +18,7 @@
diff --git a/weather/app/route/view/templates/weather.html b/gallery/easel/route/view/templates/weather.html
similarity index 100%
rename from weather/app/route/view/templates/weather.html
rename to gallery/easel/route/view/templates/weather.html
diff --git a/weather/logging.yaml b/gallery/logging.yaml
similarity index 100%
rename from weather/logging.yaml
rename to gallery/logging.yaml
diff --git a/weather/main.py b/gallery/main.py
similarity index 69%
rename from weather/main.py
rename to gallery/main.py
index f398f2f..c745037 100644
--- a/weather/main.py
+++ b/gallery/main.py
@@ -3,15 +3,15 @@ from pathlib import Path
import uvicorn
-from gismeteo.api import GismeteoApi
-from weather.app import build_app
+from gallery.easel import build_app
+from gallery.painting.gismeteo.api import GismeteoApi
app = build_app(GismeteoApi())
def run():
uvicorn.run(
- "weather.main:app",
+ "gallery.main:app",
host="0.0.0.0",
port=8000,
log_config=str(Path(__file__).parent / "logging.yaml"),
diff --git a/weather/app/route/__init__.py b/gallery/painting/__init__.py
similarity index 100%
rename from weather/app/route/__init__.py
rename to gallery/painting/__init__.py
diff --git a/gallery/painting/gismeteo/__init__.py b/gallery/painting/gismeteo/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/gismeteo/api.py b/gallery/painting/gismeteo/api.py
similarity index 88%
rename from gismeteo/api.py
rename to gallery/painting/gismeteo/api.py
index 8c9de6a..73280f8 100644
--- a/gismeteo/api.py
+++ b/gallery/painting/gismeteo/api.py
@@ -6,11 +6,10 @@ import aiohttp
from aiocache import cached
from bs4 import BeautifulSoup
-from weather.api import WeatherApi
-from weather.model import WeatherResponse, WeatherValue
+from gallery.sketch.weather.api import WeatherApi
+from gallery.sketch.weather.model import WeatherResponse, WeatherValue
from . import datehelp
-from .location import LOCATION_BUNDLE
from .parser import DAYS_PARSER, LOCATION_PARSER, ONE_DAY_PARSER, ROW_PARSERS
logger = logging.getLogger("gismeteo")
@@ -80,14 +79,18 @@ class GismeteoApi(WeatherApi):
values=values,
)
+ async def get_locations(self) -> list[str]:
+ return [
+ "orel-4432",
+ "zmiyevka-184640",
+ ]
+
@cached(ttl=CACHE_TTL)
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
- location = LOCATION_BUNDLE.parse(location_id)
- data = await self._request(f"weather-{location}/{datehelp.dump(date)}")
+ data = await self._request(f"weather-{location_id}/{datehelp.dump(date)}")
return self._parse_oneday(date, data)
@cached(ttl=CACHE_TTL)
async def get_days(self, location_id: str, days: int) -> WeatherResponse:
- location = LOCATION_BUNDLE.parse(location_id)
- data = await self._request(f"weather-{location}/{days}-days")
+ data = await self._request(f"weather-{location_id}/{days}-days")
return self._parse_manydays(data)
diff --git a/gismeteo/core.py b/gallery/painting/gismeteo/core.py
similarity index 100%
rename from gismeteo/core.py
rename to gallery/painting/gismeteo/core.py
diff --git a/gismeteo/datehelp.py b/gallery/painting/gismeteo/datehelp.py
similarity index 95%
rename from gismeteo/datehelp.py
rename to gallery/painting/gismeteo/datehelp.py
index ed05d1b..196a604 100644
--- a/gismeteo/datehelp.py
+++ b/gallery/painting/gismeteo/datehelp.py
@@ -14,7 +14,7 @@ class Day(str, Enum):
def parse(value: str) -> datetime.date:
- if value == "today" or value == "mock":
+ if value in ["today", "mock"]:
return datetime.date.today()
elif value == "tomorrow":
return datetime.date.today() + datetime.timedelta(days=1)
diff --git a/gallery/painting/gismeteo/mock/__init__.py b/gallery/painting/gismeteo/mock/__init__.py
new file mode 100644
index 0000000..72e3ba2
--- /dev/null
+++ b/gallery/painting/gismeteo/mock/__init__.py
@@ -0,0 +1,5 @@
+from pathlib import Path
+
+from gallery.sketch.mock import MockData
+
+GISMETEO_MOCK_DATA = MockData(Path(__file__).parent / "data")
diff --git a/gismeteo/mock/data/10-days.html b/gallery/painting/gismeteo/mock/data/10-days.html
similarity index 100%
rename from gismeteo/mock/data/10-days.html
rename to gallery/painting/gismeteo/mock/data/10-days.html
diff --git a/gismeteo/mock/data/today.html b/gallery/painting/gismeteo/mock/data/today.html
similarity index 100%
rename from gismeteo/mock/data/today.html
rename to gallery/painting/gismeteo/mock/data/today.html
diff --git a/gismeteo/parser.py b/gallery/painting/gismeteo/parser.py
similarity index 98%
rename from gismeteo/parser.py
rename to gallery/painting/gismeteo/parser.py
index 33e5a93..1e3f794 100644
--- a/gismeteo/parser.py
+++ b/gallery/painting/gismeteo/parser.py
@@ -5,7 +5,7 @@ from typing import Iterable
import dateparser
from bs4 import Tag
-from weather.model import Cloudness, Precipitation, Sky, WindDirection
+from gallery.sketch.weather.model import Cloudness, Precipitation, Sky, WindDirection
from .core import BaseWidgetParser, RowParser
diff --git a/gallery/sketch/mock.py b/gallery/sketch/mock.py
new file mode 100644
index 0000000..c0aba23
--- /dev/null
+++ b/gallery/sketch/mock.py
@@ -0,0 +1,15 @@
+import json
+from pathlib import Path
+
+
+class MockData:
+
+ def __init__(self, data_dir) -> None:
+ self._data_dir = data_dir
+
+ def get_html(self, key: str) -> str:
+ return (self._data_dir / f"{key}.html").read_text()
+
+ def get_json(self, key: str) -> dict:
+ data = json.loads((Path(__file__).parent / f"data/{key}.json").read_text())
+ return data
diff --git a/gallery/sketch/schedule/__init_.py b/gallery/sketch/schedule/__init_.py
new file mode 100644
index 0000000..e69de29
diff --git a/gallery/sketch/schedule/model.py b/gallery/sketch/schedule/model.py
new file mode 100644
index 0000000..4ac4306
--- /dev/null
+++ b/gallery/sketch/schedule/model.py
@@ -0,0 +1,26 @@
+import datetime
+
+from pydantic import BaseModel
+
+
+class Model(BaseModel):
+ class Config:
+ use_enum_values = True
+
+
+class Channel(Model):
+ id: str
+ name: str
+
+
+class ScheduleItem(Model):
+ start: datetime.datetime
+ end: datetime.datetime
+ label: str
+ category: str | None
+
+
+class Schedule(Model):
+ channel: Channel
+ date: datetime.date
+ items: list[ScheduleItem]
diff --git a/gallery/sketch/weather/__init__.py b/gallery/sketch/weather/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/weather/api.py b/gallery/sketch/weather/api.py
similarity index 78%
rename from weather/api.py
rename to gallery/sketch/weather/api.py
index cf9f808..1838b5d 100644
--- a/weather/api.py
+++ b/gallery/sketch/weather/api.py
@@ -4,6 +4,9 @@ from .model import WeatherResponse
class WeatherApi:
+ async def get_locations(self) -> list[str]:
+ raise NotImplementedError
+
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
raise NotImplementedError
diff --git a/gallery/sketch/weather/mock/__init__.py b/gallery/sketch/weather/mock/__init__.py
new file mode 100644
index 0000000..adf4734
--- /dev/null
+++ b/gallery/sketch/weather/mock/__init__.py
@@ -0,0 +1,12 @@
+from pathlib import Path
+
+from gallery.sketch.mock import MockData
+from gallery.sketch.weather.model import WeatherResponse
+
+
+class WeatherMockData(MockData):
+ def get_response(self, key: str) -> WeatherResponse:
+ return WeatherResponse(**self.get_json(key))
+
+
+WEATHER_MOCK_DATA = WeatherMockData(Path(__file__).parent / "data")
diff --git a/gismeteo/mock/data/day.json b/gallery/sketch/weather/mock/data/day.json
similarity index 100%
rename from gismeteo/mock/data/day.json
rename to gallery/sketch/weather/mock/data/day.json
diff --git a/gismeteo/mock/data/days.json b/gallery/sketch/weather/mock/data/days.json
similarity index 100%
rename from gismeteo/mock/data/days.json
rename to gallery/sketch/weather/mock/data/days.json
diff --git a/weather/model.py b/gallery/sketch/weather/model.py
similarity index 100%
rename from weather/model.py
rename to gallery/sketch/weather/model.py
diff --git a/weather/util.py b/gallery/sketch/weather/util.py
similarity index 84%
rename from weather/util.py
rename to gallery/sketch/weather/util.py
index f4d9896..767b668 100644
--- a/weather/util.py
+++ b/gallery/sketch/weather/util.py
@@ -1,6 +1,6 @@
import datetime
-from weather.model import Cloudness, Precipitation, Sky, WeatherValue, WindDirection
+from .model import Cloudness, Precipitation, Sky, WeatherValue, WindDirection
def build_weather_value(date: datetime.datetime) -> WeatherValue:
diff --git a/gismeteo/location.py b/gismeteo/location.py
deleted file mode 100644
index f314160..0000000
--- a/gismeteo/location.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from typing import NamedTuple
-
-
-class LocationValue(NamedTuple):
- location_id: int
- name: str
-
- def __str__(self) -> str:
- return f"{self.name}-{self. location_id}"
-
- @classmethod
- def parse(cls, source: str) -> "LocationValue":
- name, location = source.split("-")
- return cls(int(location), name)
-
-
-class LocationBundle:
- def __init__(self, *values: LocationValue) -> None:
- self._values = values
- self._values_by_name = {value.name: value for value in self._values}
- self._values_by_id = {value.location_id: value for value in self._values}
-
- def parse(self, value: str) -> LocationValue:
- if str.isdigit(value):
- return self._values_by_id[int(value)]
- if value in self._values_by_name:
- return self._values_by_name[value]
- return LocationValue.parse(value)
-
-
-LOCATION_BUNDLE = LocationBundle(
- LocationValue(4432, "orel"),
- LocationValue(184640, "zmiyevka"),
-)
diff --git a/gismeteo/mock/__init__.py b/gismeteo/mock/__init__.py
deleted file mode 100644
index 65fdb84..0000000
--- a/gismeteo/mock/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import json
-from pathlib import Path
-
-from gismeteo.api import WeatherResponse
-
-
-class MockData:
-
- def get_html(self, key: str) -> str:
- return (Path(__file__).parent / f"data/{key}.html").read_text()
-
- def get_response(self, key: str) -> WeatherResponse:
- data = json.loads((Path(__file__).parent / f"data/{key}.json").read_text())
- return WeatherResponse(**data)
-
-
-MOCK_DATA = MockData()
diff --git a/pyproject.toml b/pyproject.toml
index e4e6883..9702c22 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,10 +1,10 @@
[tool.poetry]
-name = "weather"
+name = "gallery"
version = "0.1.0"
description = ""
authors = ["shmyga "]
readme = "README.md"
-packages = [{ include = "weather" }, { include = "gismeteo" }]
+packages = [{ include = "gallery" }]
[tool.poetry.dependencies]
python = "^3.12"
@@ -32,7 +32,7 @@ requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.scripts]
-app = 'weather.main:run'
+gallery = "gallery.main:run"
[tool.pytest.ini_options]
addopts = "-p no:warnings"
diff --git a/scripts/build b/scripts/build
index 68a9e40..cb1748a 100755
--- a/scripts/build
+++ b/scripts/build
@@ -2,4 +2,4 @@
set -e
cd "$(dirname $(dirname "$0"))" || exit
-docker build -t shmyga/weather .
+docker build -t shmyga/gallery .
diff --git a/scripts/lint b/scripts/lint
new file mode 100755
index 0000000..7bb1550
--- /dev/null
+++ b/scripts/lint
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+set -e
+cd "$(dirname $(dirname "$0"))" || exit
+
+poetry run pylint gallery
diff --git a/scripts/publish b/scripts/publish
index e1023ca..12298a5 100755
--- a/scripts/publish
+++ b/scripts/publish
@@ -2,7 +2,7 @@
set -e
cd "$(dirname $(dirname "$0"))" || exit
-IMAGE_NAME=shmyga/weather
+IMAGE_NAME=shmyga/gallery
docker tag $IMAGE_NAME instreamatic.com:8083/$IMAGE_NAME
docker push instreamatic.com:8083/$IMAGE_NAME
diff --git a/scripts/run b/scripts/run
index e9a5dea..9f45915 100755
--- a/scripts/run
+++ b/scripts/run
@@ -2,4 +2,4 @@
set -e
cd "$(dirname $(dirname "$0"))" || exit
-docker run --rm -p 8000:80 shmyga/weather
+docker run --rm -p 8000:80 shmyga/gallery
diff --git a/scripts/test b/scripts/test
new file mode 100755
index 0000000..621b46d
--- /dev/null
+++ b/scripts/test
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+set -e
+cd "$(dirname $(dirname "$0"))" || exit
+
+poetry run pytest tests
diff --git a/tests/test_gismeteo_api.py b/tests/test_gismeteo_api.py
index 0e4740a..3ead3ca 100644
--- a/tests/test_gismeteo_api.py
+++ b/tests/test_gismeteo_api.py
@@ -2,8 +2,8 @@ import datetime
import pytest
-from gismeteo.api import GismeteoApi
-from gismeteo.mock import MOCK_DATA
+from gallery.painting.gismeteo.api import GismeteoApi
+from gallery.painting.gismeteo.mock import GISMETEO_MOCK_DATA
@pytest.fixture(name="gismeteo_api", scope="module")
@@ -11,17 +11,17 @@ def gismeteo_api_fixture() -> GismeteoApi:
api = GismeteoApi()
async def _request(endpoint: str) -> str:
- return MOCK_DATA.get_html(endpoint.split("/")[-1])
+ return GISMETEO_MOCK_DATA.get_html(endpoint.split("/")[-1])
api._request = _request
return api
async def test_day(gismeteo_api: GismeteoApi):
- result = await gismeteo_api.get_day("zmiyevka", datetime.date.today())
+ result = await gismeteo_api.get_day("test", datetime.date.today())
assert len(result.values) == 8
async def test_days(gismeteo_api: GismeteoApi):
- result = await gismeteo_api.get_days("zmiyevka", 10)
+ result = await gismeteo_api.get_days("test", 10)
assert len(result.values) == 10