v0.1.0 - initial release #1
24
src/apply.py
24
src/apply.py
@@ -18,6 +18,7 @@ def apply_changes(
|
|||||||
) -> None:
|
) -> None:
|
||||||
categories = wp.list_categories()
|
categories = wp.list_categories()
|
||||||
category_map = _build_category_map(categories)
|
category_map = _build_category_map(categories)
|
||||||
|
wp_timezone = wp.get_timezone()
|
||||||
|
|
||||||
_create_missing_categories(result, wp, category_map)
|
_create_missing_categories(result, wp, category_map)
|
||||||
_create_missing_tags(result, wp)
|
_create_missing_tags(result, wp)
|
||||||
@@ -27,7 +28,7 @@ def apply_changes(
|
|||||||
for post in result.posts:
|
for post in result.posts:
|
||||||
if not post.should_update:
|
if not post.should_update:
|
||||||
continue
|
continue
|
||||||
_apply_post(post, wp, category_map)
|
_apply_post(post, wp, category_map, wp_timezone)
|
||||||
state.posts[post.identity] = PostState(
|
state.posts[post.identity] = PostState(
|
||||||
source_timestamp=post.source_timestamp,
|
source_timestamp=post.source_timestamp,
|
||||||
materialized_at=int(time.time()),
|
materialized_at=int(time.time()),
|
||||||
@@ -74,7 +75,12 @@ def _create_missing_tags(result: EvaluationResult, wp: WordPressCLI) -> None:
|
|||||||
wp.create_tag(tag)
|
wp.create_tag(tag)
|
||||||
|
|
||||||
|
|
||||||
def _apply_post(post: PostPlan, wp: WordPressCLI, category_map: Dict[tuple[int, str], int]) -> None:
|
def _apply_post(
|
||||||
|
post: PostPlan,
|
||||||
|
wp: WordPressCLI,
|
||||||
|
category_map: Dict[tuple[int, str], int],
|
||||||
|
wp_timezone,
|
||||||
|
) -> None:
|
||||||
category_ids: List[int] = []
|
category_ids: List[int] = []
|
||||||
for path in post.categories:
|
for path in post.categories:
|
||||||
segments = [segment for segment in path.split("/") if segment]
|
segments = [segment for segment in path.split("/") if segment]
|
||||||
@@ -88,7 +94,7 @@ def _apply_post(post: PostPlan, wp: WordPressCLI, category_map: Dict[tuple[int,
|
|||||||
parent = category_map[map_key]
|
parent = category_map[map_key]
|
||||||
category_ids.append(parent)
|
category_ids.append(parent)
|
||||||
|
|
||||||
created_on, last_modified = _normalize_post_dates(post.created_on, post.last_modified)
|
created_on, last_modified = _normalize_post_dates(post.created_on, post.last_modified, wp_timezone)
|
||||||
|
|
||||||
post_id = wp.find_post_id(post.identity)
|
post_id = wp.find_post_id(post.identity)
|
||||||
if post_id is None:
|
if post_id is None:
|
||||||
@@ -119,13 +125,14 @@ def _apply_post(post: PostPlan, wp: WordPressCLI, category_map: Dict[tuple[int,
|
|||||||
def _normalize_post_dates(
|
def _normalize_post_dates(
|
||||||
created_on: Optional[str],
|
created_on: Optional[str],
|
||||||
last_modified: Optional[str],
|
last_modified: Optional[str],
|
||||||
|
wp_timezone,
|
||||||
) -> tuple[Optional[str], Optional[str]]:
|
) -> tuple[Optional[str], Optional[str]]:
|
||||||
if not created_on and not last_modified:
|
if not created_on and not last_modified:
|
||||||
return created_on, last_modified
|
return created_on, last_modified
|
||||||
|
|
||||||
now = datetime.now()
|
now = datetime.now(wp_timezone)
|
||||||
created_dt = _parse_post_date(created_on)
|
created_dt = _parse_post_date(created_on, wp_timezone)
|
||||||
modified_dt = _parse_post_date(last_modified)
|
modified_dt = _parse_post_date(last_modified, wp_timezone)
|
||||||
|
|
||||||
if created_dt and created_dt > now:
|
if created_dt and created_dt > now:
|
||||||
created_dt = now
|
created_dt = now
|
||||||
@@ -139,10 +146,11 @@ def _normalize_post_dates(
|
|||||||
return created_str, modified_str
|
return created_str, modified_str
|
||||||
|
|
||||||
|
|
||||||
def _parse_post_date(value: Optional[str]) -> Optional[datetime]:
|
def _parse_post_date(value: Optional[str], wp_timezone) -> Optional[datetime]:
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
parsed = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
||||||
|
return parsed.replace(tzinfo=wp_timezone)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from datetime import timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from .errors import WordPressError
|
from .errors import WordPressError
|
||||||
|
|
||||||
@@ -78,6 +80,26 @@ class WordPressCLI:
|
|||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise WordPressError(f"Invalid tag id from wp cli: {output}") from exc
|
raise WordPressError(f"Invalid tag id from wp cli: {output}") from exc
|
||||||
|
|
||||||
|
def get_timezone(self):
|
||||||
|
tz_name = self._run(
|
||||||
|
["wp", "option", "get", "timezone_string"],
|
||||||
|
capture_output=True,
|
||||||
|
).stdout.strip()
|
||||||
|
if tz_name and tz_name.upper() != "UTC":
|
||||||
|
try:
|
||||||
|
return ZoneInfo(tz_name)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
offset_value = self._run(
|
||||||
|
["wp", "option", "get", "gmt_offset"],
|
||||||
|
capture_output=True,
|
||||||
|
).stdout.strip()
|
||||||
|
try:
|
||||||
|
offset = float(offset_value)
|
||||||
|
except ValueError:
|
||||||
|
offset = 0.0
|
||||||
|
return timezone(timedelta(hours=offset))
|
||||||
|
|
||||||
def create_category(self, name: str, parent: int) -> int:
|
def create_category(self, name: str, parent: int) -> int:
|
||||||
result = self._run(
|
result = self._run(
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user