@@ -228,6 +228,7 @@ typedef struct {
228228 int detached ;
229229 int readable ;
230230 int writable ;
231+ int appending ;
231232 char finalizing ;
232233
233234 /* True if this is a vanilla Buffered object (rather than a user derived
@@ -1350,6 +1351,33 @@ _io__Buffered_tell_impl(buffered *self)
13501351 return PyLong_FromOff_t (pos );
13511352}
13521353
1354+ static PyObject *
1355+ _buffered_seek_unlocked (buffered * self , Py_off_t target , int whence )
1356+ {
1357+ Py_off_t n ;
1358+ PyObject * res = NULL ;
1359+
1360+ if (self -> writable ) {
1361+ res = _bufferedwriter_flush_unlocked (self );
1362+ if (res == NULL )
1363+ return res ;
1364+ Py_CLEAR (res );
1365+ }
1366+
1367+ /* TODO: align on block boundary and read buffer if needed? */
1368+ if (whence == 1 )
1369+ target -= RAW_OFFSET (self );
1370+ n = _buffered_raw_seek (self , target , whence );
1371+ if (n == -1 )
1372+ return res ;
1373+ self -> raw_pos = -1 ;
1374+ res = PyLong_FromOff_t (n );
1375+ if (res != NULL && self -> readable )
1376+ _bufferedreader_reset_buf (self );
1377+
1378+ return res ;
1379+ }
1380+
13531381/*[clinic input]
13541382@critical_section
13551383_io._Buffered.seek
@@ -1362,7 +1390,7 @@ static PyObject *
13621390_io__Buffered_seek_impl (buffered * self , PyObject * targetobj , int whence )
13631391/*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/
13641392{
1365- Py_off_t target , n ;
1393+ Py_off_t target ;
13661394 PyObject * res = NULL ;
13671395
13681396 CHECK_INITIALIZED (self )
@@ -1430,25 +1458,8 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
14301458 return NULL ;
14311459
14321460 /* Fallback: invoke raw seek() method and clear buffer */
1433- if (self -> writable ) {
1434- res = _bufferedwriter_flush_unlocked (self );
1435- if (res == NULL )
1436- goto end ;
1437- Py_CLEAR (res );
1438- }
1461+ res = _buffered_seek_unlocked (self , target , whence );
14391462
1440- /* TODO: align on block boundary and read buffer if needed? */
1441- if (whence == 1 )
1442- target -= RAW_OFFSET (self );
1443- n = _buffered_raw_seek (self , target , whence );
1444- if (n == -1 )
1445- goto end ;
1446- self -> raw_pos = -1 ;
1447- res = PyLong_FromOff_t (n );
1448- if (res != NULL && self -> readable )
1449- _bufferedreader_reset_buf (self );
1450-
1451- end :
14521463 LEAVE_BUFFERED (self )
14531464 return res ;
14541465}
@@ -1926,6 +1937,27 @@ _bufferedwriter_reset_buf(buffered *self)
19261937 self -> write_end = -1 ;
19271938}
19281939
1940+ static void
1941+ _bufferedwriter_set_append (buffered * self )
1942+ {
1943+ PyObject * mode ;
1944+
1945+ mode = _PyObject_GetAttrId (self -> raw , & PyId_mode );
1946+ if (mode != NULL ) {
1947+ /* Raw fileobj has no mode string so as far as we can know it has
1948+ normal write behavior */
1949+ if (PyUnicode_FindChar (mode , 'a' , 0 , PyUnicode_GET_LENGTH (mode ), 1 ) != -1 ) {
1950+ self -> appending = 1 ;
1951+ } else {
1952+ self -> appending = 0 ;
1953+ }
1954+ Py_DECREF (mode );
1955+ } else {
1956+ PyErr_Clear ();
1957+ self -> appending = 0 ;
1958+ }
1959+ }
1960+
19291961/*[clinic input]
19301962_io.BufferedWriter.__init__
19311963 raw: object
@@ -1956,6 +1988,8 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
19561988 self -> readable = 0 ;
19571989 self -> writable = 1 ;
19581990
1991+ _bufferedwriter_set_append (self );
1992+
19591993 self -> buffer_size = buffer_size ;
19601994 if (_buffered_init (self ) < 0 )
19611995 return -1 ;
@@ -2111,6 +2145,14 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
21112145 self -> pos = 0 ;
21122146 self -> raw_pos = 0 ;
21132147 }
2148+
2149+ if (self -> appending ) {
2150+ res = _buffered_seek_unlocked (self , 0 , SEEK_END );
2151+ if (res == NULL )
2152+ goto error ;
2153+ Py_DECREF (res );
2154+ }
2155+
21142156 avail = Py_SAFE_DOWNCAST (self -> buffer_size - self -> pos , Py_off_t , Py_ssize_t );
21152157 if (buffer -> len <= avail && buffer -> len < self -> buffer_size ) {
21162158 memcpy (self -> buffer + self -> pos , buffer -> buf , buffer -> len );
@@ -2504,6 +2546,8 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
25042546 self -> readable = 1 ;
25052547 self -> writable = 1 ;
25062548
2549+ _bufferedwriter_set_append (self );
2550+
25072551 if (_buffered_init (self ) < 0 )
25082552 return -1 ;
25092553 _bufferedreader_reset_buf (self );
0 commit comments