Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MRG] Add convenience function Event.encoded_dataset() #888

Merged
merged 10 commits into from
Nov 17, 2023
Prev Previous commit
Next Next commit
Doc improvements
  • Loading branch information
scaramallion committed Nov 17, 2023
commit d8298d98a32cb9a36430f26fb9b0f843f3503ecb
13 changes: 7 additions & 6 deletions docs/changelog/v2.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Fixes
* Fixed reserved A-ASSOCIATE-AC parameters being tested (:issue:`746`)
* Fixed datasets not transferring correctly when using
:attr:`~pynetdicom._config.STORE_RECV_CHUNKED_DATASET` (:issue:`756`)
* Fixed maximum length of PatientID attribute in qrscp app (:issue:`785`)
* Sanitize filenames for received datasets for non-conformant SOP Instance UIDs
(:issue:`823`)
* Fixed maximum length of *Patient ID* attribute in ``qrscp`` app (:issue:`785`)
* Sanitise filenames for received datasets for non-conformant SOP Instance
UIDs (:issue:`823`)

Enhancements
............
Expand All @@ -23,10 +23,11 @@ Enhancements
:class:`~pynetdicom.service_class.QueryRetrieveServiceClass` (:issue:`878`)
* Added support for :class:`Inventory Query/Retrieve Service Class
<pynetdicom.service_class.InventoryQueryRetrieveServiceClass>` (:issue:`879`)
* Added :meth:`pynetdicom.event.Event.encoded_dataset` to simplify writing
the raw encoded dataset to file
* Added :meth:`~pynetdicom.events.Event.encoded_dataset` to simplify accessing
the encoded dataset without first decoding it

Changes
.......

* Add preliminary support for Python 3.12
* Dropped support for Python 3.7, 3.8 and 3.9
* Added support for Python 3.12
5 changes: 3 additions & 2 deletions docs/tutorials/create_scp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,9 @@ complex code:
We've modified the handler to use :meth:`~pynetdicom.events.Event.encoded_dataset`,
which writes the preamble, prefix, file meta information elements and the
:attr:`raw dataset<dimse_primitives.C_STORE.DataSet>` received in the C-STORE
request directly to file. If you need separate access to just encoded dataset
then you can call ``encoded_dataset(include_meta=False)`` instead.
request directly to file. If you need separate access to just the encoded dataset
then you can call :meth:`~pynetdicom.events.Event.encoded_dataset` with
`include_meta=False` instead.

The second change we've made is to demonstrate how extra parameters can be
passed to the handler by binding using a 3-tuple rather than a 2-tuple. The
Expand Down
21 changes: 17 additions & 4 deletions pynetdicom/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
)
from pynetdicom.pdu import _PDUType
from pynetdicom.pdu_primitives import SOPClassCommonExtendedNegotiation
from pynetdicom.presentation import PresentationContexttuple
from pynetdicom.presentation import PresentationContextTuple

_RequestType = (
C_ECHO
Expand Down Expand Up @@ -441,7 +441,7 @@ def __init__(
# Define type hints for dynamic attributes
self.request: "_RequestType"
self._is_cancelled: Callable[[int], bool]
self.context: "PresentationContexttuple"
self.context: "PresentationContextTuple"
self.current_state: str
self.fsm_event: str
self.next_state: str
Expand Down Expand Up @@ -626,14 +626,22 @@ def dataset_path(self) -> Path:
return cast(Path, path)

def encoded_dataset(self, include_meta: bool = True) -> bytes:
"""Return the encoded dataset sent by the peer without decoding it.
"""Return the encoded C-STORE dataset sent by the peer without first
decoding it.

Examples
--------
Retrieve the encoded dataset as sent by the peer::

def handle_store(event: pynetdicom.events.Event) -> int:
stream: bytes = event.encoded_dataset(inclue_meta=False)

return 0x0000

Write the encoded dataset to file in the DICOM File Format without
having to first decode it::

def handle_store(event: pynetdicom.evt.Event, dst: pathlib.Path) -> int:
def handle_store(event: pynetdicom.events.Event, dst: pathlib.Path) -> int:
with dst.open("wb") as f:
f.write(event.encoded_dataset())

Expand All @@ -650,6 +658,11 @@ def handle_store(event: pynetdicom.evt.Event, dst: pathlib.Path) -> int:
bytes
The encoded dataset as sent by the peer, with or without the file
meta information.

Raises
------
AttributeError
If the corresponding event is not a C-STORE request.
"""
try:
stream = self.request.DataSet.getvalue()
Expand Down
7 changes: 7 additions & 0 deletions pynetdicom/tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ def test_raises(self):
with pytest.raises(AttributeError, match=msg):
event.dataset

msg = (
r"The corresponding event is not a C-STORE request "
r"and has no 'Data Set' parameter"
)
with pytest.raises(AttributeError, match=msg):
event.encoded_dataset()

msg = (
r"The corresponding event is not a C-FIND, C-GET or C-MOVE request "
r"and has no 'Identifier' parameter"
Expand Down