Skip to content

Commit 890d7a5

Browse files
author
Martin Belanger
committed
python: fix iterators failing on empty lists
The python bindings implement hosts(), subsystems(), controllers(), and namespaces() as iterators. However, these iterators all fail on empty lists. This hopefully fixes this issue. Signed-off-by: Martin Belanger <[email protected]>
1 parent 305b209 commit 890d7a5

2 files changed

Lines changed: 55 additions & 20 deletions

File tree

libnvme/nvme.i

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,17 @@ PyObject *hostid_from_file();
395395
#include "fabrics.h"
396396
#define STR_OR_NONE(str) (!(str) ? "None" : str)
397397

398+
struct nvme_host * nvme_first_host(struct nvme_root * r);
399+
struct nvme_host * nvme_next_host(struct nvme_root * r, struct nvme_host * h);
400+
struct nvme_subsystem * nvme_first_subsystem(struct nvme_host * h);
401+
struct nvme_subsystem * nvme_next_subsystem(struct nvme_host * h, struct nvme_subsystem * s);
402+
struct nvme_ctrl * nvme_subsystem_first_ctrl(struct nvme_subsystem * s);
403+
struct nvme_ctrl * nvme_subsystem_next_ctrl(struct nvme_subsystem * s, struct nvme_ctrl * c);
404+
struct nvme_ns * nvme_subsystem_first_ns(struct nvme_subsystem * s);
405+
struct nvme_ns * nvme_subsystem_next_ns(struct nvme_subsystem * s, struct nvme_ns * n);
406+
struct nvme_ns * nvme_ctrl_first_ns(struct nvme_ctrl * c);
407+
struct nvme_ns * nvme_ctrl_next_ns(struct nvme_ctrl * c, struct nvme_ns * n);
408+
398409
struct nvme_root {
399410
%immutable config_file;
400411
%immutable application;
@@ -544,9 +555,14 @@ struct nvme_ns {
544555
else if (!strcmp(level, "emerg")) log_level = LOG_EMERG;
545556
nvme_init_logging($self, log_level, false, false);
546557
}
547-
struct nvme_host *hosts() {
548-
return nvme_first_host($self);
549-
}
558+
%pythoncode %{
559+
def hosts(self):
560+
"""Iterator over all host objects"""
561+
h = nvme_first_host(self)
562+
while h:
563+
yield h
564+
h = nvme_next_host(self, h)
565+
%}
550566
void refresh_topology() {
551567
nvme_refresh_topology($self);
552568
}
@@ -620,9 +636,14 @@ struct nvme_ns {
620636
};
621637
return ret;
622638
}
623-
struct nvme_subsystem* subsystems() {
624-
return nvme_first_subsystem($self);
625-
}
639+
%pythoncode %{
640+
def subsystems(self):
641+
"""Iterator over all subsystem objects"""
642+
s = nvme_first_subsystem(self)
643+
while s:
644+
yield s
645+
s = nvme_next_subsystem(self, s)
646+
%}
626647
}
627648

628649
%{
@@ -692,12 +713,22 @@ struct nvme_ns {
692713
};
693714
return ret;
694715
}
695-
struct nvme_ctrl *controllers() {
696-
return nvme_subsystem_first_ctrl($self);
697-
}
698-
struct nvme_ns *namespaces() {
699-
return nvme_subsystem_first_ns($self);
700-
}
716+
%pythoncode %{
717+
def controllers(self):
718+
"""Iterator over all controller objects"""
719+
c = nvme_subsystem_first_ctrl(self)
720+
while c:
721+
yield c
722+
c = nvme_subsystem_next_ctrl(self, c)
723+
%}
724+
%pythoncode %{
725+
def namespaces(self):
726+
"""Iterator over all namespace objects"""
727+
ns = nvme_subsystem_first_ns(self)
728+
while ns:
729+
yield ns
730+
ns = nvme_subsystem_next_ns(self, ns)
731+
%}
701732
%immutable name;
702733
const char *name;
703734
%immutable host;
@@ -898,9 +929,14 @@ struct nvme_ns {
898929
};
899930
return ret;
900931
}
901-
struct nvme_ns* namespaces() {
902-
return nvme_ctrl_first_ns($self);
903-
}
932+
%pythoncode %{
933+
def namespaces(self):
934+
"""Iterator over all namespace objects"""
935+
ns = nvme_ctrl_first_ns(self)
936+
while ns:
937+
yield ns
938+
ns = nvme_ctrl_next_ns(self, ns)
939+
%}
904940
}
905941

906942
%{

libnvme/tests/gc.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
host = nvme.host(root)
1313
print(f'host: {host}')
1414

15-
subsystem = host.subsystems()
16-
print(f'subsystem: {subsystem}')
17-
1815
ctrls = []
1916
for i in range(10):
2017
ctrl = nvme.ctrl(
@@ -25,8 +22,10 @@
2522
ctrls.append(ctrl)
2623
print(f'ctrl {i}: {ctrl}')
2724

28-
ns = subsystem.namespaces() if subsystem is not None else None
29-
print(f'ns: {ns}')
25+
for s in host.subsystems():
26+
print(f'subsystem: {s}')
27+
for ns in s.namespaces():
28+
print(f'ns: {ns}')
3029

3130
# Deleting objects in the following order would create a segmentation
3231
# fault if it weren't for the %pythonappend in nvme.i. This test is to

0 commit comments

Comments
 (0)