dv_schema_models 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: dv_schema_models
3
+ Version: 0.9.0
4
+ Summary: Turns Harvard Dataverse Project metadatablocks schema and dataset JSON into Pydantic models.
5
+ Author: Ken Lui
6
+ Author-email: Ken Lui <kenlh.lui@utoronto.ca>
7
+ License-Expression: MIT
8
+ Requires-Dist: pydantic>=2.0.0
9
+ Requires-Dist: pydantic-settings>=2.0.0
10
+ Requires-Python: >=3.10, <4.0
11
+ Project-URL: homepage, https://github.com/kenlhlui/dv_schema_models
12
+ Project-URL: source, https://github.com/kenlhlui/dv_schema_models
13
+ Project-URL: changelog, https://github.com/kenlhlui/dv_schema_models/blob/main/CHANGELOG.md
14
+ Project-URL: releasenotes, https://github.com/kenlhlui/dv_schema_models/releases
15
+ Project-URL: documentation, https://kenlhlui.github.io/dv_schema_models
16
+ Project-URL: issues, https://github.com/kenlhlui/dv_schema_models/issues
17
+ Description-Content-Type: text/markdown
18
+
19
+ # dv_schema_models
20
+
21
+ Pydantic models for Dataverse metadata — parse the schema, load dataset
22
+ exports, and validate field values against the schema.
23
+
24
+ > [!CAUTION]
25
+ > This library is under active development and the API is not yet stable. Breaking changes may occur between releases. Please pin to a specific version in your `pyproject.toml` or `requirements.txt` if you want to avoid surprises.
26
+
27
+ ## Pre-requisites
28
+ 1. Python 3.10+
29
+
30
+ ## Installation
31
+
32
+ 1. With `uv` (recommended):
33
+ ```bash
34
+ uv add dv_schema_models
35
+ ```
36
+
37
+ 2. With `pip`:
38
+ ```bash
39
+ pip install dv_schema_models
40
+ ```
41
+
42
+ To export schemas to Excel (see [usage #5](#5-export-the-schema-to-a-spreadsheet)), install with the `spreadsheet` extra:
43
+ ```bash
44
+ uv add "dv_schema_models[spreadsheet]" # or: pip install "dv_schema_models[spreadsheet]"
45
+ ```
46
+
47
+ ## Concepts
48
+
49
+ | Thing | What it is |
50
+ |---|---|
51
+ | **Schema** | `/api/metadatablocks` response — defines what fields *can* exist, their types, and rules |
52
+ | **Dataset instance** | `GET /api/datasets/:id` response — the actual metadata values for one dataset |
53
+ | **Record model** | A Pydantic model *generated from* the schema, used to validate instance values |
54
+
55
+ ## Usage
56
+
57
+ ### 1. Load and query the schema
58
+
59
+ ```python
60
+ import json
61
+ from dv_schema_models.dataverse_schema import load_schema
62
+
63
+ schema = load_schema(json.load(open("dv_schema.json")))
64
+
65
+ schema.block_names() # ['citation', 'geospatial', ...]
66
+ block = schema.get_block("citation")
67
+ block.fields.keys() # top-level field names
68
+ block.required_fields() # leaf fields where isRequired=True
69
+ block.all_leaf_fields() # flattened, including nested compound fields
70
+
71
+ field = block.get_field("keyword")
72
+ field.is_compound() # True — has childFields
73
+ field.iter_leaf_fields() # [keywordValue, keywordVocabulary, ...]
74
+ ```
75
+
76
+ ### 2. Load a dataset and read values
77
+
78
+ ```python
79
+ import json
80
+ from dv_schema_models.dataset_instance import IsPartOf, load_dataset
81
+
82
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
83
+
84
+ # Load the possible typeNames for a given block
85
+ dataset.field_names("citation") # ['title', 'author', 'keyword', ...]
86
+ dataset.data.latestVersion.metadataBlocks.get("citation").field_names() # same
87
+
88
+
89
+ # Shortcut from the top level
90
+ dataset.get_value("citation", "title") # plain string
91
+
92
+ # Or drill down
93
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
94
+ block.get_value("keyword") # unwrapped Python value (str / list / dict)
95
+ block.get_field("author").simple_value() # [{'authorName': 'Author1', 'authorAffiliation': 'Author1Aff'...} ... {'authorName': 'Author2', 'authorAffiliation': 'Author2Aff'...}]
96
+
97
+ # Pull one subfield out of a compound field
98
+ block.get_subfield_values("author", "authorName") # ['Author1', 'Author2']
99
+
100
+ # Walk the isPartOf chain (dataset -> collection -> parent collection -> ...), possibly None
101
+ IsPartOf.get_field_list(dataset.data.isPartOf, "identifier") # ['sub-collection', 'top-collection']
102
+ ```
103
+
104
+ ### 3. Work with files
105
+
106
+ ```python
107
+ from dv_schema_models.dataset_instance import load_dataset
108
+ from dv_schema_models.file_instance import FileInstance
109
+
110
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
111
+
112
+ files = dataset.data.latestVersion.files or []
113
+ FileInstance.sum_field(files, "filesize") # sum a DataFile field across files, e.g. total filesize
114
+ FileInstance.list_field(files, "dataFile.filename") # list a field's values across files, dotted path for nested fields
115
+ ```
116
+
117
+ `sum_field` skips files with no `dataFile` or a `None` value for the field. Returns `None` (and logs a warning) if any present value isn't numeric.
118
+
119
+ `list_field` takes a dotted path (e.g. `"restricted"` for a top-level field, `"dataFile.checksum.type"` for a nested one) and skips entries where the path is missing or `None`.
120
+
121
+ ### 4. Work with role assignments
122
+
123
+ ```python
124
+ import json
125
+ from dv_schema_models.role_assignments import load_role_assignments
126
+
127
+ role_assignments = load_role_assignments(json.load(open("ds_role_assignments.json")))
128
+
129
+ role_assignments.count_field("assignee") # number of assignments with an "assignee" field
130
+ role_assignments.count_field("roleName", "Curator") # number of assignments where roleName == "Curator"
131
+ role_assignments.get_value("assignee") # ['@personA', '@personB', ...]
132
+
133
+ # Fields not on the schema (e.g. the `_roleAlias` Dataverse sends) are still reachable
134
+ role_assignments.data[0].get_raw("_roleAlias") # 'curator'
135
+ ```
136
+
137
+ `load_role_assignments` also accepts the error envelope Dataverse returns when the request isn't permitted (`{"status": "ERROR", "message": "..."}`) — `data` is `None`, and `message` is reachable via `role_assignments.model_extra`.
138
+
139
+ ### 5. Validate instance values against the schema
140
+
141
+ ```python
142
+ import json
143
+ from dv_schema_models.dataverse_schema import load_schema
144
+ from dv_schema_models.dataset_instance import load_dataset
145
+ from dv_schema_models.schema_driven_records import build_record_model, flatten_instance
146
+
147
+
148
+ schema = load_schema(json.load(open("dv_schema.json")))
149
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
150
+
151
+ citation_schema = schema.get_block("citation")
152
+ CitationRecord = build_record_model(citation_schema) # dynamic Pydantic model
153
+
154
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
155
+ raw = flatten_instance(block) # {typeName: value, ...}
156
+ record = CitationRecord.model_validate(raw)
157
+ ```
158
+
159
+ The generated model enforces field names, required/optional status, list wrapping for `multiple=True` fields, and `int`/`float` types where declared by the schema.
160
+
161
+ ### 6. Discover available fields
162
+
163
+ ```python
164
+ # Fields actually present in this dataset instance
165
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
166
+ block.field_names() # e.g. ['title', 'author', 'keyword', ...]
167
+
168
+ # All fields the schema defines (including absent/optional ones)
169
+ schema.get_block("citation").all_leaf_fields().keys()
170
+
171
+ # After validation, access as typed attributes
172
+ record = CitationRecord.model_validate(flatten_instance(block))
173
+ record.title # str
174
+ record.author # list[...] for multiple=True compound fields
175
+ record.keyword # None if not present in this dataset (optional fields default to None)
176
+ # Note: field names with dots become underscores — e.g. 'resolution.Spatial' → record.resolution_Spatial
177
+ ```
178
+
179
+ ### 7. Export the schema to a spreadsheet
180
+
181
+ Requires the `spreadsheet` extra (see [Installation](#installation)).
182
+
183
+ ```python
184
+ import json
185
+ from dv_schema_models.dataverse_schema import load_schema
186
+ from dv_schema_models.schema_spreadsheet import SchemaSpreadsheet
187
+
188
+ schema = load_schema(json.load(open("dv_schema.json")))
189
+ SchemaSpreadsheet(schema).write("dv_schema.xlsx")
190
+ ```
191
+
192
+ Writes an `.xlsx` workbook with one formatted worksheet per metadata block plus a combined **All** sheet. See [docs/schema_spreadsheet/README.md](docs/schema_spreadsheet/README.md) for the output layout, column mapping, and architecture.
193
+
194
+ ## Input file shapes
195
+
196
+ **Schema** — output of Dataverse `/api/metadatablocks`:
197
+ ```json
198
+ {"status": "OK", "data": [{"id": 10, "name": "citation", "fields": {...}}]}
199
+ ```
200
+
201
+ **Dataset** — output of Dataverse `GET /api/datasets/:id`:
202
+ ```json
203
+ {"status": "OK", "data": {"latestVersion": {"metadataBlocks": {"citation": {"fields": [...]}}}}}
204
+ ```
205
+
206
+ **Role assignments** — output of Dataverse `GET /api/datasets/:id/assignments`:
207
+ ```json
208
+ {"status": "OK", "data": [{"id": 1, "assignee": "@user", "roleId": 7, "roleName": "Curator", "definitionPointId": 34847}]}
209
+ ```
210
+ Error responses (e.g. `{"status": "ERROR", "message": "..."}`, no `data` key) are also accepted — see [usage #4](#4-work-with-role-assignments).
211
+
212
+ ## Citation
213
+ If you use this library in your work, please cite according to [CITATION](CITATION.cff)
214
+
215
+ ## License
216
+ [MIT](LICENSE)
@@ -0,0 +1,198 @@
1
+ # dv_schema_models
2
+
3
+ Pydantic models for Dataverse metadata — parse the schema, load dataset
4
+ exports, and validate field values against the schema.
5
+
6
+ > [!CAUTION]
7
+ > This library is under active development and the API is not yet stable. Breaking changes may occur between releases. Please pin to a specific version in your `pyproject.toml` or `requirements.txt` if you want to avoid surprises.
8
+
9
+ ## Pre-requisites
10
+ 1. Python 3.10+
11
+
12
+ ## Installation
13
+
14
+ 1. With `uv` (recommended):
15
+ ```bash
16
+ uv add dv_schema_models
17
+ ```
18
+
19
+ 2. With `pip`:
20
+ ```bash
21
+ pip install dv_schema_models
22
+ ```
23
+
24
+ To export schemas to Excel (see [usage #5](#5-export-the-schema-to-a-spreadsheet)), install with the `spreadsheet` extra:
25
+ ```bash
26
+ uv add "dv_schema_models[spreadsheet]" # or: pip install "dv_schema_models[spreadsheet]"
27
+ ```
28
+
29
+ ## Concepts
30
+
31
+ | Thing | What it is |
32
+ |---|---|
33
+ | **Schema** | `/api/metadatablocks` response — defines what fields *can* exist, their types, and rules |
34
+ | **Dataset instance** | `GET /api/datasets/:id` response — the actual metadata values for one dataset |
35
+ | **Record model** | A Pydantic model *generated from* the schema, used to validate instance values |
36
+
37
+ ## Usage
38
+
39
+ ### 1. Load and query the schema
40
+
41
+ ```python
42
+ import json
43
+ from dv_schema_models.dataverse_schema import load_schema
44
+
45
+ schema = load_schema(json.load(open("dv_schema.json")))
46
+
47
+ schema.block_names() # ['citation', 'geospatial', ...]
48
+ block = schema.get_block("citation")
49
+ block.fields.keys() # top-level field names
50
+ block.required_fields() # leaf fields where isRequired=True
51
+ block.all_leaf_fields() # flattened, including nested compound fields
52
+
53
+ field = block.get_field("keyword")
54
+ field.is_compound() # True — has childFields
55
+ field.iter_leaf_fields() # [keywordValue, keywordVocabulary, ...]
56
+ ```
57
+
58
+ ### 2. Load a dataset and read values
59
+
60
+ ```python
61
+ import json
62
+ from dv_schema_models.dataset_instance import IsPartOf, load_dataset
63
+
64
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
65
+
66
+ # Load the possible typeNames for a given block
67
+ dataset.field_names("citation") # ['title', 'author', 'keyword', ...]
68
+ dataset.data.latestVersion.metadataBlocks.get("citation").field_names() # same
69
+
70
+
71
+ # Shortcut from the top level
72
+ dataset.get_value("citation", "title") # plain string
73
+
74
+ # Or drill down
75
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
76
+ block.get_value("keyword") # unwrapped Python value (str / list / dict)
77
+ block.get_field("author").simple_value() # [{'authorName': 'Author1', 'authorAffiliation': 'Author1Aff'...} ... {'authorName': 'Author2', 'authorAffiliation': 'Author2Aff'...}]
78
+
79
+ # Pull one subfield out of a compound field
80
+ block.get_subfield_values("author", "authorName") # ['Author1', 'Author2']
81
+
82
+ # Walk the isPartOf chain (dataset -> collection -> parent collection -> ...), possibly None
83
+ IsPartOf.get_field_list(dataset.data.isPartOf, "identifier") # ['sub-collection', 'top-collection']
84
+ ```
85
+
86
+ ### 3. Work with files
87
+
88
+ ```python
89
+ from dv_schema_models.dataset_instance import load_dataset
90
+ from dv_schema_models.file_instance import FileInstance
91
+
92
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
93
+
94
+ files = dataset.data.latestVersion.files or []
95
+ FileInstance.sum_field(files, "filesize") # sum a DataFile field across files, e.g. total filesize
96
+ FileInstance.list_field(files, "dataFile.filename") # list a field's values across files, dotted path for nested fields
97
+ ```
98
+
99
+ `sum_field` skips files with no `dataFile` or a `None` value for the field. Returns `None` (and logs a warning) if any present value isn't numeric.
100
+
101
+ `list_field` takes a dotted path (e.g. `"restricted"` for a top-level field, `"dataFile.checksum.type"` for a nested one) and skips entries where the path is missing or `None`.
102
+
103
+ ### 4. Work with role assignments
104
+
105
+ ```python
106
+ import json
107
+ from dv_schema_models.role_assignments import load_role_assignments
108
+
109
+ role_assignments = load_role_assignments(json.load(open("ds_role_assignments.json")))
110
+
111
+ role_assignments.count_field("assignee") # number of assignments with an "assignee" field
112
+ role_assignments.count_field("roleName", "Curator") # number of assignments where roleName == "Curator"
113
+ role_assignments.get_value("assignee") # ['@personA', '@personB', ...]
114
+
115
+ # Fields not on the schema (e.g. the `_roleAlias` Dataverse sends) are still reachable
116
+ role_assignments.data[0].get_raw("_roleAlias") # 'curator'
117
+ ```
118
+
119
+ `load_role_assignments` also accepts the error envelope Dataverse returns when the request isn't permitted (`{"status": "ERROR", "message": "..."}`) — `data` is `None`, and `message` is reachable via `role_assignments.model_extra`.
120
+
121
+ ### 5. Validate instance values against the schema
122
+
123
+ ```python
124
+ import json
125
+ from dv_schema_models.dataverse_schema import load_schema
126
+ from dv_schema_models.dataset_instance import load_dataset
127
+ from dv_schema_models.schema_driven_records import build_record_model, flatten_instance
128
+
129
+
130
+ schema = load_schema(json.load(open("dv_schema.json")))
131
+ dataset = load_dataset(json.load(open("ds_metadata.json")))
132
+
133
+ citation_schema = schema.get_block("citation")
134
+ CitationRecord = build_record_model(citation_schema) # dynamic Pydantic model
135
+
136
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
137
+ raw = flatten_instance(block) # {typeName: value, ...}
138
+ record = CitationRecord.model_validate(raw)
139
+ ```
140
+
141
+ The generated model enforces field names, required/optional status, list wrapping for `multiple=True` fields, and `int`/`float` types where declared by the schema.
142
+
143
+ ### 6. Discover available fields
144
+
145
+ ```python
146
+ # Fields actually present in this dataset instance
147
+ block = dataset.data.latestVersion.metadataBlocks.get("citation")
148
+ block.field_names() # e.g. ['title', 'author', 'keyword', ...]
149
+
150
+ # All fields the schema defines (including absent/optional ones)
151
+ schema.get_block("citation").all_leaf_fields().keys()
152
+
153
+ # After validation, access as typed attributes
154
+ record = CitationRecord.model_validate(flatten_instance(block))
155
+ record.title # str
156
+ record.author # list[...] for multiple=True compound fields
157
+ record.keyword # None if not present in this dataset (optional fields default to None)
158
+ # Note: field names with dots become underscores — e.g. 'resolution.Spatial' → record.resolution_Spatial
159
+ ```
160
+
161
+ ### 7. Export the schema to a spreadsheet
162
+
163
+ Requires the `spreadsheet` extra (see [Installation](#installation)).
164
+
165
+ ```python
166
+ import json
167
+ from dv_schema_models.dataverse_schema import load_schema
168
+ from dv_schema_models.schema_spreadsheet import SchemaSpreadsheet
169
+
170
+ schema = load_schema(json.load(open("dv_schema.json")))
171
+ SchemaSpreadsheet(schema).write("dv_schema.xlsx")
172
+ ```
173
+
174
+ Writes an `.xlsx` workbook with one formatted worksheet per metadata block plus a combined **All** sheet. See [docs/schema_spreadsheet/README.md](docs/schema_spreadsheet/README.md) for the output layout, column mapping, and architecture.
175
+
176
+ ## Input file shapes
177
+
178
+ **Schema** — output of Dataverse `/api/metadatablocks`:
179
+ ```json
180
+ {"status": "OK", "data": [{"id": 10, "name": "citation", "fields": {...}}]}
181
+ ```
182
+
183
+ **Dataset** — output of Dataverse `GET /api/datasets/:id`:
184
+ ```json
185
+ {"status": "OK", "data": {"latestVersion": {"metadataBlocks": {"citation": {"fields": [...]}}}}}
186
+ ```
187
+
188
+ **Role assignments** — output of Dataverse `GET /api/datasets/:id/assignments`:
189
+ ```json
190
+ {"status": "OK", "data": [{"id": 1, "assignee": "@user", "roleId": 7, "roleName": "Curator", "definitionPointId": 34847}]}
191
+ ```
192
+ Error responses (e.g. `{"status": "ERROR", "message": "..."}`, no `data` key) are also accepted — see [usage #4](#4-work-with-role-assignments).
193
+
194
+ ## Citation
195
+ If you use this library in your work, please cite according to [CITATION](CITATION.cff)
196
+
197
+ ## License
198
+ [MIT](LICENSE)
@@ -0,0 +1,158 @@
1
+ [build-system] # https://docs.astral.sh/uv/concepts/build-backend/
2
+ requires = ["uv_build>=0.11.31,<0.12"]
3
+ build-backend = "uv_build"
4
+
5
+ [project] # https://packaging.python.org/en/latest/specifications/pyproject-toml/
6
+ name = "dv_schema_models"
7
+ version = "0.9.0"
8
+ description = "Turns Harvard Dataverse Project metadatablocks schema and dataset JSON into Pydantic models."
9
+ readme = "README.md"
10
+
11
+ authors = [
12
+ { name = "Ken Lui", email = "kenlh.lui@utoronto.ca" },
13
+ ]
14
+ requires-python = ">=3.10,<4.0"
15
+ dependencies = [
16
+ "pydantic (>=2.0.0)",
17
+ "pydantic-settings (>=2.0.0)",
18
+ ]
19
+ license = "MIT"
20
+
21
+ [project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels
22
+ homepage = "https://github.com/kenlhlui/dv_schema_models"
23
+ source = "https://github.com/kenlhlui/dv_schema_models"
24
+ changelog = "https://github.com/kenlhlui/dv_schema_models/blob/main/CHANGELOG.md"
25
+ releasenotes = "https://github.com/kenlhlui/dv_schema_models/releases"
26
+ documentation = "https://kenlhlui.github.io/dv_schema_models"
27
+ issues = "https://github.com/kenlhlui/dv_schema_models/issues"
28
+
29
+ [dependency-groups] # https://docs.astral.sh/uv/concepts/projects/dependencies/#development-dependencies
30
+ dev = [
31
+ "codespell (>=2.4.1)",
32
+ "commitizen (>=4.3.0)",
33
+ "coverage[toml] (>=7.6.10)",
34
+ "ipykernel (>=6.29.4)",
35
+ "ipython (>=8.18.0)",
36
+ "ipywidgets (>=8.1.2)",
37
+ "zensical (>=0.0.51)",
38
+ "mkdocstrings[python] (>=0.26.2)",
39
+ "poethepoet (>=0.32.1)",
40
+ "prek",
41
+ "pytest (>=8.3.4)",
42
+ "pytest-mock (>=3.14.0)",
43
+ "pytest-xdist (>=3.6.1)",
44
+ "ruff (>=0.9.2)",
45
+ "ty (>=0.0.6)",
46
+ "mkdocstrings-python (>=2.0.5)",
47
+ "httpx2>=2.5.0",
48
+ ]
49
+
50
+ [tool.codespell] # https://github.com/codespell-project/codespell
51
+ builtin = "en-GB_to_en-US,clear,code,rare"
52
+ check-filenames = true
53
+ skip = "./*_cache/,./.venv,./reports"
54
+
55
+ [tool.commitizen] # https://commitizen-tools.github.io/commitizen/config/
56
+ bump_message = "bump: v$current_version → v$new_version"
57
+ tag_format = "v$version"
58
+ update_changelog_on_bump = true
59
+ version_provider = "uv"
60
+ version_scheme = "pep440"
61
+
62
+ [tool.coverage.report] # https://coverage.readthedocs.io/en/latest/config.html#report
63
+ precision = 1
64
+ show_missing = true
65
+ skip_covered = true
66
+
67
+ [tool.coverage.run] # https://coverage.readthedocs.io/en/latest/config.html#run
68
+ branch = true
69
+ command_line = "--module pytest"
70
+ data_file = "reports/.coverage"
71
+ source = ["src"]
72
+
73
+ [tool.coverage.xml] # https://coverage.readthedocs.io/en/latest/config.html#xml
74
+ output = "reports/coverage.xml"
75
+
76
+ [tool.pytest.ini_options] # https://docs.pytest.org/en/latest/reference/reference.html#ini-options-ref
77
+ addopts = "--color=yes --doctest-modules --exitfirst --failed-first --verbosity=2 --junitxml=reports/pytest.xml"
78
+ testpaths = ["src", "tests"]
79
+ xfail_strict = true
80
+
81
+ [tool.ruff] # https://docs.astral.sh/ruff/settings/
82
+ fix = true
83
+ line-length = 100
84
+ src = ["src", "tests"]
85
+ target-version = "py310"
86
+
87
+ [tool.ruff.format]
88
+ docstring-code-format = true
89
+ skip-magic-trailing-comma = true
90
+
91
+ [tool.ruff.lint]
92
+ select = ["ALL"]
93
+ ignore = ["CPY", "FIX", "T20", "ARG001", "COM812", "D203", "D213", "E501", "PD008", "PD009", "PGH003", "RET504", "S101", "TD003"]
94
+ unfixable = ["ERA001", "F401", "F841", "T201", "T203"]
95
+
96
+ [tool.ruff.lint.flake8-annotations]
97
+ allow-star-arg-any = true
98
+ ignore-fully-untyped = true
99
+
100
+ [tool.ruff.lint.flake8-tidy-imports]
101
+ ban-relative-imports = "all"
102
+
103
+ [tool.ruff.lint.isort]
104
+ split-on-trailing-comma = false
105
+
106
+ [tool.ruff.lint.pycodestyle]
107
+ max-doc-length = 100
108
+
109
+ [tool.ruff.lint.pydocstyle]
110
+ convention = "numpy"
111
+
112
+ [tool.ty.environment]
113
+ python-platform = "all"
114
+
115
+ [tool.ty.rules]
116
+ unused-ignore-comment = "warn"
117
+
118
+ [tool.poe.executor] # https://github.com/nat-n/poethepoet
119
+ type = "simple"
120
+
121
+ [tool.poe.tasks]
122
+
123
+ [tool.poe.tasks.docs]
124
+ help = "Build or serve the documentation"
125
+ shell = """
126
+ if [ $serve ]
127
+ then {
128
+ zensical serve
129
+ } else {
130
+ zensical build
131
+ } fi
132
+ """
133
+
134
+ [[tool.poe.tasks.docs.args]]
135
+ help = "Serve the documentation locally with live reload"
136
+ type = "boolean"
137
+ name = "serve"
138
+ options = ["--serve"]
139
+
140
+ [tool.poe.tasks.lint]
141
+ help = "Lint this package"
142
+ cmd = """
143
+ prek run
144
+ --all-files
145
+ --color always
146
+ """
147
+
148
+ [tool.poe.tasks.test]
149
+ help = "Test this package"
150
+
151
+ [[tool.poe.tasks.test.sequence]]
152
+ cmd = "coverage run"
153
+
154
+ [[tool.poe.tasks.test.sequence]]
155
+ cmd = "coverage report"
156
+
157
+ [[tool.poe.tasks.test.sequence]]
158
+ cmd = "coverage xml"
@@ -0,0 +1 @@
1
+ """dv_schema_models."""