Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ruff: Enable pydocstyle w/ numpy convention #303

Merged
merged 25 commits into from Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e326b67
ruff: Enable pydocstyle w/ numpy convention
tony Nov 26, 2023
034bd9c
ruff(pydocstyle): Run automated fixes
tony Nov 26, 2023
130c5c2
ruff(pydocstyle): Run automated fixes (unsafe ones)
tony Nov 26, 2023
c668849
fix(ucn_to_unicode): String doctest
tony Nov 26, 2023
36f6333
util: pydocstyle manual fixes
tony Nov 26, 2023
557adce
tests(util): pydocstyle manual fixes
tony Nov 26, 2023
960f455
tests(unihan): pydocstyle manual fixes
tony Nov 26, 2023
a8057e5
tests(pytest_plugin): pydocstyle manual fixes
tony Nov 26, 2023
1eb23e9
tests(expansion): pydocstyle manual fixes
tony Nov 26, 2023
77b6e41
tests: pydocstyle manual fixes
tony Nov 26, 2023
34877b0
tests(internal): pydocstyle manual fixes
tony Nov 26, 2023
161f56d
tests(internal[app_dirs]): pydocstyle manual fixes
tony Nov 26, 2023
a5c7117
types(unihan-etl): pydocstyle manual fixes
tony Nov 26, 2023
8a1a0a1
pytest_plugin: pydocstyle manual fixes
tony Nov 26, 2023
ddd5e7e
Options: pydocstyle manual fixes
tony Nov 26, 2023
fb15e58
Expansion: pydocstyle manual fixes
tony Nov 26, 2023
10fddf3
Core: pydocstyle manual fixes
tony Nov 26, 2023
85735b6
Constants: pydocstyle manual fixes
tony Nov 26, 2023
f7076d8
internal(app_dirs): pydocstyle manual fixes
tony Nov 26, 2023
62a52a0
__main__: pydocstyle manual fixes
tony Nov 26, 2023
d8a49a2
__init__: pydocstyle manual fixes
tony Nov 26, 2023
2798b22
__about__: pydocstyle manual fixes
tony Nov 26, 2023
a282405
docs(conf): pydocstyle manual fixes
tony Nov 26, 2023
c417998
conftest: pydocstyle manual fixes
tony Nov 26, 2023
1b5be37
docs(CHANGES): Note pydocstyle improvements
tony Nov 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGES
Expand Up @@ -19,6 +19,14 @@ $ pipx install --suffix=@next unihan-etl --pip-args '\--pre' --force

<!-- Maintainers, insert changes / features for the next release here -->

### Development

- ci: Add pydocstyle rule to ruff (#303)

### Documentation

- Add docstrings to functions, methods, classes, and packages (#303)

## unihan-etl 0.29.0 (2023-11-19)

_Maintenance only, no bug fixes, or new features_
Expand Down
5 changes: 4 additions & 1 deletion conftest.py
@@ -1,4 +1,4 @@
"""Conftest.py (root-level)
"""Conftest.py (root-level).

We keep this in root pytest fixtures in pytest's doctest plugin to be available, as well
as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin
Expand All @@ -24,6 +24,7 @@ def add_doctest_fixtures(
request: pytest.FixtureRequest,
doctest_namespace: t.Dict[str, t.Any],
) -> None:
"""Harness pytest fixtures to doctest namespace."""
if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"):
request.getfixturevalue("set_home")
doctest_namespace["request"] = request
Expand All @@ -34,6 +35,7 @@ def set_home(
monkeypatch: pytest.MonkeyPatch,
unihan_user_path: pathlib.Path,
) -> None:
"""Set home directory for pytest tests."""
monkeypatch.setenv("HOME", str(unihan_user_path))


Expand All @@ -44,5 +46,6 @@ def setup(
unihan_ensure_quick: None,
unihan_ensure_full: None,
) -> None:
"""Configure test fixtures for pytest."""
if USING_ZSH:
request.getfixturevalue("unihan_zshrc")
6 changes: 4 additions & 2 deletions docs/conf.py
@@ -1,4 +1,5 @@
# flake8: NOQA: E501
"""Sphinx configuration for unihan-etl."""
import inspect
import pathlib
import sys
Expand Down Expand Up @@ -147,7 +148,7 @@

def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:
"""
Determine the URL corresponding to Python object
Determine the URL corresponding to Python object.

Notes
-----
Expand Down Expand Up @@ -217,11 +218,12 @@ def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:


def remove_tabs_js(app: "Sphinx", exc: Exception) -> None:
"""Remove tabs.js from _static after build."""
# Fix for sphinx-inline-tabs#18
if app.builder.format == "html" and not exc:
tabs_js = pathlib.Path(app.builder.outdir) / "_static" / "tabs.js"
tabs_js.unlink(missing_ok=True)


def setup(app: "Sphinx") -> None:
app.connect("build-finished", remove_tabs_js)
"""Configure Sphinx app hooks."""
4 changes: 4 additions & 0 deletions pyproject.toml
Expand Up @@ -156,12 +156,16 @@ select = [
"TRY", # Trycertatops
"PERF", # Perflint
"RUF", # Ruff-specific rules
"D", # pydocstyle
]

[tool.ruff.isort]
known-first-party = ["unihan_etl", "cihai"]
combine-as-imports = true

[tool.ruff.pydocstyle]
convention = "numpy"

[tool.ruff.per-file-ignores]
"*/__init__.py" = ["F401"]

Expand Down
1 change: 1 addition & 0 deletions src/unihan_etl/__about__.py
@@ -1,3 +1,4 @@
"""Metadata for unihan-etl package."""
__title__ = "unihan-etl"
__package_name__ = "unihan_etl"
__description__ = "Export UNIHAN data of Chinese, Japanese, Korean to CSV, JSON or YAML"
Expand Down
1 change: 1 addition & 0 deletions src/unihan_etl/__init__.py
@@ -1 +1,2 @@
"""Create structured, customized exports of UNIHAN."""
from .__about__ import __version__
1 change: 1 addition & 0 deletions src/unihan_etl/__main__.py
Expand Up @@ -13,6 +13,7 @@


def run() -> "_ExitCode":
"""Execute unihan-etl via CLI entrypoint."""
base = pathlib.Path(__file__).parent.parent
sys.path.insert(0, str(base))
from .core import Packager
Expand Down
17 changes: 17 additions & 0 deletions src/unihan_etl/_internal/app_dirs.py
@@ -1,3 +1,19 @@
"""AppDir wrapper for ``appdirs`` package.

Special features
----------------

This module offers several advantages over
`appdirs <https://github.com/ActiveState/appdirs>`_:

- :mod:`dataclasses`-based object
- :mod:`pathlib` paths
- Variable expansion:

- Environment variables are expanded via :func:`os.path.expandvars`
- XDG environmental variables are expanded via :func:`os.path.expandvars`
- Tilde expansion is expanded via :func:`os.path.expanduser`
"""
import dataclasses
import os
import pathlib
Expand Down Expand Up @@ -60,6 +76,7 @@ class AppDirs:
user_log_dir: pathlib.Path = dataclasses.field(default=MISSING_DIR)

def __post_init__(self, _app_dirs: "BaseAppDirs") -> None:
"""Initialize attributes for AppDirs object."""
dir_attrs = [key for key in _app_dirs.__dir__() if key.endswith("_dir")]
dir_mapping: t.Dict[str, str] = {k: getattr(_app_dirs, k) for k in dir_attrs}
for attr in dir_attrs:
Expand Down
3 changes: 2 additions & 1 deletion src/unihan_etl/constants.py
@@ -1,4 +1,4 @@
#: Dictionary of tuples mapping locations of files to fields
"""Constants for unihan_etl."""
import importlib.util

from appdirs import AppDirs as BaseAppDirs
Expand All @@ -11,6 +11,7 @@
from unihan_etl.types import ColumnDataTuple
from unihan_etl.util import get_fields

#: Dictionary of tuples mapping locations of files to fields
UNIHAN_MANIFEST = {
"Unihan_DictionaryIndices.txt": (
"kCheungBauerIndex",
Expand Down
27 changes: 21 additions & 6 deletions src/unihan_etl/core.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
"""Build Unihan into tabular / structured format and export it."""
"""Download + ETL UNIHAN into structured format and export it."""
import argparse
import codecs
import csv
Expand Down Expand Up @@ -79,17 +79,22 @@ def files_exist(path: pathlib.Path, files: t.List[str]) -> bool:


class FieldNotFound(Exception):
"""Raise if field not found in file list."""

def __init__(self, field: str) -> None:
return super().__init__(f"Field not found in file list: '{field}'")


class FileNotSupported(Exception):
"""Raise if field requested is not included in current file list."""

def __init__(self, field: str) -> None:
return super().__init__(f"File not supported: '{field}'")


#: Return list of files from list of fields.
def get_files(fields: t.Sequence[str]) -> t.List[str]:
"""Return list of files required by fields. Simple dependency resolver."""
files = set()

for field in fields:
Expand All @@ -112,7 +117,6 @@ def get_parser() -> argparse.ArgumentParser:

Returns
-------

:py:class:`argparse.ArgumentParser` :
argument parser for CLI use.
"""
Expand Down Expand Up @@ -428,6 +432,7 @@ def export_csv(
destination: "StrPath",
fields: "ColumnData",
) -> None:
"""Export UNIHAN in flattened, CSV format."""
listified_data = listify(data, fields)

with pathlib.Path(destination).open("w") as f:
Expand All @@ -437,12 +442,14 @@ def export_csv(


def export_json(data: "UntypedNormalizedData", destination: "StrPath") -> None:
"""Export UNIHAN in JSON format."""
with codecs.open(str(destination), "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
log.info(f"Saved output to: {destination}")


def export_yaml(data: "UntypedNormalizedData", destination: "StrPath") -> None:
"""Export UNIHAN in YAML format."""
import yaml

with codecs.open(str(destination), "w", encoding="utf-8") as f:
Expand All @@ -451,12 +458,14 @@ def export_yaml(data: "UntypedNormalizedData", destination: "StrPath") -> None:


def is_default_option(field_name: str, val: t.Any) -> bool:
"""Return True if option is a unihan-etl default."""
return bool(val == getattr(DEFAULT_OPTIONS, field_name, ""))


def validate_options(
options: Options,
) -> "TypeGuard[Options]":
"""Validate unihan-etl options."""
if not is_default_option("input_files", options.input_files) and is_default_option(
"fields", options.fields
):
Expand Down Expand Up @@ -485,16 +494,22 @@ def validate_options(


class Packager:
"""Download and generate a tabular release of
`UNIHAN <http://www.unicode.org/reports/tr38/>`_."""
"""Download, ETL, and customize and export of UNIHAN.

See Also
--------
- `UNIHAN <http://www.unicode.org/reports/tr38/>`_

"""

options: Options

def __init__(
self,
options: t.Union[Options, "t.Mapping[str, t.Any]"] = DEFAULT_OPTIONS,
) -> None:
"""
"""Initialize UNIHAN Packager.

Parameters
----------
options : dict or Options
Expand Down Expand Up @@ -611,7 +626,7 @@ def setup_logger(
logger: t.Optional[logging.Logger] = None,
level: "LogLevel" = "DEBUG",
) -> None:
"""Setup logging for CLI use.
"""Configure logger for CLI use.

Parameters
----------
Expand Down