diff --git a/Makefile b/Makefile
index 6a52726a..6a1bb1d5 100644
--- a/Makefile
+++ b/Makefile
@@ -68,8 +68,8 @@ help:
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
lint: ## run linting and code quality checks
- black --check erdantic tests docs
- flake8 erdantic tests docs
+ ruff format --check erdantic tests docs
+ ruff check erdantic tests docs
pypitest: dist
twine upload --repository testpypi dist/*
diff --git a/erdantic/__init__.py b/erdantic/__init__.py
index d31abe4e..0994c924 100644
--- a/erdantic/__init__.py
+++ b/erdantic/__init__.py
@@ -1,6 +1,6 @@
-from erdantic.erd import create, draw, EntityRelationshipDiagram, to_dot
-import erdantic.pydantic # noqa: F401
import erdantic.dataclasses # noqa: F401
+from erdantic.erd import EntityRelationshipDiagram, create, draw, to_dot
+import erdantic.pydantic # noqa: F401
from erdantic.version import __version__
__version__
diff --git a/erdantic/base.py b/erdantic/base.py
index 05b1e161..a3bc12a0 100644
--- a/erdantic/base.py
+++ b/erdantic/base.py
@@ -5,7 +5,6 @@
from erdantic.exceptions import InvalidModelAdapterError, ModelAdapterNotFoundError
from erdantic.typing import Final, GenericAlias, repr_type
-
_row_template = """
{name} | {type_name} |
"""
diff --git a/erdantic/cli.py b/erdantic/cli.py
index 65f7bb2b..d067176d 100644
--- a/erdantic/cli.py
+++ b/erdantic/cli.py
@@ -1,7 +1,7 @@
from enum import Enum
from importlib import import_module
from pathlib import Path
-from typing import List, Optional, TYPE_CHECKING
+from typing import TYPE_CHECKING, List, Optional
import typer
@@ -10,7 +10,6 @@
from erdantic.exceptions import ModelOrModuleNotFoundError
from erdantic.version import __version__
-
app = typer.Typer()
diff --git a/erdantic/dataclasses.py b/erdantic/dataclasses.py
index 6be24012..6c38b921 100644
--- a/erdantic/dataclasses.py
+++ b/erdantic/dataclasses.py
@@ -1,7 +1,6 @@
import dataclasses
from typing import Any, List, Union
-
from erdantic.base import Field, Model, register_model_adapter
from erdantic.exceptions import InvalidFieldError, InvalidModelError
from erdantic.typing import GenericAlias, is_many, is_nullable
diff --git a/erdantic/erd.py b/erdantic/erd.py
index 57667e91..24722af6 100644
--- a/erdantic/erd.py
+++ b/erdantic/erd.py
@@ -5,15 +5,15 @@
import pygraphviz as pgv
-from erdantic.base import Field, get_model_adapter, Model, model_adapter_registry
+from erdantic.base import Field, Model, get_model_adapter, model_adapter_registry
from erdantic.exceptions import (
NotATypeError,
- _StringForwardRefError,
StringForwardRefError,
- _UnevaluatedForwardRefError,
UnevaluatedForwardRefError,
UnknownFieldError,
UnknownModelTypeError,
+ _StringForwardRefError,
+ _UnevaluatedForwardRefError,
)
from erdantic.typing import get_recursive_args
from erdantic.version import __version__
diff --git a/erdantic/examples/__init__.py b/erdantic/examples/__init__.py
index 2dfd71a3..c7defb59 100644
--- a/erdantic/examples/__init__.py
+++ b/erdantic/examples/__init__.py
@@ -1,7 +1,6 @@
"""Example data model classes."""
-from erdantic.examples import dataclasses
-from erdantic.examples import pydantic
+from erdantic.examples import dataclasses, pydantic
__all__ = [
"dataclasses",
diff --git a/erdantic/exceptions.py b/erdantic/exceptions.py
index 58721193..ef2f14e3 100644
--- a/erdantic/exceptions.py
+++ b/erdantic/exceptions.py
@@ -1,9 +1,11 @@
-from typing import Optional, TYPE_CHECKING
-
-from typing import ForwardRef # docs claim Python >= 3.7.4 but actually it's in Python 3.7.0+
+from typing import (
+ TYPE_CHECKING,
+ ForwardRef, # docs claim Python >= 3.7.4 but actually it's in Python 3.7.0+
+ Optional,
+)
if TYPE_CHECKING:
- from erdantic.base import Model, Field
+ from erdantic.base import Field, Model
class ErdanticException(Exception):
diff --git a/erdantic/pydantic.py b/erdantic/pydantic.py
index e4f6aa9b..fdd80e90 100644
--- a/erdantic/pydantic.py
+++ b/erdantic/pydantic.py
@@ -1,4 +1,4 @@
-from typing import Any, List, Union, Type
+from typing import Any, List, Type, Union
import pydantic
import pydantic.fields
@@ -6,7 +6,7 @@
from erdantic.base import Field, Model, register_model_adapter
from erdantic.exceptions import InvalidFieldError, InvalidModelError
-from erdantic.typing import GenericAlias, repr_type_with_mro, is_many, is_nullable
+from erdantic.typing import GenericAlias, is_many, is_nullable, repr_type_with_mro
class PydanticField(Field[pydantic.fields.FieldInfo]):
diff --git a/erdantic/typing.py b/erdantic/typing.py
index 16ee6a75..76f8535b 100644
--- a/erdantic/typing.py
+++ b/erdantic/typing.py
@@ -20,7 +20,6 @@
from erdantic.exceptions import _StringForwardRefError, _UnevaluatedForwardRefError
-
try:
from typing import get_args, get_origin # type: ignore # Python 3.8+
except ImportError:
diff --git a/pyproject.toml b/pyproject.toml
index 7899475e..df2b1c3f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -41,20 +41,21 @@ erdantic = "erdantic.cli:app"
"Bug Tracker" = "https://github.com/drivendataorg/erdantic/issues"
"Changelog" = "https://erdantic.drivendata.org/stable/changelog/"
-[tool.black]
+[tool.ruff]
line-length = 99
-include = '\.pyi?$'
-exclude = '''
-/(
- \.eggs
- | \.git
- | \.mypy_cache
- | \.tox
- | \.venv
- | build
- | dist
-)/
-'''
+src = ["erdantic/**/*.py", "tests/**/*.py"]
+
+[tool.ruff.lint]
+select = [
+ "E", # Pyflakes
+ "F", # Pycodestyle
+ "I", # isort
+]
+unfixable = ["F"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["erdantic"]
+force-sort-within-sections = true
[tool.mypy]
ignore_missing_imports = true
diff --git a/requirements-dev.txt b/requirements-dev.txt
index a22742c6..57465377 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,8 +1,6 @@
-e .
-black
build
-flake8
jupyterlab
mdx_truly_sane_lists==1.3
mike
@@ -15,5 +13,6 @@ nbconvert<6.5
pytest<8
pytest-cases
pytest-cov
+ruff>=0.1.14
twine
wheel
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 01ec7be1..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[flake8]
-ignore = E501, W503
-max-line-length = 99
diff --git a/tests/scripts/generate_static_assets.py b/tests/scripts/generate_static_assets.py
index ab464c02..2f7cf326 100644
--- a/tests/scripts/generate_static_assets.py
+++ b/tests/scripts/generate_static_assets.py
@@ -1,7 +1,6 @@
from pathlib import Path
from types import ModuleType
-
import erdantic as erd
import erdantic.erd
import erdantic.examples.dataclasses
diff --git a/tests/test_adapters.py b/tests/test_adapters.py
index 1de22cb4..ccdaa65b 100644
--- a/tests/test_adapters.py
+++ b/tests/test_adapters.py
@@ -7,15 +7,13 @@
from pytest_cases import param_fixtures
import erdantic as erd
+from erdantic.dataclasses import DataClassField, DataClassModel
import erdantic.erd
import erdantic.examples.dataclasses
import erdantic.examples.pydantic
-from erdantic.dataclasses import DataClassField, DataClassModel
from erdantic.pydantic import PydanticField, PydanticModel
-
from tests.utils import assert_dot_equals
-
ASSETS_DIR = Path(__file__).parent / "assets"
# key, model class, field class, examples module
diff --git a/tests/test_base.py b/tests/test_base.py
index dad13ca2..19c84c1b 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -1,7 +1,7 @@
import pytest
import erdantic as erd
-from erdantic.base import Field, get_model_adapter, Model, register_model_adapter
+from erdantic.base import Field, Model, get_model_adapter, register_model_adapter
from erdantic.examples.pydantic import Party
from erdantic.exceptions import InvalidModelAdapterError, ModelAdapterNotFoundError
from erdantic.pydantic import PydanticModel
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 0b39537f..576f3776 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -12,7 +12,6 @@
from erdantic.exceptions import ModelOrModuleNotFoundError
from erdantic.version import __version__
-
runner = CliRunner()
diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
index 63d5ac6e..792d2fdb 100644
--- a/tests/test_dataclasses.py
+++ b/tests/test_dataclasses.py
@@ -1,7 +1,11 @@
import dataclasses
-from typing import Dict, List, Tuple, get_type_hints
-
-from typing import ForwardRef # docs claim Python >= 3.7.4 but actually it's in Python 3.7.0+
+from typing import (
+ Dict,
+ ForwardRef, # docs claim Python >= 3.7.4 but actually it's in Python 3.7.0+
+ List,
+ Tuple,
+ get_type_hints,
+)
import pytest
diff --git a/tests/test_erd.py b/tests/test_erd.py
index 0a83a150..c16cfde7 100644
--- a/tests/test_erd.py
+++ b/tests/test_erd.py
@@ -5,15 +5,15 @@
import erdantic as erd
from erdantic.erd import Edge, find_models
+import erdantic.examples.dataclasses as examples_dataclasses
+import erdantic.examples.pydantic as examples_pydantic
+from erdantic.examples.pydantic import Adventurer, Party, Quest, QuestGiver
from erdantic.exceptions import (
- NotATypeError,
InvalidModelAdapterError,
ModelAdapterNotFoundError,
+ NotATypeError,
UnknownModelTypeError,
)
-from erdantic.examples.pydantic import Party, Adventurer, Quest, QuestGiver
-import erdantic.examples.pydantic as examples_pydantic
-import erdantic.examples.dataclasses as examples_dataclasses
from erdantic.pydantic import PydanticModel
diff --git a/tests/test_typing.py b/tests/test_typing.py
index 7da52b0e..2ecaeb9c 100644
--- a/tests/test_typing.py
+++ b/tests/test_typing.py
@@ -1,7 +1,6 @@
from enum import Enum, IntFlag
import sys
import typing
-
from typing import ForwardRef # docs claim Python >= 3.7.4 but actually it's in Python 3.7.0+
try: