Next / Previous / Contents / Shipman's homepage

16. Sox._sortParams(): Classify content and attribute arguments

sox.py
# - - -   S o x . _ s o r t P a r a m s

    def _sortParams(self, p, kw):
        '''Check and process a content-list.

          [ (p is a sequence) and
            (kw is a dict) ->
              if (p is a valid content-list) and
              (the keys of kw and the dict elements of p are all
              xml-names) and
              (the values from kw and the values of dict elements
              of p are all unicode-okay) ->
                return (a list of unicode values made from
                the non-dictionary elements of p, a dictionary made
                from the dictionary elements of p as unicode
                plus the elements of kw as unicode)
              else -> raise SoxError ]
        '''

We start by building an empty dictionary in which to accumulate attribute key-value pairs, and an empty list in which to accumulate content items.

sox.py
        #-- 1
        contentList = []
        attribs = {}

The handling of the elements of p is by type. We process them by using a class dictionary ._typeRouter whose keys are the valid types, and each related value is a function that conforms to the interface defined in Section 8.1, “content-processor.

sox.py
        #-- 2
        # [ if the type of each element of p is a key in
        #   self._typeRouter ->
        #     contentList  +:=  content derived from that element as
        #         Unicode by self._typeRouter[that type], if any
        #     attribs  +:=  attributes derived from that element as
        #         Unicode by self._typeRouter[that type], if any
        #   else ->
        #     contentList  +:=  (anything)
        #     attribs  +:=  (anything)
        #     raise SoxError ]
        for param in p:
            #-- 2 body

            #-- 2.1
            # [ if type(param) is a key in self._typeRouter ->
            #     processor  :=  the corresponding value
            #   else -> raise SoxError ]
            try:
                processor = self._typeRouter[type(param)]
            except KeyError:
                raise SoxError("Argument %r is not a valid type "
                    "for element content." % param)

            #-- 2.2
            # [ contentList  +:=  content derived from param as
            #         Unicode by processor, if any
            #     attribs  +:=  attributes derived from param as
            #         Unicode by processor, if any ]
            processor(self, param, contentList, attribs)

That takes care of all the positional arguments. Next, we fold the dictionary kw of keyword arguments into attribs. We can't use the dict.update() method for this merger because we must check the keys to make sure they are valid XML names, and convert the keys and the values to Unicode.

sox.py
        #-- 3
        # [ if (all the keys of kw are xml-names) and
        #   (all the values from kw are unicode-okay) ->
        #     attrib  +:=  key-value pairs from kw, with keys
        #         and values as unicode
        #   else ->
        #     attrib  +:=  (anything)
        #     raise SoxError ]
        for key, value in kw.items():
            #-- 3 body
            # [ if (key is an xml-name) and (value is unicode-okay) ->
            #      attrib[key as unicode]  :=  value as unicode
            #   else -> raise SoxError ]
            #-- 3.1
            # [ if key is an xml-name ->
            #     uniKey  :=  key as unicode
            #   else -> raise SoxError ]
            uniKey = self._nameCheck(key)

            #-- 3.2
            # [ if value is unicode or can be converted etc. ->
            #     uniValue  :=  value, so converted
            #   else -> raise SoxError ]
            uniValue = self._unicodify(value)

            #-- 3.3
            attribs[uniKey] = uniValue

        #-- 4
        return (contentList, attribs)