Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,30 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version}}
- name: Install Poetry with pipx
run: pipx install poetry
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r dev-requirements.txt
run: poetry install --no-root
- name: Run tests
run: python -m pytest --cov=record_validator/
run: poetry run python -m pytest --cov=record_validator/ --cov-report=xml
- name: Send report to Coveralls
uses: AndreMiras/coveralls-python-action@develop
uses: coverallsapp/github-action@v2
with:
parallel: true
github-token: ${{ secrets.GITHUB_TOKEN}}
flag-name: ${{ matrix.python-version}}
finish:
needs: test
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: AndreMiras/coveralls-python-action@develop
- name: Coveralls finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
24 changes: 12 additions & 12 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "4.0" \
annotated-types==0.7.0 ; python_version >= "3.10" \
--hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \
--hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89
colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" \
colorama==0.4.6 ; python_version >= "3.10" and sys_platform == "win32" \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
coverage[toml]==7.6.1 ; python_version >= "3.10" and python_version < "4.0" \
coverage==7.6.1 ; python_version >= "3.10" \
--hash=sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca \
--hash=sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d \
--hash=sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6 \
Expand Down Expand Up @@ -80,16 +80,16 @@ coverage[toml]==7.6.1 ; python_version >= "3.10" and python_version < "4.0" \
exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \
--hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \
--hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc
iniconfig==2.0.0 ; python_version >= "3.10" and python_version < "4.0" \
iniconfig==2.0.0 ; python_version >= "3.10" \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
packaging==24.1 ; python_version >= "3.10" and python_version < "4.0" \
packaging==24.1 ; python_version >= "3.10" \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
pluggy==1.5.0 ; python_version >= "3.10" and python_version < "4.0" \
pluggy==1.5.0 ; python_version >= "3.10" \
--hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \
--hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669
pydantic-core==2.20.1 ; python_version >= "3.10" and python_version < "4.0" \
pydantic-core==2.20.1 ; python_version >= "3.10" \
--hash=sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d \
--hash=sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f \
--hash=sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686 \
Expand Down Expand Up @@ -179,21 +179,21 @@ pydantic-core==2.20.1 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f \
--hash=sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a \
--hash=sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27
pydantic==2.8.2 ; python_version >= "3.10" and python_version < "4.0" \
pydantic==2.8.2 ; python_version >= "3.10" \
--hash=sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a \
--hash=sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8
pymarc==5.2.2 ; python_version >= "3.10" and python_version < "4.0" \
pymarc==5.2.2 ; python_version >= "3.10" \
--hash=sha256:0913b4167a4337190598914c3642c5ae4f0f64a26bc4316f380cc54f65d8a741 \
--hash=sha256:d654ee1faae5d80845b7a44b27deb6ea9b5377994d16aeba5d3e19e7856d7d43
pytest-cov==5.0.0 ; python_version >= "3.10" and python_version < "4.0" \
pytest-cov==5.0.0 ; python_version >= "3.10" \
--hash=sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652 \
--hash=sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857
pytest==8.3.2 ; python_version >= "3.10" and python_version < "4.0" \
pytest==8.3.2 ; python_version >= "3.10" \
--hash=sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5 \
--hash=sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce
tomli==2.0.1 ; python_version >= "3.10" and python_full_version <= "3.11.0a6" \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "4.0" \
typing-extensions==4.12.2 ; python_version >= "3.10" \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
25 changes: 21 additions & 4 deletions poetry.lock

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

28 changes: 18 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
[tool.poetry]
[project]
name = "record-validator"
version = "0.1.0"
description = ""
authors = ["Charlotte Kostelic <charlottekostelic@gmail.com>"]
version = "0.1.1"
description = "MARC record validator for shelf-ready materials"
authors = [{name = "Charlotte Kostelic", email = "charlottekostelic@bookops.org"}]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.10"
pydantic = "^2.8.2"
pymarc = "^5.2.2"

requires-python = ">=3.10"
dependencies = [
"pydantic (>=2.8.2)",
"pymarc (>=5.2.2)"
]

[tool.poetry.group.dev.dependencies]
pytest = "^8.3.2"
pytest-cov = "^5.0.0"

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = '--cov=overload_web/'

[tool.coverage.run]
relative_files = true
source = ["."]
omit = ["tests/*"]

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["E501"]

[[tool.mypy.overrides]]
module = ["tests.*"]
disallow_untyped_defs = false
4 changes: 3 additions & 1 deletion record_validator/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
"""

from typing import Annotated, Union
from pydantic import Tag, Discriminator, TypeAdapter

from pydantic import Discriminator, Tag, TypeAdapter
from pymarc import Field as MarcField

from record_validator.constants import AllFields
from record_validator.field_models import (
AuxBibCallNo,
Expand Down
4 changes: 3 additions & 1 deletion record_validator/base_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ class for all control field models.
"""

from typing import Annotated, Any, Dict, List, Literal, Union
from pymarc import Field as MarcField

from pydantic import BaseModel, ConfigDict, Field, model_serializer, model_validator
from pymarc import Field as MarcField

from record_validator.constants import AllFields, AllSubfields


Expand Down
3 changes: 2 additions & 1 deletion record_validator/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ class ValidOrderItems(Enum):
"""

MAB = {"order_location": "MAB", "item_location": "rcmb2", "item_type": "2"}
MAS = {"order_location": "MAS", "item_location": "rcmb2", "item_type": "2"}
MAF = {"order_location": "MAF", "item_location": "rcmf2", "item_type": "55"}
MAF_NO_ITEM_TYPE = {
"order_location": "MAF",
Expand Down Expand Up @@ -144,6 +143,8 @@ class ValidOrderItems(Enum):
"item_type": None,
}
MAP = {"order_location": "MAP", "item_location": "rcmp2", "item_type": "2"}
MAS = {"order_location": "MAS", "item_location": "rcmb2", "item_type": "2"}
PAD = {"order_location": "PAD", "item_location": "rcpd2", "item_type": "55"}
PAH = {"order_location": "PAH", "item_location": "rcph2", "item_type": "55"}
PAH_NO_ITEM_TYPE = {
"order_location": "PAH",
Expand Down
5 changes: 4 additions & 1 deletion record_validator/field_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""This module contains classes that define MARC fields provided in vendor records"""

from typing import Annotated, Any, Dict, List, Literal, Optional, Union

from pydantic import Field, model_validator
from record_validator.base_fields import BaseDataField, BaseControlField

from record_validator.base_fields import BaseControlField, BaseDataField


class AuxBibCallNo(BaseDataField):
Expand Down Expand Up @@ -341,6 +343,7 @@ class ItemField(BaseDataField):
"rc2ma",
"rcmp2",
"rcmb2",
"rcpd2",
"rcph2",
"rcpm2",
"rcpt2",
Expand Down
2 changes: 2 additions & 0 deletions record_validator/marc_errors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""A module to translate errors from the validator to a more readable format"""

from typing import Any, Dict, List, Tuple, Union

from pydantic_core import ErrorDetails

from record_validator.adapters import get_adapter
from record_validator.constants import AllFields, AllSubfields

Expand Down
7 changes: 3 additions & 4 deletions record_validator/marc_models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""This module contains pydantic models for validating vendor-provided MARC records."""

from typing import Annotated, Dict, List, Union

from pydantic import BaseModel, ConfigDict, Field
from pydantic.functional_validators import AfterValidator, BeforeValidator
from pymarc import Field as MarcField
from record_validator.validators import (
validate_leader,
validate_all,
)

from record_validator.validators import validate_all, validate_leader


class RecordModel(BaseModel):
Expand Down
6 changes: 2 additions & 4 deletions record_validator/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""This module contains utility functions for working with MARC records."""

from itertools import chain
import re
from itertools import chain
from typing import Any, Dict, List, Union

from pymarc import Field as MarcField


Expand Down Expand Up @@ -59,7 +60,6 @@ def get_record_type(fields: List[Union[MarcField, Dict[str, Any]]]) -> str:
subject_fields = [i for i in field_list if next(iter(i)).startswith("6")]

aux_call_nos = list(chain(*[dict2subfield(i, "h") for i in aux_call_no_fields]))
order_locs = list(chain(*[dict2subfield(i, "t") for i in field_list if "960" in i]))
phys_desc = list(chain(*[dict2subfield(i, "a") for i in field_list if "300" in i]))
subjects = list(chain(*[dict2subfield(i, "v") for i in subject_fields]))

Expand All @@ -71,8 +71,6 @@ def get_record_type(fields: List[Union[MarcField, Dict[str, Any]]]) -> str:
material_type = "other"
elif any(j is not None for j in [catalogue.match(str(i)) for i in subjects]):
material_type = "other"
elif any(i == "PAD" for i in order_locs) is True:
material_type = "other"
elif any(j is not None for j in [multivol.match(str(i)) for i in phys_desc]):
material_type = "other"
elif any(j is not None for j in [pamphlet.match(str(i)) for i in phys_desc]):
Expand Down
Loading