@@ -204,6 +204,7 @@ typedef struct {
204204 int detached ;
205205 int readable ;
206206 int writable ;
207+ int appending ;
207208 char finalizing ;
208209
209210 /* True if this is a vanilla Buffered object (rather than a user derived
@@ -1204,6 +1205,33 @@ buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
12041205 return PyLong_FromOff_t (pos );
12051206}
12061207
1208+ static PyObject *
1209+ _buffered_seek_unlocked (buffered * self , Py_off_t target , int whence )
1210+ {
1211+ Py_off_t n ;
1212+ PyObject * res = NULL ;
1213+
1214+ if (self -> writable ) {
1215+ res = _bufferedwriter_flush_unlocked (self );
1216+ if (res == NULL )
1217+ return res ;
1218+ Py_CLEAR (res );
1219+ }
1220+
1221+ /* TODO: align on block boundary and read buffer if needed? */
1222+ if (whence == 1 )
1223+ target -= RAW_OFFSET (self );
1224+ n = _buffered_raw_seek (self , target , whence );
1225+ if (n == -1 )
1226+ return res ;
1227+ self -> raw_pos = -1 ;
1228+ res = PyLong_FromOff_t (n );
1229+ if (res != NULL && self -> readable )
1230+ _bufferedreader_reset_buf (self );
1231+
1232+ return res ;
1233+ }
1234+
12071235/*[clinic input]
12081236_io._Buffered.seek
12091237 target as targetobj: object
@@ -1215,7 +1243,7 @@ static PyObject *
12151243_io__Buffered_seek_impl (buffered * self , PyObject * targetobj , int whence )
12161244/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
12171245{
1218- Py_off_t target , n ;
1246+ Py_off_t target ;
12191247 PyObject * res = NULL ;
12201248
12211249 CHECK_INITIALIZED (self )
@@ -1276,25 +1304,8 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
12761304 return NULL ;
12771305
12781306 /* Fallback: invoke raw seek() method and clear buffer */
1279- if (self -> writable ) {
1280- res = _bufferedwriter_flush_unlocked (self );
1281- if (res == NULL )
1282- goto end ;
1283- Py_CLEAR (res );
1284- }
1307+ res = _buffered_seek_unlocked (self , target , whence );
12851308
1286- /* TODO: align on block boundary and read buffer if needed? */
1287- if (whence == 1 )
1288- target -= RAW_OFFSET (self );
1289- n = _buffered_raw_seek (self , target , whence );
1290- if (n == -1 )
1291- goto end ;
1292- self -> raw_pos = -1 ;
1293- res = PyLong_FromOff_t (n );
1294- if (res != NULL && self -> readable )
1295- _bufferedreader_reset_buf (self );
1296-
1297- end :
12981309 LEAVE_BUFFERED (self )
12991310 return res ;
13001311}
@@ -1767,6 +1778,27 @@ _bufferedwriter_reset_buf(buffered *self)
17671778 self -> write_end = -1 ;
17681779}
17691780
1781+ static void
1782+ _bufferedwriter_set_append (buffered * self )
1783+ {
1784+ PyObject * mode ;
1785+
1786+ mode = _PyObject_GetAttrId (self -> raw , & PyId_mode );
1787+ if (mode != NULL ) {
1788+ /* Raw fileobj has no mode string so as far as we can know it has
1789+ normal write behavior */
1790+ if (PyUnicode_FindChar (mode , 'a' , 0 , PyUnicode_GET_LENGTH (mode ), 1 ) != -1 ) {
1791+ self -> appending = 1 ;
1792+ } else {
1793+ self -> appending = 0 ;
1794+ }
1795+ Py_DECREF (mode );
1796+ } else {
1797+ PyErr_Clear ();
1798+ self -> appending = 0 ;
1799+ }
1800+ }
1801+
17701802/*[clinic input]
17711803_io.BufferedWriter.__init__
17721804 raw: object
@@ -1795,6 +1827,8 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
17951827 self -> readable = 0 ;
17961828 self -> writable = 1 ;
17971829
1830+ _bufferedwriter_set_append (self );
1831+
17981832 self -> buffer_size = buffer_size ;
17991833 if (_buffered_init (self ) < 0 )
18001834 return -1 ;
@@ -1944,6 +1978,14 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
19441978 self -> pos = 0 ;
19451979 self -> raw_pos = 0 ;
19461980 }
1981+
1982+ if (self -> appending ) {
1983+ res = _buffered_seek_unlocked (self , 0 , SEEK_END );
1984+ if (res == NULL )
1985+ goto error ;
1986+ Py_DECREF (res );
1987+ }
1988+
19471989 avail = Py_SAFE_DOWNCAST (self -> buffer_size - self -> pos , Py_off_t , Py_ssize_t );
19481990 if (buffer -> len <= avail ) {
19491991 memcpy (self -> buffer + self -> pos , buffer -> buf , buffer -> len );
@@ -2309,6 +2351,8 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
23092351 self -> readable = 1 ;
23102352 self -> writable = 1 ;
23112353
2354+ _bufferedwriter_set_append (self );
2355+
23122356 if (_buffered_init (self ) < 0 )
23132357 return -1 ;
23142358 _bufferedreader_reset_buf (self );
0 commit comments