mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Use `_StrPath in sphinx.util.i18n` (#13050)
This commit is contained in:
@@ -316,9 +316,9 @@ class Sphinx:
|
|||||||
catalog.write_mo(self.config.language,
|
catalog.write_mo(self.config.language,
|
||||||
self.config.gettext_allow_fuzzy_translations)
|
self.config.gettext_allow_fuzzy_translations)
|
||||||
|
|
||||||
locale_dirs: list[str | None] = list(repo.locale_dirs)
|
locale_dirs: list[_StrPath | None] = list(repo.locale_dirs)
|
||||||
locale_dirs += [None]
|
locale_dirs += [None]
|
||||||
locale_dirs += [path.join(package_dir, 'locale')]
|
locale_dirs += [_StrPath(package_dir, 'locale')]
|
||||||
|
|
||||||
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
||||||
if has_translation or self.config.language == 'en':
|
if has_translation or self.config.language == 'en':
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ class BuildEnvironment:
|
|||||||
for docname in self.found_docs:
|
for docname in self.found_docs:
|
||||||
domain = docname_to_domain(docname, self.config.gettext_compact)
|
domain = docname_to_domain(docname, self.config.gettext_compact)
|
||||||
if domain in mo_paths:
|
if domain in mo_paths:
|
||||||
self.dependencies[docname].add(mo_paths[domain])
|
self.dependencies[docname].add(str(mo_paths[domain]))
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
raise DocumentError(
|
raise DocumentError(
|
||||||
__('Failed to scan documents in %s: %r') % (self.srcdir, exc)
|
__('Failed to scan documents in %s: %r') % (self.srcdir, exc)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import path
|
from os import path
|
||||||
from typing import TYPE_CHECKING, NamedTuple
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import babel.dates
|
import babel.dates
|
||||||
from babel.messages.mofile import write_mo
|
from babel.messages.mofile import write_mo
|
||||||
@@ -15,11 +15,11 @@ from babel.messages.pofile import read_po
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util._pathlib import _StrPath
|
||||||
from sphinx.util.osutil import (
|
from sphinx.util.osutil import (
|
||||||
SEP,
|
SEP,
|
||||||
_last_modified_time,
|
_last_modified_time,
|
||||||
canon_path,
|
canon_path,
|
||||||
relpath,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -64,34 +64,36 @@ from datetime import UTC
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LocaleFileInfoBase(NamedTuple):
|
class CatalogInfo:
|
||||||
base_dir: str
|
__slots__ = ('base_dir', 'domain', 'charset')
|
||||||
domain: str
|
|
||||||
charset: str
|
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, base_dir: str | os.PathLike[str], domain: str, charset: str
|
||||||
|
) -> None:
|
||||||
|
self.base_dir = _StrPath(base_dir)
|
||||||
|
self.domain = domain
|
||||||
|
self.charset = charset
|
||||||
|
|
||||||
class CatalogInfo(LocaleFileInfoBase):
|
|
||||||
@property
|
@property
|
||||||
def po_file(self) -> str:
|
def po_file(self) -> str:
|
||||||
return self.domain + '.po'
|
return f'{self.domain}.po'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mo_file(self) -> str:
|
def mo_file(self) -> str:
|
||||||
return self.domain + '.mo'
|
return f'{self.domain}.mo'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def po_path(self) -> str:
|
def po_path(self) -> _StrPath:
|
||||||
return path.join(self.base_dir, self.po_file)
|
return self.base_dir / self.po_file
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mo_path(self) -> str:
|
def mo_path(self) -> _StrPath:
|
||||||
return path.join(self.base_dir, self.mo_file)
|
return self.base_dir / self.mo_file
|
||||||
|
|
||||||
def is_outdated(self) -> bool:
|
def is_outdated(self) -> bool:
|
||||||
return (
|
return not self.mo_path.exists() or (
|
||||||
not path.exists(self.mo_path)
|
_last_modified_time(self.mo_path) < _last_modified_time(self.po_path)
|
||||||
or _last_modified_time(self.mo_path) < _last_modified_time(self.po_path)
|
)
|
||||||
) # fmt: skip
|
|
||||||
|
|
||||||
def write_mo(self, locale: str, use_fuzzy: bool = False) -> None:
|
def write_mo(self, locale: str, use_fuzzy: bool = False) -> None:
|
||||||
with open(self.po_path, encoding=self.charset) as file_po:
|
with open(self.po_path, encoding=self.charset) as file_po:
|
||||||
@@ -118,38 +120,33 @@ class CatalogRepository:
|
|||||||
language: str,
|
language: str,
|
||||||
encoding: str,
|
encoding: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.basedir = basedir
|
self.basedir = _StrPath(basedir)
|
||||||
self._locale_dirs = locale_dirs
|
self._locale_dirs = locale_dirs
|
||||||
self.language = language
|
self.language = language
|
||||||
self.encoding = encoding
|
self.encoding = encoding
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def locale_dirs(self) -> Iterator[str]:
|
def locale_dirs(self) -> Iterator[_StrPath]:
|
||||||
if not self.language:
|
if not self.language:
|
||||||
return
|
return
|
||||||
|
|
||||||
for locale_dir in self._locale_dirs:
|
for locale_dir in self._locale_dirs:
|
||||||
locale_dir = path.join(self.basedir, locale_dir)
|
locale_path = self.basedir / locale_dir / self.language / 'LC_MESSAGES'
|
||||||
locale_path = path.join(locale_dir, self.language, 'LC_MESSAGES')
|
if locale_path.exists():
|
||||||
if path.exists(locale_path):
|
yield self.basedir / locale_dir
|
||||||
yield locale_dir
|
|
||||||
else:
|
else:
|
||||||
logger.verbose(__('locale_dir %s does not exist'), locale_path)
|
logger.verbose(__('locale_dir %s does not exist'), locale_path)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pofiles(self) -> Iterator[tuple[str, str]]:
|
def pofiles(self) -> Iterator[tuple[_StrPath, _StrPath]]:
|
||||||
for locale_dir in self.locale_dirs:
|
for locale_dir in self.locale_dirs:
|
||||||
basedir = path.join(locale_dir, self.language, 'LC_MESSAGES')
|
locale_path = locale_dir / self.language / 'LC_MESSAGES'
|
||||||
for root, dirnames, filenames in os.walk(basedir):
|
for abs_path in locale_path.rglob('*.po'):
|
||||||
|
rel_path = abs_path.relative_to(locale_path)
|
||||||
# skip dot-directories
|
# skip dot-directories
|
||||||
dot_directories = [d for d in dirnames if d.startswith('.')]
|
if any(part.startswith('.') for part in rel_path.parts[:-1]):
|
||||||
for dirname in dot_directories:
|
continue
|
||||||
dirnames.remove(dirname)
|
yield locale_path, rel_path
|
||||||
|
|
||||||
for filename in filenames:
|
|
||||||
if filename.endswith('.po'):
|
|
||||||
fullpath = path.join(root, filename)
|
|
||||||
yield basedir, relpath(fullpath, basedir)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def catalogs(self) -> Iterator[CatalogInfo]:
|
def catalogs(self) -> Iterator[CatalogInfo]:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import babel
|
import babel
|
||||||
import pytest
|
import pytest
|
||||||
@@ -18,16 +19,16 @@ def test_catalog_info_for_file_and_path():
|
|||||||
cat = i18n.CatalogInfo('path', 'domain', 'utf-8')
|
cat = i18n.CatalogInfo('path', 'domain', 'utf-8')
|
||||||
assert cat.po_file == 'domain.po'
|
assert cat.po_file == 'domain.po'
|
||||||
assert cat.mo_file == 'domain.mo'
|
assert cat.mo_file == 'domain.mo'
|
||||||
assert cat.po_path == os.path.join('path', 'domain.po')
|
assert cat.po_path == str(Path('path', 'domain.po'))
|
||||||
assert cat.mo_path == os.path.join('path', 'domain.mo')
|
assert cat.mo_path == str(Path('path', 'domain.mo'))
|
||||||
|
|
||||||
|
|
||||||
def test_catalog_info_for_sub_domain_file_and_path():
|
def test_catalog_info_for_sub_domain_file_and_path():
|
||||||
cat = i18n.CatalogInfo('path', 'sub/domain', 'utf-8')
|
cat = i18n.CatalogInfo('path', 'sub/domain', 'utf-8')
|
||||||
assert cat.po_file == 'sub/domain.po'
|
assert cat.po_file == 'sub/domain.po'
|
||||||
assert cat.mo_file == 'sub/domain.mo'
|
assert cat.mo_file == 'sub/domain.mo'
|
||||||
assert cat.po_path == os.path.join('path', 'sub/domain.po')
|
assert cat.po_path == str(Path('path', 'sub', 'domain.po'))
|
||||||
assert cat.mo_path == os.path.join('path', 'sub/domain.mo')
|
assert cat.mo_path == str(Path('path', 'sub', 'domain.mo'))
|
||||||
|
|
||||||
|
|
||||||
def test_catalog_outdated(tmp_path):
|
def test_catalog_outdated(tmp_path):
|
||||||
@@ -48,8 +49,9 @@ def test_catalog_write_mo(tmp_path):
|
|||||||
(tmp_path / 'test.po').write_text('#', encoding='utf8')
|
(tmp_path / 'test.po').write_text('#', encoding='utf8')
|
||||||
cat = i18n.CatalogInfo(tmp_path, 'test', 'utf-8')
|
cat = i18n.CatalogInfo(tmp_path, 'test', 'utf-8')
|
||||||
cat.write_mo('en')
|
cat.write_mo('en')
|
||||||
assert os.path.exists(cat.mo_path)
|
mo_path = Path(cat.mo_path)
|
||||||
with open(cat.mo_path, 'rb') as f:
|
assert mo_path.exists()
|
||||||
|
with open(mo_path, 'rb') as f:
|
||||||
assert read_mo(f) is not None
|
assert read_mo(f) is not None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user