Source code for pynetdicom.utils

"""Various utility functions."""

import codecs
from io import BytesIO
import logging
import unicodedata


LOGGER = logging.getLogger('pynetdicom.utils')


[docs]def validate_ae_title(ae_title): """Return a valid AE title from `ae_title`, if possible. An AE title: * Must be no more than 16 characters * Leading and trailing spaces are not significant * The characters should belong to the Default Character Repertoire excluding 0x5C (backslash) and all control characters If the supplied `ae_title` is greater than 16 characters once non-significant spaces have been removed then the returned AE title will be truncated to remove the excess characters. If the supplied `ae_title` is less than 16 characters once non-significant spaces have been removed, the spare trailing characters will be set to space (0x20) Parameters ---------- ae_title : str or bytes The AE title to check Returns ------- str or bytes A valid AE title (with the same type as the supplied `ae_title`), truncated to 16 characters if necessary. If Python 3 then only returns bytes. Raises ------ ValueError If `ae_title` is an empty string, contains only spaces or contains control characters or backslash TypeError If `ae_title` is not a string or bytes """ try: is_bytes = False if isinstance(ae_title, bytes): is_bytes = True ae_title = ae_title.decode('ascii') # Remove leading and trailing spaces significant_characters = ae_title.strip() # Remove trailing nulls (required as AE titles may be padded by nulls) # and common control chars (optional, for convenience) significant_characters = significant_characters.rstrip('\0\r\t\n') # Check for backslash or control characters for char in significant_characters: if unicodedata.category(char)[0] == "C" or char == "\\": raise ValueError("Invalid value for an AE title; must not " "contain backslash or control characters") # AE title OK if 0 < len(significant_characters) <= 16: while len(significant_characters) < 16: significant_characters += ' ' if is_bytes: return codecs.encode(significant_characters, 'ascii') return significant_characters # AE title too long : truncate elif len(significant_characters.strip()) > 16: if is_bytes: return codecs.encode(significant_characters[:16], 'ascii') return significant_characters[:16] # AE title empty str else: raise ValueError("Invalid value for an AE title; must be a " "non-empty string or bytes.") except AttributeError: raise TypeError("Invalid value for an AE title; must be a " "non-empty string or bytes.") except ValueError: raise except: raise TypeError("Invalid value for an AE title; must be a " "non-empty string or bytes.")
[docs]def pretty_bytes(bytestream, prefix=' ', delimiter=' ', items_per_line=16, max_size=512, suffix=''): """Turn the bytestring `bytestream` into a list of nicely formatted str. Parameters ---------- bytestream : bytes or io.BytesIO The bytes to convert to a nicely formatted string list prefix : str Insert `prefix` at the start of every item in the output string list delimiter : str Delimit each of the bytes in `bytestream` using `delimiter` items_per_line : int The number of bytes in each item of the output string list. max_size : int or None The maximum number of bytes to add to the output string list. A value of None indicates that all of `bytestream` should be output. suffix : str Append `suffix` to the end of every item in the output string list Returns ------- list of str The output string list """ lines = [] if isinstance(bytestream, BytesIO): bytestream = bytestream.getvalue() cutoff_output = False byte_count = 0 for ii in range(0, len(bytestream), items_per_line): # chunk is a bytes in python3 and a str in python2 chunk = bytestream[ii:ii + items_per_line] byte_count += len(chunk) # Python 2 compatibility if isinstance(chunk, str): gen = (format(ord(x), '02x') for x in chunk) else: gen = (format(x, '02x') for x in chunk) if max_size is not None and byte_count <= max_size: line = prefix + delimiter.join(gen) lines.append(line + suffix) elif max_size is not None and byte_count > max_size: cutoff_output = True break else: line = prefix + delimiter.join(gen) lines.append(line + suffix) if cutoff_output: lines.insert(0, prefix + 'Only dumping {0!s} bytes.'.format(max_size)) return lines