Package: pyramid_input
Thepyramid_inputpackage is a pyramid plugin that adds a “tween”
that parses and combines all data presented in the HTTP request in one
standardized request attribute. The following data is currently accepted
(in increasing order of precedence):Query string parametersRequest payload (i.e. the “request body”) in several different formatsSeeExamplefor a detailed example.ProjectHomepage:https://github.com/canaryhealth/pyramid_inputBugs:https://github.com/canaryhealth/pyramid_input/issuesInstallation$pipinstallpyramid_inputUsageEnable the tween either in your INI file via:pyramid.includes=pyramid_inputor in code in your package’s application initialization via:defmain(global_config,**settings):# ...config.include('pyramid_input')# ...If needed, adjust pyramid_input’s behaviour by setting the variousConfigurationoptions in your INI file.Then, access a request’s input parameters, regardless of their
origin or encoding, simply as:defrequest_handler(request):ifrequest.input.somekey=='some-value':...ExampleThe pyramid_input tween makes all of the following requests present
the identical structure in therequest.inputattribute:Interpreting GET data:GET /path?foo=bar&zig.zag=zog&zig.zen-0=mig&zig.zen-1=magInterpreting and merging GET and POST form data:POST /path?foo=bar
Content-Type: application/x-www-form-urlencoded

zig.zag=zog&zig.zen-0=mig&zig.zen-1=magInterpreting and merging GET and JSON payload data:POST /path?foo=bar
Content-Type: application/json

{"zig": {"zag": "zog", "zen": ["mig", "mag"]}}Interpreting and merging GET and YAML payload data:POST /path?foo=bar
Content-Type: application/yaml

zig:
  zag: zog
  zen:
    - mig
    - magInterpreting and merging GET and XML payload data:POST /path?foo=bar
Content-Type: application/xml

<zig>
  <zag>zog</zag>
  <zen>mig</zen>
  <zen>mag</zen>
</zig>All of the above will result in the identical data structure being
contained in therequest.inputattribute:request.input={'foo':'bar','zig':{'zag':'zog','zen':['mig','mag']}}Please note that in all cases the original parameters (inrequest.GET,request.POST,request.params,request.bodyandrequest.json_body) are left as-is, so if the raw data is needed, it
can be accessed directly.Query String ParsingThe HTTP query string parameters are “unflattened” using FormEncode’svariable_decodeimplementation, which converts the key-value pairs
into a nested tree structure. For example, the following query string
parameters:?simple=val1&dict.subkey=val2&dict.list-0=el0&dict.list-1=el1is transformed into the structure:{simple:val1dict:{subkey:val2list:[el0,el1]}}Note that query string parameters are by default overwritten by any
HTTP request payload data.Payload ParsingThe request payload (aka. request body) is parsed when the request’sContent-Typeis one of the following values:application/x-www-form-urlencoded,multipart/form-dataThe standard HTTPPOSTencoding; the key-value pairs are parsed
exactly the same way as the query string, i.e. they are unflattened
using FormEncode’svariable_decodeimplementation. Note that formultipart/form-data(the content-type used for standard
HTTP-based file uploading), nothing special is done: thefileobject that is inrequest.POSTis simply referenced as-is inrequest.inputas well.application/json,application/x-json,text/json,text/x-json,...+jsonThe payload is parsed using the built-in JSON parser, and no further
processing is done. The data is required to be a dictionary unless
thepyramid_input.require-dictis set to false, and if this is
violated, request processing is aborted with a 400 “Bad Request”
response error.application/yaml,application/x-yaml,text/yaml,text/x-yaml,...+yamlIf thePyYAMLpackage is available, the payload is parsed using
the YAML parser, and no further processing is done. The data is
required to be a dictionary unless thepyramid_input.require-dictis set to false, and if this is violated, request processing is
aborted with a 400 “Bad Request” response error.application/xml,application/x-xml,text/xml,text/x-xml,...+xmlThe payload is parsed using the built-in ElementTree parser and the
XML document is converted to a tree via a fairly simplistic mapping
process. Note that this mapping process is “lossy”, i.e. some
aspects of the XML serialization (such as order of interleaved
non-similar children nodes) are lost in the convertion.CombinationWhen both query string paramaters and a payload is specified in the
request, the output of parsing both data sources are then combined
together to form a single data tree. By default (i.e. whenpyramid_input.combine.deepis true), the payload data overrides the
query string data by overlaying and merging the two tree structures
recursively.A recursive deep merge basically means that dict keys get merged with
dict keys, and all other type combinations turn into lists.The deep merge can be disabled by setting thepyramid_input.combine.deepoption to false, in which case the
payload top-level dict keys completely override the query string
top-level keys, without any inspection of sub-keys.For example, given the following query string tree structure:foo:bardict:list:[a,b]item:cand the following payload tree structure:bar:foodict:list:ditem:ea deep merge will result in:foo:barbar:foodict:list:[a,b,d]item:[c,e]and a non-deep merge will result in:foo:barbar:foodict:list:ditem:eConfigurationThe following configuration settings can be set in your application’smainsection:pyramid_input.enabled: bool, default: truepyramid_input.attribute-name: str, default: ‘input’pyramid_input.combine.deep: bool, default: truepyramid_input.include: list(glob), default:/**pyramid_input.exclude: list(glob), default: nullpyramid_input.require-dict: bool, default: truepyramid_input.fail-unknown: bool, default: trueIf the request’s Content-Type is unknown (or its parser disabled)
andpyramid_input.fail-unknownis true, a 400 “bad request” error
is returned.  If set to false, the payload is ignored.pyramid_input.native-dict: bool, default: falseIf true,request.inputwill be a standard pythondictobject.
If false (the default), then it will be a recursiveaadictobject
(which is a subclass of dict that supports attribute-based access to
its items).pyramid_input.error-handler: symbol-spec, default: nullOn error (such as a 400 “Bad Request” for invalid JSON), this
function is called with thepyramid.httpexceptions.Exceptionsubclass that caused the error. The default implementation has
this function signature equivalent:deffunction(request,error):returnerrorpyramid_input.reparse-methods: list(str), default: ‘PATCH’Enable a workaround for pyramid 1.4.2+ that does not properly parse
theapplication/x-www-form-urlencodedrequest body if the request
method is PATCH. It is unknown if other methods have this issue or
if it has been fixed.pyramid_input.json.enable: bool, default: truepyramid_input.json.parser: symbol-spec, default: nullSpecifies the JSON parser. If not specified, uses Pyramid’s
pre-existingRequest.json_bodyattribute.pyramid_input.yaml.enable: bool, default: truepyramid_input.yaml.parser: symbol-spec, default: ‘yaml.load’pyramid_input.xml.enable: bool, default: truepyramid_input.xml.parser: symbol-spec, default: ‘xml.etree.ElementTree.fromstring’