Add fastapi code

This commit is contained in:
2022-11-27 13:16:21 +01:00
parent 7cc1a424dc
commit 337ca690cf
2880 changed files with 643628 additions and 0 deletions

View File

@ -0,0 +1,19 @@
from __future__ import absolute_import
import sys
# This is the canonical package information.
__author__ = 'Andrew Dunham'
__license__ = 'Apache'
__copyright__ = "Copyright (c) 2012-2013, Andrew Dunham"
# We get the version from a sub-file that can be automatically generated.
from ._version import __version__
from .multipart import (
FormParser,
MultipartParser,
QuerystringParser,
OctetStreamParser,
create_form_parser,
parse_form,
)

View File

@ -0,0 +1 @@
__version__ = '0.0.5'

View File

@ -0,0 +1,171 @@
import base64
import binascii
from .exceptions import Base64Error, DecodeError
class Base64Decoder(object):
"""This object provides an interface to decode a stream of Base64 data. It
is instantiated with an "underlying object", and whenever a write()
operation is performed, it will decode the incoming data as Base64, and
call write() on the underlying object. This is primarily used for decoding
form data encoded as Base64, but can be used for other purposes::
from multipart.decoders import Base64Decoder
fd = open("notb64.txt", "wb")
decoder = Base64Decoder(fd)
try:
decoder.write("Zm9vYmFy") # "foobar" in Base64
decoder.finalize()
finally:
decoder.close()
# The contents of "notb64.txt" should be "foobar".
This object will also pass all finalize() and close() calls to the
underlying object, if the underlying object supports them.
Note that this class maintains a cache of base64 chunks, so that a write of
arbitrary size can be performed. You must call :meth:`finalize` on this
object after all writes are completed to ensure that all data is flushed
to the underlying object.
:param underlying: the underlying object to pass writes to
"""
def __init__(self, underlying):
self.cache = bytearray()
self.underlying = underlying
def write(self, data):
"""Takes any input data provided, decodes it as base64, and passes it
on to the underlying object. If the data provided is invalid base64
data, then this method will raise
a :class:`multipart.exceptions.DecodeError`
:param data: base64 data to decode
"""
# Prepend any cache info to our data.
if len(self.cache) > 0:
data = self.cache + data
# Slice off a string that's a multiple of 4.
decode_len = (len(data) // 4) * 4
val = data[:decode_len]
# Decode and write, if we have any.
if len(val) > 0:
try:
decoded = base64.b64decode(val)
except Base64Error:
raise DecodeError('There was an error raised while decoding '
'base64-encoded data.')
self.underlying.write(decoded)
# Get the remaining bytes and save in our cache.
remaining_len = len(data) % 4
if remaining_len > 0:
self.cache = data[-remaining_len:]
else:
self.cache = b''
# Return the length of the data to indicate no error.
return len(data)
def close(self):
"""Close this decoder. If the underlying object has a `close()`
method, this function will call it.
"""
if hasattr(self.underlying, 'close'):
self.underlying.close()
def finalize(self):
"""Finalize this object. This should be called when no more data
should be written to the stream. This function can raise a
:class:`multipart.exceptions.DecodeError` if there is some remaining
data in the cache.
If the underlying object has a `finalize()` method, this function will
call it.
"""
if len(self.cache) > 0:
raise DecodeError('There are %d bytes remaining in the '
'Base64Decoder cache when finalize() is called'
% len(self.cache))
if hasattr(self.underlying, 'finalize'):
self.underlying.finalize()
def __repr__(self):
return "%s(underlying=%r)" % (self.__class__.__name__, self.underlying)
class QuotedPrintableDecoder(object):
"""This object provides an interface to decode a stream of quoted-printable
data. It is instantiated with an "underlying object", in the same manner
as the :class:`multipart.decoders.Base64Decoder` class. This class behaves
in exactly the same way, including maintaining a cache of quoted-printable
chunks.
:param underlying: the underlying object to pass writes to
"""
def __init__(self, underlying):
self.cache = b''
self.underlying = underlying
def write(self, data):
"""Takes any input data provided, decodes it as quoted-printable, and
passes it on to the underlying object.
:param data: quoted-printable data to decode
"""
# Prepend any cache info to our data.
if len(self.cache) > 0:
data = self.cache + data
# If the last 2 characters have an '=' sign in it, then we won't be
# able to decode the encoded value and we'll need to save it for the
# next decoding step.
if data[-2:].find(b'=') != -1:
enc, rest = data[:-2], data[-2:]
else:
enc = data
rest = b''
# Encode and write, if we have data.
if len(enc) > 0:
self.underlying.write(binascii.a2b_qp(enc))
# Save remaining in cache.
self.cache = rest
return len(data)
def close(self):
"""Close this decoder. If the underlying object has a `close()`
method, this function will call it.
"""
if hasattr(self.underlying, 'close'):
self.underlying.close()
def finalize(self):
"""Finalize this object. This should be called when no more data
should be written to the stream. This function will not raise any
exceptions, but it may write more data to the underlying object if
there is data remaining in the cache.
If the underlying object has a `finalize()` method, this function will
call it.
"""
# If we have a cache, write and then remove it.
if len(self.cache) > 0:
self.underlying.write(binascii.a2b_qp(self.cache))
self.cache = b''
# Finalize our underlying stream.
if hasattr(self.underlying, 'finalize'):
self.underlying.finalize()
def __repr__(self):
return "%s(underlying=%r)" % (self.__class__.__name__, self.underlying)

View File

@ -0,0 +1,58 @@
import binascii
from six import PY3
class FormParserError(ValueError):
"""Base error class for our form parser."""
pass
class ParseError(FormParserError):
"""This exception (or a subclass) is raised when there is an error while
parsing something.
"""
#: This is the offset in the input data chunk (*NOT* the overall stream) in
#: which the parse error occured. It will be -1 if not specified.
offset = -1
class MultipartParseError(ParseError):
"""This is a specific error that is raised when the MultipartParser detects
an error while parsing.
"""
pass
class QuerystringParseError(ParseError):
"""This is a specific error that is raised when the QuerystringParser
detects an error while parsing.
"""
pass
class DecodeError(ParseError):
"""This exception is raised when there is a decoding error - for example
with the Base64Decoder or QuotedPrintableDecoder.
"""
pass
# On Python 3.3, IOError is the same as OSError, so we don't want to inherit
# from both of them. We handle this case below.
if IOError is not OSError: # pragma: no cover
class FileError(FormParserError, IOError, OSError):
"""Exception class for problems with the File class."""
pass
else: # pragma: no cover
class FileError(FormParserError, OSError):
"""Exception class for problems with the File class."""
pass
# We check which version of Python we're on to figure out what error we need
# to catch for invalid Base64.
if PY3: # pragma: no cover
Base64Error = binascii.Error
else: # pragma: no cover
Base64Error = TypeError

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,138 @@
try:
import unittest2 as unittest
except ImportError:
import unittest
import os
import re
import sys
import types
import functools
def ensure_in_path(path):
"""
Ensure that a given path is in the sys.path array
"""
if not os.path.isdir(path):
raise RuntimeError('Tried to add nonexisting path')
def _samefile(x, y):
try:
return os.path.samefile(x, y)
except (IOError, OSError):
return False
except AttributeError:
# Probably on Windows.
path1 = os.path.abspath(x).lower()
path2 = os.path.abspath(y).lower()
return path1 == path2
# Remove existing copies of it.
for pth in sys.path:
if _samefile(pth, path):
sys.path.remove(pth)
# Add it at the beginning.
sys.path.insert(0, path)
# Check if pytest is imported. If so, we use it to create marking decorators.
# If not, we just create a function that does nothing.
try:
import pytest
except ImportError:
pytest = None
if pytest is not None:
slow_test = pytest.mark.slow_test
xfail = pytest.mark.xfail
else:
slow_test = lambda x: x
def xfail(*args, **kwargs):
if len(args) > 0 and isinstance(args[0], types.FunctionType):
return args[0]
return lambda x: x
# We don't use the py.test parametrizing function, since it seems to break
# with unittest.TestCase subclasses.
def parametrize(field_names, field_values):
# If we're not given a list of field names, we make it.
if not isinstance(field_names, (tuple, list)):
field_names = (field_names,)
field_values = [(val,) for val in field_values]
# Create a decorator that saves this list of field names and values on the
# function for later parametrizing.
def decorator(func):
func.__dict__['param_names'] = field_names
func.__dict__['param_values'] = field_values
return func
return decorator
# This is a metaclass that actually performs the parametrization.
class ParametrizingMetaclass(type):
IDENTIFIER_RE = re.compile('[^A-Za-z0-9]')
def __new__(klass, name, bases, attrs):
new_attrs = attrs.copy()
for attr_name, attr in attrs.items():
# We only care about functions
if not isinstance(attr, types.FunctionType):
continue
param_names = attr.__dict__.pop('param_names', None)
param_values = attr.__dict__.pop('param_values', None)
if param_names is None or param_values is None:
continue
# Create multiple copies of the function.
for i, values in enumerate(param_values):
assert len(param_names) == len(values)
# Get a repr of the values, and fix it to be a valid identifier
human = '_'.join(
[klass.IDENTIFIER_RE.sub('', repr(x)) for x in values]
)
# Create a new name.
# new_name = attr.__name__ + "_%d" % i
new_name = attr.__name__ + "__" + human
# Create a replacement function.
def create_new_func(func, names, values):
# Create a kwargs dictionary.
kwargs = dict(zip(names, values))
@functools.wraps(func)
def new_func(self):
return func(self, **kwargs)
# Manually set the name and return the new function.
new_func.__name__ = new_name
return new_func
# Actually create the new function.
new_func = create_new_func(attr, param_names, values)
# Save this new function in our attrs dict.
new_attrs[new_name] = new_func
# Remove the old attribute from our new dictionary.
del new_attrs[attr_name]
# We create the class as normal, except we use our new attributes.
return type.__new__(klass, name, bases, new_attrs)
# This is a class decorator that actually applies the above metaclass.
def parametrize_class(klass):
return ParametrizingMetaclass(klass.__name__,
klass.__bases__,
klass.__dict__)

File diff suppressed because it is too large Load Diff