Skip to content

Commit e3c9987

Browse files
committed
Remove the resize method on mmap object on platforms don't support it
1 parent 5c6937a commit e3c9987

File tree

3 files changed

+50
-43
lines changed

3 files changed

+50
-43
lines changed

Lib/test/test_mmap.py

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def test_basic(self):
5757
f.write(b'\0'* (PAGESIZE-3) )
5858
f.flush()
5959
m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
60+
self.addCleanup(m.close)
6061
finally:
6162
f.close()
6263

@@ -114,31 +115,34 @@ def test_basic(self):
114115
# Try to seek to negative position...
115116
self.assertRaises(ValueError, m.seek, -len(m)-1, 2)
116117

117-
# Try resizing map
118+
@unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize')
119+
def test_resize(self):
120+
# Create a file to be mmap'ed.
121+
f = open(TESTFN, 'bw+')
118122
try:
119-
m.resize(512)
120-
except SystemError:
121-
# resize() not supported
122-
# No messages are printed, since the output of this test suite
123-
# would then be different across platforms.
124-
pass
125-
else:
126-
# resize() is supported
127-
self.assertEqual(len(m), 512)
128-
# Check that we can no longer seek beyond the new size.
129-
self.assertRaises(ValueError, m.seek, 513, 0)
130-
131-
# Check that the underlying file is truncated too
132-
# (bug #728515)
133-
f = open(TESTFN, 'rb')
134-
try:
135-
f.seek(0, 2)
136-
self.assertEqual(f.tell(), 512)
137-
finally:
138-
f.close()
139-
self.assertEqual(m.size(), 512)
123+
# Write 2 pages worth of data to the file
124+
f.write(b'\0'* 2 * PAGESIZE)
125+
f.flush()
126+
m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
127+
self.addCleanup(m.close)
128+
finally:
129+
f.close()
140130

141-
m.close()
131+
# Try resizing map
132+
m.resize(512)
133+
self.assertEqual(len(m), 512)
134+
# Check that we can no longer seek beyond the new size.
135+
self.assertRaises(ValueError, m.seek, 513, 0)
136+
137+
# Check that the underlying file is truncated too
138+
# (bug #728515)
139+
f = open(TESTFN, 'rb')
140+
try:
141+
f.seek(0, 2)
142+
self.assertEqual(f.tell(), 512)
143+
finally:
144+
f.close()
145+
self.assertEqual(m.size(), 512)
142146

143147
def test_access_parameter(self):
144148
# Test for "access" keyword parameter
@@ -186,7 +190,7 @@ def test_access_parameter(self):
186190
# Ensuring that readonly mmap can't be resized
187191
try:
188192
m.resize(2*mapsize)
189-
except SystemError: # resize is not universally supported
193+
except AttributeError: # resize is not universally supported
190194
pass
191195
except TypeError:
192196
pass
@@ -242,8 +246,9 @@ def test_access_parameter(self):
242246
with open(TESTFN, "rb") as fp:
243247
self.assertEqual(fp.read(), b'c'*mapsize,
244248
"Copy-on-write test data file should not be modified.")
245-
# Ensuring copy-on-write maps cannot be resized
246-
self.assertRaises(TypeError, m.resize, 2*mapsize)
249+
if hasattr(m, 'resize'):
250+
# Ensuring copy-on-write maps cannot be resized
251+
self.assertRaises(TypeError, m.resize, 2*mapsize)
247252
m.close()
248253

249254
# Ensuring invalid access parameter raises exception
@@ -285,10 +290,11 @@ def test_trackfd_parameter(self):
285290
with self.assertRaises(OSError) as err_cm:
286291
m.size()
287292
self.assertEqual(err_cm.exception.errno, errno.EBADF)
288-
with self.assertRaises(ValueError):
289-
m.resize(size * 2)
290-
with self.assertRaises(ValueError):
291-
m.resize(size // 2)
293+
if hasattr(m, 'resize'):
294+
with self.assertRaises(ValueError):
295+
m.resize(size * 2)
296+
with self.assertRaises(ValueError):
297+
m.resize(size // 2)
292298
self.assertEqual(m.closed, False)
293299

294300
# Smoke-test other API
@@ -311,8 +317,9 @@ def test_trackfd_neg1(self):
311317
with mmap.mmap(-1, size, trackfd=False) as m:
312318
with self.assertRaises(OSError):
313319
m.size()
314-
with self.assertRaises(ValueError):
315-
m.resize(size // 2)
320+
if hasattr(m, 'resize'):
321+
with self.assertRaises(ValueError):
322+
m.resize(size // 2)
316323
self.assertEqual(len(m), size)
317324
m[0] = ord('a')
318325
assert m[0] == ord('a')
@@ -617,7 +624,7 @@ def test_offset (self):
617624
# Try resizing map
618625
try:
619626
m.resize(512)
620-
except SystemError:
627+
except AttributeError:
621628
pass
622629
else:
623630
# resize() is supported
@@ -812,14 +819,12 @@ def test_write_returning_the_number_of_bytes_written(self):
812819
self.assertEqual(mm.write(b"yz"), 2)
813820
self.assertEqual(mm.write(b"python"), 6)
814821

822+
@unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize')
815823
def test_resize_past_pos(self):
816824
m = mmap.mmap(-1, 8192)
817825
self.addCleanup(m.close)
818826
m.read(5000)
819-
try:
820-
m.resize(4096)
821-
except SystemError:
822-
self.skipTest("resizing not supported")
827+
m.resize(4096)
823828
self.assertEqual(m.read(14), b'')
824829
self.assertRaises(ValueError, m.read_byte)
825830
self.assertRaises(ValueError, m.write_byte, 42)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removed the :mmap:`~mmap.mmap.resize` method on platforms that don't support the
2+
underlying syscall, instead of raising a :exec:`SystemError`.

Modules/mmapmodule.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ is_writable(mmap_object *self)
634634
return 0;
635635
}
636636

637+
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
637638
static int
638639
is_resizeable(mmap_object *self)
639640
{
@@ -656,6 +657,7 @@ is_resizeable(mmap_object *self)
656657
return 0;
657658

658659
}
660+
#endif /* defined(MS_WINDOWS) || defined(HAVE_MREMAP) */
659661

660662

661663
static PyObject *
@@ -768,6 +770,7 @@ mmap_size_method(PyObject *op, PyObject *Py_UNUSED(ignored))
768770
/ new size?
769771
*/
770772

773+
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
771774
static PyObject *
772775
mmap_resize_method(PyObject *op, PyObject *args)
773776
{
@@ -882,11 +885,6 @@ mmap_resize_method(PyObject *op, PyObject *args)
882885
#endif /* MS_WINDOWS */
883886

884887
#ifdef UNIX
885-
#ifndef HAVE_MREMAP
886-
PyErr_SetString(PyExc_SystemError,
887-
"mmap: resizing not available--no mremap()");
888-
return NULL;
889-
#else
890888
void *newmap;
891889

892890
if (self->fd != -1 && ftruncate(self->fd, self->offset + new_size) == -1) {
@@ -911,10 +909,10 @@ mmap_resize_method(PyObject *op, PyObject *args)
911909
self->data = newmap;
912910
self->size = new_size;
913911
Py_RETURN_NONE;
914-
#endif /* HAVE_MREMAP */
915912
#endif /* UNIX */
916913
}
917914
}
915+
#endif /* defined(MS_WINDOWS) || defined(HAVE_MREMAP) */
918916

919917
static PyObject *
920918
mmap_tell_method(PyObject *op, PyObject *Py_UNUSED(ignored))
@@ -1202,7 +1200,9 @@ static struct PyMethodDef mmap_object_methods[] = {
12021200
{"read", mmap_read_method, METH_VARARGS},
12031201
{"read_byte", mmap_read_byte_method, METH_NOARGS},
12041202
{"readline", mmap_read_line_method, METH_NOARGS},
1203+
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
12051204
{"resize", mmap_resize_method, METH_VARARGS},
1205+
#endif
12061206
{"seek", mmap_seek_method, METH_VARARGS},
12071207
{"seekable", mmap_seekable_method, METH_NOARGS},
12081208
{"size", mmap_size_method, METH_NOARGS},

0 commit comments

Comments
 (0)