Giter VIP home page Giter VIP logo

python-hl7's Introduction

python-hl7's People

Contributors

andriyor avatar jcgoette avatar johnpaulett avatar joseph-wortmann avatar kahlertl avatar rectalogic avatar timgates42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-hl7's Issues

AttributeError: 'HL7StreamProtocol' object has no attribute '_reject_connection'

MLLP using asyncio is not working on python3.6 version. any workaround to solve this issue?

eventhough i have installed asyncio package getting below error while opening the socket connection especially in python3.6 version.

Unhandled exception; stopping loop: 'Exception in callback HL7StreamProtocol.connection_made(<_SelectorSoc...e, bufsize=0>>)'
Traceback (most recent call last):
File "/usr/lib64/python3.6/asyncio/events.py", line 145, in _run
self._callback(*self._args)
File "/usr/lib/python3.6/site-packages/hl7-0.4.2-py3.6.egg/hl7/mllp/streams.py", line 204, in connection_made
if self._reject_connection:
AttributeError: 'HL7StreamProtocol' object has no attribute '_reject_connection'
Traceback (most recent call last):
File "sender.py", line 41, in
aiorun.run(main(), stop_on_unhandled_errors=True)
File "/usr/lib/python3.6/site-packages/aiorun.py", line 351, in run
raise pending_exception_to_raise
File "/usr/lib64/python3.6/asyncio/events.py", line 145, in _run
self._callback(*self._args)
File "/usr/lib/python3.6/site-packages/hl7-0.4.2-py3.6.egg/hl7/mllp/streams.py", line 204, in connection_made
AttributeError: 'HL7StreamProtocol' object has no attribute '_reject_connection'

Rewriting HL7 messages fails

I'm working on a project that modifies HL7 messages and have run into a couple bugs. Your documentation say that the library may eventually contain the ability to create HL7.

  1. Modifying a field to greater depth fails
MSH|^~\\&|field|rep1~rep2|

A call to

seg.assign_field("NewRep", 3, 1)

Will fail because the field object contains a string, not a repetition. The desired behavior is to replace the sting with a repetition containing the new value.

I have a fix for this.

  1. Added fields are not escaped.

Fields get added through Segment.assign_fields(). My first thought was to add escaping to this method. However, this breaks several tests that construct HL7 message. It does not appear to break parsing, but it does break creation of ACK messages.

I'm not sure what a fix for this should be. Candidates:

  • All code that adds fields call escape() explicitly.
  • Code alternate to assign_fields() that escapes the value before writing.

If given some guidance, I'll implement that fix and then offer a pull request.

Unable to send messages with mllp_send

When trying to send messages using mllp_send it fails with the following error. I am able to send the same message with other tools like HL7 Inspector.

$ mllp_send --file lab.hl7 --port 9662 mirth.avilpage.com
Traceback (most recent call last):
  File "/Users/curatech/.virtualenvs/py37/bin/mllp_send", line 8, in <module>
    sys.exit(mllp_send())
  File "/Users/curatech/.virtualenvs/py37/lib/python3.7/site-packages/hl7/client.py", line 236, in mllp_send
    for message in message_stream:
  File "/Users/curatech/.virtualenvs/py37/lib/python3.7/site-packages/hl7/client.py", line 134, in read_stream
    raise MLLPException('buffer not terminated: %s' % _buffer)
hl7.client.MLLPException: buffer not terminated: b'MSH|^~\\&|GHH LAB|ELAB-3|GHH OE|BLDG4|200202150930||ORU^R01|CNTRL-3456|P|2.4\nPID|||555-44-4444||EVERYWOMAN^EVE^E^^^^L|JONES|196203520|F|||153 FERNWOOD DR.^^STATESVILLE^OH^35292||(206)3345232|(206)752-121||||AC555444444||67-A4335^OH^20030520\nOBR|1|845439^GHH OE|1045813^GHH LAB|1554-5^GLUCOSE|||200202150730||||||||555-55-5555^PRIMARY^PATRICIA P^^^^MD^^LEVEL SEVEN HEALTHCARE, INC.|||||||||F||||||444-44-4444^HIPPOCRATES^HOWARD H^^^^MD\nOBX|1|SN|1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F'

Test message

MSH|^~\&|GHH LAB|ELAB-3|GHH OE|BLDG4|200202150930||ORU^R01|CNTRL-3456|P|2.4
PID|||555-44-4444||EVERYWOMAN^EVE^E^^^^L|JONES|196203520|F|||153 FERNWOOD DR.^^STATESVILLE^OH^35292||(206)3345232|(206)752-121||||AC555444444||67-A4335^OH^20030520
OBR|1|845439^GHH OE|1045813^GHH LAB|1554-5^GLUCOSE|||200202150730||||||||555-55-5555^PRIMARY^PATRICIA P^^^^MD^^LEVEL SEVEN HEALTHCARE, INC.|||||||||F||||||444-44-4444^HIPPOCRATES^HOWARD H^^^^MD
OBX|1|SN|1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F

Await hl7_reader.readmessage() never completes

I am facing the issue that await hl7_reader.readmessage() never completes. Using await asyncio.wait_for(hl7_reader.readmessage(), timeout=5) I can see that a timeout is thrown every time. What may cause this issue?

assertionError

hi!
i am getting an assertion Error when i create a python script. Using Jupyter seems to work.
i have python 3.7.3 interpreter. Ipython 7.4.0
platform: Windows 10

i am still learning python.
not sure if there is something wrong with my code or is it something else.

import hl7
f_open = open("message")
hlmessage = f_open.read()
myhl7 = hl7.parse("hlmessage")

my hl7 message which i wrote to file.

MSH|^&|EPIC|EPICADT|SMS|SMSADT|199912271408|CHARRIS|ADT^A04|1817457|D|2.5|
PID||0493575^^^2^ID 1|454721||DOE^JOHN^^^^|DOE^JOHN^^^^|19480203|M||B|254 MYSTREET AVE^^MYTOWN^OH^44123^USA||(216)123-4567|||M|NON|400003403
1129086|
NK1||ROE^MARIE^^^^|SPO||(216)123-4567||EC|||||||||||||||||||||||||||
PV1||O|168 219C~PMA^^^^^^^^^||||277^ALLEN MYLASTNAME^BONNIE^^^^|||||||||| ||2688684|||||||||||||||||||||||||199912271408||||||002376853

Assertion errors when I try to save message to a textField in Django

Question ( not saying this is a bug in python-hl7)
Something has changed ( we use 0.4.5) potentially in the messages we're seeing from an external source.

Previously I was assigning the message ok like so:

django_model.content = message ( a hl7.Message)

django_model.save()

But I'm seeing assertion errors - what could cause assertion errors in trying to write a message object to a string.

The message object has been constructed / inited already and a couple of fields parsed out ok.

Buggy ASCII escaping

If you escape a string containing any ASCII characters, this will lead to a TypeError:

import hl7

msg = hl7.Message(separator='\r', separators='\r|^~\&')
msg.escape('asdf')
Traceback (most recent call last):
  File "hl7/__init__.py", line 630, in escape
    return ''.join(rv)
TypeError: sequence item 0: expected str instance, bytes found

unicode does not work for me

Hey there!

unicode(h) only gets me the last segment. Python 2.7 and hl7 0.2.5

I had to do the following:

for x in range(0,len(h)):
print(unicode(h[x]))

hl7.client is not visible

It is mention about hl7.client.MLLPClient in API docs, but it is impossible to import hl7.client when installed using pip. You omit client section in __init__.py file.
Adding from .client import MLLPClient should fix the problem.

hl7 library in python 3.3

I have found some errors in the hl7 library
in the library unicode is used, but in python 3.3 unicode is replaced by str in this library (line48,80,91 in init.py).
it is the same with basestring it must also be replaced by str (in init.py line 116).

thanks in advance

Readmessage fails on HTML \E\ Escape Sequence

The follow fails when there is HTML messages in a segment with the \E\ escape sequence.

hl7_message = await hl7_reader.readmessage()

The data does not fully load--which never finds the end sequence when reading.

Getting error with the first line of code while creating newHL7 message

This is the only two lines of code:

import hl7
new_message = hl7.Message("ADT", "A01")

running this code shows this error:

C:...\hl7\containers.py:332: SyntaxWarning: invalid escape sequence '|'
self, separator=None, sequence=[], esc="\", separators="\r|~^&", factory=None
Traceback (most recent call last):
File "C:...\HL7msg.py", line 10, in
new_message = hl7.Message("ADT", "A01")
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:...\hl7\containers.py", line 334, in init
assert not separator or separator == separators[0]
AssertionError

Python version : Python 3.12.0

Defaulting to standard delimiters is surprising

https://github.com/johnpaulett/python-hl7/blob/6d85f25d678e366d2617690d4ee1216bb8027db1/hl7/parser.py#L351-LL370

  • The current parser behavior is to fill in any missing MSH-2 delimiters with the standard ones

According to the HL7 2.3 spec though

At any given site, the subset of the possible delimiters may be limited by negotiations between applications. This
implies that the receiving applications will use the agreed upon delimiters, as they appear in the Message Header
segment (MSH), to parse the message.

So it should be valid to use less delimiters. The issue is that by assuming the standard delimiters, python-hl7 will incorrectly split fields when parsing if a standard delimiter character (such as "&") is used in the content.

I am having problems with component separators

Hello.

I am facing some issues with component separators using the library (I was used to using a proprietary implementation before so I am net at python-hl7)
something simple as a message from:

message = 'MSH|^~\&|\r'
message += 'PID|Field1|Component1^Component2|Component1^SubComponent1&SubComponent2^Component3|Repeat1~Repeat2\r'

send that trough mllp and receive it with this library:

By what I understood from the docs, I could access my_message['PID'][2][1] to Access Component1. But that fails in 2 ways. First my_message['PID'] returns a length 1"list" so I have to access my_message['PID'] [0][2]. The same happend for the next level I have to access it as my_message['PID'][0][2][0][1]

Sorry if this is not a bug, but by what I understood from the documentation that is not the expected behavior:

A sample that I reproduce this would be:

message = 'MSH|^~\&|\r'
message += 'PID|Field1|Component1^Component2|Component1^Sub-Component1&Sub-Component2^Component3|Repeat1~Repeat2\r'

hl7_message = hl7.parse(message)

If I read hl7_message['PID'][2] here it already crashes...
I need to read as hl7_message['PID'][0][2]

Did I missunderstand completely the docs or is there something really wrong?

Add Batch and File containers

I've run into a need to be able to parse batch and file HL7 and retain the FHS/FTS and BHS/BTS information.

Obviously I can do this outside of python-hl7, but I thought that others might also be able to use it (and I hate writing the same code twice).

Seems to me the cleanest way to do this is to add two new container types (Batch and File) and two new parse methods (parse_batch and parse_file) given that the rules for parsing batches and files don't directly track to the rules for parsing a message.

The Batch container would provide access to the BHS and BTS information (as Segments if present, they're optional) and the contained messages as Messages. It would serialize back out as a hl7 batch.

The File container would provide access to the FHS and FTS information (as Segments if present, they're optional) and either the contained Batches or the contained Messages (the BHS/BTS segments are optional). It would serialize back out as an hl7 file.

The parse_batch and parse_file methods would take into account the optional FHS/FTS and BHS/BTS segments. I'm also thinking about a parse_hl7 top-level "factory" method that figures out if its a Message, Batch or File and does the right thing.

Finally, I would add an isbatch method that was similar to the isfile method in util.

This would be a non-breaking change.

If you agree with that approach I will write it and drop a PR.

Is there any socket timeout implemented on MLLPClient?

Hello, I'm using this library to perform some health check on a HL7 service that is receiving messages.
The logic is: everything is good if I have back a message (AA or AE doesn't matter), but give me an error if the service does not respond or the answer is not understandable (HL7 standard).
I'm trying to trap the possible errors on the MLLPClient call, and it throws me error if the service's port is closed/firewalled or if the service doesn't respond at all to my send_message .

The problem is: If perform this health check and the server doesn't respond but does not close the socket, the MLLPClient blocks my health check. In other words it seems there is not any timeout implemented.

Is there any chance to have this kind of timeout implemented? I have tried to do it myself, modifying the client.py, but unsuccessfully... Can you help me? Thanks

ishl7() broken for Mount Sinai (MSH) in 0.4.2

We just upgraded from 0.4.1 to 0.4.2 and many of our messages now fail to pass. We receive messages from Mount Sinai (MSH) and it appears ishl7() now scans the message for any occurrence of MSH and fails it if >1 - so all messages from Mount Sinai fail this check (sample below is deidentified)

>>> import hl7
>>> m = ('MSH|^~\\&|HNAM_PM|HNA500|AIG||20131017140041||ADT^A01|Q150084616T145947960|P|2.3\r'
...  'PID|1|2148790^^^MSH_MRN^MR|2148790^^^MSH_MRN^MR~162840^^^MSH_EMPI^CM|3722^0^^MSH_DTC^REFE~184737^0^^IID^DONOR '
...  '~Q2147670^0^^MSQ_MRN|RUFUSS^MELLODIAL^^^^^CURRENT||19521129|F|RUFUSS^MELLODIAL^^^^^PREVIOUS|OT|221 '
...  'CANVIEW '
...  'AVENUE^66-D^BRONX^NY^10454^USA^HOME^^058||3472444150^HOME~(000)000-0000^ALTERNATE||ENGLISH|M|PEN|O75622322^^^MSH_FIN_NBR^FIN '
...  'NB|125544697|||HIS|||0\r'
...  'PV1|0001|I|MBN1^MBN1^06|4| '
...  '863968||03525^FARP^YONAN|03525^FARP^YONAN|""|NUR|||N|5|| '
...  'U|03525^FARP^YONAN|I|01|T22~SLF|||||||||||||||||||E||AC|||20140210225300|""\r'
...  'DG1|0001|I9|440.21^ATHEROSCLEROSIS W/INT CLAUDCTN^I9|ATHEROSCLEROSIS W/INT '
...  'CLAUDCTN|""|A|||||||.00||9\r'
...  'IN1|0001|A10A|A10|HIP COMP MCAID|PO BOX 223^""^NEW YORK^NY^10116^US^^^""|HIP '
...  'ON '
...  'LINE|""|""|""|||""|""|25892261^""^""|C|BENNETT^NELLY|4^SELF|10981226|322-10 '
...  'GOODLIN AVE^APT '
...  'B31^FLUSHING^NY^11355^US^^^61|Y|""||||||Y||""|||||||-JNJ45517\r'
...  'IN2||062420044|""|||""|||||||||||||||||||60094|""|||||||||||||||||||||||||||||||\r'
...  'IN1|0002|GMED|""|MEDICAID|""|""|""|""|""|||""|""||X|BENNETT^NELLY|4^SELF|10981226|322-10 '
...  'GOODLIN AVE^APT B31^FLUSHING^NY^11355^US^^^61|""|""||||||""||||||\r'
...  'IN2||062420044|""|||""|||||||||||||||||||""|""||||||||||||||||||||||||||||||||""\r'
...  'IN1|0003|SLFJ|""|SELF-PAY|""|""|""|""|""|||""|""||P|BENNETT^NELLY|4^SELF|10981226|322-10 '
...  'GOODLIN AVE^APT B31^FLUSHING^NY^11355^US^^^61|""|""||||||""||||||\r\n')
>>> hl7.ishl7(m)
False

Return ack message to source port

Can this library, and specifically the start_hl7_server function with aiorun + async/await, be used to return an ack message to the source port of a connection, instead of to the port with the open connection?

separator not valid in Field creation

Hi,
It seems that there is a bug introduced in 0.4.3 version. Indeed, with 0.4.2 version, I can write that:

import hl7
f=hl7.Field("|", ["MSH"])
print(f)
MSH

With version 0.4.3 (and later):

import hl7
f=hl7.Field("|", ["MSH"])
Traceback (most recent call last):
  File "/snap/pycharm-community/312/plugins/python-ce/helpers/pydev/pydevconsole.py", line 364, in runcode
    coro = func()
  File "<input>", line 1, in <module>
  File "/home/bc/Orthanc-Team/python-orthanc-tools/venv3/lib/python3.8/site-packages/hl7/containers.py", line 784, in __init__
    assert not separator or separator == separators[2]
AssertionError

Is it the expected behavior ?

Thanks for your support and your great job!

Support for trio

Hi! I'm starting work on a project which takes in HL7 data with python-hl7 and writes that data to a database. To support concurrency, I was planning on using the threading stdlib module, but since python-hl7 and txHL7 don't provide out-of-the-box support for synchronous (blocking) networking (correct me if I'm wrong), I started looking at async options instead.

It seems like trio is gaining a lot of support as a simpler async implementation that avoids pitfalls in asyncio and leads to shorter, more readable code. The author of trio has a few articles (1 2) that explain how it makes asynchronous code easier to write.

trio-asyncio is a compatibility layer that allows using asyncio libraries in trio applications, but it seems like it's not as easy as using a library that has native trio support. anyio is a library that lets other libraries natively support trio, asyncio, and curio (an older library similar to trio).

Given that you're actively working on an asyncio support for python-hl7, I was wondering what your thoughts are on trio support. I think there are a couple possible ways to proceed (any of these is OK, just wondering what you think):

  • Support only asyncio; trio users can use trio-asyncio.
  • Support trio, asyncio, and curio by using anyio.
  • Support only trio. May actually save you time and make it easier to write the MLLP feature given trio's emphasis on simplicity and usability, but would limit which projects can use this feature.

MLLP using asyncio,the HL7 Receiver occur “Error occurred in main: __aexit__ AttributeError”

Refer to the documentation, I plan to use asyncio to make an HL7 server, the relevant code is as follows:

import aiorun
import asyncio
import hl7
from hl7.mllp import start_hl7_server, HL7StreamReader, HL7StreamWriter
  
async def process_hl7_messages(hl7_reader=HL7StreamReader, hl7_writer=HL7StreamWriter):
      """This will be called every time a socket connects
      with us.
      """
      peername = hl7_writer.get_extra_info("peername")
      print("Connection established {}".format(peername))
      try:
          # We're going to keep listening until the writer
          # is closed. Only writers have closed status.
          #while not hl7_writer.is_closing():
              hl7_message = await hl7_reader.readmessage()
              print("Received message:{}".format(hl7_message))
              # Now let's send the ACK and wait for the
              # writer to drain
              hl7_writer.writemessage(hl7_message.create_ack())
              await hl7_writer.drain()
      except asyncio.IncompleteReadError:
          # Oops, something went wrong, if the writer is not
          # closed or closing, close it.
          #if not hl7_writer.is_closing():
              hl7_writer.close()
              await hl7_writer.wait_closed()
      print("Connection closed {}".format(peername))
      
async def main():
      try:
          # Start the server in a with clause to make sure we
          # close it
          async with await start_hl7_server(
              client_connected_cb=process_hl7_messages, host='10.5.47.17', port=9090
          ) as hl7_server:
              # And now we server forever. Or until we are
              # cancelled...
              await hl7_server.serve_forever()
      
      except asyncio.CancelledError:
          # Cancelled errors are expected
          pass
      except Exception as e:
          print("Error occurred in main:", e, e.__class__.__name__,)
          
aiorun.run(main(), stop_on_unhandled_errors=True)

I commented out :
“while not hl7_writer.is_closing():”
“if not hl7_writer.is_closing():”
since it doesn't seem to be implemented.

environment ubuntu 16.04, Python 3.5.2,when run "python3 server_test.py" the following error occurred:
"Error occurred in main: aexit AttributeError"
Hope someone can help me with this

use socket.sendall() instead of socket.send()

In a big project I currently encounter the fact, that another software receives just a partial MLLP message.

While debugging this issue I looked at the code of
https://github.com/johnpaulett/python-hl7/blob/main/hl7/client.py

Though I'm still not 100% sure, that hl7.client is the culprit in the current scenario I noticed, that

hl7.client.MLLPClient.send()
contains following line:

self.socket.send(data)

reading the documentation of https://docs.python.org/3/library/socket.html#socket.socket.send
one can read:

Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. 

This is not done in the code. So perhaps better to use self.socket.sendall(data)

https://docs.python.org/3/library/socket.html#socket.socket.sendall

Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs.

MLLP client doesn't receive full ack response when expected

MLLP client sends HL7 message properly, the server receives it, and tries to send ack message back. However, in many systems, probably due to low-level implementation details, HL7 ack message is divided into smaller chunks and send back as separate TCP packets.

MLLP client may receive the first \x0b byte from the response, which is the beginning of the MLLP envelope, then it will close the connection, due to use of ctx manager. Client will never receive full MSH+MSA message. This is against the protocol, and may cause various problems on the other system starting with inability to confirm reception of the message on it's side.

I don't have any solution for this yet, but temporary solution would to read the response until some deadline before closing the connection.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.