diff --git a/gallery.code-workspace b/gallery.code-workspace index 7959793..dc60536 100644 --- a/gallery.code-workspace +++ b/gallery.code-workspace @@ -34,6 +34,8 @@ "request": "launch", "module": "uvicorn", "args": ["gallery.main:app", "--reload", "--log-config", "gallery/logging.yaml"], + "justMyCode": true, + "consoleTitle": "gallery:app", }, { "name": "gallery:static", @@ -41,6 +43,7 @@ "request": "launch", "type": "node-terminal", "command": "npm run dev", + "consoleTitle": "gallery:static", }, ], }, diff --git a/gallery/easel/route/api/schedule.py b/gallery/easel/route/api/schedule.py index 531e130..ca9a702 100644 --- a/gallery/easel/route/api/schedule.py +++ b/gallery/easel/route/api/schedule.py @@ -13,8 +13,6 @@ def mount(app: FastAPI): return await schedule_api.get_channels() @app.get("/api/schedule/{channel}/{date}", tags=["API"]) - async def get_api_schedule_channel_schedule( - request: AppRequest, channel: str, date: datetime.date - ) -> Schedule: + async def get_api_schedule_channel_schedule(request: AppRequest, channel: str, date: datetime.date) -> Schedule: schedule_api = request.app.state.api.schedule return await schedule_api.get_channel_schedule(ChannelId(channel), date) diff --git a/gallery/easel/route/api/weather.py b/gallery/easel/route/api/weather.py index 8820f51..eb455a5 100644 --- a/gallery/easel/route/api/weather.py +++ b/gallery/easel/route/api/weather.py @@ -8,22 +8,16 @@ from gallery.sketch.weather.model import Location, WeatherResponse def mount(app: FastAPI): @app.get("/api/weather/locations", tags=["API"]) - async def get_api_weather_locations( - request: AppRequest, query: str - ) -> list[Location]: + async def get_api_weather_locations(request: AppRequest, query: str) -> list[Location]: weather_api = request.app.state.api.weather return await weather_api.find_locations(query) @app.get("/api/weather/{location}/day/{date}", tags=["API"]) - async def get_api_weather_day( - request: AppRequest, location: str, date: datetime.date - ) -> WeatherResponse: + async def get_api_weather_day(request: AppRequest, location: str, date: datetime.date) -> WeatherResponse: weather_api = request.app.state.api.weather return await weather_api.get_day(location, date) @app.get("/api/weather/{location}/days/{days}", tags=["API"]) - async def get_api_weather_days( - request: AppRequest, location: str, days: int - ) -> WeatherResponse: + async def get_api_weather_days(request: AppRequest, location: str, days: int) -> WeatherResponse: weather_api = request.app.state.api.weather return await weather_api.get_days(location, days) diff --git a/gallery/easel/route/view/common/__init__.py b/gallery/easel/route/view/common/__init__.py index a112193..4ab69bf 100644 --- a/gallery/easel/route/view/common/__init__.py +++ b/gallery/easel/route/view/common/__init__.py @@ -3,11 +3,8 @@ from typing import NamedTuple from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse -from fastapi.templating import Jinja2Templates -from gallery.version import __version__ - -from ..translation import _ +from ..common.utils.template import build_templates class Section(NamedTuple): @@ -25,8 +22,7 @@ base_dir = Path(__file__).parent router = APIRouter() -templates = Jinja2Templates(directory=base_dir / "templates") -templates.env.globals.update({"_": _}) +templates = build_templates() @router.get("/", response_class=HTMLResponse) @@ -35,7 +31,6 @@ async def get_section_list(request: Request): request=request, name="root_index.html", context={ - "version": __version__, "sections": SECTIONS, }, ) diff --git a/gallery/easel/route/view/common/templates/base.html b/gallery/easel/route/view/common/templates/base.html index 78f7be5..b563d9d 100644 --- a/gallery/easel/route/view/common/templates/base.html +++ b/gallery/easel/route/view/common/templates/base.html @@ -112,7 +112,7 @@ Created by shmyga · © 2026 - + #} \ No newline at end of file diff --git a/gallery/easel/route/view/common/utils/__init__.py b/gallery/easel/route/view/common/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gallery/easel/route/view/common/util.py b/gallery/easel/route/view/common/utils/tag.py similarity index 100% rename from gallery/easel/route/view/common/util.py rename to gallery/easel/route/view/common/utils/tag.py diff --git a/gallery/easel/route/view/common/utils/template.py b/gallery/easel/route/view/common/utils/template.py new file mode 100644 index 0000000..25f66ab --- /dev/null +++ b/gallery/easel/route/view/common/utils/template.py @@ -0,0 +1,25 @@ +from pathlib import Path + +from babel.dates import format_date +from fastapi.templating import Jinja2Templates + +from gallery.version import __version__ + +from ...translation import _ + + +def build_templates(templates_dir: Path | None = None, filters: dict | None = None) -> Jinja2Templates: + directory = [Path(__file__).parent.parent / "templates"] + if templates_dir: + directory.append(templates_dir) + templates = Jinja2Templates(directory=directory) + templates.env.globals.update( + { + "_": _, + "version": __version__, + "format_date": format_date, + } + ) + if filters: + templates.env.filters.update(filters) + return templates diff --git a/gallery/easel/route/view/schedule/__init__.py b/gallery/easel/route/view/schedule/__init__.py index e0a3a3a..a2c5737 100644 --- a/gallery/easel/route/view/schedule/__init__.py +++ b/gallery/easel/route/view/schedule/__init__.py @@ -1,34 +1,22 @@ import datetime from pathlib import Path -from babel.dates import format_date from fastapi import APIRouter from fastapi.responses import HTMLResponse, RedirectResponse -from fastapi.templating import Jinja2Templates from gallery.easel.core import AppRequest from gallery.sketch.schedule.catalog import BUNDLE -from gallery.version import __version__ -from ..common.util import TagType, TagUtil -from ..translation import _ +from ..common.utils.tag import TagType, TagUtil +from ..common.utils.template import build_templates from .filters import timedelta_format -base_dir = Path(__file__).parent -templates = Jinja2Templates( - directory=[ - base_dir.parent / "common/templates", - base_dir / "templates", - ] -) -templates.env.globals.update( +templates = build_templates( + Path(__file__).parent / "templates", { - "_": _, - "version": __version__, - "format_date": format_date, - } + "timedelta_format": timedelta_format, + }, ) -templates.env.filters["timedelta_format"] = timedelta_format router = APIRouter() @@ -42,7 +30,6 @@ async def get_schedule_list(request: AppRequest): request=request, name="index.html", context={ - "version": __version__, "channels": channels_data, }, ) @@ -57,7 +44,6 @@ async def get_schedule_tag(request: AppRequest, tag: str, live: bool = False): request=request, name="schedule.html", context={ - "version": __version__, "tag_util": TagUtil, "datetime": datetime, "response": results[0], @@ -84,7 +70,6 @@ async def get_channel_tag(request: AppRequest, channel: str, tag: str): request=request, name="channel.html", context={ - "version": __version__, "tag_util": TagUtil, "datetime": datetime, "response": response, diff --git a/gallery/easel/route/view/translation.py b/gallery/easel/route/view/translation.py index c1dd0da..50e2087 100644 --- a/gallery/easel/route/view/translation.py +++ b/gallery/easel/route/view/translation.py @@ -5,9 +5,7 @@ from fastapi import Cookie, Header, Request from gallery.util import root_path -_translation: ContextVar[gettext.GNUTranslations | gettext.NullTranslations] = ( - ContextVar("translation") -) +_translation: ContextVar[gettext.GNUTranslations | gettext.NullTranslations] = ContextVar("translation") async def set_language( @@ -19,9 +17,7 @@ async def set_language( lang = language or accept_language.split(",")[0].split("-")[0] try: - t = gettext.translation( - "messages", localedir=root_path / "locales", languages=[lang] - ) + t = gettext.translation("messages", localedir=root_path / "locales", languages=[lang]) except FileNotFoundError: t = gettext.NullTranslations() diff --git a/gallery/easel/route/view/weather/__init__.py b/gallery/easel/route/view/weather/__init__.py index 8da22a0..df09178 100644 --- a/gallery/easel/route/view/weather/__init__.py +++ b/gallery/easel/route/view/weather/__init__.py @@ -3,33 +3,21 @@ from pathlib import Path from fastapi import APIRouter from fastapi.responses import HTMLResponse, RedirectResponse -from fastapi.templating import Jinja2Templates -from babel.dates import format_date + from gallery.easel.core import AppRequest from gallery.sketch.weather.model import WeatherResponse -from gallery.version import __version__ -from ..common.util import TagType, TagUtil -from ..translation import _ +from ..common.utils.tag import TagType, TagUtil +from ..common.utils.template import build_templates from .filters import cloudness_icon, wind_direction_icon - -base_dir = Path(__file__).parent -templates = Jinja2Templates( - directory=[ - base_dir.parent / "common/templates", - base_dir / "templates", - ] -) -templates.env.globals.update( +templates = build_templates( + Path(__file__).parent / "templates", { - "_": _, - "version": __version__, - "format_date": format_date, - } + "wind_direction_icon": wind_direction_icon, + "cloudness_icon": cloudness_icon, + }, ) -templates.env.filters["wind_direction_icon"] = wind_direction_icon -templates.env.filters["cloudness_icon"] = cloudness_icon def build_weather_response(request: AppRequest, response: WeatherResponse): diff --git a/gallery/painting/gismeteo/core.py b/gallery/painting/gismeteo/core.py index edde261..b168e57 100644 --- a/gallery/painting/gismeteo/core.py +++ b/gallery/painting/gismeteo/core.py @@ -4,6 +4,7 @@ from bs4 import Tag T = TypeVar("T") + class WidgetParser: def parse_widget(self, tag: Tag) -> Tag: raise NotImplementedError diff --git a/gallery/painting/gismeteo/parser.py b/gallery/painting/gismeteo/parser.py index b956da9..d3677b9 100644 --- a/gallery/painting/gismeteo/parser.py +++ b/gallery/painting/gismeteo/parser.py @@ -36,9 +36,7 @@ class DateParser(RowParser[datetime.datetime]): KEY = "date" def parse_row(self, tag: Tag) -> Iterable[datetime.datetime]: - datetime_date_tag = tag.select_one( - ".widget-row.widget-row-datetime-date > .row-item" - ) + datetime_date_tag = tag.select_one(".widget-row.widget-row-datetime-date > .row-item") if datetime_date_tag: date_str = datetime_date_tag.find(text=True, recursive=False).text date = dateparser.parse(date_str, languages=["ru"]) @@ -108,21 +106,15 @@ class TemperatureParser(RowParser[list[int]]): KEY = "temperature" def parse_row(self, tag: Tag) -> Iterable[list[int]]: - for item in tag.select( - ".widget-row-chart[data-row=temperature-air] > .chart > .values > .value" - ): - yield [ - int(value.attrs["value"]) for value in item.select("temperature-value") - ] + for item in tag.select(".widget-row-chart[data-row=temperature-air] > .chart > .values > .value"): + yield [int(value.attrs["value"]) for value in item.select("temperature-value")] class WindSpeedParser(RowParser[int]): KEY = "wind_speed" def parse_row(self, tag: Tag) -> Iterable[int]: - for item in tag.select( - ".widget-row-wind > .row-item > .wind-speed > speed-value" - ): + for item in tag.select(".widget-row-wind > .row-item > .wind-speed > speed-value"): yield int(item.attrs["value"]) @@ -152,22 +144,16 @@ class WindDirectionParser(RowParser[WindDirection]): } def parse_row(self, tag: Tag) -> Iterable[float]: - for item in tag.select( - ".widget-row-wind > .row-item > .wind-speed > .wind-direction" - ): + for item in tag.select(".widget-row-wind > .row-item > .wind-speed > .wind-direction"): wind_direction_str = item.text.lower().strip() - yield WindDirectionDeg.from_direction( - self.WIND_DIRECTION_MAP[wind_direction_str] - ).value + yield WindDirectionDeg.from_direction(self.WIND_DIRECTION_MAP[wind_direction_str]).value class PrecipitationParser(RowParser[float]): KEY = "precipitation" def parse_row(self, tag: Tag) -> Iterable[float]: - for item in tag.select( - ".widget-row[data-row=precipitation-bars] > .row-item > .item-unit" - ): + for item in tag.select(".widget-row[data-row=precipitation-bars] > .row-item > .item-unit"): yield float(item.text.replace(",", ".")) @@ -175,9 +161,7 @@ class PressureParser(RowParser[list[int]]): KEY = "pressure" def parse_row(self, tag: Tag) -> Iterable[list[int]]: - for item in tag.select( - ".widget-row-chart[data-row=pressure] > .chart > .values > .value" - ): + for item in tag.select(".widget-row-chart[data-row=pressure] > .chart > .values > .value"): yield [int(value.attrs["value"]) for value in item.select("pressure-value")] diff --git a/gallery/painting/matchtv/api.py b/gallery/painting/matchtv/api.py index 25d9cde..7075f3a 100644 --- a/gallery/painting/matchtv/api.py +++ b/gallery/painting/matchtv/api.py @@ -25,32 +25,20 @@ class MatchTvApi(ScheduleApi): ChannelId.MATCH_STRANA, ] - async def get_channel_schedule( - self, channel_id: ChannelId, date: datetime.date - ) -> Schedule: + async def get_channel_schedule(self, channel_id: ChannelId, date: datetime.date) -> Schedule: endpoint = f"tvguide/{channel_id}?date={date:%Y%m%d}" data = await self.SOURCE.request(endpoint) soup = BeautifulSoup(data, features="html.parser") values = [] - channel_name = ( - soup.select_one(".p-tv-guide-header__title") - .text.replace("Телепрограмма ", "") - .strip() - ) - current_day = datetime.datetime.combine( - date.today(), datetime.datetime.min.time() - ) + channel_name = soup.select_one(".p-tv-guide-header__title").text.replace("Телепрограмма ", "").strip() + current_day = datetime.datetime.combine(date.today(), datetime.datetime.min.time()) end = current_day + datetime.timedelta(days=1, hours=6) prev_value: ScheduleValue | None = None for item in soup.select( ".p-tv-guide-schedule-channel-carcass__transmissions .p-tv-guide-schedule-channel-transmission" ): - title = item.select_one( - ".p-tv-guide-schedule-channel-transmission__title" - ).text.strip() - time_str = item.select_one( - ".p-tv-guide-schedule-channel-transmission__time-block" - ).text.strip() + title = item.select_one(".p-tv-guide-schedule-channel-transmission__title").text.strip() + time_str = item.select_one(".p-tv-guide-schedule-channel-transmission__time-block").text.strip() hours, minutes = map(int, time_str.split(":")) item_date = current_day.replace(hour=hours, minute=minutes) if prev_value is not None and item_date.hour < prev_value.start.hour: @@ -62,6 +50,4 @@ class MatchTvApi(ScheduleApi): if prev_value is not None: prev_value.end = item_date prev_value = value - return Schedule( - channel=Channel(id=channel_id, name=channel_name), date=date, values=values - ) + return Schedule(channel=Channel(id=channel_id, name=channel_name), date=date, values=values) diff --git a/gallery/painting/openweather/api.py b/gallery/painting/openweather/api.py index 7752a92..3f500b6 100644 --- a/gallery/painting/openweather/api.py +++ b/gallery/painting/openweather/api.py @@ -55,10 +55,7 @@ class OpenWeatherApi(WeatherApi): value = FORECAST_ITEM_PARSER.parse(item) item_date = value.date.replace(hour=0, minute=0) values_by_date[item_date].append(value) - values = [ - merge_weather_values(date, values) - for date, values in values_by_date.items() - ] + values = [merge_weather_values(date, values) for date, values in values_by_date.items()] return WeatherResponse( location=location_id, date=datetime.date.today(), diff --git a/gallery/painting/openweather/mock/__init__.py b/gallery/painting/openweather/mock/__init__.py deleted file mode 100644 index c4c7734..0000000 --- a/gallery/painting/openweather/mock/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from pathlib import Path - -from gallery.sketch.mock import MockData - -OPENWEATHER_MOCK_DATA = MockData(Path(__file__).parent / "data") diff --git a/gallery/painting/openweather/openweather.py b/gallery/painting/openweather/openweather.py index 37791ad..492f232 100644 --- a/gallery/painting/openweather/openweather.py +++ b/gallery/painting/openweather/openweather.py @@ -75,9 +75,7 @@ class OpenWeather: self._source = ApiSource(self.BASE_URL) async def get_forecast(self, lat: float, lon: float) -> Forecast: - endpoint = ( - f"data/2.5/forecast?lat={lat}&lon={lon}&appid={self._api_key}&units=metric" - ) + endpoint = f"data/2.5/forecast?lat={lat}&lon={lon}&appid={self._api_key}&units=metric" response = await self._source.request(endpoint) response_data = json.loads(response) return Forecast(**response_data) diff --git a/gallery/painting/openweather/parser.py b/gallery/painting/openweather/parser.py index 3083b0d..8ee5e23 100644 --- a/gallery/painting/openweather/parser.py +++ b/gallery/painting/openweather/parser.py @@ -24,11 +24,7 @@ class ForecastItemParser: def parse(self, item: ForecastItem) -> WeatherValue: item_date = datetime.datetime.fromtimestamp(item.dt, datetime.UTC) - item_date = ( - item_date.replace(tzinfo=datetime.timezone.utc) - .astimezone(tz=None) - .replace(tzinfo=None) - ) + item_date = item_date.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None).replace(tzinfo=None) value = build_weather_value(item_date) # TODO parse temperature interval flag value.temperature = [round(item.main.temp)] @@ -38,12 +34,8 @@ class ForecastItemParser: value.wind_speed = round(item.wind.speed) value.wind_gust = round(item.wind.gust) value.wind_direction = item.wind.deg - value.sky.cloudness = self.CLOUDNESS_MAP.get( - item.weather[0].description, Cloudness.CLEAR - ) - value.sky.precipitation = self.PRECIPITATION_MAP.get( - item.weather[0].description, Precipitation.NO - ) + value.sky.cloudness = self.CLOUDNESS_MAP.get(item.weather[0].description, Cloudness.CLEAR) + value.sky.precipitation = self.PRECIPITATION_MAP.get(item.weather[0].description, Precipitation.NO) if item.rain: value.precipitation = round(item.rain.interval_3h, 1) return value diff --git a/gallery/painting/yandextv/api.py b/gallery/painting/yandextv/api.py index b9856c9..f3c66b4 100644 --- a/gallery/painting/yandextv/api.py +++ b/gallery/painting/yandextv/api.py @@ -60,9 +60,7 @@ class YandexTvApi(ScheduleApi): async def get_channels(self) -> list[ChannelId]: return list(CHANNELS_MAP.keys()) - async def get_channel_schedule( - self, channel_id: ChannelId, date: datetime.date - ) -> Schedule: + async def get_channel_schedule(self, channel_id: ChannelId, date: datetime.date) -> Schedule: endpoint = f"channel/{CHANNELS_MAP[channel_id]}?date={date:%Y-%m-%d}" data = await self.SOURCE.request(endpoint) soup = BeautifulSoup(data, features="html.parser") @@ -70,9 +68,7 @@ class YandexTvApi(ScheduleApi): raise RuntimeError("Captcha") values = [] channel_name = soup.select_one(".channel-header__text").text.strip() - current_day = datetime.datetime.combine( - date.today(), datetime.datetime.min.time() - ) + current_day = datetime.datetime.combine(date.today(), datetime.datetime.min.time()) end = current_day + datetime.timedelta(days=1, hours=6) prev_value: ScheduleValue | None = None for item in soup.select(".channel-schedule .channel-schedule__event"): @@ -89,6 +85,4 @@ class YandexTvApi(ScheduleApi): if prev_value is not None: prev_value.end = item_date prev_value = value - return Schedule( - channel=Channel(id=channel_id, name=channel_name), date=date, values=values - ) + return Schedule(channel=Channel(id=channel_id, name=channel_name), date=date, values=values) diff --git a/gallery/sketch/schedule/api.py b/gallery/sketch/schedule/api.py index e7b9832..e7e8e4f 100644 --- a/gallery/sketch/schedule/api.py +++ b/gallery/sketch/schedule/api.py @@ -11,18 +11,14 @@ class ScheduleApi(Api): async def get_channels(self) -> list[ChannelId]: raise NotImplementedError - async def get_channel_schedule( - self, channel_id: ChannelId, date: datetime.date - ) -> Schedule: + async def get_channel_schedule(self, channel_id: ChannelId, date: datetime.date) -> Schedule: raise NotImplementedError async def get_all_schedules(self, date: datetime.date) -> list[Schedule]: channels = await self.get_channels() results = [] for channel in channels: - results.append( - await self.get_channel_schedule(channel_id=channel, date=date) - ) + results.append(await self.get_channel_schedule(channel_id=channel, date=date)) if self.INTERVAL > 0: await asyncio.sleep(self.INTERVAL) return results diff --git a/gallery/sketch/schedule/cached.py b/gallery/sketch/schedule/cached.py index 7182df1..47cb410 100644 --- a/gallery/sketch/schedule/cached.py +++ b/gallery/sketch/schedule/cached.py @@ -27,15 +27,11 @@ class CachedScheduleApi(ScheduleApi, CachedApi[ScheduleApi]): ), **CACHE_PRESET._asdict(), ) - async def get_channel_schedule( - self, channel_id: ChannelId, date: datetime.date - ) -> Schedule: + async def get_channel_schedule(self, channel_id: ChannelId, date: datetime.date) -> Schedule: return await self._api.get_channel_schedule(channel_id, date) @cached( - key_builder=lambda fun, self, date: ( - f"api.{self.CACHE_KEY}.{self.provider}.all.{date}" - ), + key_builder=lambda fun, self, date: (f"api.{self.CACHE_KEY}.{self.provider}.all.{date}"), **CACHE_PRESET._asdict(), ) async def get_all_schedules(self, date: datetime.date) -> list[Schedule]: diff --git a/gallery/sketch/source.py b/gallery/sketch/source.py index d24151b..f2d602f 100644 --- a/gallery/sketch/source.py +++ b/gallery/sketch/source.py @@ -7,9 +7,7 @@ logger = logging.getLogger("source") class ApiSource: DEFAULT_USER_AGENT = ( - "Mozilla/5.0 (X11; Linux x86_64) " - "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/126.0.0.0 Safari/537.36" + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" ) DEFAULT_TIMEOUT = 30.0 diff --git a/gallery/sketch/weather/util.py b/gallery/sketch/weather/util.py index dbaec21..6c4f7c9 100644 --- a/gallery/sketch/weather/util.py +++ b/gallery/sketch/weather/util.py @@ -23,9 +23,7 @@ def build_weather_value(date: datetime.datetime) -> WeatherValue: ) -def merge_weather_values( - date: datetime.datetime, values: list[WeatherValue] -) -> WeatherValue: +def merge_weather_values(date: datetime.datetime, values: list[WeatherValue]) -> WeatherValue: result = build_weather_value(date) temperatures = [] pressures = [] diff --git a/gallery/version.py b/gallery/version.py index b5fdc75..f56f621 100644 --- a/gallery/version.py +++ b/gallery/version.py @@ -1 +1,6 @@ __version__ = "0.2.2" + +import tomllib +from pathlib import Path + +__version__ = tomllib.loads((Path(__file__).parent.parent / "pyproject.toml").read_text())["tool"]["poetry"]["version"] diff --git a/pyproject.toml b/pyproject.toml index c2197c0..020acaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ aiohttp = "^3.9.5" beautifulsoup4 = "^4.12.3" dateparser = "^1.2.0" pydantic = "^2.8.2" -aiocache = {extras = ["redis"], version = "^0.12.2"} +aiocache = { extras = ["redis"], version = "^0.12.2" } [tool.poetry.group.app.dependencies] fastapi = "^0.111.1" @@ -35,9 +35,13 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] gallery = "gallery.main:run" +[tool.black] +line-length = 120 + +[tool.isort] +profile = "black" + [tool.pytest.ini_options] addopts = "-p no:warnings" asyncio_mode = "auto" testpaths = ["tests"] - -[tool.poetry_bumpversion.file."gallery/version.py"] \ No newline at end of file diff --git a/scripts/format b/scripts/format new file mode 100755 index 0000000..ff80289 --- /dev/null +++ b/scripts/format @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e +cd "$(dirname $(dirname "$0"))" || exit + +TARGET="gallery" + +poetry run isort $TARGET +poetry run black $TARGET -q diff --git a/scripts/lint b/scripts/lint index 7bb1550..7437b5b 100755 --- a/scripts/lint +++ b/scripts/lint @@ -2,4 +2,8 @@ set -e cd "$(dirname $(dirname "$0"))" || exit -poetry run pylint gallery +TARGET="gallery" + +poetry run pylint $TARGET +poetry run isort $TARGET --check-only +poetry run black $TARGET -q --check --diff diff --git a/scripts/setup b/scripts/setup new file mode 100755 index 0000000..6201da2 --- /dev/null +++ b/scripts/setup @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e +cd "$(dirname $(dirname "$0"))" || exit + +PYTHON_VERSION=3.12 +poetry env use ${PYTHON_VERSION} +poetry install + +cd static || exit + +if [[ -f $HOME/.nvm/nvm.sh ]]; then + source "$HOME/.nvm/nvm.sh" + nvm use +fi +npm ci