refactor: rename project to gallery

This commit is contained in:
2024-08-11 20:46:04 +03:00
parent 3785b8ce5d
commit 72fd378c40
48 changed files with 117 additions and 92 deletions
+1
View File
@@ -0,0 +1 @@
# Gallery
@@ -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"
]
}
]
@@ -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
@@ -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):
@@ -1,6 +1,6 @@
import datetime
from enum import Enum
from typing import NamedTuple, Optional
from typing import NamedTuple
class TagType(str, Enum):
@@ -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)
@@ -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:

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@@ -18,7 +18,7 @@
<body class="app-container">
<ul>
{% for location in locations %}
<li><a href="weather/{{location.name}}-{{location.location_id}}">{{location.name}}</a></li>
<li><a href="weather/{{location}}">{{location}}</a></li>
{% endfor %}
</ul>
</body>
+3 -3
View File
@@ -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"),
@@ -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)
@@ -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)
@@ -0,0 +1,5 @@
from pathlib import Path
from gallery.sketch.mock import MockData
GISMETEO_MOCK_DATA = MockData(Path(__file__).parent / "data")
@@ -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
+15
View File
@@ -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
View File
+26
View File
@@ -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]
View File
@@ -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
+12
View File
@@ -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")
@@ -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:
-34
View File
@@ -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"),
)
-17
View File
@@ -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()
+3 -3
View File
@@ -1,10 +1,10 @@
[tool.poetry]
name = "weather"
name = "gallery"
version = "0.1.0"
description = ""
authors = ["shmyga <shmyga.z@gmail.com>"]
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"
+1 -1
View File
@@ -2,4 +2,4 @@
set -e
cd "$(dirname $(dirname "$0"))" || exit
docker build -t shmyga/weather .
docker build -t shmyga/gallery .
Executable
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -e
cd "$(dirname $(dirname "$0"))" || exit
poetry run pylint gallery
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
Executable
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -e
cd "$(dirname $(dirname "$0"))" || exit
poetry run pytest tests
+5 -5
View File
@@ -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