Migrating from edi-835-parser¶
This guide is for projects that use the edi-835-parser library and want to move to oxedi.
You have two paths:
- Keep your code and change the import.
- Move to the native API.
Switch the import¶
pip install "oxedi[edi-835-parser]"
# before: from edi_835_parser import parse
from oxedi.edi_835_parser import parse
frame = parse("remittances/").to_dataframe() # same rows, columns, order and dtypes
oxedi.edi_835_parser exposes the same API as the library:
parsereads a file, or every.txt,.835and.DATfile of a folder.parse_bytes(data, file_path=...),parse_file_obj(f)andparse_many([...])(bytes or binary file objects) read from memory.
The frame equals edi-835-parser 1.8.0's cell for cell on our test files. Payer ids that are not
numbers (N104 with qualifier XV) work.
What changes for you¶
These are the differences you are most likely to notice.
- One
TransactionSetperST, not per file. The separators come from the ISA instead of being guessed per element. - Repeated segments take the first. A second
NM1*QC,NM1*82orDTM*232/233in a claim makes the library raiseAssertionError. oxedi takes the first. - A claim without
NM1*QC. The library raisesAssertionError. oxedi givespatientasNoneand counts it once incount_patients. - An unknown claim status gives
"unknown"instead of an error. - Path-like inputs.
parsealso acceptspathlib.Path, where the library raisesTypeError.""givesFileNotFoundErrorinstead ofIndexError. - Errors name the file. The
ParseErrorfor a single path names the file.
extended=True¶
extra = parse("remittances/").to_dataframe(extended=True)
This adds what the library drops: claims without services, claim adjustments, PLB and unmapped
REF/AMT. It keeps the strict columns in the same order and only adds columns that start with
x_, plus the rows the library drops. When claim-only or provider-adjustment rows exist, some
strict columns widen their dtype: int to float, bool to object, and an object column
holding only None to float64 with NaN.
Edge cases¶
These matter only for unusual files.
Details: files that start oddly
The compatibility layer gives an empty result for these, where the library reads on or raises:
- Arbitrary non-whitespace bytes before the ISA (other than a UTF-8 BOM followed by ASCII whitespace), a doubled BOM, or non-ASCII whitespace after a BOM. The library reads the segments after the first.
- A vertical tab or form feed before the ISA without a BOM.
- Without a BOM, an unreadable ISA preceded by a newline. The library raises
IndexError.
The native API (oxedi.parse) is strict and raises ParseError for all of these.
It does read a file that starts with a UTF-8 BOM (then optional spaces, tabs or line
breaks) before the ISA. The mark stays in the first segment's raw, write() gives the
file back unchanged, and a ByteOrderMark diagnostic says it was there. The compatibility
layer keeps the library's reading (no interchange for such a file).
Move to the native API¶
The native API needs no pandas:
| edi-835-parser | oxedi |
|---|---|
parse(path) |
oxedi.parse_file(path) returning a Result |
.to_dataframe() |
result.tables["services"].to_polars() / .to_pandas() (pip install "oxedi[polars]" or "oxedi[pandas]"), joined to claims on claim and to payments on payment |
.count_claims() |
result.count_claims() |
.count_patients() |
result.count_patients() (a null id is not a patient. Ids are text, so 0123 and 123 are different patients, unlike edi-835-parser) |
.sum_payments() (float) |
result.sum_payments() (Decimal) |
transaction_set.payer / .payee |
result.payer / result.payee (dict of text values: name, identification_code, address, city, state, zip_code. ValueError when payments has more than one row) |
| none | SQL: duckdb.sql("select ... from claims") with claims = result.tables["claims"] |
Extras and pandas¶
The extras pin pandas differently: oxedi[pandas] asks for pandas>=2 and so allows pandas 3,
while oxedi[edi-835-parser] pins pandas>=2.0.3,<3, the range the compatibility layer's
parity with edi-835-parser 1.8.0 is tested on.