Skip to content

Commit 2c7e3b2

Browse files
Martin Belangerigaw
authored andcommitted
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 e08f9e9 commit 2c7e3b2

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
@@ -411,6 +411,17 @@ PyObject *hostid_from_file();
411411
#include "fabrics.h"
412412
#define STR_OR_NONE(str) (!(str) ? "None" : str)
413413

414+
struct nvme_host * nvme_first_host(struct nvme_root * r);
415+
struct nvme_host * nvme_next_host(struct nvme_root * r, struct nvme_host * h);
416+
struct nvme_subsystem * nvme_first_subsystem(struct nvme_host * h);
417+
struct nvme_subsystem * nvme_next_subsystem(struct nvme_host * h, struct nvme_subsystem * s);
418+
struct nvme_ctrl * nvme_subsystem_first_ctrl(struct nvme_subsystem * s);
419+
struct nvme_ctrl * nvme_subsystem_next_ctrl(struct nvme_subsystem * s, struct nvme_ctrl * c);
420+
struct nvme_ns * nvme_subsystem_first_ns(struct nvme_subsystem * s);
421+
struct nvme_ns * nvme_subsystem_next_ns(struct nvme_subsystem * s, struct nvme_ns * n);
422+
struct nvme_ns * nvme_ctrl_first_ns(struct nvme_ctrl * c);
423+
struct nvme_ns * nvme_ctrl_next_ns(struct nvme_ctrl * c, struct nvme_ns * n);
424+
414425
struct nvme_root {
415426
%immutable config_file;
416427
%immutable application;
@@ -560,9 +571,14 @@ struct nvme_ns {
560571
else if (!strcmp(level, "emerg")) log_level = LOG_EMERG;
561572
nvme_init_logging($self, log_level, false, false);
562573
}
563-
struct nvme_host *hosts() {
564-
return nvme_first_host($self);
565-
}
574+
%pythoncode %{
575+
def hosts(self):
576+
"""Iterator over all host objects"""
577+
h = nvme_first_host(self)
578+
while h:
579+
yield h
580+
h = nvme_next_host(self, h)
581+
%}
566582
void refresh_topology() {
567583
nvme_refresh_topology($self);
568584
}
@@ -636,9 +652,14 @@ struct nvme_ns {
636652
};
637653
return ret;
638654
}
639-
struct nvme_subsystem* subsystems() {
640-
return nvme_first_subsystem($self);
641-
}
655+
%pythoncode %{
656+
def subsystems(self):
657+
"""Iterator over all subsystem objects"""
658+
s = nvme_first_subsystem(self)
659+
while s:
660+
yield s
661+
s = nvme_next_subsystem(self, s)
662+
%}
642663
}
643664

644665
%{
@@ -708,12 +729,22 @@ struct nvme_ns {
708729
};
709730
return ret;
710731
}
711-
struct nvme_ctrl *controllers() {
712-
return nvme_subsystem_first_ctrl($self);
713-
}
714-
struct nvme_ns *namespaces() {
715-
return nvme_subsystem_first_ns($self);
716-
}
732+
%pythoncode %{
733+
def controllers(self):
734+
"""Iterator over all controller objects"""
735+
c = nvme_subsystem_first_ctrl(self)
736+
while c:
737+
yield c
738+
c = nvme_subsystem_next_ctrl(self, c)
739+
%}
740+
%pythoncode %{
741+
def namespaces(self):
742+
"""Iterator over all namespace objects"""
743+
ns = nvme_subsystem_first_ns(self)
744+
while ns:
745+
yield ns
746+
ns = nvme_subsystem_next_ns(self, ns)
747+
%}
717748
%immutable name;
718749
const char *name;
719750
%immutable host;
@@ -924,9 +955,14 @@ struct nvme_ns {
924955
};
925956
return ret;
926957
}
927-
struct nvme_ns* namespaces() {
928-
return nvme_ctrl_first_ns($self);
929-
}
958+
%pythoncode %{
959+
def namespaces(self):
960+
"""Iterator over all namespace objects"""
961+
ns = nvme_ctrl_first_ns(self)
962+
while ns:
963+
yield ns
964+
ns = nvme_ctrl_next_ns(self, ns)
965+
%}
930966
}
931967

932968
%{

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)