Skip to content

Commit fd3af8b

Browse files
committed
pybricks.tools: Add helper for awaitable constants.
We have a few functions with this structure: async def some_func(): if simple_case: # This commits adds a helper to do this: return some_constant return await some_awaitable_operation() Also apply this to the touch sensor value of the Powered Up device.
1 parent 9cd734b commit fd3af8b

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

pybricks/iodevices/pb_type_iodevices_pupdevice.c

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,6 @@ static mp_obj_t get_pup_data_tuple(mp_obj_t self_in) {
165165
return mp_obj_new_tuple(mode_info[current_mode].num_values, values);
166166
}
167167

168-
static mp_obj_t iodevices_PUPDevice_touch_sensor_true(mp_obj_t self_in) {
169-
return mp_const_true;
170-
}
171-
172-
static mp_obj_t iodevices_PUPDevice_touch_sensor_false(mp_obj_t self_in) {
173-
return mp_const_false;
174-
}
175-
176-
static pbio_error_t iodevices_PUPDevice_touch_sensor_iter_once(pbio_os_state_t *state, mp_obj_t self_in) {
177-
return PBIO_SUCCESS;
178-
}
179-
180168
// pybricks.iodevices.PUPDevice.read
181169
static mp_obj_t iodevices_PUPDevice_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
182170
PB_PARSE_ARGS_METHOD(n_args, pos_args, kw_args,
@@ -189,19 +177,7 @@ static mp_obj_t iodevices_PUPDevice_read(size_t n_args, const mp_obj_t *pos_args
189177
if (self->passive_id == LEGO_DEVICE_TYPE_ID_LPF2_TOUCH) {
190178
uint32_t value;
191179
pb_assert(pbio_port_get_analog_value(self->port, self->passive_id, false, &value));
192-
193-
if (!pb_module_tools_run_loop_is_active()) {
194-
return mp_obj_new_bool(value);
195-
}
196-
197-
// REVISIT: we could probably make something more efficient here.
198-
pb_type_async_t config = {
199-
.parent_obj = MP_OBJ_FROM_PTR(self),
200-
.iter_once = iodevices_PUPDevice_touch_sensor_iter_once,
201-
.return_map = value ? iodevices_PUPDevice_touch_sensor_true : iodevices_PUPDevice_touch_sensor_false,
202-
};
203-
204-
return pb_type_async_wait_or_await(&config, &self->device_base.last_awaitable, false);
180+
return pb_type_async_return_constant(mp_obj_new_bool(value), &self->device_base.last_awaitable);
205181
}
206182

207183
// Other passive devices don't support reading.

pybricks/tools/pb_type_async.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_type_async,
103103
* Returns an awaitable operation if the runloop is active, or awaits the
104104
* operation here and now.
105105
*
106-
* @param [in] config Configuration of the operation
106+
* @param [in] config Configuration of the operation.
107107
* @param [in, out] prev Candidate iterable object that might be re-used, otherwise assigned newly allocated object.
108108
* @param [in] stop_prev Whether to stop ongoing awaitable if it is active.
109109
* @returns An awaitable if the runloop is active, otherwise the mapped return value.
@@ -147,3 +147,41 @@ mp_obj_t pb_type_async_wait_or_await(pb_type_async_t *config, pb_type_async_t **
147147
pb_assert(err);
148148
return config->return_map ? config->return_map(config->parent_obj) : mp_const_none;
149149
}
150+
151+
/**
152+
* Return map for a constant awaitable.
153+
*
154+
* @param [in] parent_obj The constant.
155+
* @returns The same constant.
156+
*/
157+
static mp_obj_t pb_type_async_constant_return_map(mp_obj_t parent_obj) {
158+
return parent_obj;
159+
}
160+
161+
/**
162+
* Returns an awaitable operation that yields once and then returns a constant
163+
* result. If the runloop is not active, this just returns the given value.
164+
*
165+
* Can be used to return constants from functions that still need to be
166+
* awaitable for other reasons.
167+
*
168+
* @param [in] config Configuration of the operation.
169+
* @param [in, out] prev Candidate iterable object that might be
170+
* re-used, otherwise assigned newly allocated object.
171+
* @returns An awaitable if the runloop is active, otherwise the constant return value.
172+
*/
173+
mp_obj_t pb_type_async_return_constant(mp_obj_t ret_obj, pb_type_async_t **prev) {
174+
175+
// In synchronous mode, return right away.
176+
if (!pb_module_tools_run_loop_is_active()) {
177+
return ret_obj;
178+
}
179+
180+
// Async case returns soon.
181+
pb_type_async_t config = {
182+
.parent_obj = ret_obj,
183+
.return_map = pb_type_async_constant_return_map,
184+
// no .iter_once means yield once before completing
185+
};
186+
return pb_type_async_wait_or_await(&config, prev, false);
187+
}

pybricks/tools/pb_type_async.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ typedef struct {
7575

7676
mp_obj_t pb_type_async_wait_or_await(pb_type_async_t *config, pb_type_async_t **prev, bool stop_prev);
7777

78+
mp_obj_t pb_type_async_return_constant(mp_obj_t ret_obj, pb_type_async_t **prev);
79+
7880
void pb_type_async_schedule_stop_iteration(pb_type_async_t *iter);
7981

8082
#endif // PYBRICKS_INCLUDED_ASYNC_H

0 commit comments

Comments
 (0)