<commit_before>import re

from StringIO import StringIO

from lxml import etree as et

from pyws.errors import BadRequest
from pyws.functions.args import List, Dict, String
from pyws.response import Response
from pyws.protocols.base import Protocol

from utils import *
from wsdl import WsdlGenerator

TAG_NAME_RE = re.compile('{(.*?)}(.*)')
ENCODING = 'utf-8'

def get_element_name(el):
    name = el.tag
    mo = TAG_NAME_RE.search(name)
    if mo:
        return mo.group(1), mo.group(2)
    return None, name

NIL = '{http://www.w3.org/2001/XMLSchema-instance}nil'

def xml2obj(xml, schema):
    children = xml.getchildren()
    if not children:
        if xml.text is None:
            result = None
        else:
            result = unicode(xml.text)
    elif issubclass(schema, List):
        result = []
        for child in children:
            result.append(xml2obj(child, schema.element_type))
    elif issubclass(schema, Dict):
        result = {}
        schema = dict((field.name, field.type) for field in schema.fields)
        for child in children:
            name = get_element_name(child)[1]
            obj = xml2obj(child, schema[name])
            if name not in result:
                result[name] = obj
            else:
                if not isinstance(result[name], list):
                    result[name] = [result[name]]
                result[name].append(obj)
    else:
        raise BadRequest('Couldn\'t decode XML')
    return result

def obj2xml(root, contents, namespace=None):
    kwargs = namespace and {'namespace': namespace} or {}
    if isinstance(contents, (list, tuple)):
        for item in contents:
            element = et.SubElement(root, 'item', **kwargs)
            obj2xml(element, item, namespace)
    elif isinstance(contents, dict):
        for name, item in contents.iteritems():
            element = et.SubElement(root, name, **kwargs)
            obj2xml(element, item, namespace)
    elif contents is not None:
        root.text = unicode(contents)
    elif contents is None:
        root.set(NIL, 'true')
    return root


class SoapProtocol(Protocol):

    namespaces = {'se': SOAP_ENV_NS}

    def __init__(self, service_name, tns_prefix, *args, **kwargs):
        super(SoapProtocol, self).__init__(*args, **kwargs)
        self.service_name = service_name
        self.tns_prefix   = tns_prefix

    def get_function(self, request):

        if request.tail == 'wsdl':
            return self.get_wsdl

        request.xml = et.parse(StringIO(request.text.encode(ENCODING)))

        env = request.xml.xpath('/se:Envelope', namespaces=self.namespaces)

        if len(env) == 0:
            raise BadRequest('No {%s}Envelope element.' % SOAP_ENV_NS)
        env = env[0]

        body = env.xpath('./se:Body', namespaces=self.namespaces)

        if len(body) == 0:
            raise BadRequest('No {%s}Body element.' % SOAP_ENV_NS)
        if len(body) > 1:
            raise BadRequest(
                'There must be only one {%s}Body element.' % SOAP_ENV_NS)
        body = body[0]

        func = body.getchildren()
        if len(env) == 0:
            raise BadRequest(
                '{%s}Body element has no child elements.' % SOAP_ENV_NS)
        if len(env) > 1:
            raise BadRequest('{%s}Body element '
                'has more than one child element.' % SOAP_ENV_NS)
        func = func[0]

        request.func_xml = func

        func_name = get_element_name(func)[1]
        if func_name.endswith('_request'):
            func_name = func_name[:-8]

        return func_name

    def get_arguments(self, request, arguments):
        return xml2obj(request.func_xml, arguments)
<commit_msg>a littile bit of refactoring for SOAP protocol<commit_after>import re

from StringIO import StringIO

from lxml import etree as et

from pyws.errors import BadRequest
from pyws.functions.args import List, Dict, String
from pyws.response import Response
from pyws.protocols.base import Protocol

from utils import *
from wsdl import WsdlGenerator

TAG_NAME_RE = re.compile('{(.*?)}(.*)')
ENCODING = 'utf-8'

def get_element_name(el):
    name = el.tag
    mo = TAG_NAME_RE.search(name)
    if mo:
        return mo.group(1), mo.group(2)
    return None, name

NIL = '{http://www.w3.org/2001/XMLSchema-instance}nil'

def xml2obj(xml, schema):
    children = xml.getchildren()
    if not children:
        if xml.text is None:
            result = None
        else:
            result = unicode(xml.text)
    elif issubclass(schema, List):
        result = []
        for child in children:
            result.append(xml2obj(child, schema.element_type))
    elif issubclass(schema, Dict):
        result = {}
        schema = dict((field.name, field.type) for field in schema.fields)
        for child in children:
            name = get_element_name(child)[1]
            obj = xml2obj(child, schema[name])
            if name not in result:
                result[name] = obj
            else:
                if not isinstance(result[name], list):
                    result[name] = [result[name]]
                result[name].append(obj)
    else:
        raise BadRequest('Couldn\'t decode XML')
    return result

def obj2xml(root, contents, namespace=None):
    kwargs = namespace and {'namespace': namespace} or {}
    if isinstance(contents, (list, tuple)):
        for item in contents:
            element = et.SubElement(root, 'item', **kwargs)
            obj2xml(element, item, namespace)
    elif isinstance(contents, dict):
        for name, item in contents.iteritems():
            element = et.SubElement(root, name, **kwargs)
            obj2xml(element, item, namespace)
    elif contents is not None:
        root.text = unicode(contents)
    elif contents is None:
        root.set(NIL, 'true')
    return root

class ParsedData(object):
    pass


class SoapProtocol(Protocol):

    namespaces = {'se': SOAP_ENV_NS}

    def __init__(self, service_name, tns_prefix, *args, **kwargs):
        super(SoapProtocol, self).__init__(*args, **kwargs)
        self.service_name = service_name
        self.tns_prefix   = tns_prefix

    def parse_request(self, request):

        if hasattr(request, 'parsed_data'):
            return request.parsed_data

        request.parsed_data = ParsedData()

        xml = et.fromstring(request.text.encode(ENCODING))

        env = xml.xpath('/se:Envelope', namespaces=self.namespaces)

        if len(env) == 0:
            raise BadRequest('No {%s}Envelope element.' % SOAP_ENV_NS)
        env = env[0]

        body = env.xpath('./se:Body', namespaces=self.namespaces)

        if len(body) == 0:
            raise BadRequest('No {%s}Body element.' % SOAP_ENV_NS)
        if len(body) > 1:
            raise BadRequest(
                'There must be only one {%s}Body element.' % SOAP_ENV_NS)
        body = body[0]

        func = body.getchildren()
        if len(env) == 0:
            raise BadRequest(
                '{%s}Body element has no child elements.' % SOAP_ENV_NS)
        if len(env) > 1:
            raise BadRequest('{%s}Body element '
                'has more than one child element.' % SOAP_ENV_NS)
        func = func[0]

        func_name = get_element_name(func)[1]
        if func_name.endswith('_request'):
            func_name = func_name[:-8]

        request.parsed_data.xml = xml
        request.parsed_data.func_xml = func
        request.parsed_data.func_name = func_name

        return request.parsed_data

    def get_function(self, request):

        if request.tail == 'wsdl':
            return self.get_wsdl

        return self.parse_request(request).func_name

    def get_arguments(self, request, arguments):
        return xml2obj(self.parse_request(request).func_xml, arguments)

{'fraction_non_alphanumeric': 0.1097953404556571, 'fraction_numerical': 0.006693268116874759, 'mean_word_length': 2.3261986301369864, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 34}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6516770', 'n_tokens_mistral': 2392, 'n_tokens_neox': 2305, 'n_words': 614}