3232import requests
3333import retrying
3434
35- from dicomweb_client .uri import build_query_string , parse_query_parameters
35+ from dicomweb_client .uri import (
36+ build_query_string ,
37+ parse_query_parameters ,
38+ _validate_uid
39+ )
3640
3741
3842logger = logging .getLogger (__name__ )
@@ -200,7 +204,8 @@ def __init__(
200204 proxies : Optional [Dict [str , str ]] = None ,
201205 headers : Optional [Dict [str , str ]] = None ,
202206 callback : Optional [Callable ] = None ,
203- chunk_size : int = 10 ** 6
207+ chunk_size : int = 10 ** 6 ,
208+ permissive_uid : bool = False
204209 ) -> None :
205210 """Instatiate client.
206211
@@ -235,6 +240,14 @@ def __init__(
235240 when streaming data from the server using chunked transfer encoding
236241 (used by ``iter_*()`` methods as well as the ``store_instances()``
237242 method); defaults to ``10**6`` bytes (1MB)
243+ permissive_uid: bool, optional
244+ If ``True``, relaxes the DICOM Standard validation for UIDs (see
245+ main docstring for details). This option is made available since
246+ users may be occasionally forced to work with DICOMs or services
247+ that may be in violation of the standard. Unless required, use of
248+ this flag is **not** recommended, since non-conformant UIDs may
249+ lead to unexpected errors downstream, e.g., rejection by a DICOMweb
250+ server, etc.
238251
239252 Warning
240253 -------
@@ -314,6 +327,7 @@ def __init__(
314327 if callback is not None :
315328 self ._session .hooks = {'response' : [callback , ]}
316329 self ._chunk_size = chunk_size
330+ self ._permissive_uid = permissive_uid
317331 self .set_http_retry_params ()
318332
319333 def _get_transaction_url (self , transaction : _Transaction ) -> str :
@@ -2163,29 +2177,6 @@ def delete_study(
21632177 url += f'?{ additional_params_query_string } '
21642178 self ._http_delete (url )
21652179
2166- def _assert_uid_format (self , uid : str ) -> None :
2167- """Check whether a DICOM UID has the correct format.
2168-
2169- Parameters
2170- ----------
2171- uid: str
2172- DICOM UID
2173-
2174- Raises
2175- ------
2176- TypeError
2177- When `uid` is not a string
2178- ValueError
2179- When `uid` doesn't match the regular expression pattern
2180- ``"^[.0-9]+$"``
2181-
2182- """
2183- if not isinstance (uid , str ):
2184- raise TypeError ('DICOM UID must be a string.' )
2185- pattern = re .compile ('^[.0-9]+$' )
2186- if not pattern .search (uid ):
2187- raise ValueError ('DICOM UID has invalid format.' )
2188-
21892180 def search_for_series (
21902181 self ,
21912182 study_instance_uid : Optional [str ] = None ,
@@ -2238,7 +2229,7 @@ def search_for_series(
22382229
22392230 """ # noqa: E501
22402231 if study_instance_uid is not None :
2241- self . _assert_uid_format (study_instance_uid )
2232+ _validate_uid (study_instance_uid , self . _permissive_uid )
22422233 logger .info (f'search for series of study "{ study_instance_uid } "' )
22432234 else :
22442235 logger .info ('search for series' )
@@ -2297,12 +2288,12 @@ def _get_series(
22972288 f'retrieve series "{ series_instance_uid } " '
22982289 f'of study "{ study_instance_uid } "'
22992290 )
2300- self . _assert_uid_format (study_instance_uid )
2291+ _validate_uid (study_instance_uid , self . _permissive_uid )
23012292 if series_instance_uid is None :
23022293 raise ValueError (
23032294 'Series Instance UID is required for retrieval of series.'
23042295 )
2305- self . _assert_uid_format (series_instance_uid )
2296+ _validate_uid (series_instance_uid , self . _permissive_uid )
23062297 url = self ._get_series_url (
23072298 _Transaction .RETRIEVE ,
23082299 study_instance_uid ,
@@ -2457,7 +2448,7 @@ def retrieve_series_metadata(
24572448 'Study Instance UID is required for retrieval of '
24582449 'series metadata.'
24592450 )
2460- self . _assert_uid_format (study_instance_uid )
2451+ _validate_uid (study_instance_uid , self . _permissive_uid )
24612452 if series_instance_uid is None :
24622453 raise ValueError (
24632454 'Series Instance UID is required for retrieval of '
@@ -2467,7 +2458,7 @@ def retrieve_series_metadata(
24672458 f'retrieve metadata of series "{ series_instance_uid } " '
24682459 f'of study "{ study_instance_uid } "'
24692460 )
2470- self . _assert_uid_format (series_instance_uid )
2461+ _validate_uid (series_instance_uid , self . _permissive_uid )
24712462 url = self ._get_series_url (
24722463 _Transaction .RETRIEVE ,
24732464 study_instance_uid ,
@@ -2660,7 +2651,7 @@ def search_for_instances(
26602651 if series_instance_uid is not None :
26612652 message += f' of series "{ series_instance_uid } "'
26622653 if study_instance_uid is not None :
2663- self . _assert_uid_format (study_instance_uid )
2654+ _validate_uid (study_instance_uid , self . _permissive_uid )
26642655 message += f' of study "{ study_instance_uid } "'
26652656 logger .info (message )
26662657 url = self ._get_instances_url (
@@ -2727,12 +2718,12 @@ def retrieve_instance(
27272718 raise ValueError (
27282719 'Study Instance UID is required for retrieval of instance.'
27292720 )
2730- self . _assert_uid_format (study_instance_uid )
2721+ _validate_uid (study_instance_uid , self . _permissive_uid )
27312722 if series_instance_uid is None :
27322723 raise ValueError (
27332724 'Series Instance UID is required for retrieval of instance.'
27342725 )
2735- self . _assert_uid_format (series_instance_uid )
2726+ _validate_uid (series_instance_uid , self . _permissive_uid )
27362727 if sop_instance_uid is None :
27372728 raise ValueError (
27382729 'SOP Instance UID is required for retrieval of instance.'
@@ -2742,7 +2733,7 @@ def retrieve_instance(
27422733 f'of series "{ series_instance_uid } " '
27432734 f'of study "{ study_instance_uid } "'
27442735 )
2745- self . _assert_uid_format (sop_instance_uid )
2736+ _validate_uid (sop_instance_uid , self . _permissive_uid )
27462737 url = self ._get_instances_url (
27472738 _Transaction .RETRIEVE ,
27482739 study_instance_uid ,
0 commit comments