Skip to content

Commit 45894a4

Browse files
committed
basic read object
1 parent b4400c5 commit 45894a4

3 files changed

Lines changed: 98 additions & 0 deletions

File tree

lib/src/rdswrapper.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,46 @@ class RdsObject {
165165
}
166166
};
167167

168+
class RdaObject {
169+
private:
170+
std::unique_ptr<rds2cpp::RdaFile> parsed;
171+
172+
public:
173+
RdaObject(const std::string& file) {
174+
try {
175+
rds2cpp::ParseRdaOptions options;
176+
parsed = std::make_unique<rds2cpp::RdaFile>(rds2cpp::parse_rda(file, options));
177+
} catch (const std::exception& e) {
178+
throw std::runtime_error(std::string("Error in 'RdaObject' constructor: ") + e.what());
179+
}
180+
}
181+
182+
py::list get_object_names() const {
183+
if (!parsed) throw std::runtime_error("Null parsed in 'get_object_names'");
184+
const auto& pairlist = parsed->contents;
185+
py::list names;
186+
for (size_t i = 0; i < pairlist.tag_names.size(); ++i) {
187+
if (pairlist.has_tag[i]) {
188+
names.append(pairlist.tag_names[i]);
189+
} else {
190+
names.append(py::none());
191+
}
192+
}
193+
return names;
194+
}
195+
};
196+
168197
PYBIND11_MODULE(lib_rds_parser, m) {
169198
py::register_exception<std::runtime_error>(m, "RdsParserError");
170199

171200
py::class_<RdsObject>(m, "RdsObject")
172201
.def(py::init<const std::string&>())
173202
.def("get_robject", &RdsObject::get_robject, py::return_value_policy::reference_internal);
174203

204+
py::class_<RdaObject>(m, "RdaObject")
205+
.def(py::init<const std::string&>())
206+
.def("get_object_names", &RdaObject::get_object_names);
207+
175208
py::class_<RdsReader>(m, "RdsReader")
176209
.def(py::init<const rds2cpp::RObject*>())
177210
.def("get_rtype", &RdsReader::get_rtype)

src/rds2py/PyRdaReader.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Low-level interface for reading RData files.
2+
3+
This module provides the core functionality for parsing RData (.RData/.rda) files
4+
and converting them into dictionary representations that can be further processed
5+
by higher-level functions.
6+
"""
7+
8+
from .lib_rds_parser import RdaObject
9+
10+
__author__ = "jkanche"
11+
__copyright__ = "jkanche"
12+
__license__ = "MIT"
13+
14+
15+
class PyRdaParserError(Exception):
16+
"""Exception raised for errors during RData parsing."""
17+
18+
pass
19+
20+
21+
class PyRdaParser:
22+
"""Parser for reading RData files.
23+
24+
This class provides low-level access to RData file contents, handling the binary
25+
format and converting it into Python data structures. It reuses the same
26+
``RdsReader``-based object processing from :py:class:`~.PyRdsParser`.
27+
28+
Attributes:
29+
rda_object:
30+
Internal representation of the RData file.
31+
"""
32+
33+
def __init__(self, file_path: str):
34+
"""Initialize the parser.
35+
36+
Args:
37+
file_path:
38+
Path to the RData file to be read.
39+
"""
40+
try:
41+
self.rda_object = RdaObject(file_path)
42+
except Exception as e:
43+
raise PyRdaParserError(f"Error initializing 'PyRdaParser': {str(e)}")
44+
45+
def get_object_names(self):
46+
"""Get the names of all objects stored in the RData file.
47+
48+
Returns:
49+
A list of object names (strings).
50+
"""
51+
return list(self.rda_object.get_object_names())

tests/test_rdata.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Tests for RData (.RData/.rda) file reading."""
2+
3+
from rds2py.PyRdaReader import PyRdaParser
4+
5+
__author__ = "jkanche"
6+
__copyright__ = "jkanche"
7+
__license__ = "MIT"
8+
9+
10+
class TestPyRdaParser:
11+
def test_object_names(self):
12+
parser = PyRdaParser("tests/data/simple.RData")
13+
names = parser.get_object_names()
14+
assert set(names) == {"int_vec", "dbl_vec", "str_vec", "bool_vec"}

0 commit comments

Comments
 (0)