@@ -3319,6 +3319,8 @@ typedef struct {
33193319 struct statx stx ;
33203320} Py_statx_result ;
33213321
3322+ #define Py_statx_result_CAST (op ) _Py_CAST(Py_statx_result*, (op))
3323+
33223324#define M (attr , type , offset , doc ) \
33233325 {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
33243326#define MM (attr , type , member , doc ) \
@@ -3339,10 +3341,6 @@ static PyMemberDef pystatx_result_members[] = {
33393341 MM (st_blocks , Py_T_ULONGLONG , blocks , "number of blocks allocated" ),
33403342 MM (stx_attributes_mask , Py_T_ULONGLONG , attributes_mask ,
33413343 "Mask of supported bits in stx_attributes" ),
3342- MX (st_atime , Py_T_DOUBLE , atime_sec , "time of last access" ),
3343- MX (st_birthtime , Py_T_DOUBLE , btime_sec , "time of creation" ),
3344- MX (st_ctime , Py_T_DOUBLE , ctime_sec , "time of last change" ),
3345- MX (st_mtime , Py_T_DOUBLE , mtime_sec , "time of last modification" ),
33463344 MM (stx_rdev_major , Py_T_UINT , rdev_major , "represented device major number" ),
33473345 MM (stx_rdev_minor , Py_T_UINT , rdev_minor , "represented device minor number" ),
33483346 MX (st_rdev , Py_T_ULONGLONG , rdev , "device type (if inode device)" ),
@@ -3384,31 +3382,59 @@ static PyMemberDef pystatx_result_members[] = {
33843382#undef MM
33853383#undef M
33863384
3387- static PyObject *
3388- pystatx_result_get_nsec (PyObject * op , void * context )
3389- {
3390- uint16_t offset = (uintptr_t )context ;
3391- struct statx_timestamp * ts = (void * )op + offset ;
3392- _posixstate * state = PyType_GetModuleState (Py_TYPE (op ));
3393- assert (state != NULL );
3394- return stat_nanosecond_timestamp (state , ts -> tv_sec , ts -> tv_nsec );
3395- }
33963385
3397- /* The low 16 bits of the context pointer are the offset from the start of
3398- Py_statx_result to the struct statx member. */
3399- #define GM (attr , type , member , doc ) \
3400- {#attr, pystatx_result_get_##type, NULL, PyDoc_STR(doc), \
3401- (void *)(offsetof(Py_statx_result, stx.stx_##member))}
3386+ #define STATX_GET_DOUBLE (ATTR , MEMBER , MASK ) \
3387+ static PyObject* \
3388+ pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3389+ { \
3390+ Py_statx_result *self = Py_statx_result_CAST(op); \
3391+ if (!(self->stx.stx_mask & MASK)) { \
3392+ Py_RETURN_NONE; \
3393+ } \
3394+ double btime_sec = self->MEMBER; \
3395+ return PyFloat_FromDouble(btime_sec); \
3396+ }
3397+
3398+ STATX_GET_DOUBLE (st_atime , atime_sec , STATX_ATIME )
3399+ STATX_GET_DOUBLE (st_birthtime , btime_sec , STATX_BTIME )
3400+ STATX_GET_DOUBLE (st_ctime , ctime_sec , STATX_CTIME )
3401+ STATX_GET_DOUBLE (st_mtime , mtime_sec , STATX_MTIME )
3402+
3403+ #define STATX_GET_NSEC (ATTR , MEMBER , MASK ) \
3404+ static PyObject* \
3405+ pystatx_result_get_##ATTR(PyObject *op, void *context) \
3406+ { \
3407+ Py_statx_result *self = Py_statx_result_CAST(op); \
3408+ if (!(self->stx.stx_mask & MASK)) { \
3409+ Py_RETURN_NONE; \
3410+ } \
3411+ struct statx_timestamp *ts = &self->stx.MEMBER; \
3412+ _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3413+ assert(state != NULL); \
3414+ return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3415+ }
3416+
3417+ STATX_GET_NSEC (st_atime_ns , stx_atime , STATX_ATIME )
3418+ STATX_GET_NSEC (st_birthtime_ns , stx_atime , STATX_BTIME )
3419+ STATX_GET_NSEC (st_ctime_ns , stx_ctime , STATX_CTIME )
3420+ STATX_GET_NSEC (st_mtime_ns , stx_mtime , STATX_MTIME )
3421+
3422+ #define G (attr , doc ) \
3423+ {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
34023424
34033425static PyGetSetDef pystatx_result_getset [] = {
3404- GM (st_atime_ns , nsec , atime , "time of last access in nanoseconds" ),
3405- GM (st_birthtime_ns , nsec , btime , "time of creation in nanoseconds" ),
3406- GM (st_ctime_ns , nsec , ctime , "time of last change in nanoseconds" ),
3407- GM (st_mtime_ns , nsec , mtime , "time of last modification in nanoseconds" ),
3426+ G (st_atime , "time of last access" ),
3427+ G (st_birthtime , "time of creation" ),
3428+ G (st_ctime , "time of last modification" ),
3429+ G (st_mtime , "time of last modification" ),
3430+ G (st_atime_ns , "time of last access in nanoseconds" ),
3431+ G (st_birthtime_ns , "time of creation in nanoseconds" ),
3432+ G (st_ctime_ns , "time of last change in nanoseconds" ),
3433+ G (st_mtime_ns , "time of last modification in nanoseconds" ),
34083434 {NULL },
34093435};
34103436
3411- #undef GM
3437+ #undef G
34123438
34133439static PyObject *
34143440pystatx_result_repr (PyObject * op )
@@ -3452,23 +3478,25 @@ pystatx_result_repr(PyObject *op)
34523478 }
34533479
34543480 for (size_t i = 0 ; i < Py_ARRAY_LENGTH (pystatx_result_getset ) - 1 ; ++ i ) {
3455- if (i > 0 ) {
3456- WRITE_ASCII (", " );
3457- }
3458-
34593481 PyGetSetDef * d = & pystatx_result_getset [i ];
3460- WRITE_ASCII (d -> name );
3461- WRITE_ASCII ("=" );
3462-
34633482 PyObject * o = d -> get (op , d -> closure );
34643483 if (o == NULL ) {
34653484 goto error ;
34663485 }
3467- if (PyUnicodeWriter_WriteRepr (writer , o ) < 0 ) {
3486+
3487+ if (o != Py_None ) {
3488+ if (i > 0 ) {
3489+ WRITE_ASCII (", " );
3490+ }
3491+
3492+ WRITE_ASCII (d -> name );
3493+ WRITE_ASCII ("=" );
3494+ if (PyUnicodeWriter_WriteRepr (writer , o ) < 0 ) {
3495+ Py_DECREF (o );
3496+ goto error ;
3497+ }
34683498 Py_DECREF (o );
3469- goto error ;
34703499 }
3471- Py_DECREF (o );
34723500 }
34733501
34743502 WRITE_ASCII (")" );
0 commit comments