Skip to content

Commit

Permalink
Merge pull request #307 from pbs-data-solutions/user-native
Browse files Browse the repository at this point in the history
Add function to load user native xml
  • Loading branch information
sanders41 authored Jun 3, 2024
2 parents b733df7 + 4cb4aff commit 68d42c0
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 3 deletions.
7 changes: 6 additions & 1 deletion prelude_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from prelude_parser._prelude_parser import parse_site_native_file, parse_subject_native_file
from prelude_parser._prelude_parser import (
parse_site_native_file,
parse_subject_native_file,
parse_user_native_file,
)
from prelude_parser.parser import parse_to_classes, parse_to_dict

__all__ = [
"parse_site_native_file",
"parse_subject_native_file",
"parse_user_native_file",
"parse_to_classes",
"parse_to_dict",
]
7 changes: 6 additions & 1 deletion prelude_parser/_prelude_parser.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ from __future__ import annotations

from pathlib import Path

from prelude_parser._prelude_parser import SiteNative, SubjectNative # type: ignore[attr-defined]
from prelude_parser._prelude_parser import ( # type: ignore[attr-defined]
SiteNative,
SubjectNative,
UserNative,
)
from prelude_parser.types import FlatFormInfo

def _parse_flat_file_to_dict(
Expand All @@ -13,6 +17,7 @@ def _parse_flat_file_to_pandas_dict(
) -> dict[str, FlatFormInfo]: ...
def parse_site_native_file(xml_file: str | Path) -> SiteNative: ...
def parse_subject_native_file(xml_file: str | Path) -> SubjectNative: ...
def parse_user_native_file(xml_file: str | Path) -> UserNative: ...

class FileNotFoundError(Exception):
pass
Expand Down
18 changes: 17 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ use std::fs::read_to_string;
use std::path::PathBuf;

use chrono::{Datelike, NaiveDate};
pub use prelude_xml_parser::native::{site_native::SiteNative, subject_native::SubjectNative};
pub use prelude_xml_parser::native::{
site_native::SiteNative, subject_native::SubjectNative, user_native::UserNative,
};
use prelude_xml_parser::parse_site_native_file as parse_site_native_file_rs;
use prelude_xml_parser::parse_subject_native_file as parse_subject_native_file_rs;
use prelude_xml_parser::parse_user_native_file as parse_user_native_file_rs;
use pyo3::prelude::*;
use pyo3::types::{IntoPyDict, PyDict, PyList};
use roxmltree::Document;
Expand Down Expand Up @@ -252,14 +255,27 @@ fn parse_subject_native_file(_py: Python, xml_file: PathBuf) -> PyResult<Subject
}
}

#[pyfunction]
fn parse_user_native_file(_py: Python, xml_file: PathBuf) -> PyResult<UserNative> {
match parse_user_native_file_rs(&xml_file) {
Ok(native) => Ok(native),
Err(e) => Err(ParsingError::new_err(format!(
"Error parsing xml file: {:?}",
e
))),
}
}

#[pymodule]
fn _prelude_parser(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<SiteNative>()?;
m.add_class::<SubjectNative>()?;
m.add_class::<UserNative>()?;
m.add_function(wrap_pyfunction!(_parse_flat_file_to_dict, m)?)?;
m.add_function(wrap_pyfunction!(_parse_flat_file_to_pandas_dict, m)?)?;
m.add_function(wrap_pyfunction!(parse_site_native_file, m)?)?;
m.add_function(wrap_pyfunction!(parse_subject_native_file, m)?)?;
m.add_function(wrap_pyfunction!(parse_user_native_file, m)?)?;
m.add(
"FileNotFoundError",
py.get_type_bound::<FileNotFoundError>(),
Expand Down
58 changes: 58 additions & 0 deletions tests/assets/user_native.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<export_from_vision_EDC date="02-Jun-2024 06:59 -0500" createdBy="Paul Sanders" role="Project Manager" numberSubjectsProcessed="3">

<user uniqueId="1691421275437" lastLanguage="" creator="Paul Sanders(1681162687395)" numberOfForms="1">
<form name="form.name.demographics" lastModified="2023-08-07 10:15:41 -0500" whoLastModifiedName="Paul Sanders" whoLastModifiedRole="Project Manager" whenCreated="1691421341578" hasErrors="false" hasWarnings="false" locked="false" user="" dateTimeChanged="" formTitle="User Demographics" formIndex="1" formGroup="" formState="In-Work">
<state value="form.state.in.work" signer="Paul Sanders - Project Manager" signerUniqueId="1681162687395" dateSigned="2023-08-07 10:15:41 -0500" />
<category name="demographics" type="normal" highestIndex="0">
<field name="address" type="text" dataType="string" errorCode="undefined" whenCreated="2024-01-12 14:14:09 -0600" keepHistory="true" />
<field name="email" type="text" dataType="string" errorCode="undefined" whenCreated="2023-08-07 10:15:41 -0500" keepHistory="true">
<entry id="1">
<value by="Paul Sanders" byUniqueId="1681162687395" role="Project Manager" when="2023-08-07 10:15:41 -0500" xml:space="preserve">[email protected]</value>
</entry>
</field>
</category>
<category name="Administrative" type="normal" highestIndex="0">
<field name="study_assignment" type="text" dataType="" errorCode="undefined" whenCreated="2023-08-07 10:15:41 -0500" keepHistory="true">
<entry id="1">
<value by="set from calculation" byUniqueId="" role="System" when="2023-08-07 10:15:41 -0500" xml:space="preserve">On 07-Aug-2023 10:15 -0500, Paul Sanders assigned user from another study</value>
<reason by="set from calculation" byUniqueId="" role="System" when="2023-08-07 10:15:41 -0500" xml:space="preserve">calculated value</reason>
</entry>
</field>
</category>
</form>
</user>

<user uniqueId="1681162687395" lastLanguage="" creator="1609858291483(1609858291483)" numberOfForms="2">
<form name="form.name.demographics" lastModified="2023-04-10 16:39:30 -0500" whoLastModifiedName="1609858291483" whoLastModifiedRole="role.administrator" whenCreated="1681162770378" hasErrors="false" hasWarnings="false" locked="false" user="" dateTimeChanged="" formTitle="User Demographics" formIndex="1" formGroup="" formState="In-Work">
<state value="form.state.in.work" signer="1609858291483 - Administrator" signerUniqueId="1609858291483" dateSigned="2023-04-10 16:39:30 -0500" />
<category name="demographics" type="normal" highestIndex="0">
<field name="address" type="text" dataType="string" errorCode="undefined" whenCreated="2023-04-15 10:21:14 -0500" keepHistory="true" />
<field name="email" type="text" dataType="string" errorCode="undefined" whenCreated="2023-04-10 16:39:30 -0500" keepHistory="true">
<entry id="1">
<value by="1609858291483" byUniqueId="1609858291483" role="Administrator" when="2023-04-10 16:39:30 -0500" xml:space="preserve">[email protected]</value>
</entry>
</field>
</category>
<category name="Administrative" type="normal" highestIndex="0">
<field name="study_assignment" type="text" dataType="" errorCode="undefined" whenCreated="2023-04-10 16:39:30 -0500" keepHistory="true">
<entry id="1">
<value by="set from calculation" byUniqueId="" role="System" when="2023-04-10 16:39:30 -0500" xml:space="preserve">On 10-Apr-2023 16:39 -0500, 1609858291483 assigned user from another study</value>
<reason by="set from calculation" byUniqueId="" role="System" when="2023-04-10 16:39:30 -0500" xml:space="preserve">calculated value</reason>
</entry>
</field>
</category>
</form>
<form name="training.form.name.checklist" lastModified="" whenCreated="1702998014133" hasErrors="false" hasWarnings="false" locked="false" user="" dateTimeChanged="" formTitle="Training Checklist" formIndex="1" formGroup="Training" formState="New">
<state value="form.state.new" signer="System set" signerUniqueId="system" dateSigned="2023-12-19 09:00:14 -0600" />
<category name="Training_Modules" type="normal" highestIndex="0">
<field name="date(1)" type="setToday" dataType="date" errorCode="undefined" whenCreated="2023-12-19 09:00:15 -0600" keepHistory="true" />
</category>
<category name="Other_Training_Modules" type="indexed" highestIndex="1">
<field name="date_field(1)" type="setToday" dataType="date" errorCode="undefined" whenCreated="2023-12-19 09:00:15 -0600" keepHistory="true" />
</category>
<category name="21CFR11" type="normal" highestIndex="0" />
</form>
</user>

</export_from_vision_EDC>
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ def site_native_xml():
@pytest.fixture
def subject_native_xml():
return ASSETS_PATH / "subject_native.xml"


@pytest.fixture
def user_native_xml():
return ASSETS_PATH / "user_native.xml"
7 changes: 7 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
parse_subject_native_file,
parse_to_classes,
parse_to_dict,
parse_user_native_file,
)
from prelude_parser._prelude_parser import FileNotFoundError, InvalidFileTypeError, ParsingError

Expand All @@ -23,6 +24,12 @@ def test_parse_subject_native(subject_native_xml):
assert result.patients[0].patient_id == "ABC-001"


def test_parse_user_native(user_native_xml):
result = parse_user_native_file(user_native_xml)

assert result.users[0].unique_id == "1691421275437"


def test_parse_to_classes(test_file_1):
result = parse_to_classes(test_file_1)
assert len(result) == 2
Expand Down

0 comments on commit 68d42c0

Please sign in to comment.