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

Pyproject #38

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
58 changes: 46 additions & 12 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
attrs = project.renderers.withPackages {
inherit python;
extras = [ "tests" ];
extraPackages = python-pkgs: [ python-pkgs.ipykernel ];
extraPackages = python-pkgs: [
python-pkgs.ipykernel
python-pkgs.python-lsp-server
python-pkgs.pylsp-mypy
];
};
pythonEnv = python.withPackages attrs;
in
Expand Down
14 changes: 10 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
build-backend = "setuptools.build_meta"
requires = ["matplotlib", "setuptools"]
cgahr marked this conversation as resolved.
Show resolved Hide resolved
requires = ["setuptools"]

[project]
authors = [
Expand All @@ -16,7 +16,8 @@ classifiers = [
]
dependencies = [
"appdirs",
"matplotlib"
"matplotlib",
"tomli; python_version < '3.11'"
]
description = "Perfect matplotlib figures for latex"
dynamic = ["version"]
Expand Down Expand Up @@ -46,7 +47,10 @@ Homepage = "https://github.com/cgahr/latexplotlib"
Issues = "https://github.com/cgahr/latexplotlib/issues"

[tool.coverage.report]
exclude_lines = ["if TYPE_CHECKING:"]
exclude_lines = [
"if TYPE_CHECKING:",
"import tomli as tomllib" # tested via GitHub actions
]

[tool.coverage.run]
source = ["src"]
Expand Down Expand Up @@ -117,7 +121,8 @@ src = ["src"]
[tool.ruff.lint]
fixable = ["I"]
ignore = [
"ANN101" # missing-type-self
"ANN101", # missing-type-self
"ANN102" # missing-type-cls
]
select = [
"A",
Expand Down Expand Up @@ -177,6 +182,7 @@ suppress-dummy-args = true
"ARG002", # unused-method-argument
"INP", # implicit-namespace-package
"PLR0913", # too-many-arguments
"PLR6301",
"S101", # assert
"SLF001" # private-member-access
]
Expand Down
2 changes: 0 additions & 2 deletions src/latexplotlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import Any

from ._cleanup import purge_old_styles
from ._config import size
from ._latexplotlib import (
convert_inches_to_pt,
Expand All @@ -27,5 +26,4 @@ def __getattr__(name: str) -> Any: # noqa: ANN401
return getattr(plt, name)


purge_old_styles(__path__)
make_styles_available(__path__)
40 changes: 0 additions & 40 deletions src/latexplotlib/_cleanup.py

This file was deleted.

108 changes: 65 additions & 43 deletions src/latexplotlib/_config.py
Original file line number Diff line number Diff line change
@@ -1,75 +1,86 @@
import json
from collections.abc import Iterator, Mapping
import sys
import warnings
from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
from typing import Union

from appdirs import user_config_dir

if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib

Number = Union[int, float]
ConfigData = Union[Number, bool]

GOLDEN_RATIO: float = (5**0.5 + 1) / 2
NAME: str = "latexplotlib"
_PURGED_OLD = "_purged_old_styles"

CONFIGFILE: str = "config.ini"
CONFIGDIR: Path = Path(user_config_dir(NAME))
CONFIGPATH: Path = CONFIGDIR / CONFIGFILE
DEFAULT_CONFIG: dict[str, Number] = {"width": 630, "height": 412, _PURGED_OLD: False}

DEFAULT_WIDTH = 630
DEFAULT_HEIGHT = 412

class Config:
def __init__(self, path: Path) -> None:
self.path = path

if not self.path.exists():
self.reset()
def find_pyproject_toml() -> Path | None:
pyproject = "pyproject.toml"
path = Path().absolute()
while path != Path("/"):
if (path / pyproject).exists():
return path / pyproject
path = path.parent

self._config = self._open(path)

def _open(self, path: Path) -> dict[str, ConfigData]:
with path.open(encoding="utf-8") as fh:
config: dict[str, ConfigData] = json.load(fh)
return config
return None

def _write(self, cfg: Mapping[str, ConfigData]) -> None:
if not self.path.parent.exists():
self.path.parent.mkdir(parents=True)

with self.path.open("w", encoding="utf-8") as fh:
json.dump(cfg, fh, indent=4)
def find_config_ini() -> Path | None:
if CONFIGPATH.exists():
msg = f"""
Configuring latexplotlib via '{CONFIGPATH}' is being deprecated. Please use
the [tool.latexplotlib] section of the 'pyproject.toml' file instead. If a
'pyproject.toml' file is present in the current directory or a parent
directory, the configuration at '{CONFIGPATH}' is being ignored.

def reset(self) -> None:
if self.path.exists():
self.path.unlink()
To silence this warning, please delete the config file '{CONFIGPATH}'.
"""
warnings.warn(msg, DeprecationWarning, stacklevel=5)

self._write(DEFAULT_CONFIG)
return CONFIGPATH

def reload(self) -> None:
self._config = self._open(self.path)
return None

def __getitem__(self, name: str) -> ConfigData:
return self._config.get(name, DEFAULT_CONFIG[name])

def __setitem__(self, name: str, value: ConfigData) -> None:
self._config[name] = value
self._write(self._config)
class Size:
_width: Number
_height: Number

def __init__(self, *, width: Number, height: Number) -> None:
self._width, self._height = width, height

config = Config(CONFIGPATH)
@classmethod
def from_pyproject_toml(cls, path: Path) -> "Size":
with path.open("rb") as fh:
cfg = tomllib.load(fh)

config = cfg.get("tool", {}).get("latexplotlib", {})

class Size:
_width: Number
_height: Number
return cls(
width=config.get("width", DEFAULT_WIDTH),
height=config.get("height", DEFAULT_HEIGHT),
)

def __init__(self) -> None:
self._width, self._height = config["width"], config["height"]
@classmethod
def from_config_ini(cls, path: Path) -> "Size":
with path.open(encoding="utf-8") as fh:
config: dict[str, Number] = json.load(fh)

def reload(self) -> None:
config.reload()
self._width, self._height = config["width"], config["height"]
return cls(
width=config.get("width", DEFAULT_WIDTH),
height=config.get("height", DEFAULT_HEIGHT),
)

def get(self) -> tuple[Number, Number]:
"""Returns the current size of the figure in pts.
Expand All @@ -96,7 +107,6 @@ def set(self, width: Number, height: Number) -> None:
height : int
The height of the latex page in pts.
"""
config["width"], config["height"] = width, height
self._width, self._height = width, height

@contextmanager
Expand All @@ -123,4 +133,16 @@ def __str__(self) -> str:
return str(f"{self._width}pt, {self._height}pt")


size = Size()
def get_size() -> Size:
if (path := find_pyproject_toml()) is not None:
# look for config.ini to emit deprecation warning if it exists
_ = find_config_ini()
return Size.from_pyproject_toml(path)

if (path := find_config_ini()) is not None:
return Size.from_config_ini(path)

return Size(width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT)


size = get_size()
Loading
Loading