Skip to content

Commit 5aa311d

Browse files
committed
py: Add attrtuple object, for space-efficient tuples with attr access.
If you need the functionality of a namedtuple but will only make 1 or a few instances, then use an attrtuple instead.
1 parent 23a2b11 commit 5aa311d

7 files changed

Lines changed: 120 additions & 9 deletions

File tree

bare-arm/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define MICROPY_PY___FILE__ (0)
2828
#define MICROPY_PY_GC (0)
2929
#define MICROPY_PY_ARRAY (0)
30+
#define MICROPY_PY_ATTRTUPLE (0)
3031
#define MICROPY_PY_COLLECTIONS (0)
3132
#define MICROPY_PY_MATH (0)
3233
#define MICROPY_PY_CMATH (0)

minimal/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define MICROPY_PY___FILE__ (0)
3131
#define MICROPY_PY_GC (0)
3232
#define MICROPY_PY_ARRAY (0)
33+
#define MICROPY_PY_ATTRTUPLE (0)
3334
#define MICROPY_PY_COLLECTIONS (0)
3435
#define MICROPY_PY_MATH (0)
3536
#define MICROPY_PY_CMATH (0)

py/mpconfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,12 @@ typedef double mp_float_t;
502502
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
503503
#endif
504504

505+
// Whether to support attrtuple type (MicroPython extension)
506+
// It provides space-efficient tuples with attribute access
507+
#ifndef MICROPY_PY_ATTRTUPLE
508+
#define MICROPY_PY_ATTRTUPLE (1)
509+
#endif
510+
505511
// Whether to provide "collections" module
506512
#ifndef MICROPY_PY_COLLECTIONS
507513
#define MICROPY_PY_COLLECTIONS (1)

py/objattrtuple.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2015 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/objtuple.h"
28+
29+
#if MICROPY_PY_ATTRTUPLE || MICROPY_PY_COLLECTIONS
30+
31+
// this helper function is used by collections.namedtuple
32+
#if !MICROPY_PY_COLLECTIONS
33+
STATIC
34+
#endif
35+
void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o) {
36+
mp_print_str(print, "(");
37+
for (mp_uint_t i = 0; i < o->len; i++) {
38+
if (i > 0) {
39+
mp_print_str(print, ", ");
40+
}
41+
mp_printf(print, "%q=", fields[i]);
42+
mp_obj_print_helper(print, o->items[i], PRINT_REPR);
43+
}
44+
mp_print_str(print, ")");
45+
}
46+
47+
#endif
48+
49+
#if MICROPY_PY_ATTRTUPLE
50+
51+
STATIC void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
52+
(void)kind;
53+
mp_obj_tuple_t *o = o_in;
54+
const qstr *fields = (const qstr*)o->items[o->len];
55+
mp_obj_attrtuple_print_helper(print, fields, o);
56+
}
57+
58+
STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
59+
if (dest[0] == MP_OBJ_NULL) {
60+
// load attribute
61+
mp_obj_tuple_t *self = self_in;
62+
mp_uint_t len = self->len;
63+
const qstr *fields = (const qstr*)self->items[len];
64+
for (mp_uint_t i = 0; i < len; i++) {
65+
if (fields[i] == attr) {
66+
dest[0] = self->items[i];
67+
return;
68+
}
69+
}
70+
}
71+
}
72+
73+
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, mp_uint_t n, const mp_obj_t *items) {
74+
mp_obj_tuple_t *o = mp_obj_new_tuple(n + 1, NULL);
75+
o->base.type = &mp_type_attrtuple;
76+
for (mp_uint_t i = 0; i < n; i++) {
77+
o->items[i] = items[i];
78+
}
79+
o->items[n] = (void*)fields;
80+
return o;
81+
}
82+
83+
const mp_obj_type_t mp_type_attrtuple = {
84+
{ &mp_type_type },
85+
.name = MP_QSTR_tuple, // reuse tuple to save on a qstr
86+
.print = mp_obj_attrtuple_print,
87+
.unary_op = mp_obj_tuple_unary_op,
88+
.binary_op = mp_obj_tuple_binary_op,
89+
.attr = mp_obj_attrtuple_attr,
90+
.subscr = mp_obj_tuple_subscr,
91+
.getiter = mp_obj_tuple_getiter,
92+
};
93+
94+
#endif // MICROPY_PY_ATTRTUPLE

py/objnamedtuple.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,9 @@ STATIC mp_uint_t namedtuple_find_field(mp_obj_namedtuple_type_t *type, qstr name
5656
STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
5757
(void)kind;
5858
mp_obj_namedtuple_t *o = o_in;
59-
mp_printf(print, "%q(", o->tuple.base.type->name);
59+
mp_printf(print, "%q", o->tuple.base.type->name);
6060
const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields;
61-
for (mp_uint_t i = 0; i < o->tuple.len; i++) {
62-
if (i > 0) {
63-
mp_print_str(print, ", ");
64-
}
65-
mp_printf(print, "%q=", fields[i]);
66-
mp_obj_print_helper(print, o->tuple.items[i], PRINT_REPR);
67-
}
68-
mp_print_str(print, ")");
61+
mp_obj_attrtuple_print_helper(print, fields, &o->tuple);
6962
}
7063

7164
STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {

py/objtuple.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,19 @@ mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
4040
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);
4141
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in);
4242

43+
extern const mp_obj_type_t mp_type_attrtuple;
44+
45+
#define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \
46+
const mp_obj_tuple_t tuple_obj_name = { \
47+
.base = {&mp_type_attrtuple}, \
48+
.len = nitems, \
49+
.items = { __VA_ARGS__ , (void*)fields } \
50+
}
51+
52+
#if MICROPY_PY_COLLECTIONS
53+
void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o);
54+
#endif
55+
56+
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, mp_uint_t n, const mp_obj_t *items);
57+
4358
#endif // __MICROPY_INCLUDED_PY_OBJTUPLE_H__

py/py.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ PY_O_BASENAME = \
5555
map.o \
5656
obj.o \
5757
objarray.o \
58+
objattrtuple.o \
5859
objbool.o \
5960
objboundmeth.o \
6061
objcell.o \

0 commit comments

Comments
 (0)