Skip to content

Commit d43bae1

Browse files
committed
Support os.PathLike object in the C extension
1 parent c37eed5 commit d43bae1

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
History
44
-------
55

6+
2.1.0
7+
++++++++++++++++++
8+
9+
* The C extension now correctly supports objects that implement the
10+
``os.PathLike`` interface.
11+
612
2.0.3 (2020-10-16)
713
++++++++++++++++++
814

extension/maxminddb.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,27 @@ static int ip_converter(PyObject *obj, struct sockaddr_storage *ip_address);
4848
#endif
4949

5050
static int Reader_init(PyObject *self, PyObject *args, PyObject *kwds) {
51-
char *filename;
51+
PyObject *filepath = NULL;
5252
int mode = 0;
5353

5454
static char *kwlist[] = {"database", "mode", NULL};
55-
if (!PyArg_ParseTupleAndKeywords(
56-
args, kwds, "s|i", kwlist, &filename, &mode)) {
55+
if (!PyArg_ParseTupleAndKeywords(args,
56+
kwds,
57+
"O&|i",
58+
kwlist,
59+
PyUnicode_FSConverter,
60+
&filepath,
61+
&mode)) {
62+
return -1;
63+
}
64+
65+
char *filename = PyBytes_AS_STRING(filepath);
66+
if (filename == NULL) {
5767
return -1;
5868
}
5969

6070
if (mode != 0 && mode != 1) {
71+
Py_XDECREF(filepath);
6172
PyErr_Format(
6273
PyExc_ValueError,
6374
"Unsupported open mode (%i). Only "
@@ -67,6 +78,7 @@ static int Reader_init(PyObject *self, PyObject *args, PyObject *kwds) {
6778
}
6879

6980
if (0 != access(filename, R_OK)) {
81+
Py_XDECREF(filepath);
7082
PyErr_Format(PyExc_FileNotFoundError,
7183
"No such file or directory: '%s'",
7284
filename);
@@ -75,18 +87,21 @@ static int Reader_init(PyObject *self, PyObject *args, PyObject *kwds) {
7587

7688
MMDB_s *mmdb = (MMDB_s *)malloc(sizeof(MMDB_s));
7789
if (NULL == mmdb) {
90+
Py_XDECREF(filepath);
7891
PyErr_NoMemory();
7992
return -1;
8093
}
8194

8295
Reader_obj *mmdb_obj = (Reader_obj *)self;
8396
if (!mmdb_obj) {
97+
Py_XDECREF(filepath);
8498
free(mmdb);
8599
PyErr_NoMemory();
86100
return -1;
87101
}
88102

89103
uint16_t status = MMDB_open(filename, MMDB_MODE_MMAP, mmdb);
104+
Py_XDECREF(filepath);
90105

91106
if (MMDB_SUCCESS != status) {
92107
free(mmdb);

tests/reader_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import ipaddress
55
import os
6+
import pathlib
67
import threading
78
import unittest
89
import unittest.mock as mock
@@ -242,6 +243,12 @@ def test_ipv6_address_in_ipv4_database(self):
242243
reader.get(self.ipf("2001::"))
243244
reader.close()
244245

246+
def test_openning_path(self):
247+
with open_database(
248+
pathlib.Path("tests/data/test-data/MaxMind-DB-test-decoder.mmdb"), self.mode
249+
) as reader:
250+
self.assertEqual(reader.metadata().database_type, "MaxMind DB Decoder Test")
251+
245252
def test_no_extension_exception(self):
246253
real_extension = maxminddb.extension
247254
maxminddb.extension = None

0 commit comments

Comments
 (0)