Skip to content

Commit 805b820

Browse files
committed
ci: use pyproject.toml
1 parent c8b5e65 commit 805b820

10 files changed

+139
-109
lines changed

.github/workflows/python.yml

+9-12
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,29 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v4
2222
- name: Setup Go environment
23-
uses: actions/setup-go@v5.0.1
23+
uses: actions/setup-go@v5
2424
with:
2525
go-version: '1.22'
2626
- name: Setup Java JDK
27-
uses: actions/setup-java@v4.2.1
27+
uses: actions/setup-java@v4
2828
with:
29-
distribution: 'temurin'
30-
java-version: '22'
29+
distribution: temurin
30+
java-version: 22
3131
cache: maven
3232
- name: Set up Python 3.10
33-
uses: actions/setup-python@v3
33+
uses: actions/setup-python@v5
3434
with:
35-
python-version: "3.10"
35+
python-version: '3.10'
36+
cache: pip
3637
- name: Install dependencies
3738
run: |
38-
sudo add-apt-repository ppa:maxmind/ppa
39-
sudo apt update
4039
sudo apt install libmaxminddb0 libmaxminddb-dev
4140
python -m pip install --upgrade pip
42-
pip install ".[test]" ruff pytest-cov
43-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
44-
python -V
41+
pip install ".[test,dev]"
4542
- name: Check with ruff
4643
run: |
4744
ruff check
4845
ruff format --check
4946
- name: Test with pytest
5047
run: |
51-
pytest tests/*
48+
pytest

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
- [MaxMind-DB-Writer-python](#maxmind-db-writer-python)
2+
* [Install](#install)
3+
* [Usage](#usage)
4+
* [Examples](#examples)
5+
* [Using the Java Client](#using-the-java-client)
6+
+ [TLDR](#tldr)
7+
+ [Underlying Principles](#underlying-principles)
8+
* [Type Enforcement](#type-enforcement)
9+
* [Reference:](#reference-)
10+
111
# MaxMind-DB-Writer-python
212

313
Make `mmdb` format ip library file which can be read by [`maxmind` official language reader](https://dev.maxmind.com/geoip/geoip2/downloadable/)

examples/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
# coding: utf-8

examples/csv_to_mmdb.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# coding: utf-8
21
import csv
32
from collections import defaultdict
43

@@ -14,7 +13,7 @@ def main():
1413
data = defaultdict(list)
1514

1615
# merge cidr
17-
with open("fake_ip_info.csv", "r") as f:
16+
with open("fake_ip_info.csv") as f:
1817
reader = csv.DictReader(f)
1918
for line in reader:
2019
data[(line["country"], line["isp"])].append(

mmdb_writer.py

+42-43
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# coding: utf-8
21
__version__ = "0.2.1"
32

43
import logging
@@ -7,12 +6,12 @@
76
import time
87
from decimal import Decimal
98
from enum import IntEnum
10-
from typing import Union, List, Dict, Literal
9+
from typing import Dict, List, Literal, Union
1110

12-
from netaddr import IPSet, IPNetwork
11+
from netaddr import IPNetwork, IPSet
1312

1413

15-
class MmdbBaseType(object):
14+
class MmdbBaseType:
1615
def __init__(self, value):
1716
self.value = value
1817

@@ -97,7 +96,7 @@ class MMDBTypeID(IntEnum):
9796
UINT64_MAX = 0xFFFFFFFFFFFFFFFF
9897

9998

100-
class SearchTreeNode(object):
99+
class SearchTreeNode:
101100
def __init__(self, left=None, right=None):
102101
self.left = left
103102
self.right = right
@@ -123,12 +122,12 @@ def __setitem__(self, key, value):
123122
self.right = value
124123

125124

126-
class SearchTreeLeaf(object):
125+
class SearchTreeLeaf:
127126
def __init__(self, value):
128127
self.value = value
129128

130129
def __repr__(self):
131-
return "SearchTreeLeaf(value={value})".format(value=self.value)
130+
return f"SearchTreeLeaf(value={self.value})"
132131

133132
__str__ = __repr__
134133

@@ -156,7 +155,7 @@ def __repr__(self):
156155
FloatType = Union[Literal["f32", "f64", "float32", "float64"] | MmdbF32 | MmdbF64]
157156

158157

159-
class Encoder(object):
158+
class Encoder:
160159
def __init__(
161160
self, cache=True, int_type: IntType = "auto", float_type: FloatType = "f64"
162161
):
@@ -224,7 +223,8 @@ def _encode_uint(self, type_id, max_len):
224223
def _encode_unsigned_value(value):
225224
if value < 0 or value >= value_max:
226225
raise ValueError(
227-
f"encode uint{max_len * 8} fail: {value} not in range(0, {value_max})"
226+
f"encode uint{max_len * 8} fail: "
227+
f"{value} not in range(0, {value_max})"
228228
)
229229
res = b""
230230
while value != 0 and len(res) < max_len:
@@ -353,7 +353,7 @@ def python_type_id(self, value):
353353
raise ValueError(f"unknown float_type={self.float_type}")
354354
elif value_type is Decimal:
355355
return MMDBTypeID.DOUBLE
356-
raise TypeError("unknown type {value_type}".format(value_type=value_type))
356+
raise TypeError(f"unknown type {value_type}")
357357

358358
def encode_meta(self, meta):
359359
res = self._make_header(MMDBTypeID.MAP, len(meta))
@@ -383,8 +383,8 @@ def encode(self, value, type_id=None):
383383

384384
try:
385385
encoder = self.type_encoder[type_id]
386-
except KeyError:
387-
raise ValueError("unknown type_id={type_id}".format(type_id=type_id))
386+
except KeyError as err:
387+
raise ValueError(f"unknown type_id={type_id}") from err
388388

389389
if isinstance(value, MmdbBaseType):
390390
value = value.value
@@ -406,7 +406,7 @@ def encode(self, value, type_id=None):
406406
return res
407407

408408

409-
class TreeWriter(object):
409+
class TreeWriter:
410410
encoder_cls = Encoder
411411

412412
def __init__(
@@ -541,7 +541,7 @@ def bits_rstrip(n, length=None, keep=0):
541541
return map(int, bin(n)[2:].rjust(length, "0")[:keep])
542542

543543

544-
class MMDBWriter(object):
544+
class MMDBWriter:
545545
def __init__(
546546
self,
547547
ip_version=4,
@@ -554,18 +554,20 @@ def __init__(
554554
):
555555
"""
556556
Args:
557-
ip_version (int, optional): The IP version of the database. Defaults to 4.
558-
database_type (str, optional): The type of the database. Defaults to "GeoIP".
559-
languages (List[str], optional): A list of languages. Defaults to [].
560-
description (Union[Dict[str, str], str], optional): A description of the database for every language.
561-
ipv4_compatible (bool, optional): Whether the database is compatible with IPv4. Defaults to False.
562-
int_type (Union[str, MmdbU16, MmdbU32, MmdbU64, MmdbU128, MmdbI32], optional): The type of integer to use. Defaults to "auto".
563-
float_type (Union[str, MmdbF32, MmdbF64], optional): The type of float to use. Defaults to "f64".
557+
ip_version: The IP version of the database. Defaults to 4.
558+
database_type: The type of the database. Defaults to "GeoIP".
559+
languages: A list of languages. Defaults to [].
560+
description: A description of the database for every language.
561+
ipv4_compatible: Whether the database is compatible with IPv4.
562+
int_type: The type of integer to use. Defaults to "auto".
563+
float_type: The type of float to use. Defaults to "f64".
564564
565565
Note:
566-
If you want to store an IPv4 address in an IPv6 database, you should set ipv4_compatible=True.
566+
If you want to store an IPv4 address in an IPv6 database, you should set
567+
ipv4_compatible=True.
567568
568-
If you want to use a specific integer type, you can set int_type to "u16", "u32", "u64", "u128", or "i32".
569+
If you want to use a specific integer type, you can set int_type to
570+
"u16", "u32", "u64", "u128", or "i32".
569571
"""
570572
self.tree = SearchTreeNode()
571573
self.ipv4_compatible = ipv4_compatible
@@ -582,16 +584,12 @@ def __init__(
582584
self._bit_length = 128 if ip_version == 6 else 32
583585

584586
if ip_version not in [4, 6]:
585-
raise ValueError(
586-
"ip_version should be 4 or 6, {} is incorrect".format(ip_version)
587-
)
587+
raise ValueError(f"ip_version should be 4 or 6, {ip_version} is incorrect")
588588
if ip_version == 4 and ipv4_compatible:
589589
raise ValueError("ipv4_compatible=True can set when ip_version=6")
590590
if not self.binary_format_major_version:
591591
raise ValueError(
592-
"major_version can't be empty or 0: {}".format(
593-
self.binary_format_major_version
594-
)
592+
f"major_version can't be empty or 0: {self.binary_format_major_version}"
595593
)
596594
if isinstance(description, str):
597595
self.description = {i: description for i in languages}
@@ -602,22 +600,22 @@ def __init__(
602600
self.int_type = int_type
603601
self.float_type = float_type
604602

605-
def insert_network(
606-
self, network: IPSet, content: MMDBType, overwrite=True, python_type_id_map=None
607-
):
603+
def insert_network(self, network: IPSet, content: MMDBType):
608604
"""
609605
Inserts a network into the MaxMind database.
610606
611607
Args:
612-
network (IPSet): The network to be inserted. It should be an instance of netaddr.IPSet.
613-
content (MMDBType): The content associated with the network. It can be a dictionary, list, string, bytes, integer, or boolean.
614-
overwrite (bool, optional): If True, existing network data will be overwritten. Defaults to True.
615-
python_type_id_map: abc
608+
network: The network to be inserted. It should be an instance of
609+
netaddr.IPSet.
610+
content: The content associated with the network. It can be a
611+
dictionary, list, string, bytes, integer, or boolean.
612+
616613
617614
Raises:
618615
ValueError: If the network is not an instance of netaddr.IPSet.
619616
ValueError: If an IPv6 address is inserted into an IPv4-only database.
620-
ValueError: If an IPv4 address is inserted into an IPv6 database without setting ipv4_compatible=True.
617+
ValueError: If an IPv4 address is inserted into an IPv6 database without
618+
setting ipv4_compatible=True.
621619
622620
Note:
623621
This method modifies the internal tree structure of the MMDBWriter instance.
@@ -629,15 +627,14 @@ def insert_network(
629627
for cidr in network:
630628
if self.ip_version == 4 and cidr.version == 6:
631629
raise ValueError(
632-
"You inserted a IPv6 address {} "
633-
"to an IPv4-only database.".format(cidr)
630+
f"You inserted a IPv6 address {cidr} " "to an IPv4-only database."
634631
)
635632
if self.ip_version == 6 and cidr.version == 4:
636633
if not self.ipv4_compatible:
637634
raise ValueError(
638-
"You inserted a IPv4 address {} to an IPv6 database."
635+
f"You inserted a IPv4 address {cidr} to an IPv6 database."
639636
"Please use ipv4_compatible=True option store "
640-
"IPv4 address in IPv6 database as ::/96 format".format(cidr)
637+
"IPv4 address in IPv6 database as ::/96 format"
641638
)
642639
cidr = cidr.ipv6(True)
643640
node = self.tree
@@ -661,15 +658,17 @@ def insert_network(
661658
)
662659
)
663660
logger.info(
664-
f"Inserting {cidr} ({content}) into subnet of {current_cidr} ({current_node.value})"
661+
f"Inserting {cidr} ({content}) into subnet of "
662+
f"{current_cidr} ({current_node.value})"
665663
)
666664
supernet_leaf = current_node
667665
current_node = SearchTreeNode()
668666
previous_node[ip_bit] = current_node
669667

670668
if supernet_leaf:
671669
next_bit = bits[index + 1]
672-
# Insert supernet information on each inverse bit of the current subnet
670+
# Insert supernet information on each inverse bit of
671+
# the current subnet
673672
current_node[1 - next_bit] = supernet_leaf
674673
current_node[bits[-1]] = leaf
675674

pyproject.toml

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[build-system]
2+
requires = ["flit_core >=3.2,<4"]
3+
build-backend = "flit_core.buildapi"
4+
5+
[project]
6+
name = "mmdb_writer"
7+
description = "Make `mmdb` format ip library file which can be read by maxmind official language reader"
8+
readme = "README.md"
9+
license = {file = "LICENSE"}
10+
requires-python = ">=3.6"
11+
keywords = ["mmdb", "maxmind"]
12+
authors = [{ name = "VimT", email = "[email protected]" } ]
13+
classifiers = [
14+
"Development Status :: 5 - Production/Stable",
15+
"Intended Audience :: Developers",
16+
"License :: OSI Approved :: MIT License",
17+
"Natural Language :: English",
18+
"Operating System :: OS Independent",
19+
"Programming Language :: Python :: 3.6",
20+
"Programming Language :: Python :: 3.7",
21+
"Programming Language :: Python :: 3.8",
22+
"Programming Language :: Python :: 3.9",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
26+
"Programming Language :: Python :: Implementation :: CPython",
27+
"Programming Language :: Python :: Implementation :: PyPy",
28+
"Topic :: Software Development :: Build Tools",
29+
]
30+
dependencies = [
31+
"netaddr>=0.7"
32+
]
33+
dynamic = ["version"]
34+
35+
[project.optional-dependencies]
36+
test = [
37+
"pytest >=2.7.3",
38+
"pytest-cov",
39+
"numpy",
40+
"maxminddb>=1.5",
41+
]
42+
dev = [
43+
"ruff"
44+
]
45+
46+
[project.urls]
47+
Home = "https://github.com/vimt/MaxMind-DB-Writer-python"
48+
Source = "https://github.com/vimt/MaxMind-DB-Writer-python"
49+
Tracker = "https://github.com/vimt/MaxMind-DB-Writer-python/issues"
50+
51+
[tool.flit.sdist]
52+
include = ["mmdb_writer.py"]
53+
54+
[tool.pytest.ini_options]
55+
testpaths = ["tests"]
56+
filterwarnings = [
57+
"error",
58+
]
59+
60+
[tool.ruff]
61+
fix = true
62+
show-fixes = true
63+
output-format = "full"
64+
65+
[tool.ruff.lint]
66+
select = [
67+
"B", # flake8-bugbear
68+
"E", # pycodestyle error
69+
"F", # pyflakes
70+
"I", # isort
71+
"UP", # pyupgrade
72+
"W", # pycodestyle warning
73+
]

0 commit comments

Comments
 (0)