erdantic
Advanced tools
| # SCM syntax highlighting & preventing 3-way merges | ||
| pixi.lock merge=binary linguist-language=YAML linguist-generated=true |
| name: docs-preview | ||
| on: | ||
| pull_request: | ||
| workflow_dispatch: | ||
| jobs: | ||
| build: | ||
| name: Build docs and deploy preview | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: extractions/setup-just@v2 | ||
| - uses: prefix-dev/setup-pixi@v0.8.5 | ||
| with: | ||
| cache: true | ||
| cache-key: default | ||
| environments: default | ||
| - name: Build docs | ||
| run: | | ||
| just docs | ||
| - name: Get preview identifier | ||
| id: get_id | ||
| run: | | ||
| if [[ "${{ github.event_name }}" == "pull_request" ]]; then | ||
| PREVIEW_IDENTIFIER="PR${{ github.event.number }}" | ||
| else | ||
| PREVIEW_IDENTIFIER="$(git rev-parse --short HEAD)" | ||
| fi | ||
| echo "PREVIEW_IDENTIFIER=$PREVIEW_IDENTIFIER" | tee -a $GITHUB_OUTPUT | ||
| - name: Deploy preview to Netlify | ||
| uses: nwtgck/actions-netlify@v2.0.0 | ||
| with: | ||
| publish-dir: "./docs/site" | ||
| production-deploy: false | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| deploy-message: "Deploy from GitHub Actions" | ||
| enable-pull-request-comment: true | ||
| enable-commit-comment: false | ||
| overwrites-pull-request-comment: true | ||
| alias: ${{ steps.get_id.outputs.PREVIEW_IDENTIFIER }} | ||
| env: | ||
| NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} | ||
| NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} | ||
| timeout-minutes: 1 |
| name: docs-publish | ||
| on: | ||
| push: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| inputs: | ||
| deploy-as: | ||
| type: choice | ||
| description: Deploy as | ||
| options: | ||
| - latest | ||
| - version | ||
| default: latest | ||
| is-stable: | ||
| type: boolean | ||
| description: Deploy as stable | ||
| default: false | ||
| version-format: | ||
| type: string | ||
| description: Version format | ||
| default: "v{major_minor_version}" | ||
| jobs: | ||
| build: | ||
| name: Stage docs on gh-pages | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Fail if deploying as latest but marked as stable | ||
| if: github.event.inputs.deploy-as == 'latest' && github.event.inputs.is-stable == 'true' | ||
| run: | | ||
| echo "Error: Cannot deploy as 'latest' when 'is-stable' is true." | ||
| exit 1 | ||
| - uses: actions/checkout@v4 | ||
| - uses: extractions/setup-just@v2 | ||
| - uses: prefix-dev/setup-pixi@v0.8.5 | ||
| with: | ||
| cache: true | ||
| cache-key: default | ||
| environments: default | ||
| - name: Set git user to github-actions[bot] | ||
| run: | | ||
| git config user.name github-actions[bot] | ||
| git config user.email 41898282+github-actions[bot]@users.noreply.github.com | ||
| - name: Fetch gh-pages branch | ||
| run: | | ||
| git fetch origin gh-pages --depth=1 | ||
| - name: Deploy as latest | ||
| if: github.event.inputs.deploy-as == 'latest' || github.event_name == 'push' | ||
| working-directory: docs/ | ||
| run: | | ||
| pixi run mike deploy --push latest --title=latest | ||
| - name: Get version tag | ||
| id: get-version-tag | ||
| if: github.event.inputs.deploy-as == 'version' | ||
| run: | | ||
| VERSION_TAG=$(pixi run vspect read . "${{ github.event.inputs.version-format }}") | ||
| echo "VERSION_TAG=${VERSION_TAG}" | tee -a $GITHUB_OUTPUT | ||
| - name: Deploy as version | ||
| if: github.event.inputs.deploy-as == 'version' | ||
| working-directory: docs/ | ||
| run: | | ||
| TITLE=$(uv run vspect read .. "v{version}") | ||
| TAG=${{ steps.get-version-tag.outputs.VERSION_TAG }} | ||
| pixi run mike deploy --push $TAG --title="${TITLE}" | ||
| - name: Assign stable alias | ||
| if: github.event.inputs.is-stable == 'true' | ||
| working-directory: docs/ | ||
| run: | | ||
| TAG=${{ steps.get-version-tag.outputs.VERSION_TAG }} | ||
| pixi run mike alias --push --update-aliases $TAG stable | ||
| deploy: | ||
| name: Deploy docs to Netlify | ||
| needs: build | ||
| runs-on: "ubuntu-latest" | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: gh-pages | ||
| - name: Deploy docs to Netlify | ||
| uses: nwtgck/actions-netlify@v1.1 | ||
| with: | ||
| publish-dir: "./" | ||
| production-deploy: true | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| deploy-message: "Deploy from GitHub Actions" | ||
| enable-pull-request-comment: false | ||
| enable-commit-comment: false | ||
| overwrites-pull-request-comment: false | ||
| env: | ||
| NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} | ||
| NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} | ||
| timeout-minutes: 1 |
+148
| # erdantic Changelog | ||
| ## v1.1.0 (2025-04-12) | ||
| - Removed support for Python 3.8. | ||
| - Added Python 3.13 to supported Python versions. | ||
| - Added support for [msgspec structs](https://jcristharif.com/msgspec/structs.html). ([Issue #139](https://github.com/drivendataorg/erdantic/issues/139), [PR #142](https://github.com/drivendataorg/erdantic/pull/142)) | ||
| - Added `--list-plugins` CLI flag to print information on active plugins. ([PR #144](https://github.com/drivendataorg/erdantic/pull/144)) | ||
| ## v1.0.5 (2024-09-19) | ||
| - Fixed runtime `AttributeError` that occurred when creating a diagram that includes a model with a field that uses a type annotation with the ellipsis literal (e.g., `tuple[int, ...]`). ([Issue #124](https://github.com/drivendataorg/erdantic/issues/124), [PR #127](https://github.com/drivendataorg/erdantic/pull/127)) | ||
| ## v1.0.4 (2024-07-16) | ||
| - Fixed handling of `typing.Annotated` in cases where it's not the outermost generic type. ([Issue #122](https://github.com/drivendataorg/erdantic/issues/122), [PR #123](https://github.com/drivendataorg/erdantic/pull/123)) | ||
| ## v1.0.3 (2024-05-10) | ||
| - Fixed `StopIteration` error when rendering a model that has no fields. ([Issue #120](https://github.com/drivendataorg/erdantic/issues/120), [PR #121](https://github.com/drivendataorg/erdantic/pull/121)) | ||
| ## v1.0.2 (2024-04-11) | ||
| - Fixed `AttributeError` when adding a model that has a field annotated with certain typing special forms like `Any`, `Literal`, or `TypeVar` instances. ([Issue #114](https://github.com/drivendataorg/erdantic/issues/114), [PR #115](https://github.com/drivendataorg/erdantic/pull/115)) | ||
| ## v1.0.1 (2024-04-10) | ||
| - Fixed `ModuleNotFoundError` when importing from `erdantic.examples` without attrs installed. | ||
| ## v1.0.0.post2 (2024-04-10) | ||
| - Fixed missing LICENSE file in sdist. | ||
| ## v1.0.0.post1 (2024-04-09) | ||
| - Fixed outdated note in README. | ||
| ## v1.0.0 (2024-04-09) | ||
| > [!IMPORTANT] | ||
| > This release features significant changes to erdantic, primarily to the backend process of analyzing models and representing data. If you have been primarily using the CLI or the convenience functions `create`, `draw`, and `to_dot`, then your code may continue to work without any changes. If you are doing something more advanced, you may need to update your code. | ||
| ### CLI changes | ||
| - Deprecated `--termini` option. Use the new `--terminal-model` option instead. The shorthand option `-t` remains the same. The `--termini` option still works but will emit a deprecation warning. | ||
| ### Convenience function changes | ||
| - Deprecated `termini` argument for `create`, `draw`, and `to_dot` functions. Use the new `terminal_models` argument instead. The `termini` argument still works but will emit a deprecation warning. | ||
| - Added `graph_attr`, `node_attr`, and `edge_attr` arguments to the `draw` and `to_dot` functions that allow you to override attributes on the generated pygraphviz object for the diagram. | ||
| ### Visual changes | ||
| A few changes have been made to the visual content of rendered diagrams. | ||
| - Changed the extraction of type names to use the [typenames](https://github.com/jayqi/typenames) library. This should generally produce identical rendered outputs as before, with the following exception: | ||
| - Removed the special case behavior for rendering enum classes. Enums now just show the class name without inheritance information. | ||
| - Changed collection fields (e.g., `List[TargetModel]`) to display as a "many" relationship (crow) instead of a "zero-or-many" relationship (odot + crow), treating the modality of the field as unspecified. A field will only be displayed as "zero-or-many" (odot + crow) if it is explicitly optional, like `Optional[List[TargetModel]]`. | ||
| - Fixed incorrect representation of manyness for type annotations where the outermost annotation wasn't a collection type. ([Issue #105](https://github.com/drivendataorg/erdantic/issues/105)) | ||
| ### Support for attrs | ||
| - Added support for [attrs](https://www.attrs.org/en/stable/index.html) classes, i.e., classes decorated by `attrs.define`. The source code for attrs support can be found in the new module `erdantic.plugins.attrs`. | ||
| - Added new example module `erdantic.examples.attrs`. | ||
| ### Backend changes | ||
| Significant changes have been made to the library backend to more strongly separate the model analysis process, the extracted data, and the diagram rendering process. We believe this more structured design facilitates customizing diagrams and simplifies the implementation for each data modeling framework. Please see the new documentation pages ["Customizing diagrams"](http://erdantic.drivendata.org/v1.0/customizing/) and ["Extending or modifying erdantic"](http://erdantic.drivendata.org/v1.0/extending/) for details on the new design. | ||
| A summary of some key changes is below: | ||
| - Removed the adapter base classes `Model` and `Field` and the conrete adapters `DataClassModel`, `DataClassField`, `PydanticModel`, and `PydanticField`. | ||
| - Added new Pydantic models `ModelInfo` and `FieldInfo` to replace the adapter system. These new models hold static data that have been extracted from models that erdantic analyzed. | ||
| - Removed the adapter system and associated objects such as `model_adapter_registry` and `register_model_adapter`. | ||
| - Added new plugin system to replace the adapter system as the way that modeling frameworks are supported. Plugins must implement two functions—a predicate function and a field extractor function—and be registered using `register_plugin`. All objects related to plugins can be found in the new `erdantic.plugins` module and its submodules. | ||
| - Renamed `erdantic.typing` module to `erdantic.typing_utils`. | ||
| ### Other | ||
| - Added [PEP 561 `py.typed` marker file](https://peps.python.org/pep-0561/#packaging-type-information) to indicate that the package supports type checking. | ||
| - Added IPython special method for pretty-print string representations of `EntityRelationshipDiagram` instances. | ||
| - Removed support for Python 3.7. ([PR #102](https://github.com/drivendataorg/erdantic/pull/102)) | ||
| ## v0.7.1 (2024-04-09) | ||
| This will be the last version that supports Python 3.7. | ||
| - Added version typer version ceiling of `< 0.10.0` due to incompatibility with a fix introduced in that version. | ||
| ## v0.7.0 (2024-02-11) | ||
| - Added support for Pydantic V1 legacy models. These are models created from the `pydantic.v1` namespace when Pydantic V2 is installed. ([PR #94](https://github.com/drivendataorg/erdantic/pull/94) from [@ursereg](https://github.com/ursereg)) | ||
| ## v0.6.0 (2023-07-09) | ||
| - Added support for Pydantic V2. | ||
| - Removed support for Pydantic V1. | ||
| - Changed the init signature for `PydanticField` to work with Pydantic V2's API. | ||
| - Added `is_many` and `is_nullable` functions to `erdantic.typing`. | ||
| ## v0.5.1 (2023-07-04) | ||
| - Changed Pydantic dependency to be `< 2`. This will be the final version of erdantic that supports Pydantic V1. | ||
| - Changed to pyproject.toml-based build. | ||
| ## v0.5.0 (2022-07-29) | ||
| - Removed support for Python 3.6. ([Issue #51](https://github.com/drivendataorg/erdantic/issues/51), [PR #56](https://github.com/drivendataorg/erdantic/pull/56)) | ||
| - Added support for modules as inputs to all entrypoints to diagram creation (`create`, `draw`, `to_dot`, CLI). For all modules passed, erdantic will find all supported data model classes in each module. ([Issue #23](https://github.com/drivendataorg/erdantic/issues/23), [PR #58](https://github.com/drivendataorg/erdantic/pull/58)) | ||
| - Added new parameter `limit_search_models_to` to all entrypoints to allow for limiting which data model classes will be yielded from searching a module. | ||
| ## v0.4.1 (2022-04-08) | ||
| - Fixed error when rendering a data model that has field using `typing.Literal`. ([PR #49](https://github.com/drivendataorg/erdantic/pull/49)) | ||
| ## v0.4.0 (2021-11-06) | ||
| - Added support for showing field documentation from Pydantic models with descriptions set with `Field(description=...)` in SVG tooltips. This will add an "Attributes" section to the tooltip using Google-style docstring format and lists fields where the `description` keyword argument is used. ([Issue #8](https://github.com/drivendataorg/erdantic/issues/8#issuecomment-958905131), [PR #42](https://github.com/drivendataorg/erdantic/pull/42)) | ||
| ## v0.3.0 (2021-10-28) | ||
| - Fixed handling of forward references in field type declarations. Evaluated forward references will be properly identified. Forward references not converted to `typing.ForwardRef` will throw a `StringForwardRefError` with instructions for how to resolve. Unevaluated forward references will throw an `UnevaluatedForwardRefError` with instructions for how to resolve. See [new documentation](https://erdantic.drivendata.org/stable/forward-references/) for more details. ([Issue #40](https://github.com/drivendataorg/erdantic/issues/40), [PR #41](https://github.com/drivendataorg/erdantic/pull/41)) | ||
| - Changed name of `erdantic.errors` module to `erdantic.exceptions`. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| - Added new `ErdanticException` base class from which other exceptions raised within the erdantic library are subclassed from. Changed several existing `ValueError` exceptions to new exception classes that subclass both `ErdanticException` and `ValueError`. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| - Changed `__lt__` method on `Model` and `Edge` to return `NotImplemented` instead of raising an exception to follow typical convention for unsupported input types. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| ## v0.2.1 (2021-02-16) | ||
| - Fixed runtime error when rendering a data model that had a field containing `typing.Any`. ([Issue #25](https://github.com/drivendataorg/erdantic/issues/25), [PR #26](https://github.com/drivendataorg/erdantic/issues/26)) | ||
| ## v0.2.0 (2021-02-14) | ||
| - Added option to specify models as terminal nodes. This allows you to truncate large diagrams and split them up into smaller ones. ([PR #24](https://github.com/drivendataorg/erdantic/pull/24)) | ||
| ## v0.1.2 (2021-02-10) | ||
| - Fixed bug where Pydantic fields were missing generics in their type annotations. ([PR #19](https://github.com/drivendataorg/erdantic/pull/19)) | ||
| - Added tests against static rendered DOT output. Change adapter tests to use parameterized fixtures. ([PR #21](https://github.com/drivendataorg/erdantic/pull/21)) | ||
| ## v0.1.1 (2021-02-10) | ||
| - Fixed rendered example image in the package description on PyPI. ([PR #18](https://github.com/drivendataorg/erdantic/pull/18)) | ||
| ## v0.1.0 (2021-02-10) | ||
| Initial release! 🎉 |
| # erdantic.examples.msgspec | ||
| ::: erdantic.examples.msgspec |
| # erdantic.plugins.msgspec | ||
| ::: erdantic.plugins.msgspec |
Sorry, the diff of this file is not supported yet
| """Example struct classes using [msgspec](https://jcristharif.com/msgspec/).""" | ||
| from datetime import datetime | ||
| from enum import Enum | ||
| from typing import List, Optional | ||
| import msgspec | ||
| class Alignment(str, Enum): | ||
| LAWFUL_GOOD = "lawful_good" | ||
| NEUTRAL_GOOD = "neutral_good" | ||
| CHAOTIC_GOOD = "chaotic_good" | ||
| LAWFUL_NEUTRAL = "lawful_neutral" | ||
| TRUE_NEUTRAL = "true_neutral" | ||
| CHAOTIC_NEUTRAL = "chaotic_neutral" | ||
| LAWFUL_EVIL = "lawful_evil" | ||
| NEUTRAL_EVIL = "neutral_evil" | ||
| CHAOTIC_EVIL = "chaotic_evil" | ||
| class Adventurer(msgspec.Struct): | ||
| """A person often late for dinner but with a tale or two to tell. | ||
| Attributes: | ||
| name (str): Name of this adventurer | ||
| profession (str): Profession of this adventurer | ||
| alignment (Alignment): Alignment of this adventurer | ||
| level (int): Level of this adventurer | ||
| """ | ||
| name: str | ||
| profession: str | ||
| alignment: Alignment | ||
| level: int = 1 | ||
| class QuestGiver(msgspec.Struct): | ||
| """A person who offers a task that needs completing. | ||
| Attributes: | ||
| name (str): Name of this quest giver | ||
| faction (str): Faction that this quest giver belongs to | ||
| location (str): Location this quest giver can be found | ||
| """ | ||
| name: str | ||
| faction: Optional[str] = None | ||
| location: str = "Adventurer's Guild" | ||
| class Quest(msgspec.Struct): | ||
| """A task to complete, with some monetary reward. | ||
| Attributes: | ||
| name (str): Name by which this quest is referred to | ||
| giver (QuestGiver): Person who offered the quest | ||
| reward_gold (int): Amount of gold to be rewarded for quest completion | ||
| """ | ||
| name: str | ||
| giver: QuestGiver | ||
| reward_gold: int = 100 | ||
| class Party(msgspec.Struct): | ||
| """A group of adventurers finding themselves doing and saying things altogether unexpected. | ||
| Attributes: | ||
| name (str): Name that party is known by | ||
| formed_datetime (datetime): Timestamp of when the party was formed | ||
| members (List[Adventurer]): Adventurers that belong to this party | ||
| active_quest (Optional[Quest]): Current quest that party is actively tackling | ||
| """ | ||
| name: str | ||
| formed_datetime: datetime | ||
| members: List[Adventurer] = [] | ||
| active_quest: Optional[Quest] = None |
| import re | ||
| import sys | ||
| from typing import Any, List, Type | ||
| if sys.version_info >= (3, 10): | ||
| from typing import TypeGuard | ||
| else: | ||
| from typing_extensions import TypeGuard | ||
| import msgspec | ||
| from erdantic.core import FieldInfo, FullyQualifiedName | ||
| from erdantic.exceptions import UnresolvableForwardRefError | ||
| from erdantic.plugins import register_plugin | ||
| MsgspecStruct = Type[msgspec.Struct] | ||
| def is_msgspec_struct(obj: Any) -> TypeGuard[MsgspecStruct]: | ||
| """Predicate function to determine if an object is a msgspect struct (class, not instance). | ||
| Args: | ||
| obj (Any): The object to check. | ||
| Returns: | ||
| bool: True if the object is a Struct class, False otherwise. | ||
| """ | ||
| return isinstance(obj, type) and issubclass(obj, msgspec.Struct) | ||
| def get_fields_from_msgspec_struct(model: MsgspecStruct) -> List[FieldInfo]: | ||
| """Given a msgspec struct, return a list of FieldInfo instances for each field in the | ||
| struct. | ||
| Args: | ||
| model (PydanticModel): The struct to get fields from. | ||
| Returns: | ||
| List[FieldInfo]: List of FieldInfo instances for each field in the struct | ||
| """ | ||
| try: | ||
| msgspec._utils.get_class_annotations(model) # type: ignore [attr-defined] | ||
| return [ | ||
| FieldInfo.from_raw_type( | ||
| model_full_name=FullyQualifiedName.from_object(model), | ||
| name=msgspec_field_info.name, | ||
| raw_type=msgspec_field_info.type, | ||
| ) | ||
| for msgspec_field_info in msgspec.structs.fields(model) | ||
| ] | ||
| except NameError as e: | ||
| model_full_name = FullyQualifiedName.from_object(model) | ||
| forward_ref = getattr( | ||
| e, | ||
| "name", | ||
| re.search(r"(?<=')(?:[^'])*(?=')", str(e)).group(0), # type: ignore [union-attr] | ||
| ) | ||
| msg = ( | ||
| f"Failed to resolve forward reference '{forward_ref}' in the type annotations for " | ||
| f"struct {model_full_name}. " | ||
| "erdantic does not currently support manually resolving forward references for " | ||
| "structs." | ||
| ) | ||
| raise UnresolvableForwardRefError( | ||
| msg, name=forward_ref, model_full_name=model_full_name | ||
| ) from e | ||
| register_plugin( | ||
| key="msgspec", predicate_fn=is_msgspec_struct, get_fields_fn=get_fields_from_msgspec_struct | ||
| ) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
| # This is used for test_cli.py::test_import_object_from_name | ||
| raise RuntimeError("This is a test exception") |
| from pprint import pprint | ||
| from typing import Optional | ||
| import msgspec | ||
| import pytest | ||
| from erdantic.core import EntityRelationshipDiagram, FullyQualifiedName | ||
| import erdantic.examples.msgspec as msgspec_examples | ||
| from erdantic.exceptions import UnresolvableForwardRefError | ||
| from erdantic.plugins.msgspec import ( | ||
| get_fields_from_msgspec_struct, | ||
| is_msgspec_struct, | ||
| ) | ||
| def test_is_msgspec_struct(): | ||
| class NotAStruct: | ||
| pass | ||
| assert is_msgspec_struct(msgspec_examples.Party) | ||
| assert is_msgspec_struct(msgspec_examples.QuestGiver) | ||
| assert not is_msgspec_struct( | ||
| msgspec_examples.QuestGiver(name="Gandalf", faction=None, location="Shire") | ||
| ) | ||
| assert not is_msgspec_struct("Hello") | ||
| assert not is_msgspec_struct(str) | ||
| assert not is_msgspec_struct(NotAStruct) | ||
| def test_get_fields_from_msgspec_struct(): | ||
| fields = get_fields_from_msgspec_struct(msgspec_examples.Party) | ||
| assert len(fields) == 4 | ||
| # name | ||
| assert fields[0].model_full_name == FullyQualifiedName.from_object(msgspec_examples.Party) | ||
| assert fields[0].name == "name" | ||
| assert fields[0].type_name == "str" | ||
| # formed_datetime | ||
| assert fields[1].model_full_name == FullyQualifiedName.from_object(msgspec_examples.Party) | ||
| assert fields[1].name == "formed_datetime" | ||
| assert fields[1].type_name == "datetime" | ||
| # members | ||
| assert fields[2].model_full_name == FullyQualifiedName.from_object(msgspec_examples.Party) | ||
| assert fields[2].name == "members" | ||
| assert fields[2].type_name == "List[Adventurer]" | ||
| # active_quest | ||
| assert fields[3].model_full_name == FullyQualifiedName.from_object(msgspec_examples.Party) | ||
| assert fields[3].name == "active_quest" | ||
| assert fields[3].type_name == "Optional[Quest]" | ||
| class GlobalOtherClassBefore(msgspec.Struct): | ||
| """Another struct to be referenced as a forward reference. Defined before the struct that | ||
| references it.""" | ||
| my_field: str | ||
| class GlobalWithFwdRefs(msgspec.Struct): | ||
| """Globally defined struct with forward references. This should have no problems being | ||
| automatically resolved.""" | ||
| # Resolved by resolve_types_on_dataclass in get_fields_from_msgspec_struct | ||
| imported_ref: "msgspec_examples.Party" | ||
| nested_imported_ref: Optional["msgspec_examples.Quest"] | ||
| self_ref: "GlobalWithFwdRefs" | ||
| nested_self_ref: Optional["GlobalWithFwdRefs"] | ||
| global_ref_before: "GlobalOtherClassBefore" | ||
| nested_global_ref_before: Optional["GlobalOtherClassBefore"] | ||
| global_ref_after: "GlobalOtherClassAfter" | ||
| nested_global_ref_after: Optional["GlobalOtherClassAfter"] | ||
| class GlobalOtherClassAfter(msgspec.Struct): | ||
| """Another struct to be referenced as a forward reference. Defined after the struct that | ||
| references it.""" | ||
| my_field: str | ||
| def test_forward_refs_global_scope(): | ||
| """Global scope struct with forward references that we can handle automatically.""" | ||
| # Class is defined in the global scope | ||
| fields = {fi.name: fi for fi in get_fields_from_msgspec_struct(GlobalWithFwdRefs)} | ||
| pprint({name: (fi.type_name, fi.raw_type) for name, fi in fields.items()}) | ||
| # Resolved by resolve_types_on_dataclass in get_fields_from_msgspec_struct | ||
| assert fields["imported_ref"].type_name == "Party" | ||
| assert fields["imported_ref"].raw_type == msgspec_examples.Party | ||
| assert fields["nested_imported_ref"].type_name == "Optional[Quest]" | ||
| assert fields["nested_imported_ref"].raw_type == Optional[msgspec_examples.Quest] | ||
| assert fields["self_ref"].type_name == "GlobalWithFwdRefs" | ||
| assert fields["self_ref"].raw_type == GlobalWithFwdRefs | ||
| assert fields["nested_self_ref"].type_name == "Optional[GlobalWithFwdRefs]" | ||
| assert fields["nested_self_ref"].raw_type == Optional[GlobalWithFwdRefs] | ||
| assert fields["global_ref_before"].type_name == "GlobalOtherClassBefore" | ||
| assert fields["global_ref_before"].raw_type == GlobalOtherClassBefore | ||
| assert fields["nested_global_ref_before"].type_name == "Optional[GlobalOtherClassBefore]" | ||
| assert fields["nested_global_ref_before"].raw_type == Optional[GlobalOtherClassBefore] | ||
| assert fields["global_ref_after"].type_name == "GlobalOtherClassAfter" | ||
| assert fields["global_ref_after"].raw_type == GlobalOtherClassAfter | ||
| assert fields["nested_global_ref_after"].type_name == "Optional[GlobalOtherClassAfter]" | ||
| assert fields["nested_global_ref_after"].raw_type == Optional[GlobalOtherClassAfter] | ||
| # Can add to diagram without error | ||
| diagram = EntityRelationshipDiagram() | ||
| diagram.add_model(GlobalWithFwdRefs) | ||
| def test_forward_refs_fn_scope_auto_resolvable(): | ||
| """Function scope struct with forward references that we can automatically resolve.""" | ||
| # Resolved by resolve_types_on_dataclass in get_fields_from_msgspec_struct | ||
| class FnScopeAutomaticallyResolvable(msgspec.Struct): | ||
| imported_ref: "msgspec_examples.Party" | ||
| nested_imported_ref: Optional["msgspec_examples.Quest"] | ||
| global_ref: "GlobalOtherClassBefore" | ||
| nested_global_ref: Optional["GlobalOtherClassBefore"] | ||
| fields = {fi.name: fi for fi in get_fields_from_msgspec_struct(FnScopeAutomaticallyResolvable)} | ||
| pprint({name: (fi.type_name, fi.raw_type) for name, fi in fields.items()}) | ||
| assert fields["imported_ref"].type_name == "Party" | ||
| assert fields["imported_ref"].raw_type == msgspec_examples.Party | ||
| assert fields["nested_imported_ref"].type_name == "Optional[Quest]" | ||
| assert fields["nested_imported_ref"].raw_type == Optional[msgspec_examples.Quest] | ||
| assert fields["global_ref"].type_name == "GlobalOtherClassBefore" | ||
| assert fields["global_ref"].raw_type == GlobalOtherClassBefore | ||
| assert fields["nested_global_ref"].type_name == "Optional[GlobalOtherClassBefore]" | ||
| assert fields["nested_global_ref"].raw_type == Optional[GlobalOtherClassBefore] | ||
| # Can add to diagram without error | ||
| diagram = EntityRelationshipDiagram() | ||
| diagram.add_model(FnScopeAutomaticallyResolvable) | ||
| def test_forward_refs_fn_scope_manual_resolvable(): | ||
| """Function scope model with forward references that we need to manually resolve.""" | ||
| class FnScopeOtherClassBefore(msgspec.Struct): | ||
| """Another class to be referenced as a forward reference. Defined before the class that | ||
| references it.""" | ||
| my_field: str | ||
| class FnScopeManuallyResolvable(msgspec.Struct): | ||
| self_ref: "FnScopeManuallyResolvable" | ||
| nested_self_ref: Optional["FnScopeManuallyResolvable"] | ||
| sibling_ref_before: "FnScopeOtherClassBefore" | ||
| nested_sibling_ref_before: "Optional[FnScopeOtherClassBefore]" | ||
| sibling_ref_after: "FnScopeOtherClassAfter" | ||
| nested_sibling_ref_after: Optional["FnScopeOtherClassAfter"] | ||
| class FnScopeOtherClassAfter(msgspec.Struct): | ||
| """Another class to be referenced as a forward reference. Defined after the class that | ||
| references it.""" | ||
| my_field: str | ||
| with pytest.raises(UnresolvableForwardRefError, match="'FnScopeManuallyResolvable'"): | ||
| diagram = EntityRelationshipDiagram() | ||
| diagram.add_model(FnScopeManuallyResolvable) | ||
| with pytest.raises(UnresolvableForwardRefError, match="'FnScopeManuallyResolvable'"): | ||
| get_fields_from_msgspec_struct(FnScopeManuallyResolvable) | ||
| # Don't currently support manually resolving forward references for structs | ||
| # Call attrs.resolve_types() to manually resolve | ||
| # resolve_types_on_struct(FnScopeManuallyResolvable, localns=locals()) | ||
| # Adding to diagram should now work without error | ||
| # diagram = EntityRelationshipDiagram() | ||
| # diagram.add_model(FnScopeManuallyResolvable) | ||
| # Fields should match expected | ||
| # fields = {fi.name: fi for fi in get_fields_from_msgspec_struct(FnScopeManuallyResolvable)} | ||
| # pprint({name: (fi.type_name, fi.raw_type) for name, fi in fields.items()}) | ||
| # assert fields["self_ref"].type_name == "FnScopeManuallyResolvable" | ||
| # assert fields["self_ref"].raw_type == FnScopeManuallyResolvable | ||
| # assert fields["nested_self_ref"].type_name == "Optional[FnScopeManuallyResolvable]" | ||
| # assert fields["nested_self_ref"].raw_type == Optional[FnScopeManuallyResolvable] | ||
| # assert fields["sibling_ref_before"].type_name == "FnScopeOtherClassBefore" | ||
| # assert fields["sibling_ref_before"].raw_type == FnScopeOtherClassBefore | ||
| # assert fields["nested_sibling_ref_before"].type_name == "Optional[FnScopeOtherClassBefore]" | ||
| # assert fields["nested_sibling_ref_before"].raw_type == Optional[FnScopeOtherClassBefore] | ||
| # assert fields["sibling_ref_after"].type_name == "FnScopeOtherClassAfter" | ||
| # assert fields["sibling_ref_after"].raw_type == FnScopeOtherClassAfter | ||
| # assert fields["nested_sibling_ref_after"].type_name == "Optional[FnScopeOtherClassAfter]" | ||
| # assert fields["nested_sibling_ref_after"].raw_type == Optional[FnScopeOtherClassAfter] |
| name: release | ||
| run-name: Release of ${{ inputs.version }}${{ inputs.dry-run && ' (dry run)' }} | ||
| on: | ||
| release: | ||
| types: | ||
| - published | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Version tag' | ||
| required: true | ||
| dry-run: | ||
| description: 'Dry run' | ||
| required: false | ||
| default: false | ||
| type: boolean | ||
| jobs: | ||
| build: | ||
| name: Build and publish new release | ||
| check-version: | ||
| name: Check metadata version is correct | ||
| runs-on: "ubuntu-latest" | ||
| steps: | ||
| - uses: actions/checkout@v3 | ||
| - uses: actions/checkout@v4 | ||
| - uses: conda-incubator/setup-miniconda@v3 | ||
| - uses: prefix-dev/setup-pixi@v0.8.5 | ||
| with: | ||
| miniforge-version: latest | ||
| activate-environment: "" | ||
| use-mamba: true | ||
| cache: true | ||
| cache-key: default | ||
| environments: default | ||
| - name: Install nox and uv | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| - name: Check that versions match | ||
| id: version | ||
| run: | | ||
| nox -s dev | ||
| echo "Release tag: [${{ github.event.release.tag_name }}]" | ||
| PACKAGE_VERSION=$(.nox/dev/bin/python -c "import erdantic; print(erdantic.__version__)") | ||
| echo "Input version tag: [${{ github.event.inputs.version }}] " | ||
| PACKAGE_VERSION=$(pixi run python -m vspect read .) | ||
| echo "Package version: [$PACKAGE_VERSION]" | ||
| [ ${{ github.event.release.tag_name }} == "v$PACKAGE_VERSION" ] || { exit 1; } | ||
| echo "full_version=v$PACKAGE_VERSION" >> $GITHUB_ENV | ||
| MAJOR_MINOR_VERSION=$([[ $PACKAGE_VERSION =~ ^[0-9]+\.[0-9]+ ]] && echo "${BASH_REMATCH[0]}") | ||
| echo "major_minor_version=$([[ $PACKAGE_VERSION =~ ^[0-9]+\.[0-9]+ ]] && echo "v${BASH_REMATCH[0]}")" >> $GITHUB_ENV | ||
| [[ ${{ github.event.inputs.version }} == "v$PACKAGE_VERSION" ]] || { exit 1; } | ||
| - name: Build package | ||
| run: | | ||
| nox -s build --verbose | ||
| build-and-inspect-package: | ||
| name: Build and inspect package | ||
| needs: check-version | ||
| runs-on: ubuntu-latest | ||
| environment: release | ||
| permissions: | ||
| # Need both of these for attest-build-provenance-github | ||
| id-token: write | ||
| attestations: write | ||
| - name: Build docs | ||
| run: | | ||
| nox -s docs --verbose | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: hynek/build-and-inspect-python-package@v2 | ||
| with: | ||
| attest-build-provenance-github: 'true' | ||
| - name: Publish to Test PyPI | ||
| uses: pypa/gh-action-pypi-publish@v1.3.0 | ||
| upload-to-test-pypi: | ||
| name: Upload package to PyPI | ||
| needs: build-and-inspect-package | ||
| if: github.event.inputs.dry-run == 'false' | ||
| runs-on: ubuntu-latest | ||
| environment: release | ||
| permissions: | ||
| id-token: write # Required for PyPI trusted publishing | ||
| steps: | ||
| - name: Download built artifact to dist/ | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| user: ${{ secrets.PYPI_TEST_USERNAME }} | ||
| password: ${{ secrets.PYPI_TEST_PASSWORD }} | ||
| repository_url: https://test.pypi.org/legacy/ | ||
| skip_existing: true | ||
| name: Packages | ||
| path: dist | ||
| - name: Publish to Production PyPI | ||
| uses: pypa/gh-action-pypi-publish@v1.3.0 | ||
| - uses: pypa/gh-action-pypi-publish@v1.12.4 | ||
| with: | ||
| user: ${{ secrets.PYPI_PROD_USERNAME }} | ||
| password: ${{ secrets.PYPI_PROD_PASSWORD }} | ||
| skip_existing: false | ||
| repository-url: https://test.pypi.org/legacy/ | ||
| skip-existing: true | ||
| - name: Stage docs on gh-pages (release candidate) | ||
| if: contains(steps.version.outputs.full_version, 'rc') | ||
| working-directory: docs | ||
| run: | | ||
| git fetch origin gh-pages --depth=1 | ||
| git config user.name github-actions[bot] | ||
| git config user.email 41898282+github-actions[bot]@users.noreply.github.com | ||
| RUN_MIKE="conda run -p ../.nox/docs mike" | ||
| $RUN_MIKE deploy --push \ | ||
| ${{ steps.version.outputs.major_minor_version }}rc \ | ||
| --title="${{ steps.version.outputs.major_minor_version }}rc" | ||
| upload-to-prod-pypi: | ||
| name: Upload package to PyPI | ||
| needs: upload-to-test-pypi | ||
| if: github.event.inputs.dry-run == 'false' | ||
| runs-on: ubuntu-latest | ||
| environment: release | ||
| permissions: | ||
| id-token: write # Required for PyPI trusted publishing | ||
| - name: Stage docs on gh-pages (stable) | ||
| if: ${{ ! contains(steps.version.outputs.full_version, 'rc') }} | ||
| working-directory: docs | ||
| run: | | ||
| git fetch origin gh-pages --depth=1 | ||
| git config user.name github-actions[bot] | ||
| git config user.email 41898282+github-actions[bot]@users.noreply.github.com | ||
| RUN_MIKE="conda run -p ../.nox/docs mike" | ||
| # Rename old stable version | ||
| $RUN_MIKE list -j | jq | ||
| OLD_STABLE=$($RUN_MIKE list -j | jq -r '.[] | select(.aliases | index("stable")) | .title' | awk '{print $1;}') | ||
| echo $OLD_STABLE | ||
| $RUN_MIKE retitle stable $OLD_STABLE | ||
| # Deploy new version as stable | ||
| $RUN_MIKE deploy --push --update-aliases \ | ||
| ${{ steps.version.outputs.major_minor_version }} \ | ||
| stable \ | ||
| --title="${{ github.event.release.tag_name }} (stable)" | ||
| steps: | ||
| - name: Download built artifact to dist/ | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: Packages | ||
| path: dist | ||
| deploy-docs: | ||
| name: Deploy docs to Netlify | ||
| needs: build | ||
| runs-on: "ubuntu-latest" | ||
| - uses: pypa/gh-action-pypi-publish@v1.12.4 | ||
| create-github-release: | ||
| name: Create GitHub release | ||
| needs: upload-to-prod-pypi | ||
| if: github.event.inputs.dry-run == 'false' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - uses: actions/checkout@v4 | ||
| - id: extract-changelog | ||
| uses: sean0x42/markdown-extract@v2.1.0 | ||
| with: | ||
| ref: gh-pages | ||
| file: CHANGELOG.md | ||
| pattern: ${{ github.event.inputs.version }} | ||
| - name: Deploy docs to Netlify | ||
| uses: nwtgck/actions-netlify@v1.1 | ||
| - name: Write output to file | ||
| run: | | ||
| cat <<'__EOF__' > __CHANGELOG-extracted.md | ||
| ${{ steps.extract-changelog.outputs.markdown }} | ||
| __EOF__ | ||
| - uses: ncipollo/release-action@v1 | ||
| with: | ||
| publish-dir: "./" | ||
| production-deploy: true | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| deploy-message: "Deploy from GitHub Actions" | ||
| enable-pull-request-comment: false | ||
| enable-commit-comment: false | ||
| overwrites-pull-request-comment: false | ||
| env: | ||
| NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} | ||
| NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} | ||
| timeout-minutes: 1 | ||
| tag: ${{ github.event.inputs.version }} | ||
| commit: main | ||
| artifacts: "dist/*.whl,dist/*.tar.gz" | ||
| bodyFile: "__CHANGELOG-extracted.md" |
@@ -11,2 +11,8 @@ name: tests | ||
| workflow_dispatch: | ||
| inputs: | ||
| update-deps: | ||
| description: "Update test dependencies" | ||
| required: false | ||
| default: false | ||
| type: boolean | ||
@@ -21,19 +27,19 @@ jobs: | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| - uses: extractions/setup-just@v2 | ||
| - uses: prefix-dev/setup-pixi@v0.8.5 | ||
| with: | ||
| python-version: "3.11" | ||
| cache: true | ||
| cache-key: default | ||
| environments: >- | ||
| default | ||
| typecheck | ||
| - name: Install nox and uv | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| - name: Lint | ||
| run: | | ||
| nox -s lint --verbose | ||
| just lint | ||
| - name: Typecheck | ||
| run: | | ||
| nox -s typecheck --verbose | ||
| just typecheck | ||
@@ -47,3 +53,3 @@ tests: | ||
| os: [ubuntu-latest, macos-latest] | ||
| python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] | ||
| python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] | ||
@@ -53,16 +59,34 @@ steps: | ||
| - uses: conda-incubator/setup-miniconda@v3 | ||
| - name: Get environment name | ||
| id: env_name | ||
| run: | | ||
| env_name="test-py$(echo ${{ matrix.python-version }} | tr -d .)" | ||
| echo "env_name=${env_name}" | tee -a "$GITHUB_OUTPUT" | ||
| - uses: extractions/setup-just@v2 | ||
| - uses: prefix-dev/setup-pixi@v0.8.5 | ||
| with: | ||
| miniforge-version: latest | ||
| activate-environment: "" | ||
| use-mamba: true | ||
| cache: true | ||
| cache-key: ${{ steps.env_name.outputs.env_name }} | ||
| environments: ${{ steps.env_name.outputs.env_name }} | ||
| - name: Install nox and uv | ||
| - name: Update dependencies | ||
| if: >- | ||
| ${{ | ||
| github.event_name == 'push' | ||
| || github.event_name == 'scheduled' | ||
| || (github.event_name == 'workflow_dispatch' && github.event.inputs.update-deps == 'true') | ||
| }} | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| pixi update -e ${{ steps.env_name.outputs.env_name }} | ||
| - name: Fix graphviz for macos-latest | ||
| if: ${{ matrix.os == 'macos-latest' }} | ||
| run: | | ||
| just python=${{ matrix.python-version }} fix-graphviz-test | ||
| - name: Run tests | ||
| run: | | ||
| nox -s tests-${{ matrix.python-version }} --verbose | ||
| just python=${{ matrix.python-version }} test | ||
@@ -76,3 +100,2 @@ - name: Upload test outputs | ||
| - name: Upload coverage to codecov | ||
@@ -83,77 +106,40 @@ uses: codecov/codecov-action@v3 | ||
| file: ./coverage.xml | ||
| fail_ci_if_error: true | ||
| fail_ci_if_error: ${{ (github.event_name == 'push' && true) || (github.event_name == 'pull_request' && true) || false }} | ||
| if: ${{ matrix.os == 'ubuntu-latest' }} | ||
| test-build-and-install: | ||
| name: Build distribution and test installation | ||
| test-distribution: | ||
| name: Test distribution | ||
| needs: code-quality | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| shell: bash -leo pipefail {0} # needed for micromamba environment | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: conda-incubator/setup-miniconda@v3 | ||
| - uses: mamba-org/setup-micromamba@v2 | ||
| with: | ||
| miniforge-version: latest | ||
| activate-environment: "" | ||
| use-mamba: true | ||
| environment-name: test-env | ||
| create-args: >- | ||
| python=3.13 | ||
| graphviz | ||
| - name: Install nox and uv | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| - name: Build distribution | ||
| run: | | ||
| nox -s build | ||
| - name: Test wheel with extras matrix | ||
| run: | | ||
| nox -s test_wheel --verbose | ||
| - name: Test sdist | ||
| run: | | ||
| nox -s test_sdist --verbose | ||
| docs: | ||
| name: Docs preview | ||
| needs: code-quality | ||
| if: github.event.pull_request != null | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: conda-incubator/setup-miniconda@v3 | ||
| - uses: astral-sh/setup-uv@v5 | ||
| with: | ||
| miniforge-version: latest | ||
| activate-environment: "" | ||
| use-mamba: true | ||
| enable-cache: true | ||
| cache-suffix: "test-distr" | ||
| - name: Install nox and uv | ||
| - name: Install | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| uv pip install . | ||
| - name: Test building documentation | ||
| - name: Test | ||
| run: | | ||
| nox -s docs --verbose | ||
| python -m erdantic --version | ||
| python -m erdantic --list-plugins | ||
| python -c "import erdantic; import erdantic.examples; print(erdantic.list_plugins())" | ||
| - name: Deploy site preview to Netlify | ||
| uses: nwtgck/actions-netlify@v1.1 | ||
| with: | ||
| publish-dir: "./docs/site" | ||
| production-deploy: false | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| deploy-message: "Deploy from GitHub Actions" | ||
| enable-pull-request-comment: true | ||
| enable-commit-comment: false | ||
| overwrites-pull-request-comment: true | ||
| alias: deploy-preview-${{ github.event.number }} | ||
| env: | ||
| NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} | ||
| NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} | ||
| timeout-minutes: 1 | ||
| notify: | ||
| name: Notify failed build | ||
| needs: [code-quality, tests, test-build-and-install, docs] | ||
| needs: [code-quality, tests, test-distribution] | ||
| if: failure() && github.event.pull_request == null | ||
@@ -160,0 +146,0 @@ runs-on: ubuntu-latest |
+4
-0
@@ -143,1 +143,5 @@ docs/docs/examples/ | ||
| .pyre/ | ||
| # pixi environments | ||
| .pixi | ||
| *.egg-info |
+31
-18
| # Contributing to erdantic | ||
| ... | ||
| ## Report a bug or request a feature | ||
| Please file an issue in the [issue tracker](https://github.com/drivendataorg/erdantic/issues). | ||
| ## External contributions | ||
| Pull requests from external contributors are welcome. However, we ask that any nontrivial changes be discussed with maintainers in an [issue](https://github.com/drivendataorg/erdantic/issues) first before submitting a pull request. | ||
| ## Local development | ||
| [](https://github.com/wntrblm/nox) | ||
| [![Pixi Badge][https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json&style=flat-square | ||
| ]][[pixi-url](https://pixi.sh)] | ||
| [](https://docs.astral.sh/ruff/) | ||
| [](https://mypy-lang.org/) | ||
| This project is set up using [nox](https://nox.thea.codes/en/stable/) for automation. We recommend you install nox as a global tool with [pipx](https://pipx.pypa.io/): | ||
| This project is set up using [Pixi](https://pixi.sh) for managing environments and [Just](https://github.com/casey/just) as a task runner. | ||
| Many useful recipes are defined in the [`justfile`](./justfile). You can run: | ||
| ```bash | ||
| pipx install nox | ||
| just | ||
| ``` | ||
| Many of the nox sessions are configured to use conda environments. erdantic depends on [graphviz](https://graphviz.org/), a C library, so conda is handy for installing it together alongside the Python dependencies. We recommend you install conda through the [miniforge](https://github.com/conda-forge/miniforge) distribution, which automatically comes with the faster mamba installer. | ||
| to see available recipes with brief documentation. | ||
| ### Development environment | ||
| To create a development environment, run: | ||
| Pixi handles the creation and synchronization of the default development environment. You can run commands in the environment like so: | ||
| ```bash | ||
| nox -s dev | ||
| ``` | ||
| ```bash | ||
| pixi run {some shell command} | ||
| ``` | ||
| This will create a conda environment in `.nox/dev`. You can activate it with: | ||
| You can activate the default environment with | ||
| ```bash | ||
| conda activate .nox/dev | ||
| pixi shell | ||
| ``` | ||
@@ -35,12 +44,16 @@ | ||
| To run the full test matrix on all Python versions, run: | ||
| ```bash | ||
| just test | ||
| ``` | ||
| You can run the tests for a specific Python version with, for example: | ||
| ```bash | ||
| nox -s tests | ||
| just python=3.12 test | ||
| ``` | ||
| To run tests for a specific version, use `tests-{python-version}`, e.g., | ||
| To run tests on all supported Python versions, run: | ||
| ```bash | ||
| nox -s tests-3.11 | ||
| just test-all | ||
| ``` | ||
@@ -50,7 +63,7 @@ | ||
| We use [ruff](https://docs.astral.sh/ruff/) for linting and formatting, and we use [mypy](https://github.com/python/mypy) for type-checking. You can run them with the following nox sessions: | ||
| We use [ruff](https://docs.astral.sh/ruff/) for linting and formatting, and we use [mypy](https://github.com/python/mypy) for static type checking. You can run them with the following commands: | ||
| ```bash | ||
| nox -s lint | ||
| nox -s typecheck | ||
| just lint | ||
| just typecheck | ||
| ``` |
| # erdantic.examples.pydantic | ||
| ::: erdantic.examples.pydantic | ||
| ::: erdantic.examples.pydantic_v1 | ||
| selection: | ||
@@ -5,0 +5,0 @@ filters: |
+2
-2
@@ -26,3 +26,3 @@ import inspect | ||
| readme_text = readme_text.replace( | ||
| "./HISTORY.md", | ||
| "./CHANGELOG.md", | ||
| "changelog.md", | ||
@@ -34,3 +34,3 @@ ) | ||
| def _read_changelog(): | ||
| changelog_path = REPO_ROOT / "HISTORY.md" | ||
| changelog_path = REPO_ROOT / "CHANGELOG.md" | ||
| logger.info("Reading CHANGELOG from %s", changelog_path) | ||
@@ -37,0 +37,0 @@ changelog_text = changelog_path.read_text() |
+6
-1
@@ -18,2 +18,3 @@ site_name: erdantic | ||
| - "Usage Example: dataclasses": "examples/dataclasses.ipynb" | ||
| - "Usage Example: msgspec": "examples/msgspec.ipynb" | ||
| - "Usage Example: Pydantic": "examples/pydantic.ipynb" | ||
@@ -31,2 +32,3 @@ - Advanced Usage: | ||
| - erdantic.examples.dataclasses: "api-reference/examples/dataclasses.md" | ||
| - erdantic.examples.msgspec: "api-reference/examples/msgspec.md" | ||
| - erdantic.examples.pydantic: "api-reference/examples/pydantic.md" | ||
@@ -38,2 +40,3 @@ - erdantic.examples.pydantic_v1: "api-reference/examples/pydantic_v1.md" | ||
| - erdantic.plugins.dataclasses: "api-reference/plugins/dataclasses.md" | ||
| - erdantic.plugins.msgspec: "api-reference/plugins/msgspec.md" | ||
| - erdantic.plugins.pydantic: "api-reference/plugins/pydantic.md" | ||
@@ -65,3 +68,5 @@ - erdantic.typing_utils: "api-reference/typing_utils.md" | ||
| plugins: | ||
| - search | ||
| - search: | ||
| - autorefs: | ||
| resolve_closest: true | ||
| - mkdocs-jupyter: | ||
@@ -68,0 +73,0 @@ execute: false |
@@ -1,11 +0,4 @@ | ||
| import sys | ||
| from functools import cache | ||
| from typing import Type | ||
| if sys.version_info >= (3, 9): | ||
| from functools import cache | ||
| else: | ||
| from functools import lru_cache | ||
| cache = lru_cache(maxsize=None) | ||
| from pydantic import BaseModel | ||
@@ -12,0 +5,0 @@ |
+36
-10
@@ -5,11 +5,5 @@ from enum import Enum | ||
| from pathlib import Path | ||
| import sys | ||
| from types import ModuleType | ||
| from typing import TYPE_CHECKING, List, Optional, Union | ||
| from typing import TYPE_CHECKING, Annotated, List, Optional, Union | ||
| if sys.version_info >= (3, 9): | ||
| from typing import Annotated | ||
| else: | ||
| from typing_extensions import Annotated | ||
| import typer | ||
@@ -21,3 +15,3 @@ | ||
| from erdantic.exceptions import ModelOrModuleNotFoundError | ||
| from erdantic.plugins import list_plugins | ||
| import erdantic.plugins | ||
@@ -40,3 +34,5 @@ app = typer.Typer() | ||
| else: | ||
| AvailablePluginKeys = StrEnum("AvailablePluginKeys", {key: key for key in list_plugins()}) | ||
| AvailablePluginKeys = StrEnum( | ||
| "AvailablePluginKeys", {key: key for key in erdantic.plugins.list_plugins()} | ||
| ) | ||
@@ -60,2 +56,23 @@ | ||
| def list_plugins_callback(list_plugins: bool): | ||
| if list_plugins: | ||
| active_plugins = erdantic.plugins.list_plugins() | ||
| core_plugins = [plugin for plugin, _ in erdantic.plugins.CORE_PLUGINS] | ||
| print(" " * 15 + "ACTIVE PLUGIN NAME") | ||
| print("Core plugins:") | ||
| for plugin in core_plugins: | ||
| if plugin in active_plugins: | ||
| print(" " * 15 + f" [X] {plugin}") | ||
| else: | ||
| print(" " * 15 + f" [ ] {plugin}") | ||
| other_plugins = sorted(set(active_plugins) - set(core_plugins)) | ||
| print("Other plugins:") | ||
| if other_plugins: | ||
| for plugin in other_plugins: | ||
| print(" " * 15 + f" [X] {plugin}") | ||
| else: | ||
| print(" " * 15 + " None found") | ||
| raise typer.Exit() | ||
| @app.command() | ||
@@ -146,2 +163,11 @@ def main( | ||
| ] = 0, | ||
| list_plugins: Annotated[ | ||
| Optional[bool], | ||
| typer.Option( | ||
| "--list-plugins", | ||
| callback=list_plugins_callback, | ||
| is_eager=True, | ||
| help="List active plugins and exit.", | ||
| ), | ||
| ] = False, | ||
| version: Annotated[ | ||
@@ -169,3 +195,3 @@ Optional[bool], | ||
| logger.debug("Registered plugins: %s", ", ".join(list_plugins())) | ||
| logger.debug("Registered plugins: %s", ", ".join(erdantic.plugins.list_plugins())) | ||
@@ -172,0 +198,0 @@ logger.debug("models_or_modules: %s", models_or_modules) |
+4
-4
@@ -17,3 +17,3 @@ from enum import Enum | ||
| import pydantic | ||
| import pygraphviz as pgv # type: ignore [import-not-found] | ||
| import pygraphviz as pgv # type: ignore [import-untyped, import-not-found] | ||
| from sortedcontainers_pydantic import SortedDict | ||
@@ -495,3 +495,3 @@ from typenames import REMOVE_ALL_MODULES, typenames | ||
| EntityRelationshipDiagram class, this is erdantic.core.ModelInfo.""" | ||
| annotation = self.model_fields["models"].annotation | ||
| annotation = type(self).model_fields["models"].annotation | ||
| args = get_args(annotation) | ||
@@ -504,3 +504,3 @@ return args[1] | ||
| EntityRelationshipDiagram class, this is erdantic.core.Edge.""" | ||
| annotation = self.model_fields["edges"].annotation | ||
| annotation = type(self).model_fields["edges"].annotation | ||
| args = get_args(annotation) | ||
@@ -527,3 +527,3 @@ return args[1] | ||
| self.models[key] = model_info | ||
| logger.debug("Sucessfully added model '%s'.", key) | ||
| logger.debug("Successfully added model '%s'.", key) | ||
| if recurse: | ||
@@ -530,0 +530,0 @@ logger.debug("Searching fields of '%s' for other models...", key) |
@@ -20,3 +20,9 @@ import importlib.metadata | ||
| CORE_PLUGINS = ("pydantic", "attrs", "dataclasses") | ||
| CORE_PLUGINS = ( | ||
| ("pydantic", "erdantic.plugins.pydantic"), | ||
| ("pydantic_v1", "erdantic.plugins.pydantic"), | ||
| ("attrs", "erdantic.plugins.attrs"), | ||
| ("dataclasses", "erdantic.plugins.dataclasses"), | ||
| ("msgspec", "erdantic.plugins.msgspec"), | ||
| ) | ||
@@ -29,6 +35,6 @@ _ModelType = TypeVar("_ModelType", bound=type) | ||
| def load_plugins(): | ||
| for plugin in CORE_PLUGINS: | ||
| for plugin, module in CORE_PLUGINS: | ||
| logger.debug("Loading plugin: %s", plugin) | ||
| try: | ||
| importlib.import_module(f"erdantic.plugins.{plugin}") | ||
| importlib.import_module(module) | ||
| logger.debug("Plugin successfully loaded: %s", plugin) | ||
@@ -35,0 +41,0 @@ except ModuleNotFoundError: |
| import dataclasses | ||
| import re | ||
| import sys | ||
| from typing import TYPE_CHECKING, Any, List, Type, get_type_hints | ||
| from typing import TYPE_CHECKING, Any, List, Type, cast, get_type_hints | ||
| if sys.version_info >= (3, 9): | ||
| # include_extras was added in Python 3.9 | ||
| from typing import get_type_hints | ||
| else: | ||
| from typing_extensions import get_type_hints | ||
| if sys.version_info >= (3, 10): | ||
@@ -72,3 +66,3 @@ from typing import TypeGuard | ||
| name=f.name, | ||
| raw_type=f.type, | ||
| raw_type=cast(type, f.type), # cast narrows type for typechecking | ||
| ) | ||
@@ -75,0 +69,0 @@ for f in dataclasses.fields(model) |
+8
-8
@@ -1,4 +0,4 @@ | ||
| Metadata-Version: 2.3 | ||
| Metadata-Version: 2.4 | ||
| Name: erdantic | ||
| Version: 1.0.5 | ||
| Version: 1.1.0 | ||
| Summary: Entity relationship diagrams for Python data model classes like Pydantic. | ||
@@ -13,3 +13,3 @@ Project-URL: Repository, https://github.com/drivendataorg/erdantic | ||
| License-File: LICENSE | ||
| Keywords: attrs,dataclasses,entity relationship diagram,erd,pydantic | ||
| Keywords: attrs,dataclasses,entity relationship diagram,erd,msgspec,pydantic | ||
| Classifier: Framework :: Pydantic | ||
@@ -21,3 +21,2 @@ Classifier: Framework :: Pydantic :: 2 | ||
| Classifier: Programming Language :: Python :: 3 | ||
| Classifier: Programming Language :: Python :: 3.8 | ||
| Classifier: Programming Language :: Python :: 3.9 | ||
@@ -27,4 +26,5 @@ Classifier: Programming Language :: Python :: 3.10 | ||
| Classifier: Programming Language :: Python :: 3.12 | ||
| Classifier: Programming Language :: Python :: 3.13 | ||
| Classifier: Topic :: Software Development :: Code Generators | ||
| Requires-Python: >=3.8 | ||
| Requires-Python: >=3.9 | ||
| Requires-Dist: pydantic-core | ||
@@ -39,2 +39,4 @@ Requires-Dist: pydantic>=2 | ||
| Requires-Dist: attrs; extra == 'attrs' | ||
| Provides-Extra: msgspec | ||
| Requires-Dist: msgspec; extra == 'msgspec' | ||
| Description-Content-Type: text/markdown | ||
@@ -51,5 +53,2 @@ | ||
| > [!NOTE] | ||
| > erdantic v1.0 has been released! See the [changelog](./HISTORY.md) for more information. | ||
| **erdantic** is a simple tool for drawing [entity relationship diagrams (ERDs)](https://en.wikipedia.org/wiki/Data_modeling#Entity%E2%80%93relationship_diagrams) for Python data model classes. Diagrams are rendered using the venerable [Graphviz](https://graphviz.org/) library. Supported data modeling frameworks are: | ||
@@ -60,2 +59,3 @@ | ||
| - [attrs](https://www.attrs.org/en/stable/) | ||
| - [msgspec](https://jcristharif.com/msgspec/) | ||
| - [dataclasses](https://docs.python.org/3/library/dataclasses.html) from the Python standard library | ||
@@ -62,0 +62,0 @@ |
+79
-8
@@ -1,8 +0,4 @@ | ||
| [build-system] | ||
| requires = ["hatchling"] | ||
| build-backend = "hatchling.build" | ||
| [project] | ||
| name = "erdantic" | ||
| version = "1.0.5" | ||
| version = "1.1.0" | ||
| description = "Entity relationship diagrams for Python data model classes like Pydantic." | ||
@@ -12,3 +8,3 @@ readme = "README.md" | ||
| license = { text = "MIT License" } | ||
| keywords = ["erd", "entity relationship diagram", "dataclasses", "pydantic", "attrs"] | ||
| keywords = ["erd", "entity relationship diagram", "dataclasses", "pydantic", "attrs", "msgspec"] | ||
| classifiers = [ | ||
@@ -20,3 +16,2 @@ "Intended Audience :: Developers", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.8", | ||
| "Programming Language :: Python :: 3.9", | ||
@@ -26,6 +21,7 @@ "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Python :: 3.13", | ||
| "Framework :: Pydantic", | ||
| "Framework :: Pydantic :: 2", | ||
| ] | ||
| requires-python = ">=3.8" | ||
| requires-python = ">=3.9" | ||
| dependencies = [ | ||
@@ -43,2 +39,3 @@ "pydantic >= 2", | ||
| attrs = ["attrs"] | ||
| msgspec = ["msgspec"] | ||
@@ -54,2 +51,76 @@ [project.scripts] | ||
| [build-system] | ||
| requires = ["hatchling"] | ||
| build-backend = "hatchling.build" | ||
| ## DEV | ||
| [dependency-groups] | ||
| dev = [ | ||
| { include-group = "lint" }, | ||
| { include-group = "docs" }, | ||
| "build", | ||
| "ipython", | ||
| "vspect", | ||
| ] | ||
| docs = [ | ||
| "black", | ||
| "markdown-callouts>=0.4.0", | ||
| "mdx_truly_sane_lists==1.3", | ||
| "mike", | ||
| "mkdocs>=1.4", | ||
| "mkdocs-jupyter", | ||
| "mkdocs-material>=7.2.6", | ||
| "mkdocstrings[python]>=0.19.0", | ||
| "nbconvert>=7.7.0", | ||
| "rich", | ||
| ] | ||
| lint = [ | ||
| "ruff>=0.1.14", | ||
| ] | ||
| test = [ | ||
| "filetype", | ||
| "ipython", | ||
| "pytest<8", | ||
| "pytest-cases", | ||
| "pytest-cov", | ||
| "rich", | ||
| ] | ||
| typecheck = [ | ||
| "mypy", | ||
| "pip", | ||
| ] | ||
| [tool.pixi.project] | ||
| channels = ["conda-forge"] | ||
| platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"] | ||
| [tool.pixi.dependencies] | ||
| graphviz = "==12.2.1" | ||
| [tool.pixi.pypi-dependencies] | ||
| erdantic = { path = ".", editable = true, extras = ["attrs", "msgspec"] } | ||
| [tool.pixi.feature.py39.dependencies] | ||
| python = "3.9.*" | ||
| [tool.pixi.feature.py310.dependencies] | ||
| python = "3.10.*" | ||
| [tool.pixi.feature.py311.dependencies] | ||
| python = "3.11.*" | ||
| [tool.pixi.feature.py312.dependencies] | ||
| python = "3.12.*" | ||
| [tool.pixi.feature.py313.dependencies] | ||
| python = "3.13.*" | ||
| [tool.pixi.environments] | ||
| default = ["py313", "dev"] | ||
| test-py39 = ["py39", "test"] | ||
| test-py310 = ["py310", "test"] | ||
| test-py311 = ["py311", "test"] | ||
| test-py312 = ["py312", "test"] | ||
| test-py313 = ["py313", "test"] | ||
| typecheck = ["py313", "typecheck"] | ||
| ## TOOLS | ||
| [tool.ruff] | ||
@@ -56,0 +127,0 @@ line-length = 99 |
+1
-3
@@ -10,5 +10,2 @@ # erdantic: Entity Relationship Diagrams | ||
| > [!NOTE] | ||
| > erdantic v1.0 has been released! See the [changelog](./HISTORY.md) for more information. | ||
| **erdantic** is a simple tool for drawing [entity relationship diagrams (ERDs)](https://en.wikipedia.org/wiki/Data_modeling#Entity%E2%80%93relationship_diagrams) for Python data model classes. Diagrams are rendered using the venerable [Graphviz](https://graphviz.org/) library. Supported data modeling frameworks are: | ||
@@ -19,2 +16,3 @@ | ||
| - [attrs](https://www.attrs.org/en/stable/) | ||
| - [msgspec](https://jcristharif.com/msgspec/) | ||
| - [dataclasses](https://docs.python.org/3/library/dataclasses.html) from the Python standard library | ||
@@ -21,0 +19,0 @@ |
+90
-90
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | ||
| "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| <!-- Generated by graphviz version 9.0.0 (0) | ||
| <!-- Generated by graphviz version 12.2.1 (0) | ||
| --> | ||
| <!-- Title: Entity Relationship Diagram created by erdantic Pages: 1 --> | ||
| <svg width="686pt" height="309pt" | ||
| viewBox="0.00 0.00 686.00 308.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.5)"> | ||
| <svg width="689pt" height="314pt" | ||
| viewBox="0.00 0.00 689.00 313.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 309.75)"> | ||
| <title>Entity Relationship Diagram created by erdantic</title> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-304.5 682,-304.5 682,4 -4,4"/> | ||
| <text text-anchor="middle" x="339" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-309.75 685,-309.75 685,4 -4,4"/> | ||
| <text text-anchor="middle" x="340.5" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <!-- erdantic.examples.attrs.Adventurer --> | ||
@@ -17,20 +17,20 @@ <g id="node1" class="node"> | ||
| <g id="a_node1"><a xlink:title="erdantic.examples.attrs.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:    name (str): Name of this adventurer    profession (str): Profession of this adventurer    level (int): Level of this adventurer    alignment (Alignment): Alignment of this adventurer "> | ||
| <polygon fill="none" stroke="black" points="312,-274.5 312,-296.5 438,-296.5 438,-274.5 312,-274.5"/> | ||
| <text text-anchor="start" x="341.25" y="-281.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="312,-252.5 312,-274.5 374,-274.5 374,-252.5 312,-252.5"/> | ||
| <text text-anchor="start" x="328" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="374,-252.5 374,-274.5 438,-274.5 438,-252.5 374,-252.5"/> | ||
| <text text-anchor="start" x="399.25" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-230.5 312,-252.5 374,-252.5 374,-230.5 312,-230.5"/> | ||
| <text text-anchor="start" x="314.88" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="374,-230.5 374,-252.5 438,-252.5 438,-230.5 374,-230.5"/> | ||
| <text text-anchor="start" x="399.25" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-208.5 312,-230.5 374,-230.5 374,-208.5 312,-208.5"/> | ||
| <text text-anchor="start" x="315.62" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="374,-208.5 374,-230.5 438,-230.5 438,-208.5 374,-208.5"/> | ||
| <text text-anchor="start" x="376.75" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="312,-186.5 312,-208.5 374,-208.5 374,-186.5 312,-186.5"/> | ||
| <text text-anchor="start" x="329.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="374,-186.5 374,-208.5 438,-208.5 438,-186.5 374,-186.5"/> | ||
| <text text-anchor="start" x="398.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-279.25 313.12,-301.75 439.88,-301.75 439.88,-279.25 313.12,-279.25"/> | ||
| <text text-anchor="start" x="342.75" y="-286.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-256.75 313.12,-279.25 375.38,-279.25 375.38,-256.75 313.12,-256.75"/> | ||
| <text text-anchor="start" x="329.25" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-256.75 375.38,-279.25 439.88,-279.25 439.88,-256.75 375.38,-256.75"/> | ||
| <text text-anchor="start" x="400.88" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-234.25 313.12,-256.75 375.38,-256.75 375.38,-234.25 313.12,-234.25"/> | ||
| <text text-anchor="start" x="316.12" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-234.25 375.38,-256.75 439.88,-256.75 439.88,-234.25 375.38,-234.25"/> | ||
| <text text-anchor="start" x="400.88" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-211.75 313.12,-234.25 375.38,-234.25 375.38,-211.75 313.12,-211.75"/> | ||
| <text text-anchor="start" x="316.88" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-211.75 375.38,-234.25 439.88,-234.25 439.88,-211.75 375.38,-211.75"/> | ||
| <text text-anchor="start" x="378.38" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-189.25 313.12,-211.75 375.38,-211.75 375.38,-189.25 313.12,-189.25"/> | ||
| <text text-anchor="start" x="331.12" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-189.25 375.38,-211.75 439.88,-211.75 439.88,-189.25 375.38,-189.25"/> | ||
| <text text-anchor="start" x="400.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -43,20 +43,20 @@ </g> | ||
| <g id="a_node2"><a xlink:title="erdantic.examples.attrs.Party A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes:    name (str): Name that party is known by    formed_datetime (datetime): Timestamp of when the party was formed    members (List[Adventurer]): Adventurers that belong to this party    active_quest (Optional[Quest]): Current quest that party is actively tackling "> | ||
| <polygon fill="none" stroke="black" points="0,-278.5 0,-300.5 196,-300.5 196,-278.5 0,-278.5"/> | ||
| <text text-anchor="start" x="81.88" y="-285.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-256.5 0,-278.5 99,-278.5 99,-256.5 0,-256.5"/> | ||
| <text text-anchor="start" x="34.5" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99,-256.5 99,-278.5 196,-278.5 196,-256.5 99,-256.5"/> | ||
| <text text-anchor="start" x="140.75" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-234.5 0,-256.5 99,-256.5 99,-234.5 0,-234.5"/> | ||
| <text text-anchor="start" x="2.62" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99,-234.5 99,-256.5 196,-256.5 196,-234.5 99,-234.5"/> | ||
| <text text-anchor="start" x="123.88" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-212.5 0,-234.5 99,-234.5 99,-212.5 0,-212.5"/> | ||
| <text text-anchor="start" x="24" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99,-212.5 99,-234.5 196,-234.5 196,-212.5 99,-212.5"/> | ||
| <text text-anchor="start" x="101.75" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-190.5 0,-212.5 99,-212.5 99,-190.5 0,-190.5"/> | ||
| <text text-anchor="start" x="15.75" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99,-190.5 99,-212.5 196,-212.5 196,-190.5 99,-190.5"/> | ||
| <text text-anchor="start" x="103.62" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="0,-283.25 0,-305.75 197.25,-305.75 197.25,-283.25 0,-283.25"/> | ||
| <text text-anchor="start" x="82.5" y="-290.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-260.75 0,-283.25 99.75,-283.25 99.75,-260.75 0,-260.75"/> | ||
| <text text-anchor="start" x="34.88" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-260.75 99.75,-283.25 197.25,-283.25 197.25,-260.75 99.75,-260.75"/> | ||
| <text text-anchor="start" x="141.75" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-238.25 0,-260.75 99.75,-260.75 99.75,-238.25 0,-238.25"/> | ||
| <text text-anchor="start" x="3" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-238.25 99.75,-260.75 197.25,-260.75 197.25,-238.25 99.75,-238.25"/> | ||
| <text text-anchor="start" x="124.88" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-215.75 0,-238.25 99.75,-238.25 99.75,-215.75 0,-215.75"/> | ||
| <text text-anchor="start" x="24.38" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-215.75 99.75,-238.25 197.25,-238.25 197.25,-215.75 99.75,-215.75"/> | ||
| <text text-anchor="start" x="102.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-193.25 0,-215.75 99.75,-215.75 99.75,-193.25 0,-193.25"/> | ||
| <text text-anchor="start" x="16.12" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-193.25 99.75,-215.75 197.25,-215.75 197.25,-193.25 99.75,-193.25"/> | ||
| <text text-anchor="start" x="104.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| </a> | ||
@@ -68,7 +68,7 @@ </g> | ||
| <title>erdantic.examples.attrs.Party:e->erdantic.examples.attrs.Adventurer:w</title> | ||
| <path fill="none" stroke="black" d="M205.92,-224.15C249.25,-230.11 255.51,-274.88 295.89,-283.91"/> | ||
| <polyline fill="none" stroke="black" points="196,-223.5 200.99,-223.83"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-223.83 205.98,-224.16"/> | ||
| <polygon fill="black" stroke="black" points="300.72,-284.42 310.2,-289.94 306.03,-284.98 310.33,-285.43 310.33,-285.43 310.33,-285.43 306.03,-284.98 311.14,-280.99 300.72,-284.42"/> | ||
| <polyline fill="none" stroke="black" points="299.51,-284.29 294.54,-283.77"/> | ||
| <path fill="none" stroke="black" d="M207.21,-227.67C250.68,-233.77 256.49,-279.62 296.96,-288.88"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-227 202.24,-227.34"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-227.34 207.23,-227.67"/> | ||
| <polygon fill="black" stroke="black" points="301.85,-289.4 311.31,-294.94 307.15,-289.97 311.46,-290.43 311.46,-290.43 311.46,-290.43 307.15,-289.97 312.27,-285.99 301.85,-289.4"/> | ||
| <polyline fill="none" stroke="black" points="300.64,-289.27 295.67,-288.74"/> | ||
| </g> | ||
@@ -79,16 +79,16 @@ <!-- erdantic.examples.attrs.Quest --> | ||
| <g id="a_node3"><a xlink:title="erdantic.examples.attrs.Quest A task to complete, with some monetary reward. Attributes:    name (str): Name by which this quest is referred to    giver (QuestGiver): Person who offered the quest    reward_gold (int): Amount of gold to be rewarded for quest completion "> | ||
| <polygon fill="none" stroke="black" points="304,-128.5 304,-150.5 446,-150.5 446,-128.5 304,-128.5"/> | ||
| <text text-anchor="start" x="357.75" y="-135.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="304,-106.5 304,-128.5 378,-128.5 378,-106.5 304,-106.5"/> | ||
| <text text-anchor="start" x="326" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="378,-106.5 378,-128.5 446,-128.5 446,-106.5 378,-106.5"/> | ||
| <text text-anchor="start" x="405.25" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="304,-84.5 304,-106.5 378,-106.5 378,-84.5 304,-84.5"/> | ||
| <text text-anchor="start" x="327.12" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="378,-84.5 378,-106.5 446,-106.5 446,-84.5 378,-84.5"/> | ||
| <text text-anchor="start" x="380.88" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="304,-62.5 304,-84.5 378,-84.5 378,-62.5 304,-62.5"/> | ||
| <text text-anchor="start" x="306.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="378,-62.5 378,-84.5 446,-84.5 446,-62.5 378,-62.5"/> | ||
| <text text-anchor="start" x="404.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-131 305.25,-153.5 447.75,-153.5 447.75,-131 305.25,-131"/> | ||
| <text text-anchor="start" x="359.25" y="-138.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-108.5 305.25,-131 379.5,-131 379.5,-108.5 305.25,-108.5"/> | ||
| <text text-anchor="start" x="327.38" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-108.5 379.5,-131 447.75,-131 447.75,-108.5 379.5,-108.5"/> | ||
| <text text-anchor="start" x="406.88" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-86 305.25,-108.5 379.5,-108.5 379.5,-86 305.25,-86"/> | ||
| <text text-anchor="start" x="328.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-86 379.5,-108.5 447.75,-108.5 447.75,-86 379.5,-86"/> | ||
| <text text-anchor="start" x="382.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-63.5 305.25,-86 379.5,-86 379.5,-63.5 305.25,-63.5"/> | ||
| <text text-anchor="start" x="308.25" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-63.5 379.5,-86 447.75,-86 447.75,-63.5 379.5,-63.5"/> | ||
| <text text-anchor="start" x="406.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -100,9 +100,9 @@ </g> | ||
| <title>erdantic.examples.attrs.Party:e->erdantic.examples.attrs.Quest:w</title> | ||
| <path fill="none" stroke="black" d="M205.73,-200.8C245.01,-194.92 251.04,-153.51 285.33,-142.29"/> | ||
| <polyline fill="none" stroke="black" points="196,-201.5 200.99,-201.14"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-201.14 205.97,-200.79"/> | ||
| <polyline fill="none" stroke="black" points="304,-139.5 299.06,-140.24"/> | ||
| <polygon fill="black" stroke="black" points="297.33,-135.44 298.81,-145.33 296.83,-145.63 295.35,-135.74 297.33,-135.44"/> | ||
| <polyline fill="none" stroke="black" points="299.06,-140.24 294.11,-140.98"/> | ||
| <ellipse fill="none" stroke="black" cx="289.66" cy="-141.65" rx="4" ry="4"/> | ||
| <path fill="none" stroke="black" d="M206.98,-203.8C246.3,-197.9 252.26,-156.32 286.57,-145.06"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-204.5 202.24,-204.14"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-204.14 207.22,-203.78"/> | ||
| <polyline fill="none" stroke="black" points="305.25,-142.25 300.31,-142.99"/> | ||
| <polygon fill="black" stroke="black" points="298.57,-138.2 300.06,-148.09 298.08,-148.38 296.6,-138.49 298.57,-138.2"/> | ||
| <polyline fill="none" stroke="black" points="300.31,-142.99 295.36,-143.74"/> | ||
| <ellipse fill="none" stroke="black" cx="290.91" cy="-144.4" rx="4" ry="4"/> | ||
| </g> | ||
@@ -113,16 +113,16 @@ <!-- erdantic.examples.attrs.QuestGiver --> | ||
| <g id="a_node4"><a xlink:title="erdantic.examples.attrs.QuestGiver A person who offers a task that needs completing. Attributes:    name (str): Name of this quest giver    faction (str): Faction that this quest giver belongs to    location (str): Location this quest giver can be found "> | ||
| <polygon fill="none" stroke="black" points="554,-84.5 554,-106.5 678,-106.5 678,-84.5 554,-84.5"/> | ||
| <text text-anchor="start" x="581.88" y="-91.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="554,-62.5 554,-84.5 603,-84.5 603,-62.5 554,-62.5"/> | ||
| <text text-anchor="start" x="563.5" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="603,-62.5 603,-84.5 678,-84.5 678,-62.5 603,-62.5"/> | ||
| <text text-anchor="start" x="633.75" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="554,-40.5 554,-62.5 603,-62.5 603,-40.5 554,-40.5"/> | ||
| <text text-anchor="start" x="559.75" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="603,-40.5 603,-62.5 678,-62.5 678,-40.5 603,-40.5"/> | ||
| <text text-anchor="start" x="605.62" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="554,-18.5 554,-40.5 603,-40.5 603,-18.5 554,-18.5"/> | ||
| <text text-anchor="start" x="556.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="603,-18.5 603,-40.5 678,-40.5 678,-18.5 603,-18.5"/> | ||
| <text text-anchor="start" x="633.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-86 555.75,-108.5 681,-108.5 681,-86 555.75,-86"/> | ||
| <text text-anchor="start" x="584.25" y="-93.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-63.5 555.75,-86 605.25,-86 605.25,-63.5 555.75,-63.5"/> | ||
| <text text-anchor="start" x="565.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-63.5 605.25,-86 681,-86 681,-63.5 605.25,-63.5"/> | ||
| <text text-anchor="start" x="636.38" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-41 555.75,-63.5 605.25,-63.5 605.25,-41 555.75,-41"/> | ||
| <text text-anchor="start" x="561.75" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-41 605.25,-63.5 681,-63.5 681,-41 605.25,-41"/> | ||
| <text text-anchor="start" x="608.25" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-18.5 555.75,-41 605.25,-41 605.25,-18.5 555.75,-18.5"/> | ||
| <text text-anchor="start" x="558.75" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-18.5 605.25,-41 681,-41 681,-18.5 605.25,-18.5"/> | ||
| <text text-anchor="start" x="636.38" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| </a> | ||
@@ -134,12 +134,12 @@ </g> | ||
| <title>erdantic.examples.attrs.Quest:e->erdantic.examples.attrs.QuestGiver:w</title> | ||
| <path fill="none" stroke="black" d="M455.87,-95.5C491.07,-95.5 505.8,-95.5 539.08,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="446,-95.5 451,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="451,-95.5 456,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="554,-95.5 549,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="548,-90.5 548,-100.5 546,-100.5 546,-90.5 548,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="549,-95.5 544,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="543,-90.5 543,-100.5 541,-100.5 541,-90.5 543,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="544,-95.5 539,-95.5"/> | ||
| <path fill="none" stroke="black" d="M457.62,-97.25C492.82,-97.25 507.55,-97.25 540.83,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="447.75,-97.25 452.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="452.75,-97.25 457.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="555.75,-97.25 550.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="549.75,-92.25 549.75,-102.25 547.75,-102.25 547.75,-92.25 549.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="550.75,-97.25 545.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="544.75,-92.25 544.75,-102.25 542.75,-102.25 542.75,-92.25 544.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="545.75,-97.25 540.75,-97.25"/> | ||
| </g> | ||
| </g> | ||
| </svg> |
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | ||
| "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| <!-- Generated by graphviz version 9.0.0 (0) | ||
| <!-- Generated by graphviz version 12.2.1 (0) | ||
| --> | ||
| <!-- Title: Entity Relationship Diagram created by erdantic Pages: 1 --> | ||
| <svg width="686pt" height="309pt" | ||
| viewBox="0.00 0.00 686.00 308.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.5)"> | ||
| <svg width="689pt" height="314pt" | ||
| viewBox="0.00 0.00 689.00 313.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 309.75)"> | ||
| <title>Entity Relationship Diagram created by erdantic</title> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-304.5 682,-304.5 682,4 -4,4"/> | ||
| <text text-anchor="middle" x="339" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-309.75 685,-309.75 685,4 -4,4"/> | ||
| <text text-anchor="middle" x="340.5" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <!-- erdantic.examples.dataclasses.Adventurer --> | ||
@@ -17,20 +17,20 @@ <g id="node1" class="node"> | ||
| <g id="a_node1"><a xlink:title="erdantic.examples.dataclasses.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:    name (str): Name of this adventurer    profession (str): Profession of this adventurer    alignment (Alignment): Alignment of this adventurer    level (int): Level of this adventurer "> | ||
| <polygon fill="none" stroke="black" points="312,-274.5 312,-296.5 438,-296.5 438,-274.5 312,-274.5"/> | ||
| <text text-anchor="start" x="341.25" y="-281.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="312,-252.5 312,-274.5 374,-274.5 374,-252.5 312,-252.5"/> | ||
| <text text-anchor="start" x="328" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="374,-252.5 374,-274.5 438,-274.5 438,-252.5 374,-252.5"/> | ||
| <text text-anchor="start" x="399.25" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-230.5 312,-252.5 374,-252.5 374,-230.5 312,-230.5"/> | ||
| <text text-anchor="start" x="314.88" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="374,-230.5 374,-252.5 438,-252.5 438,-230.5 374,-230.5"/> | ||
| <text text-anchor="start" x="399.25" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-208.5 312,-230.5 374,-230.5 374,-208.5 312,-208.5"/> | ||
| <text text-anchor="start" x="315.62" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="374,-208.5 374,-230.5 438,-230.5 438,-208.5 374,-208.5"/> | ||
| <text text-anchor="start" x="376.75" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="312,-186.5 312,-208.5 374,-208.5 374,-186.5 312,-186.5"/> | ||
| <text text-anchor="start" x="329.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="374,-186.5 374,-208.5 438,-208.5 438,-186.5 374,-186.5"/> | ||
| <text text-anchor="start" x="398.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-279.25 313.12,-301.75 439.88,-301.75 439.88,-279.25 313.12,-279.25"/> | ||
| <text text-anchor="start" x="342.75" y="-286.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-256.75 313.12,-279.25 375.38,-279.25 375.38,-256.75 313.12,-256.75"/> | ||
| <text text-anchor="start" x="329.25" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-256.75 375.38,-279.25 439.88,-279.25 439.88,-256.75 375.38,-256.75"/> | ||
| <text text-anchor="start" x="400.88" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-234.25 313.12,-256.75 375.38,-256.75 375.38,-234.25 313.12,-234.25"/> | ||
| <text text-anchor="start" x="316.12" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-234.25 375.38,-256.75 439.88,-256.75 439.88,-234.25 375.38,-234.25"/> | ||
| <text text-anchor="start" x="400.88" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-211.75 313.12,-234.25 375.38,-234.25 375.38,-211.75 313.12,-211.75"/> | ||
| <text text-anchor="start" x="316.88" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-211.75 375.38,-234.25 439.88,-234.25 439.88,-211.75 375.38,-211.75"/> | ||
| <text text-anchor="start" x="378.38" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-189.25 313.12,-211.75 375.38,-211.75 375.38,-189.25 313.12,-189.25"/> | ||
| <text text-anchor="start" x="331.12" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-189.25 375.38,-211.75 439.88,-211.75 439.88,-189.25 375.38,-189.25"/> | ||
| <text text-anchor="start" x="400.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -43,20 +43,20 @@ </g> | ||
| <g id="a_node2"><a xlink:title="erdantic.examples.dataclasses.Party A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes:    name (str): Name that party is known by    formed_datetime (datetime): Timestamp of when the party was formed    members (List[Adventurer]): Adventurers that belong to this party    active_quest (Optional[Quest]): Current quest that party is actively tackling "> | ||
| <polygon fill="none" stroke="black" points="0,-278.5 0,-300.5 196,-300.5 196,-278.5 0,-278.5"/> | ||
| <text text-anchor="start" x="81.88" y="-285.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-256.5 0,-278.5 99,-278.5 99,-256.5 0,-256.5"/> | ||
| <text text-anchor="start" x="34.5" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99,-256.5 99,-278.5 196,-278.5 196,-256.5 99,-256.5"/> | ||
| <text text-anchor="start" x="140.75" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-234.5 0,-256.5 99,-256.5 99,-234.5 0,-234.5"/> | ||
| <text text-anchor="start" x="2.62" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99,-234.5 99,-256.5 196,-256.5 196,-234.5 99,-234.5"/> | ||
| <text text-anchor="start" x="123.88" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-212.5 0,-234.5 99,-234.5 99,-212.5 0,-212.5"/> | ||
| <text text-anchor="start" x="24" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99,-212.5 99,-234.5 196,-234.5 196,-212.5 99,-212.5"/> | ||
| <text text-anchor="start" x="101.75" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-190.5 0,-212.5 99,-212.5 99,-190.5 0,-190.5"/> | ||
| <text text-anchor="start" x="15.75" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99,-190.5 99,-212.5 196,-212.5 196,-190.5 99,-190.5"/> | ||
| <text text-anchor="start" x="103.62" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="0,-283.25 0,-305.75 197.25,-305.75 197.25,-283.25 0,-283.25"/> | ||
| <text text-anchor="start" x="82.5" y="-290.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-260.75 0,-283.25 99.75,-283.25 99.75,-260.75 0,-260.75"/> | ||
| <text text-anchor="start" x="34.88" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-260.75 99.75,-283.25 197.25,-283.25 197.25,-260.75 99.75,-260.75"/> | ||
| <text text-anchor="start" x="141.75" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-238.25 0,-260.75 99.75,-260.75 99.75,-238.25 0,-238.25"/> | ||
| <text text-anchor="start" x="3" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-238.25 99.75,-260.75 197.25,-260.75 197.25,-238.25 99.75,-238.25"/> | ||
| <text text-anchor="start" x="124.88" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-215.75 0,-238.25 99.75,-238.25 99.75,-215.75 0,-215.75"/> | ||
| <text text-anchor="start" x="24.38" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-215.75 99.75,-238.25 197.25,-238.25 197.25,-215.75 99.75,-215.75"/> | ||
| <text text-anchor="start" x="102.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-193.25 0,-215.75 99.75,-215.75 99.75,-193.25 0,-193.25"/> | ||
| <text text-anchor="start" x="16.12" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-193.25 99.75,-215.75 197.25,-215.75 197.25,-193.25 99.75,-193.25"/> | ||
| <text text-anchor="start" x="104.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| </a> | ||
@@ -68,7 +68,7 @@ </g> | ||
| <title>erdantic.examples.dataclasses.Party:e->erdantic.examples.dataclasses.Adventurer:w</title> | ||
| <path fill="none" stroke="black" d="M205.92,-224.15C249.25,-230.11 255.51,-274.88 295.89,-283.91"/> | ||
| <polyline fill="none" stroke="black" points="196,-223.5 200.99,-223.83"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-223.83 205.98,-224.16"/> | ||
| <polygon fill="black" stroke="black" points="300.72,-284.42 310.2,-289.94 306.03,-284.98 310.33,-285.43 310.33,-285.43 310.33,-285.43 306.03,-284.98 311.14,-280.99 300.72,-284.42"/> | ||
| <polyline fill="none" stroke="black" points="299.51,-284.29 294.54,-283.77"/> | ||
| <path fill="none" stroke="black" d="M207.21,-227.67C250.68,-233.77 256.49,-279.62 296.96,-288.88"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-227 202.24,-227.34"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-227.34 207.23,-227.67"/> | ||
| <polygon fill="black" stroke="black" points="301.85,-289.4 311.31,-294.94 307.15,-289.97 311.46,-290.43 311.46,-290.43 311.46,-290.43 307.15,-289.97 312.27,-285.99 301.85,-289.4"/> | ||
| <polyline fill="none" stroke="black" points="300.64,-289.27 295.67,-288.74"/> | ||
| </g> | ||
@@ -79,16 +79,16 @@ <!-- erdantic.examples.dataclasses.Quest --> | ||
| <g id="a_node3"><a xlink:title="erdantic.examples.dataclasses.Quest A task to complete, with some monetary reward. Attributes:    name (str): Name by which this quest is referred to    giver (QuestGiver): Person who offered the quest    reward_gold (int): Amount of gold to be rewarded for quest completion "> | ||
| <polygon fill="none" stroke="black" points="304,-128.5 304,-150.5 446,-150.5 446,-128.5 304,-128.5"/> | ||
| <text text-anchor="start" x="357.75" y="-135.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="304,-106.5 304,-128.5 378,-128.5 378,-106.5 304,-106.5"/> | ||
| <text text-anchor="start" x="326" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="378,-106.5 378,-128.5 446,-128.5 446,-106.5 378,-106.5"/> | ||
| <text text-anchor="start" x="405.25" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="304,-84.5 304,-106.5 378,-106.5 378,-84.5 304,-84.5"/> | ||
| <text text-anchor="start" x="327.12" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="378,-84.5 378,-106.5 446,-106.5 446,-84.5 378,-84.5"/> | ||
| <text text-anchor="start" x="380.88" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="304,-62.5 304,-84.5 378,-84.5 378,-62.5 304,-62.5"/> | ||
| <text text-anchor="start" x="306.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="378,-62.5 378,-84.5 446,-84.5 446,-62.5 378,-62.5"/> | ||
| <text text-anchor="start" x="404.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-131 305.25,-153.5 447.75,-153.5 447.75,-131 305.25,-131"/> | ||
| <text text-anchor="start" x="359.25" y="-138.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-108.5 305.25,-131 379.5,-131 379.5,-108.5 305.25,-108.5"/> | ||
| <text text-anchor="start" x="327.38" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-108.5 379.5,-131 447.75,-131 447.75,-108.5 379.5,-108.5"/> | ||
| <text text-anchor="start" x="406.88" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-86 305.25,-108.5 379.5,-108.5 379.5,-86 305.25,-86"/> | ||
| <text text-anchor="start" x="328.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-86 379.5,-108.5 447.75,-108.5 447.75,-86 379.5,-86"/> | ||
| <text text-anchor="start" x="382.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-63.5 305.25,-86 379.5,-86 379.5,-63.5 305.25,-63.5"/> | ||
| <text text-anchor="start" x="308.25" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-63.5 379.5,-86 447.75,-86 447.75,-63.5 379.5,-63.5"/> | ||
| <text text-anchor="start" x="406.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -100,9 +100,9 @@ </g> | ||
| <title>erdantic.examples.dataclasses.Party:e->erdantic.examples.dataclasses.Quest:w</title> | ||
| <path fill="none" stroke="black" d="M205.73,-200.8C245.01,-194.92 251.04,-153.51 285.33,-142.29"/> | ||
| <polyline fill="none" stroke="black" points="196,-201.5 200.99,-201.14"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-201.14 205.97,-200.79"/> | ||
| <polyline fill="none" stroke="black" points="304,-139.5 299.06,-140.24"/> | ||
| <polygon fill="black" stroke="black" points="297.33,-135.44 298.81,-145.33 296.83,-145.63 295.35,-135.74 297.33,-135.44"/> | ||
| <polyline fill="none" stroke="black" points="299.06,-140.24 294.11,-140.98"/> | ||
| <ellipse fill="none" stroke="black" cx="289.66" cy="-141.65" rx="4" ry="4"/> | ||
| <path fill="none" stroke="black" d="M206.98,-203.8C246.3,-197.9 252.26,-156.32 286.57,-145.06"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-204.5 202.24,-204.14"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-204.14 207.22,-203.78"/> | ||
| <polyline fill="none" stroke="black" points="305.25,-142.25 300.31,-142.99"/> | ||
| <polygon fill="black" stroke="black" points="298.57,-138.2 300.06,-148.09 298.08,-148.38 296.6,-138.49 298.57,-138.2"/> | ||
| <polyline fill="none" stroke="black" points="300.31,-142.99 295.36,-143.74"/> | ||
| <ellipse fill="none" stroke="black" cx="290.91" cy="-144.4" rx="4" ry="4"/> | ||
| </g> | ||
@@ -113,16 +113,16 @@ <!-- erdantic.examples.dataclasses.QuestGiver --> | ||
| <g id="a_node4"><a xlink:title="erdantic.examples.dataclasses.QuestGiver A person who offers a task that needs completing. Attributes:    name (str): Name of this quest giver    faction (str): Faction that this quest giver belongs to    location (str): Location this quest giver can be found "> | ||
| <polygon fill="none" stroke="black" points="554,-84.5 554,-106.5 678,-106.5 678,-84.5 554,-84.5"/> | ||
| <text text-anchor="start" x="581.88" y="-91.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="554,-62.5 554,-84.5 603,-84.5 603,-62.5 554,-62.5"/> | ||
| <text text-anchor="start" x="563.5" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="603,-62.5 603,-84.5 678,-84.5 678,-62.5 603,-62.5"/> | ||
| <text text-anchor="start" x="633.75" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="554,-40.5 554,-62.5 603,-62.5 603,-40.5 554,-40.5"/> | ||
| <text text-anchor="start" x="559.75" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="603,-40.5 603,-62.5 678,-62.5 678,-40.5 603,-40.5"/> | ||
| <text text-anchor="start" x="605.62" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="554,-18.5 554,-40.5 603,-40.5 603,-18.5 554,-18.5"/> | ||
| <text text-anchor="start" x="556.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="603,-18.5 603,-40.5 678,-40.5 678,-18.5 603,-18.5"/> | ||
| <text text-anchor="start" x="633.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-86 555.75,-108.5 681,-108.5 681,-86 555.75,-86"/> | ||
| <text text-anchor="start" x="584.25" y="-93.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-63.5 555.75,-86 605.25,-86 605.25,-63.5 555.75,-63.5"/> | ||
| <text text-anchor="start" x="565.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-63.5 605.25,-86 681,-86 681,-63.5 605.25,-63.5"/> | ||
| <text text-anchor="start" x="636.38" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-41 555.75,-63.5 605.25,-63.5 605.25,-41 555.75,-41"/> | ||
| <text text-anchor="start" x="561.75" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-41 605.25,-63.5 681,-63.5 681,-41 605.25,-41"/> | ||
| <text text-anchor="start" x="608.25" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-18.5 555.75,-41 605.25,-41 605.25,-18.5 555.75,-18.5"/> | ||
| <text text-anchor="start" x="558.75" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-18.5 605.25,-41 681,-41 681,-18.5 605.25,-18.5"/> | ||
| <text text-anchor="start" x="636.38" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| </a> | ||
@@ -134,12 +134,12 @@ </g> | ||
| <title>erdantic.examples.dataclasses.Quest:e->erdantic.examples.dataclasses.QuestGiver:w</title> | ||
| <path fill="none" stroke="black" d="M455.87,-95.5C491.07,-95.5 505.8,-95.5 539.08,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="446,-95.5 451,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="451,-95.5 456,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="554,-95.5 549,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="548,-90.5 548,-100.5 546,-100.5 546,-90.5 548,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="549,-95.5 544,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="543,-90.5 543,-100.5 541,-100.5 541,-90.5 543,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="544,-95.5 539,-95.5"/> | ||
| <path fill="none" stroke="black" d="M457.62,-97.25C492.82,-97.25 507.55,-97.25 540.83,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="447.75,-97.25 452.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="452.75,-97.25 457.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="555.75,-97.25 550.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="549.75,-92.25 549.75,-102.25 547.75,-102.25 547.75,-92.25 549.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="550.75,-97.25 545.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="544.75,-92.25 544.75,-102.25 542.75,-102.25 542.75,-92.25 544.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="545.75,-97.25 540.75,-97.25"/> | ||
| </g> | ||
| </g> | ||
| </svg> |
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | ||
| "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| <!-- Generated by graphviz version 9.0.0 (0) | ||
| <!-- Generated by graphviz version 12.2.1 (0) | ||
| --> | ||
| <!-- Title: Entity Relationship Diagram created by erdantic Pages: 1 --> | ||
| <svg width="686pt" height="309pt" | ||
| viewBox="0.00 0.00 686.00 308.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.5)"> | ||
| <svg width="689pt" height="314pt" | ||
| viewBox="0.00 0.00 689.00 313.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 309.75)"> | ||
| <title>Entity Relationship Diagram created by erdantic</title> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-304.5 682,-304.5 682,4 -4,4"/> | ||
| <text text-anchor="middle" x="339" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-309.75 685,-309.75 685,4 -4,4"/> | ||
| <text text-anchor="middle" x="340.5" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <!-- erdantic.examples.pydantic_v1.Adventurer --> | ||
@@ -17,20 +17,20 @@ <g id="node1" class="node"> | ||
| <g id="a_node1"><a xlink:title="erdantic.examples.pydantic_v1.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:    name (str): Name of this adventurer    profession (str): Profession of this adventurer    alignment (Alignment): Alignment of this adventurer    level (int): Level of this adventurer "> | ||
| <polygon fill="none" stroke="black" points="312,-274.5 312,-296.5 438,-296.5 438,-274.5 312,-274.5"/> | ||
| <text text-anchor="start" x="341.25" y="-281.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="312,-252.5 312,-274.5 374,-274.5 374,-252.5 312,-252.5"/> | ||
| <text text-anchor="start" x="328" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="374,-252.5 374,-274.5 438,-274.5 438,-252.5 374,-252.5"/> | ||
| <text text-anchor="start" x="399.25" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-230.5 312,-252.5 374,-252.5 374,-230.5 312,-230.5"/> | ||
| <text text-anchor="start" x="314.88" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="374,-230.5 374,-252.5 438,-252.5 438,-230.5 374,-230.5"/> | ||
| <text text-anchor="start" x="399.25" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-208.5 312,-230.5 374,-230.5 374,-208.5 312,-208.5"/> | ||
| <text text-anchor="start" x="315.62" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="374,-208.5 374,-230.5 438,-230.5 438,-208.5 374,-208.5"/> | ||
| <text text-anchor="start" x="376.75" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="312,-186.5 312,-208.5 374,-208.5 374,-186.5 312,-186.5"/> | ||
| <text text-anchor="start" x="329.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="374,-186.5 374,-208.5 438,-208.5 438,-186.5 374,-186.5"/> | ||
| <text text-anchor="start" x="398.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-279.25 313.12,-301.75 439.88,-301.75 439.88,-279.25 313.12,-279.25"/> | ||
| <text text-anchor="start" x="342.75" y="-286.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-256.75 313.12,-279.25 375.38,-279.25 375.38,-256.75 313.12,-256.75"/> | ||
| <text text-anchor="start" x="329.25" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-256.75 375.38,-279.25 439.88,-279.25 439.88,-256.75 375.38,-256.75"/> | ||
| <text text-anchor="start" x="400.88" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-234.25 313.12,-256.75 375.38,-256.75 375.38,-234.25 313.12,-234.25"/> | ||
| <text text-anchor="start" x="316.12" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-234.25 375.38,-256.75 439.88,-256.75 439.88,-234.25 375.38,-234.25"/> | ||
| <text text-anchor="start" x="400.88" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-211.75 313.12,-234.25 375.38,-234.25 375.38,-211.75 313.12,-211.75"/> | ||
| <text text-anchor="start" x="316.88" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-211.75 375.38,-234.25 439.88,-234.25 439.88,-211.75 375.38,-211.75"/> | ||
| <text text-anchor="start" x="378.38" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-189.25 313.12,-211.75 375.38,-211.75 375.38,-189.25 313.12,-189.25"/> | ||
| <text text-anchor="start" x="331.12" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-189.25 375.38,-211.75 439.88,-211.75 439.88,-189.25 375.38,-189.25"/> | ||
| <text text-anchor="start" x="400.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -43,20 +43,20 @@ </g> | ||
| <g id="a_node2"><a xlink:title="erdantic.examples.pydantic_v1.Party A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes:    name (str): Name that party is known by    formed_datetime (datetime): Timestamp of when the party was formed    members (List[Adventurer]): Adventurers that belong to this party    active_quest (Optional[Quest]): Current quest that party is actively tackling "> | ||
| <polygon fill="none" stroke="black" points="0,-278.5 0,-300.5 196,-300.5 196,-278.5 0,-278.5"/> | ||
| <text text-anchor="start" x="81.88" y="-285.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-256.5 0,-278.5 99,-278.5 99,-256.5 0,-256.5"/> | ||
| <text text-anchor="start" x="34.5" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99,-256.5 99,-278.5 196,-278.5 196,-256.5 99,-256.5"/> | ||
| <text text-anchor="start" x="140.75" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-234.5 0,-256.5 99,-256.5 99,-234.5 0,-234.5"/> | ||
| <text text-anchor="start" x="2.62" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99,-234.5 99,-256.5 196,-256.5 196,-234.5 99,-234.5"/> | ||
| <text text-anchor="start" x="123.88" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-212.5 0,-234.5 99,-234.5 99,-212.5 0,-212.5"/> | ||
| <text text-anchor="start" x="24" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99,-212.5 99,-234.5 196,-234.5 196,-212.5 99,-212.5"/> | ||
| <text text-anchor="start" x="101.75" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-190.5 0,-212.5 99,-212.5 99,-190.5 0,-190.5"/> | ||
| <text text-anchor="start" x="15.75" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99,-190.5 99,-212.5 196,-212.5 196,-190.5 99,-190.5"/> | ||
| <text text-anchor="start" x="103.62" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="0,-283.25 0,-305.75 197.25,-305.75 197.25,-283.25 0,-283.25"/> | ||
| <text text-anchor="start" x="82.5" y="-290.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-260.75 0,-283.25 99.75,-283.25 99.75,-260.75 0,-260.75"/> | ||
| <text text-anchor="start" x="34.88" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-260.75 99.75,-283.25 197.25,-283.25 197.25,-260.75 99.75,-260.75"/> | ||
| <text text-anchor="start" x="141.75" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-238.25 0,-260.75 99.75,-260.75 99.75,-238.25 0,-238.25"/> | ||
| <text text-anchor="start" x="3" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-238.25 99.75,-260.75 197.25,-260.75 197.25,-238.25 99.75,-238.25"/> | ||
| <text text-anchor="start" x="124.88" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-215.75 0,-238.25 99.75,-238.25 99.75,-215.75 0,-215.75"/> | ||
| <text text-anchor="start" x="24.38" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-215.75 99.75,-238.25 197.25,-238.25 197.25,-215.75 99.75,-215.75"/> | ||
| <text text-anchor="start" x="102.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-193.25 0,-215.75 99.75,-215.75 99.75,-193.25 0,-193.25"/> | ||
| <text text-anchor="start" x="16.12" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-193.25 99.75,-215.75 197.25,-215.75 197.25,-193.25 99.75,-193.25"/> | ||
| <text text-anchor="start" x="104.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| </a> | ||
@@ -68,7 +68,7 @@ </g> | ||
| <title>erdantic.examples.pydantic_v1.Party:e->erdantic.examples.pydantic_v1.Adventurer:w</title> | ||
| <path fill="none" stroke="black" d="M205.92,-224.15C249.25,-230.11 255.51,-274.88 295.89,-283.91"/> | ||
| <polyline fill="none" stroke="black" points="196,-223.5 200.99,-223.83"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-223.83 205.98,-224.16"/> | ||
| <polygon fill="black" stroke="black" points="300.72,-284.42 310.2,-289.94 306.03,-284.98 310.33,-285.43 310.33,-285.43 310.33,-285.43 306.03,-284.98 311.14,-280.99 300.72,-284.42"/> | ||
| <polyline fill="none" stroke="black" points="299.51,-284.29 294.54,-283.77"/> | ||
| <path fill="none" stroke="black" d="M207.21,-227.67C250.68,-233.77 256.49,-279.62 296.96,-288.88"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-227 202.24,-227.34"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-227.34 207.23,-227.67"/> | ||
| <polygon fill="black" stroke="black" points="301.85,-289.4 311.31,-294.94 307.15,-289.97 311.46,-290.43 311.46,-290.43 311.46,-290.43 307.15,-289.97 312.27,-285.99 301.85,-289.4"/> | ||
| <polyline fill="none" stroke="black" points="300.64,-289.27 295.67,-288.74"/> | ||
| </g> | ||
@@ -79,16 +79,16 @@ <!-- erdantic.examples.pydantic_v1.Quest --> | ||
| <g id="a_node3"><a xlink:title="erdantic.examples.pydantic_v1.Quest A task to complete, with some monetary reward. Attributes:    name (str): Name by which this quest is referred to    giver (QuestGiver): Person who offered the quest    reward_gold (int): Amount of gold to be rewarded for quest completion "> | ||
| <polygon fill="none" stroke="black" points="304,-128.5 304,-150.5 446,-150.5 446,-128.5 304,-128.5"/> | ||
| <text text-anchor="start" x="357.75" y="-135.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="304,-106.5 304,-128.5 378,-128.5 378,-106.5 304,-106.5"/> | ||
| <text text-anchor="start" x="326" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="378,-106.5 378,-128.5 446,-128.5 446,-106.5 378,-106.5"/> | ||
| <text text-anchor="start" x="405.25" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="304,-84.5 304,-106.5 378,-106.5 378,-84.5 304,-84.5"/> | ||
| <text text-anchor="start" x="327.12" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="378,-84.5 378,-106.5 446,-106.5 446,-84.5 378,-84.5"/> | ||
| <text text-anchor="start" x="380.88" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="304,-62.5 304,-84.5 378,-84.5 378,-62.5 304,-62.5"/> | ||
| <text text-anchor="start" x="306.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="378,-62.5 378,-84.5 446,-84.5 446,-62.5 378,-62.5"/> | ||
| <text text-anchor="start" x="404.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-131 305.25,-153.5 447.75,-153.5 447.75,-131 305.25,-131"/> | ||
| <text text-anchor="start" x="359.25" y="-138.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-108.5 305.25,-131 379.5,-131 379.5,-108.5 305.25,-108.5"/> | ||
| <text text-anchor="start" x="327.38" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-108.5 379.5,-131 447.75,-131 447.75,-108.5 379.5,-108.5"/> | ||
| <text text-anchor="start" x="406.88" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-86 305.25,-108.5 379.5,-108.5 379.5,-86 305.25,-86"/> | ||
| <text text-anchor="start" x="328.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-86 379.5,-108.5 447.75,-108.5 447.75,-86 379.5,-86"/> | ||
| <text text-anchor="start" x="382.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-63.5 305.25,-86 379.5,-86 379.5,-63.5 305.25,-63.5"/> | ||
| <text text-anchor="start" x="308.25" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-63.5 379.5,-86 447.75,-86 447.75,-63.5 379.5,-63.5"/> | ||
| <text text-anchor="start" x="406.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -100,9 +100,9 @@ </g> | ||
| <title>erdantic.examples.pydantic_v1.Party:e->erdantic.examples.pydantic_v1.Quest:w</title> | ||
| <path fill="none" stroke="black" d="M205.73,-200.8C245.01,-194.92 251.04,-153.51 285.33,-142.29"/> | ||
| <polyline fill="none" stroke="black" points="196,-201.5 200.99,-201.14"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-201.14 205.97,-200.79"/> | ||
| <polyline fill="none" stroke="black" points="304,-139.5 299.06,-140.24"/> | ||
| <polygon fill="black" stroke="black" points="297.33,-135.44 298.81,-145.33 296.83,-145.63 295.35,-135.74 297.33,-135.44"/> | ||
| <polyline fill="none" stroke="black" points="299.06,-140.24 294.11,-140.98"/> | ||
| <ellipse fill="none" stroke="black" cx="289.66" cy="-141.65" rx="4" ry="4"/> | ||
| <path fill="none" stroke="black" d="M206.98,-203.8C246.3,-197.9 252.26,-156.32 286.57,-145.06"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-204.5 202.24,-204.14"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-204.14 207.22,-203.78"/> | ||
| <polyline fill="none" stroke="black" points="305.25,-142.25 300.31,-142.99"/> | ||
| <polygon fill="black" stroke="black" points="298.57,-138.2 300.06,-148.09 298.08,-148.38 296.6,-138.49 298.57,-138.2"/> | ||
| <polyline fill="none" stroke="black" points="300.31,-142.99 295.36,-143.74"/> | ||
| <ellipse fill="none" stroke="black" cx="290.91" cy="-144.4" rx="4" ry="4"/> | ||
| </g> | ||
@@ -113,16 +113,16 @@ <!-- erdantic.examples.pydantic_v1.QuestGiver --> | ||
| <g id="a_node4"><a xlink:title="erdantic.examples.pydantic_v1.QuestGiver A person who offers a task that needs completing. Attributes:    name (str): Name of this quest giver    faction (str): Faction that this quest giver belongs to    location (str): Location this quest giver can be found "> | ||
| <polygon fill="none" stroke="black" points="554,-84.5 554,-106.5 678,-106.5 678,-84.5 554,-84.5"/> | ||
| <text text-anchor="start" x="581.88" y="-91.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="554,-62.5 554,-84.5 603,-84.5 603,-62.5 554,-62.5"/> | ||
| <text text-anchor="start" x="563.5" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="603,-62.5 603,-84.5 678,-84.5 678,-62.5 603,-62.5"/> | ||
| <text text-anchor="start" x="633.75" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="554,-40.5 554,-62.5 603,-62.5 603,-40.5 554,-40.5"/> | ||
| <text text-anchor="start" x="559.75" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="603,-40.5 603,-62.5 678,-62.5 678,-40.5 603,-40.5"/> | ||
| <text text-anchor="start" x="605.62" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="554,-18.5 554,-40.5 603,-40.5 603,-18.5 554,-18.5"/> | ||
| <text text-anchor="start" x="556.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="603,-18.5 603,-40.5 678,-40.5 678,-18.5 603,-18.5"/> | ||
| <text text-anchor="start" x="633.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-86 555.75,-108.5 681,-108.5 681,-86 555.75,-86"/> | ||
| <text text-anchor="start" x="584.25" y="-93.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-63.5 555.75,-86 605.25,-86 605.25,-63.5 555.75,-63.5"/> | ||
| <text text-anchor="start" x="565.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-63.5 605.25,-86 681,-86 681,-63.5 605.25,-63.5"/> | ||
| <text text-anchor="start" x="636.38" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-41 555.75,-63.5 605.25,-63.5 605.25,-41 555.75,-41"/> | ||
| <text text-anchor="start" x="561.75" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-41 605.25,-63.5 681,-63.5 681,-41 605.25,-41"/> | ||
| <text text-anchor="start" x="608.25" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-18.5 555.75,-41 605.25,-41 605.25,-18.5 555.75,-18.5"/> | ||
| <text text-anchor="start" x="558.75" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-18.5 605.25,-41 681,-41 681,-18.5 605.25,-18.5"/> | ||
| <text text-anchor="start" x="636.38" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| </a> | ||
@@ -134,12 +134,12 @@ </g> | ||
| <title>erdantic.examples.pydantic_v1.Quest:e->erdantic.examples.pydantic_v1.QuestGiver:w</title> | ||
| <path fill="none" stroke="black" d="M455.87,-95.5C491.07,-95.5 505.8,-95.5 539.08,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="446,-95.5 451,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="451,-95.5 456,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="554,-95.5 549,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="548,-90.5 548,-100.5 546,-100.5 546,-90.5 548,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="549,-95.5 544,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="543,-90.5 543,-100.5 541,-100.5 541,-90.5 543,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="544,-95.5 539,-95.5"/> | ||
| <path fill="none" stroke="black" d="M457.62,-97.25C492.82,-97.25 507.55,-97.25 540.83,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="447.75,-97.25 452.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="452.75,-97.25 457.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="555.75,-97.25 550.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="549.75,-92.25 549.75,-102.25 547.75,-102.25 547.75,-92.25 549.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="550.75,-97.25 545.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="544.75,-92.25 544.75,-102.25 542.75,-102.25 542.75,-92.25 544.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="545.75,-97.25 540.75,-97.25"/> | ||
| </g> | ||
| </g> | ||
| </svg> |
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | ||
| "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| <!-- Generated by graphviz version 9.0.0 (0) | ||
| <!-- Generated by graphviz version 12.2.1 (0) | ||
| --> | ||
| <!-- Title: Entity Relationship Diagram created by erdantic Pages: 1 --> | ||
| <svg width="686pt" height="309pt" | ||
| viewBox="0.00 0.00 686.00 308.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.5)"> | ||
| <svg width="689pt" height="314pt" | ||
| viewBox="0.00 0.00 689.00 313.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 309.75)"> | ||
| <title>Entity Relationship Diagram created by erdantic</title> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-304.5 682,-304.5 682,4 -4,4"/> | ||
| <text text-anchor="middle" x="339" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-309.75 685,-309.75 685,4 -4,4"/> | ||
| <text text-anchor="middle" x="340.5" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <!-- erdantic.examples.pydantic.Adventurer --> | ||
@@ -17,20 +17,20 @@ <g id="node1" class="node"> | ||
| <g id="a_node1"><a xlink:title="erdantic.examples.pydantic.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:    name (str): Name of this adventurer    profession (str): Profession of this adventurer    alignment (Alignment): Alignment of this adventurer    level (int): Level of this adventurer "> | ||
| <polygon fill="none" stroke="black" points="312,-274.5 312,-296.5 438,-296.5 438,-274.5 312,-274.5"/> | ||
| <text text-anchor="start" x="341.25" y="-281.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="312,-252.5 312,-274.5 374,-274.5 374,-252.5 312,-252.5"/> | ||
| <text text-anchor="start" x="328" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="374,-252.5 374,-274.5 438,-274.5 438,-252.5 374,-252.5"/> | ||
| <text text-anchor="start" x="399.25" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-230.5 312,-252.5 374,-252.5 374,-230.5 312,-230.5"/> | ||
| <text text-anchor="start" x="314.88" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="374,-230.5 374,-252.5 438,-252.5 438,-230.5 374,-230.5"/> | ||
| <text text-anchor="start" x="399.25" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="312,-208.5 312,-230.5 374,-230.5 374,-208.5 312,-208.5"/> | ||
| <text text-anchor="start" x="315.62" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="374,-208.5 374,-230.5 438,-230.5 438,-208.5 374,-208.5"/> | ||
| <text text-anchor="start" x="376.75" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="312,-186.5 312,-208.5 374,-208.5 374,-186.5 312,-186.5"/> | ||
| <text text-anchor="start" x="329.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="374,-186.5 374,-208.5 438,-208.5 438,-186.5 374,-186.5"/> | ||
| <text text-anchor="start" x="398.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-279.25 313.12,-301.75 439.88,-301.75 439.88,-279.25 313.12,-279.25"/> | ||
| <text text-anchor="start" x="342.75" y="-286.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-256.75 313.12,-279.25 375.38,-279.25 375.38,-256.75 313.12,-256.75"/> | ||
| <text text-anchor="start" x="329.25" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-256.75 375.38,-279.25 439.88,-279.25 439.88,-256.75 375.38,-256.75"/> | ||
| <text text-anchor="start" x="400.88" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-234.25 313.12,-256.75 375.38,-256.75 375.38,-234.25 313.12,-234.25"/> | ||
| <text text-anchor="start" x="316.12" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-234.25 375.38,-256.75 439.88,-256.75 439.88,-234.25 375.38,-234.25"/> | ||
| <text text-anchor="start" x="400.88" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-211.75 313.12,-234.25 375.38,-234.25 375.38,-211.75 313.12,-211.75"/> | ||
| <text text-anchor="start" x="316.88" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-211.75 375.38,-234.25 439.88,-234.25 439.88,-211.75 375.38,-211.75"/> | ||
| <text text-anchor="start" x="378.38" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="313.12,-189.25 313.12,-211.75 375.38,-211.75 375.38,-189.25 313.12,-189.25"/> | ||
| <text text-anchor="start" x="331.12" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="375.38,-189.25 375.38,-211.75 439.88,-211.75 439.88,-189.25 375.38,-189.25"/> | ||
| <text text-anchor="start" x="400.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -43,20 +43,20 @@ </g> | ||
| <g id="a_node2"><a xlink:title="erdantic.examples.pydantic.Party A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes:    name (str): Name that party is known by    formed_datetime (datetime): Timestamp of when the party was formed    members (List[Adventurer]): Adventurers that belong to this party    active_quest (Optional[Quest]): Current quest that party is actively tackling "> | ||
| <polygon fill="none" stroke="black" points="0,-278.5 0,-300.5 196,-300.5 196,-278.5 0,-278.5"/> | ||
| <text text-anchor="start" x="81.88" y="-285.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-256.5 0,-278.5 99,-278.5 99,-256.5 0,-256.5"/> | ||
| <text text-anchor="start" x="34.5" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99,-256.5 99,-278.5 196,-278.5 196,-256.5 99,-256.5"/> | ||
| <text text-anchor="start" x="140.75" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-234.5 0,-256.5 99,-256.5 99,-234.5 0,-234.5"/> | ||
| <text text-anchor="start" x="2.62" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99,-234.5 99,-256.5 196,-256.5 196,-234.5 99,-234.5"/> | ||
| <text text-anchor="start" x="123.88" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-212.5 0,-234.5 99,-234.5 99,-212.5 0,-212.5"/> | ||
| <text text-anchor="start" x="24" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99,-212.5 99,-234.5 196,-234.5 196,-212.5 99,-212.5"/> | ||
| <text text-anchor="start" x="101.75" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-190.5 0,-212.5 99,-212.5 99,-190.5 0,-190.5"/> | ||
| <text text-anchor="start" x="15.75" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99,-190.5 99,-212.5 196,-212.5 196,-190.5 99,-190.5"/> | ||
| <text text-anchor="start" x="103.62" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="0,-283.25 0,-305.75 197.25,-305.75 197.25,-283.25 0,-283.25"/> | ||
| <text text-anchor="start" x="82.5" y="-290.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-260.75 0,-283.25 99.75,-283.25 99.75,-260.75 0,-260.75"/> | ||
| <text text-anchor="start" x="34.88" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-260.75 99.75,-283.25 197.25,-283.25 197.25,-260.75 99.75,-260.75"/> | ||
| <text text-anchor="start" x="141.75" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="0,-238.25 0,-260.75 99.75,-260.75 99.75,-238.25 0,-238.25"/> | ||
| <text text-anchor="start" x="3" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-238.25 99.75,-260.75 197.25,-260.75 197.25,-238.25 99.75,-238.25"/> | ||
| <text text-anchor="start" x="124.88" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="0,-215.75 0,-238.25 99.75,-238.25 99.75,-215.75 0,-215.75"/> | ||
| <text text-anchor="start" x="24.38" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-215.75 99.75,-238.25 197.25,-238.25 197.25,-215.75 99.75,-215.75"/> | ||
| <text text-anchor="start" x="102.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="0,-193.25 0,-215.75 99.75,-215.75 99.75,-193.25 0,-193.25"/> | ||
| <text text-anchor="start" x="16.12" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-193.25 99.75,-215.75 197.25,-215.75 197.25,-193.25 99.75,-193.25"/> | ||
| <text text-anchor="start" x="104.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| </a> | ||
@@ -68,7 +68,7 @@ </g> | ||
| <title>erdantic.examples.pydantic.Party:e->erdantic.examples.pydantic.Adventurer:w</title> | ||
| <path fill="none" stroke="black" d="M205.92,-224.15C249.25,-230.11 255.51,-274.88 295.89,-283.91"/> | ||
| <polyline fill="none" stroke="black" points="196,-223.5 200.99,-223.83"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-223.83 205.98,-224.16"/> | ||
| <polygon fill="black" stroke="black" points="300.72,-284.42 310.2,-289.94 306.03,-284.98 310.33,-285.43 310.33,-285.43 310.33,-285.43 306.03,-284.98 311.14,-280.99 300.72,-284.42"/> | ||
| <polyline fill="none" stroke="black" points="299.51,-284.29 294.54,-283.77"/> | ||
| <path fill="none" stroke="black" d="M207.21,-227.67C250.68,-233.77 256.49,-279.62 296.96,-288.88"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-227 202.24,-227.34"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-227.34 207.23,-227.67"/> | ||
| <polygon fill="black" stroke="black" points="301.85,-289.4 311.31,-294.94 307.15,-289.97 311.46,-290.43 311.46,-290.43 311.46,-290.43 307.15,-289.97 312.27,-285.99 301.85,-289.4"/> | ||
| <polyline fill="none" stroke="black" points="300.64,-289.27 295.67,-288.74"/> | ||
| </g> | ||
@@ -79,16 +79,16 @@ <!-- erdantic.examples.pydantic.Quest --> | ||
| <g id="a_node3"><a xlink:title="erdantic.examples.pydantic.Quest A task to complete, with some monetary reward. Attributes:    name (str): Name by which this quest is referred to    giver (QuestGiver): Person who offered the quest    reward_gold (int): Amount of gold to be rewarded for quest completion "> | ||
| <polygon fill="none" stroke="black" points="304,-128.5 304,-150.5 446,-150.5 446,-128.5 304,-128.5"/> | ||
| <text text-anchor="start" x="357.75" y="-135.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="304,-106.5 304,-128.5 378,-128.5 378,-106.5 304,-106.5"/> | ||
| <text text-anchor="start" x="326" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="378,-106.5 378,-128.5 446,-128.5 446,-106.5 378,-106.5"/> | ||
| <text text-anchor="start" x="405.25" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="304,-84.5 304,-106.5 378,-106.5 378,-84.5 304,-84.5"/> | ||
| <text text-anchor="start" x="327.12" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="378,-84.5 378,-106.5 446,-106.5 446,-84.5 378,-84.5"/> | ||
| <text text-anchor="start" x="380.88" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="304,-62.5 304,-84.5 378,-84.5 378,-62.5 304,-62.5"/> | ||
| <text text-anchor="start" x="306.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="378,-62.5 378,-84.5 446,-84.5 446,-62.5 378,-62.5"/> | ||
| <text text-anchor="start" x="404.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-131 305.25,-153.5 447.75,-153.5 447.75,-131 305.25,-131"/> | ||
| <text text-anchor="start" x="359.25" y="-138.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-108.5 305.25,-131 379.5,-131 379.5,-108.5 305.25,-108.5"/> | ||
| <text text-anchor="start" x="327.38" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-108.5 379.5,-131 447.75,-131 447.75,-108.5 379.5,-108.5"/> | ||
| <text text-anchor="start" x="406.88" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-86 305.25,-108.5 379.5,-108.5 379.5,-86 305.25,-86"/> | ||
| <text text-anchor="start" x="328.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-86 379.5,-108.5 447.75,-108.5 447.75,-86 379.5,-86"/> | ||
| <text text-anchor="start" x="382.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="305.25,-63.5 305.25,-86 379.5,-86 379.5,-63.5 305.25,-63.5"/> | ||
| <text text-anchor="start" x="308.25" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="379.5,-63.5 379.5,-86 447.75,-86 447.75,-63.5 379.5,-63.5"/> | ||
| <text text-anchor="start" x="406.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| </a> | ||
@@ -100,9 +100,9 @@ </g> | ||
| <title>erdantic.examples.pydantic.Party:e->erdantic.examples.pydantic.Quest:w</title> | ||
| <path fill="none" stroke="black" d="M205.73,-200.8C245.01,-194.92 251.04,-153.51 285.33,-142.29"/> | ||
| <polyline fill="none" stroke="black" points="196,-201.5 200.99,-201.14"/> | ||
| <polyline fill="none" stroke="black" points="200.99,-201.14 205.97,-200.79"/> | ||
| <polyline fill="none" stroke="black" points="304,-139.5 299.06,-140.24"/> | ||
| <polygon fill="black" stroke="black" points="297.33,-135.44 298.81,-145.33 296.83,-145.63 295.35,-135.74 297.33,-135.44"/> | ||
| <polyline fill="none" stroke="black" points="299.06,-140.24 294.11,-140.98"/> | ||
| <ellipse fill="none" stroke="black" cx="289.66" cy="-141.65" rx="4" ry="4"/> | ||
| <path fill="none" stroke="black" d="M206.98,-203.8C246.3,-197.9 252.26,-156.32 286.57,-145.06"/> | ||
| <polyline fill="none" stroke="black" points="197.25,-204.5 202.24,-204.14"/> | ||
| <polyline fill="none" stroke="black" points="202.24,-204.14 207.22,-203.78"/> | ||
| <polyline fill="none" stroke="black" points="305.25,-142.25 300.31,-142.99"/> | ||
| <polygon fill="black" stroke="black" points="298.57,-138.2 300.06,-148.09 298.08,-148.38 296.6,-138.49 298.57,-138.2"/> | ||
| <polyline fill="none" stroke="black" points="300.31,-142.99 295.36,-143.74"/> | ||
| <ellipse fill="none" stroke="black" cx="290.91" cy="-144.4" rx="4" ry="4"/> | ||
| </g> | ||
@@ -113,16 +113,16 @@ <!-- erdantic.examples.pydantic.QuestGiver --> | ||
| <g id="a_node4"><a xlink:title="erdantic.examples.pydantic.QuestGiver A person who offers a task that needs completing. Attributes:    name (str): Name of this quest giver    faction (str): Faction that this quest giver belongs to    location (str): Location this quest giver can be found "> | ||
| <polygon fill="none" stroke="black" points="554,-84.5 554,-106.5 678,-106.5 678,-84.5 554,-84.5"/> | ||
| <text text-anchor="start" x="581.88" y="-91.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="554,-62.5 554,-84.5 603,-84.5 603,-62.5 554,-62.5"/> | ||
| <text text-anchor="start" x="563.5" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="603,-62.5 603,-84.5 678,-84.5 678,-62.5 603,-62.5"/> | ||
| <text text-anchor="start" x="633.75" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="554,-40.5 554,-62.5 603,-62.5 603,-40.5 554,-40.5"/> | ||
| <text text-anchor="start" x="559.75" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="603,-40.5 603,-62.5 678,-62.5 678,-40.5 603,-40.5"/> | ||
| <text text-anchor="start" x="605.62" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="554,-18.5 554,-40.5 603,-40.5 603,-18.5 554,-18.5"/> | ||
| <text text-anchor="start" x="556.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="603,-18.5 603,-40.5 678,-40.5 678,-18.5 603,-18.5"/> | ||
| <text text-anchor="start" x="633.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-86 555.75,-108.5 681,-108.5 681,-86 555.75,-86"/> | ||
| <text text-anchor="start" x="584.25" y="-93.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-63.5 555.75,-86 605.25,-86 605.25,-63.5 555.75,-63.5"/> | ||
| <text text-anchor="start" x="565.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-63.5 605.25,-86 681,-86 681,-63.5 605.25,-63.5"/> | ||
| <text text-anchor="start" x="636.38" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-41 555.75,-63.5 605.25,-63.5 605.25,-41 555.75,-41"/> | ||
| <text text-anchor="start" x="561.75" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-41 605.25,-63.5 681,-63.5 681,-41 605.25,-41"/> | ||
| <text text-anchor="start" x="608.25" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="555.75,-18.5 555.75,-41 605.25,-41 605.25,-18.5 555.75,-18.5"/> | ||
| <text text-anchor="start" x="558.75" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="605.25,-18.5 605.25,-41 681,-41 681,-18.5 605.25,-18.5"/> | ||
| <text text-anchor="start" x="636.38" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| </a> | ||
@@ -134,12 +134,12 @@ </g> | ||
| <title>erdantic.examples.pydantic.Quest:e->erdantic.examples.pydantic.QuestGiver:w</title> | ||
| <path fill="none" stroke="black" d="M455.87,-95.5C491.07,-95.5 505.8,-95.5 539.08,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="446,-95.5 451,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="451,-95.5 456,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="554,-95.5 549,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="548,-90.5 548,-100.5 546,-100.5 546,-90.5 548,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="549,-95.5 544,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="543,-90.5 543,-100.5 541,-100.5 541,-90.5 543,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="544,-95.5 539,-95.5"/> | ||
| <path fill="none" stroke="black" d="M457.62,-97.25C492.82,-97.25 507.55,-97.25 540.83,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="447.75,-97.25 452.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="452.75,-97.25 457.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="555.75,-97.25 550.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="549.75,-92.25 549.75,-102.25 547.75,-102.25 547.75,-92.25 549.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="550.75,-97.25 545.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="544.75,-92.25 544.75,-102.25 542.75,-102.25 542.75,-92.25 544.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="545.75,-97.25 540.75,-97.25"/> | ||
| </g> | ||
| </g> | ||
| </svg> |
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | ||
| "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| <!-- Generated by graphviz version 9.0.0 (0) | ||
| <!-- Generated by graphviz version 12.2.1 (0) | ||
| --> | ||
| <!-- Title: Entity Relationship Diagram created by erdantic Pages: 1 --> | ||
| <svg width="879pt" height="309pt" | ||
| viewBox="0.00 0.00 879.00 308.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.5)"> | ||
| <svg width="883pt" height="314pt" | ||
| viewBox="0.00 0.00 882.50 313.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
| <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 309.75)"> | ||
| <title>Entity Relationship Diagram created by erdantic</title> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-304.5 875,-304.5 875,4 -4,4"/> | ||
| <text text-anchor="middle" x="435.5" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <polygon fill="white" stroke="none" points="-4,4 -4,-309.75 878.5,-309.75 878.5,4 -4,4"/> | ||
| <text text-anchor="middle" x="437.25" y="-5.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="9.00" fill="#a8a8a8">Created by erdantic vTEST <https://github.com/drivendataorg/erdantic></text> | ||
| <!-- erdantic.examples.pydantic.Adventurer --> | ||
@@ -17,25 +17,25 @@ <g id="node1" class="node"> | ||
| <g id="a_node1"><a xlink:title="erdantic.examples.pydantic.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:    name (str): Name of this adventurer    profession (str): Profession of this adventurer    alignment (Alignment): Alignment of this adventurer    level (int): Level of this adventurer "> | ||
| <polygon fill="none" stroke="black" points="348,-274.5 348,-296.5 510,-296.5 510,-274.5 348,-274.5"/> | ||
| <text text-anchor="start" x="395.25" y="-281.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="348,-252.5 348,-274.5 410,-274.5 410,-252.5 348,-252.5"/> | ||
| <text text-anchor="start" x="364" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="410,-252.5 410,-274.5 474,-274.5 474,-252.5 410,-252.5"/> | ||
| <text text-anchor="start" x="435.25" y="-258.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="474,-252.5 474,-274.5 510,-274.5 510,-252.5 474,-252.5"/> | ||
| <polygon fill="none" stroke="black" points="348,-230.5 348,-252.5 410,-252.5 410,-230.5 348,-230.5"/> | ||
| <text text-anchor="start" x="350.88" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="410,-230.5 410,-252.5 474,-252.5 474,-230.5 410,-230.5"/> | ||
| <text text-anchor="start" x="435.25" y="-236.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="474,-230.5 474,-252.5 510,-252.5 510,-230.5 474,-230.5"/> | ||
| <polygon fill="none" stroke="black" points="348,-208.5 348,-230.5 410,-230.5 410,-208.5 348,-208.5"/> | ||
| <text text-anchor="start" x="351.62" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="410,-208.5 410,-230.5 474,-230.5 474,-208.5 410,-208.5"/> | ||
| <text text-anchor="start" x="412.75" y="-214.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="474,-208.5 474,-230.5 510,-230.5 510,-208.5 474,-208.5"/> | ||
| <polygon fill="none" stroke="black" points="348,-186.5 348,-208.5 410,-208.5 410,-186.5 348,-186.5"/> | ||
| <text text-anchor="start" x="365.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="410,-186.5 410,-208.5 474,-208.5 474,-186.5 410,-186.5"/> | ||
| <text text-anchor="start" x="434.88" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="474,-186.5 474,-208.5 510,-208.5 510,-186.5 474,-186.5"/> | ||
| <text text-anchor="start" x="488.62" y="-192.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">1</text> | ||
| <polygon fill="none" stroke="black" points="349.12,-279.25 349.12,-301.75 511.88,-301.75 511.88,-279.25 349.12,-279.25"/> | ||
| <text text-anchor="start" x="396.75" y="-286.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Adventurer</text> | ||
| <polygon fill="none" stroke="black" points="349.12,-256.75 349.12,-279.25 411.38,-279.25 411.38,-256.75 349.12,-256.75"/> | ||
| <text text-anchor="start" x="365.25" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="411.38,-256.75 411.38,-279.25 475.88,-279.25 475.88,-256.75 411.38,-256.75"/> | ||
| <text text-anchor="start" x="436.88" y="-262.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="475.88,-256.75 475.88,-279.25 511.88,-279.25 511.88,-256.75 475.88,-256.75"/> | ||
| <polygon fill="none" stroke="black" points="349.12,-234.25 349.12,-256.75 411.38,-256.75 411.38,-234.25 349.12,-234.25"/> | ||
| <text text-anchor="start" x="352.12" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">profession</text> | ||
| <polygon fill="none" stroke="black" points="411.38,-234.25 411.38,-256.75 475.88,-256.75 475.88,-234.25 411.38,-234.25"/> | ||
| <text text-anchor="start" x="436.88" y="-240.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="475.88,-234.25 475.88,-256.75 511.88,-256.75 511.88,-234.25 475.88,-234.25"/> | ||
| <polygon fill="none" stroke="black" points="349.12,-211.75 349.12,-234.25 411.38,-234.25 411.38,-211.75 349.12,-211.75"/> | ||
| <text text-anchor="start" x="352.88" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">alignment</text> | ||
| <polygon fill="none" stroke="black" points="411.38,-211.75 411.38,-234.25 475.88,-234.25 475.88,-211.75 411.38,-211.75"/> | ||
| <text text-anchor="start" x="414.38" y="-217.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Alignment</text> | ||
| <polygon fill="none" stroke="black" points="475.88,-211.75 475.88,-234.25 511.88,-234.25 511.88,-211.75 475.88,-211.75"/> | ||
| <polygon fill="none" stroke="black" points="349.12,-189.25 349.12,-211.75 411.38,-211.75 411.38,-189.25 349.12,-189.25"/> | ||
| <text text-anchor="start" x="367.12" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">level</text> | ||
| <polygon fill="none" stroke="black" points="411.38,-189.25 411.38,-211.75 475.88,-211.75 475.88,-189.25 411.38,-189.25"/> | ||
| <text text-anchor="start" x="436.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="475.88,-189.25 475.88,-211.75 511.88,-211.75 511.88,-189.25 475.88,-189.25"/> | ||
| <text text-anchor="start" x="490.5" y="-195.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">1</text> | ||
| </a> | ||
@@ -48,26 +48,26 @@ </g> | ||
| <g id="a_node2"><a xlink:title="erdantic.examples.pydantic.Party A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes:    name (str): Name that party is known by    formed_datetime (datetime): Timestamp of when the party was formed    members (List[Adventurer]): Adventurers that belong to this party    active_quest (Optional[Quest]): Current quest that party is actively tackling "> | ||
| <polygon fill="none" stroke="black" points="0,-278.5 0,-300.5 232,-300.5 232,-278.5 0,-278.5"/> | ||
| <text text-anchor="start" x="99.88" y="-285.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-256.5 0,-278.5 99,-278.5 99,-256.5 0,-256.5"/> | ||
| <text text-anchor="start" x="34.5" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99,-256.5 99,-278.5 196,-278.5 196,-256.5 99,-256.5"/> | ||
| <text text-anchor="start" x="140.75" y="-262.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="196,-256.5 196,-278.5 232,-278.5 232,-256.5 196,-256.5"/> | ||
| <polygon fill="none" stroke="black" points="0,-234.5 0,-256.5 99,-256.5 99,-234.5 0,-234.5"/> | ||
| <text text-anchor="start" x="2.62" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99,-234.5 99,-256.5 196,-256.5 196,-234.5 99,-234.5"/> | ||
| <text text-anchor="start" x="123.88" y="-240.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="196,-234.5 196,-256.5 232,-256.5 232,-234.5 196,-234.5"/> | ||
| <polygon fill="none" stroke="black" points="0,-212.5 0,-234.5 99,-234.5 99,-212.5 0,-212.5"/> | ||
| <text text-anchor="start" x="24" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99,-212.5 99,-234.5 196,-234.5 196,-212.5 99,-212.5"/> | ||
| <text text-anchor="start" x="101.75" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="196,-212.5 196,-234.5 232,-234.5 232,-212.5 196,-212.5"/> | ||
| <text text-anchor="start" x="209.5" y="-218.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">[]</text> | ||
| <polygon fill="none" stroke="black" points="0,-190.5 0,-212.5 99,-212.5 99,-190.5 0,-190.5"/> | ||
| <text text-anchor="start" x="15.75" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99,-190.5 99,-212.5 196,-212.5 196,-190.5 99,-190.5"/> | ||
| <text text-anchor="start" x="103.62" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="196,-190.5 196,-212.5 232,-212.5 232,-190.5 196,-190.5"/> | ||
| <text text-anchor="start" x="199.38" y="-196.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">None</text> | ||
| <polygon fill="none" stroke="black" points="0,-283.25 0,-305.75 233.25,-305.75 233.25,-283.25 0,-283.25"/> | ||
| <text text-anchor="start" x="100.5" y="-290.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Party</text> | ||
| <polygon fill="none" stroke="black" points="0,-260.75 0,-283.25 99.75,-283.25 99.75,-260.75 0,-260.75"/> | ||
| <text text-anchor="start" x="34.88" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-260.75 99.75,-283.25 197.25,-283.25 197.25,-260.75 99.75,-260.75"/> | ||
| <text text-anchor="start" x="141.75" y="-266.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="197.25,-260.75 197.25,-283.25 233.25,-283.25 233.25,-260.75 197.25,-260.75"/> | ||
| <polygon fill="none" stroke="black" points="0,-238.25 0,-260.75 99.75,-260.75 99.75,-238.25 0,-238.25"/> | ||
| <text text-anchor="start" x="3" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">formed_datetime</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-238.25 99.75,-260.75 197.25,-260.75 197.25,-238.25 99.75,-238.25"/> | ||
| <text text-anchor="start" x="124.88" y="-244.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">datetime</text> | ||
| <polygon fill="none" stroke="black" points="197.25,-238.25 197.25,-260.75 233.25,-260.75 233.25,-238.25 197.25,-238.25"/> | ||
| <polygon fill="none" stroke="black" points="0,-215.75 0,-238.25 99.75,-238.25 99.75,-215.75 0,-215.75"/> | ||
| <text text-anchor="start" x="24.38" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">members</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-215.75 99.75,-238.25 197.25,-238.25 197.25,-215.75 99.75,-215.75"/> | ||
| <text text-anchor="start" x="102.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">List[Adventurer]</text> | ||
| <polygon fill="none" stroke="black" points="197.25,-215.75 197.25,-238.25 233.25,-238.25 233.25,-215.75 197.25,-215.75"/> | ||
| <text text-anchor="start" x="210.75" y="-221.95" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">[]</text> | ||
| <polygon fill="none" stroke="black" points="0,-193.25 0,-215.75 99.75,-215.75 99.75,-193.25 0,-193.25"/> | ||
| <text text-anchor="start" x="16.12" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">active_quest</text> | ||
| <polygon fill="none" stroke="black" points="99.75,-193.25 99.75,-215.75 197.25,-215.75 197.25,-193.25 99.75,-193.25"/> | ||
| <text text-anchor="start" x="104.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[Quest]</text> | ||
| <polygon fill="none" stroke="black" points="197.25,-193.25 197.25,-215.75 233.25,-215.75 233.25,-193.25 197.25,-193.25"/> | ||
| <text text-anchor="start" x="200.62" y="-199.45" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">None</text> | ||
| </a> | ||
@@ -79,7 +79,7 @@ </g> | ||
| <title>erdantic.examples.pydantic.Party:e->erdantic.examples.pydantic.Adventurer:w</title> | ||
| <path fill="none" stroke="black" d="M241.92,-224.15C285.25,-230.11 291.51,-274.88 331.89,-283.91"/> | ||
| <polyline fill="none" stroke="black" points="232,-223.5 236.99,-223.83"/> | ||
| <polyline fill="none" stroke="black" points="236.99,-223.83 241.98,-224.16"/> | ||
| <polygon fill="black" stroke="black" points="336.72,-284.42 346.2,-289.94 342.03,-284.98 346.33,-285.43 346.33,-285.43 346.33,-285.43 342.03,-284.98 347.14,-280.99 336.72,-284.42"/> | ||
| <polyline fill="none" stroke="black" points="335.51,-284.29 330.54,-283.77"/> | ||
| <path fill="none" stroke="black" d="M243.21,-227.67C286.68,-233.77 292.49,-279.62 332.96,-288.88"/> | ||
| <polyline fill="none" stroke="black" points="233.25,-227 238.24,-227.34"/> | ||
| <polyline fill="none" stroke="black" points="238.24,-227.34 243.23,-227.67"/> | ||
| <polygon fill="black" stroke="black" points="337.85,-289.4 347.31,-294.94 343.15,-289.97 347.46,-290.43 347.46,-290.43 347.46,-290.43 343.15,-289.97 348.27,-285.99 337.85,-289.4"/> | ||
| <polyline fill="none" stroke="black" points="336.64,-289.27 331.67,-288.74"/> | ||
| </g> | ||
@@ -90,20 +90,20 @@ <!-- erdantic.examples.pydantic.Quest --> | ||
| <g id="a_node3"><a xlink:title="erdantic.examples.pydantic.Quest A task to complete, with some monetary reward. Attributes:    name (str): Name by which this quest is referred to    giver (QuestGiver): Person who offered the quest    reward_gold (int): Amount of gold to be rewarded for quest completion "> | ||
| <polygon fill="none" stroke="black" points="340,-128.5 340,-150.5 518,-150.5 518,-128.5 340,-128.5"/> | ||
| <text text-anchor="start" x="411.75" y="-135.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="340,-106.5 340,-128.5 414,-128.5 414,-106.5 340,-106.5"/> | ||
| <text text-anchor="start" x="362" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="414,-106.5 414,-128.5 482,-128.5 482,-106.5 414,-106.5"/> | ||
| <text text-anchor="start" x="441.25" y="-112.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="482,-106.5 482,-128.5 518,-128.5 518,-106.5 482,-106.5"/> | ||
| <polygon fill="none" stroke="black" points="340,-84.5 340,-106.5 414,-106.5 414,-84.5 340,-84.5"/> | ||
| <text text-anchor="start" x="363.12" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="414,-84.5 414,-106.5 482,-106.5 482,-84.5 414,-84.5"/> | ||
| <text text-anchor="start" x="416.88" y="-90.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="482,-84.5 482,-106.5 518,-106.5 518,-84.5 482,-84.5"/> | ||
| <polygon fill="none" stroke="black" points="340,-62.5 340,-84.5 414,-84.5 414,-62.5 340,-62.5"/> | ||
| <text text-anchor="start" x="342.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="414,-62.5 414,-84.5 482,-84.5 482,-62.5 414,-62.5"/> | ||
| <text text-anchor="start" x="440.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="482,-62.5 482,-84.5 518,-84.5 518,-62.5 482,-62.5"/> | ||
| <text text-anchor="start" x="489.88" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">100</text> | ||
| <polygon fill="none" stroke="black" points="341.25,-131 341.25,-153.5 519.75,-153.5 519.75,-131 341.25,-131"/> | ||
| <text text-anchor="start" x="413.25" y="-138.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">Quest</text> | ||
| <polygon fill="none" stroke="black" points="341.25,-108.5 341.25,-131 415.5,-131 415.5,-108.5 341.25,-108.5"/> | ||
| <text text-anchor="start" x="363.38" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="415.5,-108.5 415.5,-131 483.75,-131 483.75,-108.5 415.5,-108.5"/> | ||
| <text text-anchor="start" x="442.88" y="-114.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="483.75,-108.5 483.75,-131 519.75,-131 519.75,-108.5 483.75,-108.5"/> | ||
| <polygon fill="none" stroke="black" points="341.25,-86 341.25,-108.5 415.5,-108.5 415.5,-86 341.25,-86"/> | ||
| <text text-anchor="start" x="364.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">giver</text> | ||
| <polygon fill="none" stroke="black" points="415.5,-86 415.5,-108.5 483.75,-108.5 483.75,-86 415.5,-86"/> | ||
| <text text-anchor="start" x="418.5" y="-92.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="483.75,-86 483.75,-108.5 519.75,-108.5 519.75,-86 483.75,-86"/> | ||
| <polygon fill="none" stroke="black" points="341.25,-63.5 341.25,-86 415.5,-86 415.5,-63.5 341.25,-63.5"/> | ||
| <text text-anchor="start" x="344.25" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">reward_gold</text> | ||
| <polygon fill="none" stroke="black" points="415.5,-63.5 415.5,-86 483.75,-86 483.75,-63.5 415.5,-63.5"/> | ||
| <text text-anchor="start" x="442.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">int</text> | ||
| <polygon fill="none" stroke="black" points="483.75,-63.5 483.75,-86 519.75,-86 519.75,-63.5 483.75,-63.5"/> | ||
| <text text-anchor="start" x="491.62" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">100</text> | ||
| </a> | ||
@@ -115,9 +115,9 @@ </g> | ||
| <title>erdantic.examples.pydantic.Party:e->erdantic.examples.pydantic.Quest:w</title> | ||
| <path fill="none" stroke="black" d="M241.73,-200.8C281.01,-194.92 287.04,-153.51 321.33,-142.29"/> | ||
| <polyline fill="none" stroke="black" points="232,-201.5 236.99,-201.14"/> | ||
| <polyline fill="none" stroke="black" points="236.99,-201.14 241.97,-200.79"/> | ||
| <polyline fill="none" stroke="black" points="340,-139.5 335.06,-140.24"/> | ||
| <polygon fill="black" stroke="black" points="333.33,-135.44 334.81,-145.33 332.83,-145.63 331.35,-135.74 333.33,-135.44"/> | ||
| <polyline fill="none" stroke="black" points="335.06,-140.24 330.11,-140.98"/> | ||
| <ellipse fill="none" stroke="black" cx="325.66" cy="-141.65" rx="4" ry="4"/> | ||
| <path fill="none" stroke="black" d="M242.98,-203.8C282.3,-197.9 288.26,-156.32 322.57,-145.06"/> | ||
| <polyline fill="none" stroke="black" points="233.25,-204.5 238.24,-204.14"/> | ||
| <polyline fill="none" stroke="black" points="238.24,-204.14 243.22,-203.78"/> | ||
| <polyline fill="none" stroke="black" points="341.25,-142.25 336.31,-142.99"/> | ||
| <polygon fill="black" stroke="black" points="334.57,-138.2 336.06,-148.09 334.08,-148.38 332.6,-138.49 334.57,-138.2"/> | ||
| <polyline fill="none" stroke="black" points="336.31,-142.99 331.36,-143.74"/> | ||
| <ellipse fill="none" stroke="black" cx="326.91" cy="-144.4" rx="4" ry="4"/> | ||
| </g> | ||
@@ -128,21 +128,21 @@ <!-- erdantic.examples.pydantic.QuestGiver --> | ||
| <g id="a_node4"><a xlink:title="erdantic.examples.pydantic.QuestGiver A person who offers a task that needs completing. Attributes:    name (str): Name of this quest giver    faction (str): Faction that this quest giver belongs to    location (str): Location this quest giver can be found "> | ||
| <polygon fill="none" stroke="black" points="626,-84.5 626,-106.5 871,-106.5 871,-84.5 626,-84.5"/> | ||
| <text text-anchor="start" x="714.38" y="-91.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="626,-62.5 626,-84.5 675,-84.5 675,-62.5 626,-62.5"/> | ||
| <text text-anchor="start" x="635.5" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="675,-62.5 675,-84.5 750,-84.5 750,-62.5 675,-62.5"/> | ||
| <text text-anchor="start" x="705.75" y="-68.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="750,-62.5 750,-84.5 871,-84.5 871,-62.5 750,-62.5"/> | ||
| <polygon fill="none" stroke="black" points="626,-40.5 626,-62.5 675,-62.5 675,-40.5 626,-40.5"/> | ||
| <text text-anchor="start" x="631.75" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="675,-40.5 675,-62.5 750,-62.5 750,-40.5 675,-40.5"/> | ||
| <text text-anchor="start" x="677.62" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="750,-40.5 750,-62.5 871,-62.5 871,-40.5 750,-40.5"/> | ||
| <text text-anchor="start" x="795.88" y="-46.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">None</text> | ||
| <polygon fill="none" stroke="black" points="626,-18.5 626,-40.5 675,-40.5 675,-18.5 626,-18.5"/> | ||
| <text text-anchor="start" x="628.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="675,-18.5 675,-40.5 750,-40.5 750,-18.5 675,-18.5"/> | ||
| <text text-anchor="start" x="705.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="750,-18.5 750,-40.5 871,-40.5 871,-18.5 750,-18.5"/> | ||
| <text text-anchor="start" x="752.75" y="-24.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">"Adventurer's Guild"</text> | ||
| <polygon fill="none" stroke="black" points="627.75,-86 627.75,-108.5 874.5,-108.5 874.5,-86 627.75,-86"/> | ||
| <text text-anchor="start" x="717" y="-93.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-weight="bold" font-size="14.00">QuestGiver</text> | ||
| <polygon fill="none" stroke="black" points="627.75,-63.5 627.75,-86 677.25,-86 677.25,-63.5 627.75,-63.5"/> | ||
| <text text-anchor="start" x="637.5" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">name</text> | ||
| <polygon fill="none" stroke="black" points="677.25,-63.5 677.25,-86 753,-86 753,-63.5 677.25,-63.5"/> | ||
| <text text-anchor="start" x="708.38" y="-69.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="753,-63.5 753,-86 874.5,-86 874.5,-63.5 753,-63.5"/> | ||
| <polygon fill="none" stroke="black" points="627.75,-41 627.75,-63.5 677.25,-63.5 677.25,-41 627.75,-41"/> | ||
| <text text-anchor="start" x="633.75" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">faction</text> | ||
| <polygon fill="none" stroke="black" points="677.25,-41 677.25,-63.5 753,-63.5 753,-41 677.25,-41"/> | ||
| <text text-anchor="start" x="680.25" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">Optional[str]</text> | ||
| <polygon fill="none" stroke="black" points="753,-41 753,-63.5 874.5,-63.5 874.5,-41 753,-41"/> | ||
| <text text-anchor="start" x="799.12" y="-47.2" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">None</text> | ||
| <polygon fill="none" stroke="black" points="627.75,-18.5 627.75,-41 677.25,-41 677.25,-18.5 627.75,-18.5"/> | ||
| <text text-anchor="start" x="630.75" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">location</text> | ||
| <polygon fill="none" stroke="black" points="677.25,-18.5 677.25,-41 753,-41 753,-18.5 677.25,-18.5"/> | ||
| <text text-anchor="start" x="708.38" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">str</text> | ||
| <polygon fill="none" stroke="black" points="753,-18.5 753,-41 874.5,-41 874.5,-18.5 753,-18.5"/> | ||
| <text text-anchor="start" x="756" y="-24.7" font-family="Times New Roman,Times,Liberation Serif,serif" font-size="14.00">"Adventurer's Guild"</text> | ||
| </a> | ||
@@ -154,12 +154,12 @@ </g> | ||
| <title>erdantic.examples.pydantic.Quest:e->erdantic.examples.pydantic.QuestGiver:w</title> | ||
| <path fill="none" stroke="black" d="M527.87,-95.5C563.07,-95.5 577.8,-95.5 611.08,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="518,-95.5 523,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="523,-95.5 528,-95.5"/> | ||
| <polyline fill="none" stroke="black" points="626,-95.5 621,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="620,-90.5 620,-100.5 618,-100.5 618,-90.5 620,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="621,-95.5 616,-95.5"/> | ||
| <polygon fill="black" stroke="black" points="615,-90.5 615,-100.5 613,-100.5 613,-90.5 615,-90.5"/> | ||
| <polyline fill="none" stroke="black" points="616,-95.5 611,-95.5"/> | ||
| <path fill="none" stroke="black" d="M529.62,-97.25C564.82,-97.25 579.55,-97.25 612.83,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="519.75,-97.25 524.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="524.75,-97.25 529.75,-97.25"/> | ||
| <polyline fill="none" stroke="black" points="627.75,-97.25 622.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="621.75,-92.25 621.75,-102.25 619.75,-102.25 619.75,-92.25 621.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="622.75,-97.25 617.75,-97.25"/> | ||
| <polygon fill="black" stroke="black" points="616.75,-92.25 616.75,-102.25 614.75,-102.25 614.75,-92.25 616.75,-92.25"/> | ||
| <polyline fill="none" stroke="black" points="617.75,-97.25 612.75,-97.25"/> | ||
| </g> | ||
| </g> | ||
| </svg> |
+31
-0
@@ -8,2 +8,3 @@ from pathlib import Path | ||
| import erdantic.core | ||
| import erdantic.plugins | ||
@@ -38,1 +39,31 @@ OUTPUTS_DIR = Path(__file__).resolve().parent / "_outputs" | ||
| monkeypatch.setattr(erdantic.core, "__version__", "TEST") | ||
| @pytest.fixture() | ||
| def custom_plugin(): | ||
| """A custom plugin to test the plugin system.""" | ||
| class CustomBaseModel: ... | ||
| def is_custom_model(obj): | ||
| return ( | ||
| isinstance(obj, type) | ||
| and issubclass(obj, CustomBaseModel) | ||
| and obj is not CustomBaseModel | ||
| ) | ||
| def get_fields_from_custom_model(model): | ||
| return [] | ||
| key = "test_plugin" | ||
| erdantic.plugins.register_plugin( | ||
| key, | ||
| predicate_fn=is_custom_model, | ||
| get_fields_fn=get_fields_from_custom_model, | ||
| ) | ||
| yield key, CustomBaseModel, is_custom_model, get_fields_from_custom_model | ||
| # Cleanup | ||
| if key in erdantic.plugins._dict: | ||
| del erdantic.plugins._dict[key] |
+19
-0
| import filecmp | ||
| import re | ||
| import subprocess | ||
@@ -29,2 +30,5 @@ | ||
| import_object_from_name("erdantic.examples.pydantic.not_a_model_class") | ||
| with pytest.raises(RuntimeError) as excinfo: | ||
| import_object_from_name("tests.module_with_error.SomeModel") | ||
| assert str(excinfo.value) == "This is a test exception" | ||
@@ -210,2 +214,17 @@ | ||
| def test_list_plugins(): | ||
| result = runner.invoke(app, ["--list-plugins"]) | ||
| print(result.output) | ||
| assert result.exit_code == 0 | ||
| assert re.findall(r"\[X\]\s*pydantic", result.output) | ||
| def test_list_plugins_custom_plugin(custom_plugin): | ||
| key, _, _, _ = custom_plugin | ||
| result = runner.invoke(app, ["--list-plugins"]) | ||
| print(result.output) | ||
| assert result.exit_code == 0 | ||
| assert re.findall(rf"\[X\]\s*{key}", result.output) | ||
| def test_help(): | ||
@@ -212,0 +231,0 @@ """Test the CLI with --help flag.""" |
@@ -7,9 +7,4 @@ import builtins | ||
| import sys | ||
| from typing import Any, AnyStr, List, Literal, Optional, Tuple, TypeVar | ||
| from typing import Annotated, Any, AnyStr, List, Literal, Optional, Tuple, TypeVar | ||
| if sys.version_info >= (3, 9): | ||
| from typing import Annotated | ||
| else: | ||
| from typing_extensions import Annotated | ||
| import IPython.lib.pretty as IPython_pretty | ||
@@ -436,3 +431,3 @@ import pydantic | ||
| """Subclass things to add a third column with the field default value.""" | ||
| out_dir = outputs_dir / "test_score-test_subclass" | ||
| out_dir = outputs_dir / "test_core-test_subclass" | ||
| out_dir.mkdir() | ||
@@ -439,0 +434,0 @@ filename = "pydantic_with_default_column" |
| import dataclasses | ||
| from dataclasses import dataclass | ||
| from pprint import pprint | ||
| import sys | ||
| from typing import Optional | ||
| from typing import Annotated, Optional, get_type_hints | ||
| if sys.version_info >= (3, 9): | ||
| from typing import Annotated, get_type_hints | ||
| else: | ||
| from typing_extensions import Annotated, get_type_hints | ||
| import pytest | ||
@@ -13,0 +7,0 @@ |
@@ -13,3 +13,2 @@ import subprocess | ||
| list_plugins, | ||
| register_plugin, | ||
| ) | ||
@@ -21,26 +20,14 @@ import erdantic.plugins.attrs | ||
| def test_register_plugin(): | ||
| """Custom plugin can be sucessfully registered and used.""" | ||
| def test_register_plugin(custom_plugin): | ||
| """Custom plugin can be successfully registered and used.""" | ||
| class CustomBaseModel: ... | ||
| key, base_model, predicate_fn, get_fields_fn = custom_plugin | ||
| def is_custom_model(obj): | ||
| return ( | ||
| isinstance(obj, type) | ||
| and issubclass(obj, CustomBaseModel) | ||
| and obj is not CustomBaseModel | ||
| ) | ||
| assert key in list_plugins() | ||
| def get_fields_from_custom_model(model): | ||
| return [] | ||
| class MyModel(base_model): ... | ||
| register_plugin("test_plugin", is_custom_model, get_fields_from_custom_model) | ||
| assert "test_plugin" in list_plugins() | ||
| class MyModel(CustomBaseModel): ... | ||
| assert identify_field_extractor_fn(MyModel) == get_fields_from_custom_model | ||
| assert identify_field_extractor_fn(MyModel) == get_fields_fn | ||
| assert identify_field_extractor_fn(erdantic.examples.pydantic.Party) not in ( | ||
| get_fields_from_custom_model, | ||
| get_fields_fn, | ||
| None, | ||
@@ -99,3 +86,3 @@ ) | ||
| """Core plugins are loaded when erdantic is imported.""" | ||
| for key in ("attrs", "dataclasses", "pydantic", "pydantic_v1"): | ||
| for key in ("attrs", "dataclasses", "msgspec", "pydantic", "pydantic_v1"): | ||
| script = textwrap.dedent( | ||
@@ -102,0 +89,0 @@ f"""\ |
| name: docs-main | ||
| on: | ||
| push: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| jobs: | ||
| build: | ||
| name: Build docs from main | ||
| runs-on: "ubuntu-latest" | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: conda-incubator/setup-miniconda@v3 | ||
| with: | ||
| miniforge-version: latest | ||
| activate-environment: "" | ||
| use-mamba: true | ||
| - name: Install nox and uv | ||
| run: | | ||
| pipx install nox | ||
| pipx install uv | ||
| - name: Build documentation | ||
| run: | | ||
| nox -s docs --verbose | ||
| - name: Stage docs on gh-pages | ||
| working-directory: docs | ||
| run: | | ||
| git fetch origin gh-pages --depth=1 | ||
| git config user.name github-actions[bot] | ||
| git config user.email 41898282+github-actions[bot]@users.noreply.github.com | ||
| RUN_MIKE="conda run -p ../.nox/docs mike" | ||
| $RUN_MIKE deploy --push ~latest --title=latest | ||
| deploy: | ||
| name: Deploy docs to Netlify | ||
| needs: build | ||
| runs-on: "ubuntu-latest" | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: gh-pages | ||
| - name: Deploy docs to Netlify | ||
| uses: nwtgck/actions-netlify@v1.1 | ||
| with: | ||
| publish-dir: "./" | ||
| production-deploy: true | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| deploy-message: "Deploy from GitHub Actions" | ||
| enable-pull-request-comment: false | ||
| enable-commit-comment: false | ||
| overwrites-pull-request-comment: false | ||
| env: | ||
| NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} | ||
| NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} | ||
| timeout-minutes: 1 |
-141
| # erdantic Changelog | ||
| ## v1.0.5 (2024-09-19) | ||
| - Fixed runtime `AttributeError` that occurred when creating a diagram that includes a model with a field that uses a type annotation with the ellipsis literal (e.g., `tuple[int, ...]`). ([Issue #124](https://github.com/drivendataorg/erdantic/issues/124), [PR #127](https://github.com/drivendataorg/erdantic/pull/127)) | ||
| ## v1.0.4 (2024-07-16) | ||
| - Fixed handling of `typing.Annotated` in cases where it's not the outermost generic type. ([Issue #122](https://github.com/drivendataorg/erdantic/issues/122), [PR #123](https://github.com/drivendataorg/erdantic/pull/123)) | ||
| ## v1.0.3 (2024-05-10) | ||
| - Fixed `StopIteration` error when rendering a model that has no fields. ([Issue #120](https://github.com/drivendataorg/erdantic/issues/120), [PR #121](https://github.com/drivendataorg/erdantic/pull/121)) | ||
| ## v1.0.2 (2024-04-11) | ||
| - Fixed `AttributeError` when adding a model that has a field annotated with certain typing special forms like `Any`, `Literal`, or `TypeVar` instances. ([Issue #114](https://github.com/drivendataorg/erdantic/issues/114), [PR #115](https://github.com/drivendataorg/erdantic/pull/115)) | ||
| ## v1.0.1 (2024-04-10) | ||
| - Fixed `ModuleNotFoundError` when importing from `erdantic.examples` without attrs installed. | ||
| ## v1.0.0.post2 (2024-04-10) | ||
| - Fixed missing LICENSE file in sdist. | ||
| ## v1.0.0.post1 (2024-04-09) | ||
| - Fixed outdated note in README. | ||
| ## v1.0.0 (2024-04-09) | ||
| > [!IMPORTANT] | ||
| > This release features significant changes to erdantic, primarily to the backend process of analyzing models and representing data. If you have been primarily using the CLI or the convenience functions `create`, `draw`, and `to_dot`, then your code may continue to work without any changes. If you are doing something more advanced, you may need to update your code. | ||
| ### CLI changes | ||
| - Deprecated `--termini` option. Use the new `--terminal-model` option instead. The shorthand option `-t` remains the same. The `--termini` option still works but will emit a deprecation warning. | ||
| ### Convenience function changes | ||
| - Deprecated `termini` argument for `create`, `draw`, and `to_dot` functions. Use the new `terminal_models` argument instead. The `termini` argument still works but will emit a deprecation warning. | ||
| - Added `graph_attr`, `node_attr`, and `edge_attr` arguments to the `draw` and `to_dot` functions that allow you to override attributes on the generated pygraphviz object for the diagram. | ||
| ### Visual changes | ||
| A few changes have been made to the visual content of rendered diagrams. | ||
| - Changed the extraction of type names to use the [typenames](https://github.com/jayqi/typenames) library. This should generally produce identical rendered outputs as before, with the following exception: | ||
| - Removed the special case behavior for rendering enum classes. Enums now just show the class name without inheritance information. | ||
| - Changed collection fields (e.g., `List[TargetModel]`) to display as a "many" relationship (crow) instead of a "zero-or-many" relationship (odot + crow), treating the modality of the field as unspecified. A field will only be displayed as "zero-or-many" (odot + crow) if it is explicitly optional, like `Optional[List[TargetModel]]`. | ||
| - Fixed incorrect representation of manyness for type annotations where the outermost annotation wasn't a collection type. ([Issue #105](https://github.com/drivendataorg/erdantic/issues/105)) | ||
| ### Support for attrs | ||
| - Added support for [attrs](https://www.attrs.org/en/stable/index.html) classes, i.e., classes decorated by `attrs.define`. The source code for attrs support can be found in the new module `erdantic.plugins.attrs`. | ||
| - Added new example module `erdantic.examples.attrs`. | ||
| ### Backend changes | ||
| Significant changes have been made to the library backend to more strongly separate the model analysis process, the extracted data, and the diagram rendering process. We believe this more structured design facilitates customizing diagrams and simplifies the implementation for each data modeling framework. Please see the new documentation pages ["Customizing diagrams"](http://erdantic.drivendata.org/v1.0/customizing/) and ["Extending or modifying erdantic"](http://erdantic.drivendata.org/v1.0/extending/) for details on the new design. | ||
| A summary of some key changes is below: | ||
| - Removed the adapter base classes `Model` and `Field` and the conrete adapters `DataClassModel`, `DataClassField`, `PydanticModel`, and `PydanticField`. | ||
| - Added new Pydantic models `ModelInfo` and `FieldInfo` to replace the adapter system. These new models hold static data that have been extracted from models that erdantic analyzed. | ||
| - Removed the adapter system and associated objects such as `model_adapter_registry` and `register_model_adapter`. | ||
| - Added new plugin system to replace the adapter system as the way that modeling frameworks are supported. Plugins must implement two functions—a predicate function and a field extractor function—and be registered using `register_plugin`. All objects related to plugins can be found in the new `erdantic.plugins` module and its submodules. | ||
| - Renamed `erdantic.typing` module to `erdantic.typing_utils`. | ||
| ### Other | ||
| - Added [PEP 561 `py.typed` marker file](https://peps.python.org/pep-0561/#packaging-type-information) to indicate that the package supports type checking. | ||
| - Added IPython special method for pretty-print string representations of `EntityRelationshipDiagram` instances. | ||
| - Removed support for Python 3.7. ([PR #102](https://github.com/drivendataorg/erdantic/pull/102)) | ||
| ## v0.7.1 (2024-04-09) | ||
| This will be the last version that supports Python 3.7. | ||
| - Added version typer version ceiling of `< 0.10.0` due to incompatibility with a fix introduced in that version. | ||
| ## v0.7.0 (2024-02-11) | ||
| - Added support for Pydantic V1 legacy models. These are models created from the `pydantic.v1` namespace when Pydantic V2 is installed. ([PR #94](https://github.com/drivendataorg/erdantic/pull/94) from [@ursereg](https://github.com/ursereg)) | ||
| ## v0.6.0 (2023-07-09) | ||
| - Added support for Pydantic V2. | ||
| - Removed support for Pydantic V1. | ||
| - Changed the init signature for `PydanticField` to work with Pydantic V2's API. | ||
| - Added `is_many` and `is_nullable` functions to `erdantic.typing`. | ||
| ## v0.5.1 (2023-07-04) | ||
| - Changed Pydantic dependency to be `< 2`. This will be the final version of erdantic that supports Pydantic V1. | ||
| - Changed to pyproject.toml-based build. | ||
| ## v0.5.0 (2022-07-29) | ||
| - Removed support for Python 3.6. ([Issue #51](https://github.com/drivendataorg/erdantic/issues/51), [PR #56](https://github.com/drivendataorg/erdantic/pull/56)) | ||
| - Added support for modules as inputs to all entrypoints to diagram creation (`create`, `draw`, `to_dot`, CLI). For all modules passed, erdantic will find all supported data model classes in each module. ([Issue #23](https://github.com/drivendataorg/erdantic/issues/23), [PR #58](https://github.com/drivendataorg/erdantic/pull/58)) | ||
| - Added new parameter `limit_search_models_to` to all entrypoints to allow for limiting which data model classes will be yielded from searching a module. | ||
| ## v0.4.1 (2022-04-08) | ||
| - Fixed error when rendering a data model that has field using `typing.Literal`. ([PR #49](https://github.com/drivendataorg/erdantic/pull/49)) | ||
| ## v0.4.0 (2021-11-06) | ||
| - Added support for showing field documentation from Pydantic models with descriptions set with `Field(description=...)` in SVG tooltips. This will add an "Attributes" section to the tooltip using Google-style docstring format and lists fields where the `description` keyword argument is used. ([Issue #8](https://github.com/drivendataorg/erdantic/issues/8#issuecomment-958905131), [PR #42](https://github.com/drivendataorg/erdantic/pull/42)) | ||
| ## v0.3.0 (2021-10-28) | ||
| - Fixed handling of forward references in field type declarations. Evaluated forward references will be properly identified. Forward references not converted to `typing.ForwardRef` will throw a `StringForwardRefError` with instructions for how to resolve. Unevaluated forward references will throw an `UnevaluatedForwardRefError` with instructions for how to resolve. See [new documentation](https://erdantic.drivendata.org/stable/forward-references/) for more details. ([Issue #40](https://github.com/drivendataorg/erdantic/issues/40), [PR #41](https://github.com/drivendataorg/erdantic/pull/41)) | ||
| - Changed name of `erdantic.errors` module to `erdantic.exceptions`. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| - Added new `ErdanticException` base class from which other exceptions raised within the erdantic library are subclassed from. Changed several existing `ValueError` exceptions to new exception classes that subclass both `ErdanticException` and `ValueError`. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| - Changed `__lt__` method on `Model` and `Edge` to return `NotImplemented` instead of raising an exception to follow typical convention for unsupported input types. ([PR #41](https://github.com/drivendataorg/erdantic/issues/41)) | ||
| ## v0.2.1 (2021-02-16) | ||
| - Fixed runtime error when rendering a data model that had a field containing `typing.Any`. ([Issue #25](https://github.com/drivendataorg/erdantic/issues/25), [PR #26](https://github.com/drivendataorg/erdantic/issues/26)) | ||
| ## v0.2.0 (2021-02-14) | ||
| - Added option to specify models as terminal nodes. This allows you to truncate large diagrams and split them up into smaller ones. ([PR #24](https://github.com/drivendataorg/erdantic/pull/24)) | ||
| ## v0.1.2 (2021-02-10) | ||
| - Fixed bug where Pydantic fields were missing generics in their type annotations. ([PR #19](https://github.com/drivendataorg/erdantic/pull/19)) | ||
| - Added tests against static rendered DOT output. Change adapter tests to use parameterized fixtures. ([PR #21](https://github.com/drivendataorg/erdantic/pull/21)) | ||
| ## v0.1.1 (2021-02-10) | ||
| - Fixed rendered example image in the package description on PyPI. ([PR #18](https://github.com/drivendataorg/erdantic/pull/18)) | ||
| ## v0.1.0 (2021-02-10) | ||
| Initial release! 🎉 |
-88
| .PHONY: clean clean-docs clean-pyc clean-test clean-build docs format lint release release-test test help | ||
| .DEFAULT_GOAL := help | ||
| define PRINT_HELP_PYSCRIPT | ||
| import re, sys | ||
| for line in sys.stdin: | ||
| match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) | ||
| if match: | ||
| target, help = match.groups() | ||
| print("%-20s %s" % (target, help)) | ||
| endef | ||
| export PRINT_HELP_PYSCRIPT | ||
| clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts | ||
| clean-build: ## remove build artifacts | ||
| rm -fr build/ | ||
| rm -fr dist/ | ||
| rm -fr .eggs/ | ||
| find . -name '*.egg-info' -exec rm -fr {} + | ||
| find . -name '*.egg' -exec rm -f {} + | ||
| clean-pyc: ## remove Python file artifacts | ||
| find . -name '*.pyc' -exec rm -f {} + | ||
| find . -name '*.pyo' -exec rm -f {} + | ||
| find . -name '*~' -exec rm -f {} + | ||
| find . -name '__pycache__' -exec rm -fr {} + | ||
| clean-test: ## remove test and coverage artifacts | ||
| rm -fr .tox/ | ||
| rm -f .coverage | ||
| rm -f coverage.xml | ||
| rm -fr htmlcov/ | ||
| rm -fr .pytest_cache | ||
| dist: clean ## builds source and wheel package | ||
| python -m build | ||
| ls -l dist | ||
| docs: clean-docs ## build documentation | ||
| echo "# CLI Help Documentation\n" > docs/docs/cli.md | ||
| @echo '```bash' >> docs/docs/cli.md | ||
| @echo "erdantic --help" >> docs/docs/cli.md | ||
| @echo '```' >> docs/docs/cli.md | ||
| @echo "" >> docs/docs/cli.md | ||
| @echo '```' >> docs/docs/cli.md | ||
| @erdantic --help >> docs/docs/cli.md | ||
| @echo '```' >> docs/docs/cli.md | ||
| sed 's|https://raw.githubusercontent.com/drivendataorg/erdantic/main/docs/docs/examples/pydantic.svg|examples/pydantic.svg|g' README.md \ | ||
| | sed 's|https://erdantic.drivendata.org/stable/||g' \ | ||
| > docs/docs/index.md | ||
| sed 's|https://erdantic.drivendata.org/stable/||g' HISTORY.md > docs/docs/changelog.md | ||
| rm -f docs/docs/examples/diagram.png | ||
| cd docs && mkdocs build | ||
| docs-notebooks: | ||
| rm -f docs/docs/examples/diagram.png | ||
| jupyter nbconvert --execute --clear-output docs/docs/examples/pydantic.ipynb | ||
| rm -f docs/docs/examples/diagram.png | ||
| jupyter nbconvert --execute --clear-output docs/docs/examples/dataclasses.ipynb | ||
| rm -f docs/docs/examples/diagram.png | ||
| format: ## format code with black | ||
| ruff format erdantic tests docs | ||
| ruff check --fix erdantic tests docs | ||
| help: | ||
| @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) | ||
| lint: ## run linting and code quality checks | ||
| ruff format --check erdantic tests docs | ||
| ruff check erdantic tests docs | ||
| pypitest: dist | ||
| twine upload --repository testpypi dist/* | ||
| requirements: ## install development requirements | ||
| pip install -r requirements-dev.txt | ||
| static-test-assets: | ||
| python tests/scripts/generate_static_assets.py | ||
| test: ## run tests | ||
| python -m pytest -vv | ||
| typecheck: ## run mypy typechecking | ||
| mypy --install-types --non-interactive erdantic |
-156
| from pathlib import Path | ||
| import platform | ||
| import shutil | ||
| import nox | ||
| def find_uv() -> tuple[bool, str]: | ||
| # Inspired by: | ||
| # https://github.com/wntrblm/nox/blob/08813c3c6b0d2171c280bbfcf219d089a16d1ac2/nox/virtualenv.py#L42 | ||
| uv = shutil.which("uv") | ||
| if uv is not None: | ||
| return True, uv | ||
| return False, "uv" | ||
| HAS_UV, UV = find_uv() | ||
| @nox.session(venv_backend="mamba|conda", python="3.11", reuse_venv=True) | ||
| def dev(session): | ||
| """Set up a development environment.""" | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", "-r", "requirements/dev.txt", external=True) | ||
| else: | ||
| session.install("-r", "requirements/dev.txt") | ||
| conda_cmd = session.virtualenv.conda_cmd | ||
| env_path = Path(session.virtualenv.location).relative_to(Path.cwd()) | ||
| session.log(f"Activate with: {conda_cmd} activate {env_path}") | ||
| @nox.session(venv_backend="uv|virtualenv", python="3.11", reuse_venv=True) | ||
| def lint(session): | ||
| session.env.pop("CONDA_PREFIX", None) # uv errors if both venv and conda env are active | ||
| session.install("-r", "requirements/lint.txt") | ||
| session.run("ruff", "format", "--check") | ||
| session.run("ruff", "check") | ||
| @nox.session(venv_backend="mamba|conda", python="3.11", reuse_venv=True) | ||
| def typecheck(session): | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", "-r", "requirements/typecheck.txt", external=True) | ||
| else: | ||
| session.install("-r", "requirements/typecheck.txt") | ||
| session.run("mypy", "--install-types", "--non-interactive") | ||
| class CoverageCleaner: | ||
| """Global coverage cleaner to clean up coverage artifacts once per nox invocation.""" | ||
| def __init__(self): | ||
| self.been_run = False | ||
| def clean(self, session): | ||
| if not self.been_run: | ||
| session.log("Cleaning up coverage artifacts.") | ||
| self.been_run = True | ||
| Path(".coverage").unlink(missing_ok=True) | ||
| Path("coverage.xml").unlink(missing_ok=True) | ||
| shutil.rmtree("htmlcov", ignore_errors=True) | ||
| coverage_cleaner = CoverageCleaner() | ||
| @nox.session( | ||
| venv_backend="mamba|conda", | ||
| python=["3.8", "3.9", "3.10", "3.11", "3.12"], | ||
| reuse_venv=True, | ||
| ) | ||
| def tests(session): | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", "-r", "requirements/tests.txt", external=True) | ||
| else: | ||
| session.install("-r", "requirements/tests.txt") | ||
| coverage_cleaner.clean(session) | ||
| session.run("pytest", "-vv") | ||
| @nox.session(venv_backend="uv|virtualenv", reuse_venv=True) | ||
| def build(session): | ||
| session.env.pop("CONDA_PREFIX", None) # uv errors if both venv and conda env are active | ||
| session.install("build") | ||
| session.run("python", "-m", "build") | ||
| @nox.session(venv_backend="mamba|conda", python="3.12", reuse_venv=False) | ||
| @nox.parametrize("extras", ["", "[attrs]"]) | ||
| def test_wheel(session, extras): | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| wheel_path = next(Path("dist").glob("*.whl")).resolve() | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", f"erdantic{extras} @ {wheel_path}", external=True) | ||
| else: | ||
| session.install(str(wheel_path) + extras) | ||
| session.run("python", "-m", "erdantic", "--version") | ||
| session.run( | ||
| "python", "-c", "import erdantic; import erdantic.examples; print(erdantic.list_plugins())" | ||
| ) | ||
| @nox.session(venv_backend="mamba|conda", python="3.12", reuse_venv=False) | ||
| def test_sdist(session): | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| sdist_path = next(Path("dist").glob("*.tar.gz")).resolve() | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", f"erdantic @ {sdist_path}", external=True) | ||
| else: | ||
| session.install(sdist_path) | ||
| session.run("python", "-m", "erdantic", "--version") | ||
| session.run( | ||
| "python", "-c", "import erdantic; import erdantic.examples; print(erdantic.list_plugins())" | ||
| ) | ||
| def _docs_base(session): | ||
| session.conda_install("graphviz", channel="conda-forge") | ||
| if platform.system() == "Windows": | ||
| session.conda_install("pygraphviz", channel="conda-forge") | ||
| if HAS_UV: | ||
| session.run(UV, "pip", "install", "-r", "requirements/docs.txt", external=True) | ||
| else: | ||
| session.install("-r", "requirements/docs.txt") | ||
| examples_dir = Path("docs/docs/examples").resolve() | ||
| examples_dir.mkdir(exist_ok=True) | ||
| for notebook_path in sorted(Path("docs/notebooks").glob("*.ipynb")): | ||
| out_path = examples_dir / notebook_path.name | ||
| session.run("jupyter", "execute", f"--output={out_path}", notebook_path) | ||
| @nox.session(venv_backend="mamba|conda", python="3.11", reuse_venv=True) | ||
| def docs(session): | ||
| _docs_base(session) | ||
| with session.chdir("docs"): | ||
| session.run("mkdocs", "build") | ||
| @nox.session(venv_backend="mamba|conda", python="3.11", reuse_venv=True) | ||
| def docs_serve(session): | ||
| _docs_base(session) | ||
| with session.chdir("docs"): | ||
| session.run("mkdocs", "serve") |
| -e .[attrs] | ||
| -r lint.txt | ||
| ipython | ||
| ipykernel |
| -e .[attrs] | ||
| black | ||
| markdown-callouts>=0.4.0 | ||
| mdx_truly_sane_lists==1.3 | ||
| mike | ||
| mkdocs>=1.4 | ||
| mkdocs-jupyter | ||
| mkdocs-material>=7.2.6 | ||
| mkdocstrings[python]>=0.19.0 | ||
| nbconvert>=7.7.0 | ||
| rich |
| ruff>=0.1.14 |
| -e .[attrs] | ||
| filetype | ||
| ipython | ||
| pytest<8 | ||
| pytest-cases | ||
| pytest-cov | ||
| rich |
| attrs | ||
| mypy | ||
| pydantic>=2 | ||
| sortedcontainers-pydantic | ||
| typenames | ||
| typer |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
2363809
38.88%114
3.64%5000
3.8%