Skip to content

Data models

Results are dataclasses with serialisation helpers. to_dict() and to_json() convert dates to strings and binary PDF values to null. exclude_none=True omits these null fields; it does not remove every empty string or list.

CaseInfo describes a search hit; CaseDetail describes the fuller CNR case page. JudgmentResult preserves a live portal result, while Judgment is the common archive/facade shape. These distinctions matter for missing fields and PDF retrieval.

models

Data models for bharat-judgements.

All models are dataclasses with built-in JSON serialization via to_dict() and to_json(). Date fields serialize to ISO 8601 strings. Enum fields serialize to their string values. Binary fields (pdf_bytes) are excluded from serialization by default.

Judgment dataclass

Judgment(
    cnr: str | None = None,
    case_id: str | None = None,
    title: str | None = None,
    court: Court | None = None,
    court_name_raw: str = "",
    bench: str | None = None,
    court_code: str | None = None,
    judges: list[str] = list(),
    author_judge: str | None = None,
    decision_date: date | None = None,
    date_of_registration: date | None = None,
    petitioner: str | None = None,
    respondent: str | None = None,
    citation: str | None = None,
    disposal_nature: str | None = None,
    description: str | None = None,
    pdf_path: str | None = None,
    available_languages: list[str] = list(),
    pdf_exists: bool | None = None,
    source: str = "archive",
    year: int | None = None,
)

Bases: _Serializable

A delivered judgment, source-agnostic.

Populated by the archive client (parquet metadata) and, in later phases, by the live judgment-search clients via a federated facade. Fields that don't apply to a given source are left None / empty.

JudgmentResult dataclass

JudgmentResult(
    title: str,
    court_name: str,
    case_number: str = "",
    judgment_date: date | None = None,
    judges: list[str] = list(),
    pdf_url: str = "",
    pdf_bytes: bytes | None = None,
    citation: str = "",
    bench_type: str = "",
    source_url: str = "",
    source_id: str = "",
    metadata: dict = dict(),
)

Bases: _Serializable

A judgment from the judgment search portal.

CaseInfo dataclass

CaseInfo(
    case_number: str,
    case_type: str,
    cnr_number: str = "",
    filing_number: str = "",
    registration_number: str = "",
    registration_date: date | None = None,
    petitioner: str = "",
    respondent: str = "",
    status: str = "",
    court_name: str = "",
    judges: list[str] = list(),
    next_hearing_date: date | None = None,
)

Bases: _Serializable

Basic case metadata from a search result.

CaseDetail dataclass

CaseDetail(
    cnr_number: str = "",
    case_type: str = "",
    filing_number: str = "",
    filing_date: date | None = None,
    registration_number: str = "",
    registration_date: date | None = None,
    first_hearing_date: date | None = None,
    next_hearing_date: date | None = None,
    decision_date: date | None = None,
    case_stage: str = "",
    status: str = "",
    coram: str = "",
    bench_type: str = "",
    court_number_and_judge: str = "",
    court_name: str = "",
    state: str = "",
    district: str = "",
    petitioners: list[PartyEntry] = list(),
    respondents: list[PartyEntry] = list(),
    acts: list[ActEntry] = list(),
    history: list[HearingEntry] = list(),
    orders: list[CaseOrder] = list(),
)

Bases: _Serializable

Full case record from a CNR lookup.

This is deliberately richer than :class:CaseInfo, which models a search result. A CNR lookup returns the whole case page — status, stage, the bench, every party with their advocates, the acts invoked, the complete hearing history and the orders — none of which a search response carries.

Fields absent from a given portal are left at their default rather than guessed: district courts report court_number_and_judge where High Courts report coram plus bench_type.

is_disposed property

is_disposed: bool

True when the portal has recorded a decision date.

PartyEntry dataclass

PartyEntry(name: str, advocate: str = '')

Bases: _Serializable

A party to a case, with the advocate(s) appearing for them.

ActEntry dataclass

ActEntry(act: str, sections: str = '')

Bases: _Serializable

An act and the sections invoked under it.

HearingEntry dataclass

HearingEntry(
    hearing_date: date | None = None,
    business_date: date | None = None,
    purpose: str = "",
    judge: str = "",
    cause_list_type: str = "",
)

Bases: _Serializable

One row of a case's hearing history.

cause_list_type and judge are only populated where the portal supplies them — district court history tables carry a judge but no cause list type, High Court tables carry both but often leave judge blank.

AdvocateSearch dataclass

AdvocateSearch(
    raw_name: str = "",
    name: str = "",
    code: str = "",
    total_records: int = 0,
    cases: list[CaseInfo] = list(),
)

Bases: _Serializable

An advocate search, with the advocate the portal resolved it to.

The response envelope echoes back who it matched — a bar code of G/504/2011 is answered with adv_name: "MR. HEMAL SHAH(6960)" — and that echo is the only confirmation available that a bar code is real. Nothing else validates one: the portal's own form takes the state part as free text on both High Court and district, so a wrong code is not an error, just a search that finds nothing.

code is the portal's internal advocate id, not a bar number and not accepted as one.

found property

found: bool

Whether the portal recognised the advocate.

True even with no cases: an advocate can exist and have nothing pending, and telling that apart from a mistyped bar code is the whole point of this class.

to_dict

to_dict(*, exclude_none: bool = False) -> dict[str, Any]

Override to carry found through serialization.

It is a property, so the field-walking base implementation would drop the one flag this class exists to expose and leave every JSON consumer recomputing it. Same reason :class:SearchResult overrides for total_pages.

Source code in src/bharat_judgements/models.py
def to_dict(self, *, exclude_none: bool = False) -> dict[str, Any]:
    """Override to carry ``found`` through serialization.

    It is a property, so the field-walking base implementation would drop
    the one flag this class exists to expose and leave every JSON
    consumer recomputing it. Same reason :class:`SearchResult` overrides
    for ``total_pages``.
    """
    result = super().to_dict(exclude_none=exclude_none)
    result["found"] = self.found
    return result

CaseOrder dataclass

CaseOrder(
    order_date: date,
    order_type: str,
    judge: str = "",
    pdf_url: str = "",
    pdf_bytes: bytes | None = None,
    order_text: str = "",
    neutral_citation: str = "",
)

Bases: _Serializable

A single order/judgment attached to a case.

CauseListPDF dataclass

CauseListPDF(
    serial_number: int,
    bench: str,
    cause_list_type: str = "",
    pdf_url: str = "",
    pdf_bytes: bytes | None = None,
)

Bases: _Serializable

A cause list PDF from HC Services.

The portal returns a table of PDF links, one per bench/judge. Each entry contains the bench name, list type, and a URL to the PDF.

CauseListEntry dataclass

CauseListEntry(
    serial_number: int,
    case_number: str,
    case_type: str = "",
    petitioner: str = "",
    respondent: str = "",
    advocate_petitioner: str = "",
    advocate_respondent: str = "",
    court_number: str = "",
    judge: str = "",
    listing_date: date | None = None,
    business_date: date | None = None,
    item_number: str = "",
    cnr_number: str = "",
    purpose: str = "",
)

Bases: _Serializable

An entry from a court's cause list (daily schedule).

Note: HC Services returns cause lists as PDFs per bench/judge. Use :class:CauseListPDF for the actual portal response. This model is retained for parsed/structured cause list data.

SearchResult dataclass

SearchResult(
    items: list[
        CaseInfo | JudgmentResult | CauseListEntry
    ] = list(),
    total_count: int = 0,
    page: int = 1,
    page_size: int = 10,
    has_next: bool = False,
)

Bases: _Serializable

Paginated search result container.

to_dict

to_dict(*, exclude_none: bool = False) -> dict[str, Any]

Override to properly serialize nested items.

Source code in src/bharat_judgements/models.py
def to_dict(self, *, exclude_none: bool = False) -> dict[str, Any]:
    """Override to properly serialize nested items."""
    result = {
        "total_count": self.total_count,
        "page": self.page,
        "page_size": self.page_size,
        "has_next": self.has_next,
        "total_pages": self.total_pages,
        "items": [item.to_dict(exclude_none=exclude_none) for item in self.items],
    }
    return result

Court dataclass

Court(
    name: str,
    code: str,
    state_code: str,
    court_type: CourtType,
    bench: str | None = None,
    judgment_code: str = "",
)

Bases: _Serializable

An Indian court with its eCourts identifiers.

judgment_compound_code property

judgment_compound_code: str

Compound code for judgments portal: {judgment_code}~{state_code}.

CourtType

Bases: str, Enum