Skip to content

Commit 6c7f4c3

Browse files
oschwaldclaude
andcommitted
Convert Metadata class to dataclass
Convert the pure Python `maxminddb.reader.Metadata` class to use @DataClass(kw_only=True) for cleaner, more maintainable code. Changes: - Added dataclass import and decorator - Removed manual __init__ method (15+ lines of boilerplate) - Removed custom __repr__ method - Preserved @Property methods for node_byte_size and search_tree_size - All functionality remains identical Breaking change: The __repr__ format changes from `maxminddb.reader.Metadata(...)` to `Metadata(...)`. This is documented in HISTORY.rst. The C extension's Metadata class is unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 89abe7e commit 6c7f4c3

2 files changed

Lines changed: 17 additions & 44 deletions

File tree

HISTORY.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ History
2222
Python 3.12+ isolated subinterpreters, multiple independent module
2323
instances, and future-proofing for Python 3.14's InterpreterPoolExecutor.
2424
Requested by R. Christian McDonald in GitHub #105.
25+
* **BREAKING**: The pure Python ``maxminddb.reader.Metadata`` class has been
26+
converted to a dataclass. The ``__repr__`` format has changed from
27+
``maxminddb.reader.Metadata(...)`` to ``Metadata(...)``. If you depend on
28+
the exact string representation of the Metadata object, you will need to
29+
update your code. All functionality remains the same, including the
30+
``node_byte_size`` and ``search_tree_size`` properties. The C extension's
31+
Metadata class is unchanged.
2532

2633
2.8.2 (2025-07-25)
2734
++++++++++++++++++

maxminddb/reader.py

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import contextlib
1111
import ipaddress
1212
import struct
13+
from dataclasses import dataclass
1314
from ipaddress import IPv4Address, IPv6Address
1415
from typing import IO, TYPE_CHECKING, Any, AnyStr
1516

@@ -307,6 +308,7 @@ def __enter__(self) -> Self:
307308
return self
308309

309310

311+
@dataclass(kw_only=True)
310312
class Metadata:
311313
"""Metadata for the MaxMind DB reader."""
312314

@@ -323,19 +325,13 @@ class Metadata:
323325
"""
324326

325327
build_epoch: int
326-
"""
327-
The Unix epoch for the build time of the database.
328-
"""
328+
"""The Unix epoch for the build time of the database."""
329329

330330
database_type: str
331-
"""
332-
A string identifying the database type, e.g., "GeoIP2-City".
333-
"""
331+
"""A string identifying the database type, e.g., "GeoIP2-City"."""
334332

335333
description: dict[str, str]
336-
"""
337-
A map from locales to text descriptions of the database.
338-
"""
334+
"""A map from locales to text descriptions of the database."""
339335

340336
ip_version: int
341337
"""
@@ -345,50 +341,20 @@ class Metadata:
345341
"""
346342

347343
languages: list[str]
348-
"""
349-
A list of locale codes supported by the database.
350-
"""
344+
"""A list of locale codes supported by the database."""
351345

352346
node_count: int
353-
"""
354-
The number of nodes in the database.
355-
"""
347+
"""The number of nodes in the database."""
356348

357349
record_size: int
358-
"""
359-
The bit size of a record in the search tree.
360-
"""
361-
362-
def __init__(self, **kwargs) -> None:
363-
"""Create new Metadata object. kwargs are key/value pairs from spec."""
364-
# Although I could just update __dict__, that is less obvious and it
365-
# doesn't work well with static analysis tools and some IDEs
366-
self.node_count = kwargs["node_count"]
367-
self.record_size = kwargs["record_size"]
368-
self.ip_version = kwargs["ip_version"]
369-
self.database_type = kwargs["database_type"]
370-
self.languages = kwargs["languages"]
371-
self.binary_format_major_version = kwargs["binary_format_major_version"]
372-
self.binary_format_minor_version = kwargs["binary_format_minor_version"]
373-
self.build_epoch = kwargs["build_epoch"]
374-
self.description = kwargs["description"]
350+
"""The bit size of a record in the search tree."""
375351

376352
@property
377353
def node_byte_size(self) -> int:
378-
"""The size of a node in bytes.
379-
380-
:type: int
381-
"""
354+
"""The size of a node in bytes."""
382355
return self.record_size // 4
383356

384357
@property
385358
def search_tree_size(self) -> int:
386-
"""The size of the search tree.
387-
388-
:type: int
389-
"""
359+
"""The size of the search tree."""
390360
return self.node_count * self.node_byte_size
391-
392-
def __repr__(self) -> str:
393-
args = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
394-
return f"{self.__module__}.{self.__class__.__name__}({args})"

0 commit comments

Comments
 (0)