Polling system for chosing MC server
This commit is contained in:
parent
8247cf1c44
commit
80c3fdf5be
2
.idea/discord.xml
generated
2
.idea/discord.xml
generated
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="true" />
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
</component>
|
||||
<component name="ProjectNotificationSettings">
|
||||
<option name="askShowProject" value="false" />
|
||||
|
@ -1,7 +1,8 @@
|
||||
from discord.ext import commands
|
||||
import asyncio
|
||||
|
||||
import discord
|
||||
import pymysql
|
||||
import asyncio
|
||||
from discord.ext import commands
|
||||
|
||||
password = open("../../../../sqlPass.txt", 'r')
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
import pymysql
|
||||
from discord.ext import commands
|
||||
|
||||
password = open("../../../../sqlPass.txt", 'r')
|
||||
|
||||
|
@ -1 +1 @@
|
||||
import discord
|
||||
|
||||
|
155
scr/Modules/TMC/McRoll.py
Normal file
155
scr/Modules/TMC/McRoll.py
Normal file
@ -0,0 +1,155 @@
|
||||
import asyncio
|
||||
import math
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import discord
|
||||
import pymysql
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
# password = open("../../../sqlPass.txt", 'r')
|
||||
|
||||
def get_con():
|
||||
return pymysql.connect(host='192.168.1.52',
|
||||
port=5618,
|
||||
user='Quentin',
|
||||
password='kaPl0wskii',
|
||||
db='mc',
|
||||
charset='utf8mb4',
|
||||
cursorclass=pymysql.cursors.DictCursor)
|
||||
|
||||
|
||||
class McRoll(commands.Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.currentPoll = None
|
||||
self.embedInfo = """Each server has a multiplier based on how long it has been sense that server has been rolled.
|
||||
When this poll is over all servers with 0 votes will be disregarded.
|
||||
If there are 4 or more servers left the two with the lowest votes will be disregarded.
|
||||
Poll is rerun until there are only 2 servers, these two are the winners. Ties reroll the poll.
|
||||
You can only vote for one server per poll. """
|
||||
|
||||
|
||||
async def start_poll(self, ctx, choices):
|
||||
embed = discord.Embed(title="Poll", description=self.embedInfo, timestamp=datetime.now() + timedelta(hours=12))
|
||||
for choice in choices.items():
|
||||
choice = choice[1]
|
||||
embed.add_field(
|
||||
name=choice['serverName'] + ' ' + (str(self.client.get_emoji(int(choice['reaction'])))
|
||||
if choice['getEmoji']
|
||||
else bytes(choice['reaction'], "utf-8").decode("unicode_escape")),
|
||||
value="Multiplier : " + str(round(2 * math.log10(choice['lastActivated'] + 1) + 1, 2)) + '\n' +
|
||||
"Last Rolled : " + str(choice['lastActivated'] * 2) + " weeks ago.")
|
||||
self.currentPoll = await ctx.channel.send(embed=embed)
|
||||
await ctx.channel.send("@everyone")
|
||||
for choice in choices.items():
|
||||
choice = choice[1]
|
||||
await self.currentPoll.add_reaction(self.client.get_emoji(int(choice['reaction']))
|
||||
if choice['getEmoji']
|
||||
else bytes(choice['reaction'], "utf-8").decode("unicode_escape"))
|
||||
await asyncio.sleep(43200)
|
||||
|
||||
for reaction in self.currentPoll.reactions:
|
||||
async for user in reaction.users():
|
||||
serverIp = self.reaction_to_serverip(reaction)
|
||||
if user.id != 533427166193385494:
|
||||
choices[serverIp]['votes'] = choices[serverIp]['votes'] + 1
|
||||
|
||||
choices[serverIp]['score'] = choices[serverIp]['votes'] * round(
|
||||
2 * math.log10(choices[serverIp]['lastActivated'] + 1) + 1, 2)
|
||||
|
||||
for choice in list(choices):
|
||||
if choices[choice]['score'] <= 0:
|
||||
choices.pop(choice)
|
||||
continue
|
||||
|
||||
if len(choices) >= 4:
|
||||
choices = self.pop_lowest(choices)
|
||||
choices = self.pop_lowest(choices)
|
||||
elif len(choices) == 3:
|
||||
choices = self.pop_lowest(choices)
|
||||
|
||||
return choices
|
||||
|
||||
|
||||
def pop_lowest(self, choices):
|
||||
lowest = {'score': 10}
|
||||
pop = False
|
||||
for choice in list(choices):
|
||||
if choices[choice]['score'] < lowest['score']:
|
||||
lowest = choices[choice]
|
||||
pop = True
|
||||
if pop:
|
||||
choices.pop(lowest['serverIP'])
|
||||
return choices
|
||||
|
||||
def reaction_to_serverip(self, reaction):
|
||||
con = get_con()
|
||||
escapedReaction = reaction.emoji.encode('unicode_escape').decode('utf-8')
|
||||
with con.cursor() as cursor:
|
||||
cursor.execute("SELECT serverIP FROM mc.server_list WHERE reaction=%s;", escapedReaction)
|
||||
serverIp = cursor.fetchone()
|
||||
con.close()
|
||||
return serverIp['serverIP']
|
||||
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_reaction_add(self, reaction, user):
|
||||
reactedUsers = {}
|
||||
if reaction.message.id == self.currentPoll.id and user.id != 533427166193385494:
|
||||
for iReaction in reaction.message.reactions:
|
||||
async for iUser in iReaction.users():
|
||||
if iUser.id != 533427166193385494:
|
||||
if iUser.id not in reactedUsers:
|
||||
reactedUsers[iUser.id] = False
|
||||
if reactedUsers[iUser.id]:
|
||||
await reaction.remove(user)
|
||||
self.currentPoll = reaction.message
|
||||
await user.send(
|
||||
"You can only vote for one option, please remove your previous vote to change it.")
|
||||
return
|
||||
self.currentPoll = reaction.message
|
||||
reactedUsers[iUser.id] = True
|
||||
|
||||
|
||||
@commands.command()
|
||||
async def mc_roll(self, ctx):
|
||||
if ctx.message.author.id != 305589587215122432:
|
||||
return
|
||||
|
||||
con = get_con()
|
||||
with con.cursor() as cursor:
|
||||
cursor.execute("SELECT serverIP, serverName, lastActivated, reaction, getEmoji "
|
||||
"FROM mc.server_list WHERE lastActivated is not null")
|
||||
choices = cursor.fetchall()
|
||||
con.close()
|
||||
|
||||
dictChoices = {}
|
||||
for choice in choices:
|
||||
choice['score'] = 0
|
||||
choice['votes'] = 0
|
||||
dictChoices[choice['serverIP']] = choice
|
||||
|
||||
dictChoices = await self.start_poll(ctx, dictChoices)
|
||||
|
||||
while len(dictChoices) > 2:
|
||||
print(dictChoices)
|
||||
dictChoices = await self.start_poll(ctx, dictChoices)
|
||||
|
||||
embed = discord.Embed(title="Winner", description="Congratulations")
|
||||
for item in list(dictChoices):
|
||||
winner = dictChoices[item]
|
||||
embed.add_field(
|
||||
name=winner['serverName'],
|
||||
value="Multiplier : " + str(round(2 * math.log10(winner['lastActivated'] + 1) + 1, 2)) + '\n' +
|
||||
"Last Rolled : " + str(winner['lastActivated'] * 2) + " weeks ago." + '\n' +
|
||||
"Votes : " + str(winner['votes']) + '\n' +
|
||||
"Calculated Votes: " + str(winner['votes'] * round(2 * math.log10(winner['lastActivated'] + 1) + 1, 2))
|
||||
)
|
||||
|
||||
await ctx.channel.send(embed=embed)
|
||||
await ctx.channel.send("@everyone")
|
||||
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(McRoll(client))
|
@ -1,6 +1,7 @@
|
||||
from discord.ext import commands
|
||||
import random
|
||||
|
||||
from discord.ext import commands
|
||||
|
||||
content = [", was just chosen to be the one.",
|
||||
", has joined!",
|
||||
", looks like someone took the slow train from Philly.",
|
||||
|
@ -1,6 +1,7 @@
|
||||
from discord.ext import commands
|
||||
import random
|
||||
|
||||
from discord.ext import commands
|
||||
|
||||
content = [" just bit the dust.",
|
||||
" gave up on life.",
|
||||
" couldn't take the heat anymore.",
|
||||
|
@ -1,5 +1,4 @@
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
|
||||
|
||||
class Spam(commands.Cog):
|
||||
|
@ -1,11 +1,13 @@
|
||||
import discord
|
||||
from discord.ext.commands import Bot
|
||||
|
||||
token = open("../token.txt")
|
||||
|
||||
cogs = ["Modules.TMC.autoReply.Join", "Modules.TMC.autoReply.Leave",
|
||||
"Modules.TMC.ChangeServer.Change"]
|
||||
"Modules.TMC.McRoll"]
|
||||
|
||||
prefix = 'o!'
|
||||
intents = discord.Intents().all()
|
||||
|
||||
"""
|
||||
tokens = open("tokens.txt", 'r')
|
||||
@ -17,7 +19,7 @@ elif bot_running == 'D':
|
||||
token = tokens[1].rstrip()
|
||||
tokens = ''
|
||||
"""
|
||||
client = Bot(command_prefix=prefix)
|
||||
client = Bot(command_prefix=prefix, intents=intents)
|
||||
client.remove_command("help")
|
||||
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: PyMySQL
|
||||
Version: 0.9.3
|
||||
Version: 0.10.1
|
||||
Summary: Pure Python MySQL Driver
|
||||
Home-page: https://github.com/PyMySQL/PyMySQL/
|
||||
Author: yutaka.matsubara
|
||||
Author-email: yutaka.matsubara@gmail.com
|
||||
Maintainer: INADA Naoki
|
||||
Maintainer: Inada Naoki
|
||||
Maintainer-email: songofacandy@gmail.com
|
||||
License: "MIT"
|
||||
Project-URL: Documentation, https://pymysql.readthedocs.io/
|
||||
@ -15,15 +15,18 @@ Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Topic :: Database
|
||||
Provides-Extra: ed25519
|
||||
Requires-Dist: PyNaCl (>=1.4.0) ; extra == 'ed25519'
|
||||
Provides-Extra: rsa
|
||||
Requires-Dist: cryptography ; extra == 'rsa'
|
||||
|
||||
@ -67,7 +70,7 @@ Requirements
|
||||
|
||||
* Python -- one of the following:
|
||||
|
||||
- CPython_ : 2.7 and >= 3.4
|
||||
- CPython_ : 2.7 and >= 3.5
|
||||
- PyPy_ : Latest version
|
||||
|
||||
* MySQL Server -- one of the following:
|
||||
@ -95,6 +98,11 @@ you need to install additional dependency::
|
||||
|
||||
$ python3 -m pip install PyMySQL[rsa]
|
||||
|
||||
To use MariaDB's "ed25519" authentication method, you need to install
|
||||
additional dependency::
|
||||
|
||||
$ python3 -m pip install PyMySQL[ed25519]
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
@ -1,11 +1,12 @@
|
||||
PyMySQL-0.9.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
PyMySQL-0.9.3.dist-info/LICENSE,sha256=MUEg3GXwgA9ziksxQAx27hTezR--d86cNUCkIbhup7Y,1070
|
||||
PyMySQL-0.9.3.dist-info/METADATA,sha256=8_R1N3H_AmpUu72ctuiQVI1Pk2SMlb9sy1uGlnxXB4U,5212
|
||||
PyMySQL-0.9.3.dist-info/RECORD,,
|
||||
PyMySQL-0.9.3.dist-info/WHEEL,sha256=_wJFdOYk7i3xxT8ElOkUJvOdOvfNGbR9g-bf6UQT6sU,110
|
||||
PyMySQL-0.9.3.dist-info/pbr.json,sha256=Lqvh8-9N7qS6SLUlEJ5GDLWioQcvR9n1WWjMEfJ5mv8,47
|
||||
PyMySQL-0.9.3.dist-info/top_level.txt,sha256=IKlV-f4o90sOdnMd6HBvo0l2nqfJOGUzkwZeaEEGuRg,8
|
||||
pymysql/__init__.py,sha256=ESllVZVoMVkJ0w9FoaMMirjFbWNc6wmHEVHzGKEBefc,4732
|
||||
PyMySQL-0.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
PyMySQL-0.10.1.dist-info/LICENSE,sha256=MUEg3GXwgA9ziksxQAx27hTezR--d86cNUCkIbhup7Y,1070
|
||||
PyMySQL-0.10.1.dist-info/METADATA,sha256=SP0KPSfmgNJ2ujhGRrRRiWOodzv62BfYnbY1OXX3DTI,5481
|
||||
PyMySQL-0.10.1.dist-info/RECORD,,
|
||||
PyMySQL-0.10.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
PyMySQL-0.10.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
|
||||
PyMySQL-0.10.1.dist-info/pbr.json,sha256=Lqvh8-9N7qS6SLUlEJ5GDLWioQcvR9n1WWjMEfJ5mv8,47
|
||||
PyMySQL-0.10.1.dist-info/top_level.txt,sha256=IKlV-f4o90sOdnMd6HBvo0l2nqfJOGUzkwZeaEEGuRg,8
|
||||
pymysql/__init__.py,sha256=KDHcmnEoEDMmRPNO5JFcxb7lsypDmwGn5Td-f-X6xDY,4733
|
||||
pymysql/__pycache__/__init__.cpython-36.pyc,,
|
||||
pymysql/__pycache__/_auth.cpython-36.pyc,,
|
||||
pymysql/__pycache__/_compat.cpython-36.pyc,,
|
||||
@ -19,15 +20,15 @@ pymysql/__pycache__/optionfile.cpython-36.pyc,,
|
||||
pymysql/__pycache__/protocol.cpython-36.pyc,,
|
||||
pymysql/__pycache__/times.cpython-36.pyc,,
|
||||
pymysql/__pycache__/util.cpython-36.pyc,,
|
||||
pymysql/_auth.py,sha256=X2AiuevuDaD2L4wJO5J7rymvJJZm6mND7WYmeIb7wEk,7720
|
||||
pymysql/_auth.py,sha256=pEeHBpQ15h2wfj6k7np6LVHVz34whEXSs5KrqeYtDGw,9564
|
||||
pymysql/_compat.py,sha256=DSxMV2ib-rhIuQIKiXX44yds_0bN2M_RddfYQiSdB6U,481
|
||||
pymysql/_socketio.py,sha256=smsw4wudNM4CKl85uis8QHfjDhz2iXQRvl8QV4TmB1w,4049
|
||||
pymysql/charset.py,sha256=tNeEkuzFXM5zeuOYm_XSM8zdt5P_paV2SyUB9B2ibqI,10330
|
||||
pymysql/connections.py,sha256=98DHxN-h3tupGBIReR98E7LSTR7-OIYh3tulXGlGdvc,49041
|
||||
pymysql/charset.py,sha256=zaaRbEQrFiE0iCd3AB52WJY9VqVxQcp8sYcoPDlPdWI,10308
|
||||
pymysql/connections.py,sha256=xR0gWxvQ6IxBcFhY9JPmYRCcvs6xSnRKUq-DZ6MpfNY,49010
|
||||
pymysql/constants/CLIENT.py,sha256=cPMxnQQbBG6xqaEDwqzggTfWIuJQ1Oy7HrIgw_vgpo4,853
|
||||
pymysql/constants/COMMAND.py,sha256=ypGdEUmi8m9cdBZ3rDU6mb7bsIyu9ldCDvc4pNF7V70,680
|
||||
pymysql/constants/CR.py,sha256=5ojVkbisyw7Qo_cTNpnHYvV6xHRZXK39Qqv8tjGbIbg,2228
|
||||
pymysql/constants/ER.py,sha256=8q1PZOxezbXbRaPZrHrQebyLDx4CvAUkBArJ9xBuW0Y,12297
|
||||
pymysql/constants/ER.py,sha256=cH5wgU-e70wd0uSygNR5IFCnnXcrR9WLwJPMH22bhUw,12296
|
||||
pymysql/constants/FIELD_TYPE.py,sha256=yHZLSyQewMxTDx4PLrI1H_iwH2FnsrgBZFa56UG2HiQ,372
|
||||
pymysql/constants/FLAG.py,sha256=Fy-PrCLnUI7fx_o5WypYnUAzWAM0E9d5yL8fFRVKffY,214
|
||||
pymysql/constants/SERVER_STATUS.py,sha256=KogVCOrV-S5aAFwyVKeKgua13nwdt1WFyHagjCZbcpM,334
|
||||
@ -40,10 +41,10 @@ pymysql/constants/__pycache__/FIELD_TYPE.cpython-36.pyc,,
|
||||
pymysql/constants/__pycache__/FLAG.cpython-36.pyc,,
|
||||
pymysql/constants/__pycache__/SERVER_STATUS.cpython-36.pyc,,
|
||||
pymysql/constants/__pycache__/__init__.cpython-36.pyc,,
|
||||
pymysql/converters.py,sha256=BWHMbquNFUKfFXyZh6Qwch6mYLyYSQeaeifL4VLuISc,12235
|
||||
pymysql/cursors.py,sha256=m6MhwWnm3CbTE4JAXzDuo6CYKC7W6JzsY4PN9eDmKJk,17238
|
||||
pymysql/err.py,sha256=PaXGLqOnDXJoeYjLbMZQE5UQ3MHFqiiHCzaDPP-_NJA,3716
|
||||
pymysql/converters.py,sha256=kUT2KQdkqNTuSxzURVnQKS1ZcatoFTUfYe5b5QSJuRI,11055
|
||||
pymysql/cursors.py,sha256=eiP_oTDi1MM5EYLHoecwbv5BXWJ1qEjfK8Uy3SjGEcs,16250
|
||||
pymysql/err.py,sha256=Vdrt2rVaSePVlB_uy0JNoeN6zYBt0_mM1UFDighLgNM,3734
|
||||
pymysql/optionfile.py,sha256=4yW8A7aAR2Aild7ibLOCzIlTCcYd90PtR8LRGJSZs8o,658
|
||||
pymysql/protocol.py,sha256=GH2yzGqPwqX2t2G87k3EJQt7bYQOLEN6QoN_m15c4Ak,12024
|
||||
pymysql/protocol.py,sha256=9hAfVK-g4i53gHMoGj9QrPApywMYVM8oxGAuKb_-PXo,12071
|
||||
pymysql/times.py,sha256=_qXgDaYwsHntvpIKSKXp1rrYIgtq6Z9pLyLnO2XNoL0,360
|
||||
pymysql/util.py,sha256=jKPts8cOMIXDndjsV3783VW-iq9uMxETWqfHP6Bd-Zo,180
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
Binary file not shown.
123
venv/Lib/site-packages/_distutils_hack/__init__.py
Normal file
123
venv/Lib/site-packages/_distutils_hack/__init__.py
Normal file
@ -0,0 +1,123 @@
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import importlib
|
||||
import warnings
|
||||
|
||||
|
||||
is_pypy = '__pypy__' in sys.builtin_module_names
|
||||
|
||||
|
||||
def warn_distutils_present():
|
||||
if 'distutils' not in sys.modules:
|
||||
return
|
||||
if is_pypy and sys.version_info < (3, 7):
|
||||
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
|
||||
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
|
||||
return
|
||||
warnings.warn(
|
||||
"Distutils was imported before Setuptools, but importing Setuptools "
|
||||
"also replaces the `distutils` module in `sys.modules`. This may lead "
|
||||
"to undesirable behaviors or errors. To avoid these issues, avoid "
|
||||
"using distutils directly, ensure that setuptools is installed in the "
|
||||
"traditional way (e.g. not an editable install), and/or make sure "
|
||||
"that setuptools is always imported before distutils.")
|
||||
|
||||
|
||||
def clear_distutils():
|
||||
if 'distutils' not in sys.modules:
|
||||
return
|
||||
warnings.warn("Setuptools is replacing distutils.")
|
||||
mods = [name for name in sys.modules if re.match(r'distutils\b', name)]
|
||||
for name in mods:
|
||||
del sys.modules[name]
|
||||
|
||||
|
||||
def enabled():
|
||||
"""
|
||||
Allow selection of distutils by environment variable.
|
||||
"""
|
||||
which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'stdlib')
|
||||
return which == 'local'
|
||||
|
||||
|
||||
def ensure_local_distutils():
|
||||
clear_distutils()
|
||||
distutils = importlib.import_module('setuptools._distutils')
|
||||
distutils.__name__ = 'distutils'
|
||||
sys.modules['distutils'] = distutils
|
||||
|
||||
# sanity check that submodules load as expected
|
||||
core = importlib.import_module('distutils.core')
|
||||
assert '_distutils' in core.__file__, core.__file__
|
||||
|
||||
|
||||
def do_override():
|
||||
"""
|
||||
Ensure that the local copy of distutils is preferred over stdlib.
|
||||
|
||||
See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
|
||||
for more motivation.
|
||||
"""
|
||||
if enabled():
|
||||
warn_distutils_present()
|
||||
ensure_local_distutils()
|
||||
|
||||
|
||||
class DistutilsMetaFinder:
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
if path is not None:
|
||||
return
|
||||
|
||||
method_name = 'spec_for_{fullname}'.format(**locals())
|
||||
method = getattr(self, method_name, lambda: None)
|
||||
return method()
|
||||
|
||||
def spec_for_distutils(self):
|
||||
import importlib.abc
|
||||
import importlib.util
|
||||
|
||||
class DistutilsLoader(importlib.abc.Loader):
|
||||
|
||||
def create_module(self, spec):
|
||||
return importlib.import_module('setuptools._distutils')
|
||||
|
||||
def exec_module(self, module):
|
||||
pass
|
||||
|
||||
return importlib.util.spec_from_loader('distutils', DistutilsLoader())
|
||||
|
||||
def spec_for_pip(self):
|
||||
"""
|
||||
Ensure stdlib distutils when running under pip.
|
||||
See pypa/pip#8761 for rationale.
|
||||
"""
|
||||
if self.pip_imported_during_build():
|
||||
return
|
||||
clear_distutils()
|
||||
self.spec_for_distutils = lambda: None
|
||||
|
||||
@staticmethod
|
||||
def pip_imported_during_build():
|
||||
"""
|
||||
Detect if pip is being imported in a build script. Ref #2355.
|
||||
"""
|
||||
import traceback
|
||||
return any(
|
||||
frame.f_globals['__file__'].endswith('setup.py')
|
||||
for frame, line in traceback.walk_stack(None)
|
||||
)
|
||||
|
||||
|
||||
DISTUTILS_FINDER = DistutilsMetaFinder()
|
||||
|
||||
|
||||
def add_shim():
|
||||
sys.meta_path.insert(0, DISTUTILS_FINDER)
|
||||
|
||||
|
||||
def remove_shim():
|
||||
try:
|
||||
sys.meta_path.remove(DISTUTILS_FINDER)
|
||||
except ValueError:
|
||||
pass
|
1
venv/Lib/site-packages/_distutils_hack/override.py
Normal file
1
venv/Lib/site-packages/_distutils_hack/override.py
Normal file
@ -0,0 +1 @@
|
||||
__import__('_distutils_hack').do_override()
|
@ -1,433 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: aiohttp
|
||||
Version: 3.5.4
|
||||
Summary: Async http client/server framework (asyncio)
|
||||
Home-page: https://github.com/aio-libs/aiohttp
|
||||
Author: Nikolay Kim
|
||||
Author-email: fafhrd91@gmail.com
|
||||
Maintainer: Nikolay Kim <fafhrd91@gmail.com>, Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||
Maintainer-email: aio-libs@googlegroups.com
|
||||
License: Apache 2
|
||||
Project-URL: Chat: Gitter, https://gitter.im/aio-libs/Lobby
|
||||
Project-URL: CI: AppVeyor, https://ci.appveyor.com/project/aio-libs/aiohttp
|
||||
Project-URL: CI: Circle, https://circleci.com/gh/aio-libs/aiohttp
|
||||
Project-URL: CI: Shippable, https://app.shippable.com/github/aio-libs/aiohttp
|
||||
Project-URL: CI: Travis, https://travis-ci.com/aio-libs/aiohttp
|
||||
Project-URL: Coverage: codecov, https://codecov.io/github/aio-libs/aiohttp
|
||||
Project-URL: Docs: RTD, https://docs.aiohttp.org
|
||||
Project-URL: GitHub: issues, https://github.com/aio-libs/aiohttp/issues
|
||||
Project-URL: GitHub: repo, https://github.com/aio-libs/aiohttp
|
||||
Platform: UNKNOWN
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Topic :: Internet :: WWW/HTTP
|
||||
Classifier: Framework :: AsyncIO
|
||||
Requires-Python: >=3.5.3
|
||||
Requires-Dist: attrs (>=17.3.0)
|
||||
Requires-Dist: chardet (<4.0,>=2.0)
|
||||
Requires-Dist: multidict (<5.0,>=4.0)
|
||||
Requires-Dist: async-timeout (<4.0,>=3.0)
|
||||
Requires-Dist: yarl (<2.0,>=1.0)
|
||||
Requires-Dist: idna-ssl (>=1.0) ; python_version < "3.7"
|
||||
Requires-Dist: typing-extensions (>=3.6.5) ; python_version < "3.7"
|
||||
Provides-Extra: speedups
|
||||
Requires-Dist: aiodns ; extra == 'speedups'
|
||||
Requires-Dist: brotlipy ; extra == 'speedups'
|
||||
Requires-Dist: cchardet ; extra == 'speedups'
|
||||
|
||||
==================================
|
||||
Async http client/server framework
|
||||
==================================
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png
|
||||
:height: 64px
|
||||
:width: 64px
|
||||
:alt: aiohttp logo
|
||||
|
||||
|
|
||||
|
||||
.. image:: https://travis-ci.com/aio-libs/aiohttp.svg?branch=master
|
||||
:target: https://travis-ci.com/aio-libs/aiohttp
|
||||
:align: right
|
||||
:alt: Travis status for master branch
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/tnddy9k6pphl8w7k/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/aio-libs/aiohttp
|
||||
:align: right
|
||||
:alt: AppVeyor status for master branch
|
||||
|
||||
.. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/aio-libs/aiohttp
|
||||
:alt: codecov.io status for master branch
|
||||
|
||||
.. image:: https://badge.fury.io/py/aiohttp.svg
|
||||
:target: https://pypi.org/project/aiohttp
|
||||
:alt: Latest PyPI package version
|
||||
|
||||
.. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest
|
||||
:target: https://docs.aiohttp.org/
|
||||
:alt: Latest Read The Docs
|
||||
|
||||
.. image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
:target: https://gitter.im/aio-libs/Lobby
|
||||
:alt: Chat on Gitter
|
||||
|
||||
Key Features
|
||||
============
|
||||
|
||||
- Supports both client and server side of HTTP protocol.
|
||||
- Supports both client and server Web-Sockets out-of-the-box and avoids
|
||||
Callback Hell.
|
||||
- Provides Web-server with middlewares and pluggable routing.
|
||||
|
||||
|
||||
Getting started
|
||||
===============
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
To get something from the web:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
|
||||
async def fetch(session, url):
|
||||
async with session.get(url) as response:
|
||||
return await response.text()
|
||||
|
||||
async def main():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
html = await fetch(session, 'http://python.org')
|
||||
print(html)
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
An example using a simple server:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# examples/server_simple.py
|
||||
from aiohttp import web
|
||||
|
||||
async def handle(request):
|
||||
name = request.match_info.get('name', "Anonymous")
|
||||
text = "Hello, " + name
|
||||
return web.Response(text=text)
|
||||
|
||||
async def wshandle(request):
|
||||
ws = web.WebSocketResponse()
|
||||
await ws.prepare(request)
|
||||
|
||||
async for msg in ws:
|
||||
if msg.type == web.WSMsgType.text:
|
||||
await ws.send_str("Hello, {}".format(msg.data))
|
||||
elif msg.type == web.WSMsgType.binary:
|
||||
await ws.send_bytes(msg.data)
|
||||
elif msg.type == web.WSMsgType.close:
|
||||
break
|
||||
|
||||
return ws
|
||||
|
||||
|
||||
app = web.Application()
|
||||
app.add_routes([web.get('/', handle),
|
||||
web.get('/echo', wshandle),
|
||||
web.get('/{name}', handle)])
|
||||
|
||||
web.run_app(app)
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
https://aiohttp.readthedocs.io/
|
||||
|
||||
|
||||
Demos
|
||||
=====
|
||||
|
||||
https://github.com/aio-libs/aiohttp-demos
|
||||
|
||||
|
||||
External links
|
||||
==============
|
||||
|
||||
* `Third party libraries
|
||||
<http://aiohttp.readthedocs.io/en/latest/third_party.html>`_
|
||||
* `Built with aiohttp
|
||||
<http://aiohttp.readthedocs.io/en/latest/built_with.html>`_
|
||||
* `Powered by aiohttp
|
||||
<http://aiohttp.readthedocs.io/en/latest/powered_by.html>`_
|
||||
|
||||
Feel free to make a Pull Request for adding your link to these pages!
|
||||
|
||||
|
||||
Communication channels
|
||||
======================
|
||||
|
||||
*aio-libs* google group: https://groups.google.com/forum/#!forum/aio-libs
|
||||
|
||||
Feel free to post your questions and ideas here.
|
||||
|
||||
*gitter chat* https://gitter.im/aio-libs/Lobby
|
||||
|
||||
We support `Stack Overflow
|
||||
<https://stackoverflow.com/questions/tagged/aiohttp>`_.
|
||||
Please add *aiohttp* tag to your question there.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Python >= 3.5.3
|
||||
- async-timeout_
|
||||
- attrs_
|
||||
- chardet_
|
||||
- multidict_
|
||||
- yarl_
|
||||
|
||||
Optionally you may install the cChardet_ and aiodns_ libraries (highly
|
||||
recommended for sake of speed).
|
||||
|
||||
.. _chardet: https://pypi.python.org/pypi/chardet
|
||||
.. _aiodns: https://pypi.python.org/pypi/aiodns
|
||||
.. _attrs: https://github.com/python-attrs/attrs
|
||||
.. _multidict: https://pypi.python.org/pypi/multidict
|
||||
.. _yarl: https://pypi.python.org/pypi/yarl
|
||||
.. _async-timeout: https://pypi.python.org/pypi/async_timeout
|
||||
.. _cChardet: https://pypi.python.org/pypi/cchardet
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
``aiohttp`` is offered under the Apache 2 license.
|
||||
|
||||
|
||||
Keepsafe
|
||||
========
|
||||
|
||||
The aiohttp community would like to thank Keepsafe
|
||||
(https://www.getkeepsafe.com) for its support in the early days of
|
||||
the project.
|
||||
|
||||
|
||||
Source code
|
||||
===========
|
||||
|
||||
The latest developer version is available in a GitHub repository:
|
||||
https://github.com/aio-libs/aiohttp
|
||||
|
||||
Benchmarks
|
||||
==========
|
||||
|
||||
If you are interested in efficiency, the AsyncIO community maintains a
|
||||
list of benchmarks on the official wiki:
|
||||
https://github.com/python/asyncio/wiki/Benchmarks
|
||||
|
||||
=========
|
||||
Changelog
|
||||
=========
|
||||
|
||||
..
|
||||
You should *NOT* be adding new change log entries to this file, this
|
||||
file is managed by towncrier. You *may* edit previous change logs to
|
||||
fix problems like typo corrections or such.
|
||||
To add a new change log entry, please see
|
||||
https://pip.pypa.io/en/latest/development/#adding-a-news-entry
|
||||
we named the news folder "changes".
|
||||
|
||||
WARNING: Don't drop the next directive!
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
3.5.4 (2019-01-12)
|
||||
==================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix stream ``.read()`` / ``.readany()`` / ``.iter_any()`` which used to return a
|
||||
partial content only in case of compressed content
|
||||
`#3525 <https://github.com/aio-libs/aiohttp/issues/3525>`_
|
||||
|
||||
|
||||
3.5.3 (2019-01-10)
|
||||
==================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix type stubs for ``aiohttp.web.run_app(access_log=True)`` and fix edge case of ``access_log=True`` and the event loop being in debug mode.
|
||||
`#3504 <https://github.com/aio-libs/aiohttp/issues/3504>`_
|
||||
- Fix ``aiohttp.ClientTimeout`` type annotations to accept ``None`` for fields
|
||||
`#3511 <https://github.com/aio-libs/aiohttp/issues/3511>`_
|
||||
- Send custom per-request cookies even if session jar is empty
|
||||
`#3515 <https://github.com/aio-libs/aiohttp/issues/3515>`_
|
||||
- Restore Linux binary wheels publishing on PyPI
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.5.2 (2019-01-08)
|
||||
==================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- ``FileResponse`` from ``web_fileresponse.py`` uses a ``ThreadPoolExecutor`` to work with files asynchronously.
|
||||
I/O based payloads from ``payload.py`` uses a ``ThreadPoolExecutor`` to work with I/O objects asynchronously.
|
||||
`#3313 <https://github.com/aio-libs/aiohttp/issues/3313>`_
|
||||
- Internal Server Errors in plain text if the browser does not support HTML.
|
||||
`#3483 <https://github.com/aio-libs/aiohttp/issues/3483>`_
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Preserve MultipartWriter parts headers on write.
|
||||
|
||||
Refactor the way how ``Payload.headers`` are handled. Payload instances now always
|
||||
have headers and Content-Type defined.
|
||||
|
||||
Fix Payload Content-Disposition header reset after initial creation.
|
||||
`#3035 <https://github.com/aio-libs/aiohttp/issues/3035>`_
|
||||
- Log suppressed exceptions in ``GunicornWebWorker``.
|
||||
`#3464 <https://github.com/aio-libs/aiohttp/issues/3464>`_
|
||||
- Remove wildcard imports.
|
||||
`#3468 <https://github.com/aio-libs/aiohttp/issues/3468>`_
|
||||
- Use the same task for app initialization and web server handling in gunicorn workers.
|
||||
It allows to use Python3.7 context vars smoothly.
|
||||
`#3471 <https://github.com/aio-libs/aiohttp/issues/3471>`_
|
||||
- Fix handling of chunked+gzipped response when first chunk does not give uncompressed data
|
||||
`#3477 <https://github.com/aio-libs/aiohttp/issues/3477>`_
|
||||
- Replace ``collections.MutableMapping`` with ``collections.abc.MutableMapping`` to avoid a deprecation warning.
|
||||
`#3480 <https://github.com/aio-libs/aiohttp/issues/3480>`_
|
||||
- ``Payload.size`` type annotation changed from `Optional[float]` to `Optional[int]`.
|
||||
`#3484 <https://github.com/aio-libs/aiohttp/issues/3484>`_
|
||||
- Ignore done tasks when cancels pending activities on ``web.run_app`` finalization.
|
||||
`#3497 <https://github.com/aio-libs/aiohttp/issues/3497>`_
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Add documentation for ``aiohttp.web.HTTPException``.
|
||||
`#3490 <https://github.com/aio-libs/aiohttp/issues/3490>`_
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- `#3487 <https://github.com/aio-libs/aiohttp/issues/3487>`_
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.5.1 (2018-12-24)
|
||||
====================
|
||||
|
||||
- Fix a regression about ``ClientSession._requote_redirect_url`` modification in debug
|
||||
mode.
|
||||
|
||||
3.5.0 (2018-12-22)
|
||||
====================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- The library type annotations are checked in strict mode now.
|
||||
- Add support for setting cookies for individual request (`#2387 <https://github.com/aio-libs/aiohttp/pull/2387>`_)
|
||||
- Application.add_domain implementation (`#2809 <https://github.com/aio-libs/aiohttp/pull/2809>`_)
|
||||
- The default ``app`` in the request returned by ``test_utils.make_mocked_request``
|
||||
can now have objects assigned to it and retrieved using the ``[]`` operator. (`#3174 <https://github.com/aio-libs/aiohttp/pull/3174>`_)
|
||||
- Make ``request.url`` accessible when transport is closed. (`#3177 <https://github.com/aio-libs/aiohttp/pull/3177>`_)
|
||||
- Add ``zlib_executor_size`` argument to ``Response`` constructor to allow compression to run in a background executor to avoid blocking the main thread and potentially triggering health check failures. (`#3205 <https://github.com/aio-libs/aiohttp/pull/3205>`_)
|
||||
- Enable users to set `ClientTimeout` in `aiohttp.request` (`#3213 <https://github.com/aio-libs/aiohttp/pull/3213>`_)
|
||||
- Don't raise a warning if ``NETRC`` environment variable is not set and ``~/.netrc`` file
|
||||
doesn't exist. (`#3267 <https://github.com/aio-libs/aiohttp/pull/3267>`_)
|
||||
- Add default logging handler to web.run_app
|
||||
|
||||
If the `Application.debug` flag is set and the default logger `aiohttp.access` is used, access logs will now be output using a `stderr` `StreamHandler` if no handlers are attached. Furthermore, if the default logger has no log level set, the log level will be set to `DEBUG`. (`#3324 <https://github.com/aio-libs/aiohttp/pull/3324>`_)
|
||||
- Add method argument to ``session.ws_connect()``.
|
||||
|
||||
Sometimes server API requires a different HTTP method for WebSocket connection establishment.
|
||||
|
||||
For example, ``Docker exec`` needs POST. (`#3378 <https://github.com/aio-libs/aiohttp/pull/3378>`_)
|
||||
- Create a task per request handling. (`#3406 <https://github.com/aio-libs/aiohttp/pull/3406>`_)
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Enable passing `access_log_class` via `handler_args` (`#3158 <https://github.com/aio-libs/aiohttp/pull/3158>`_)
|
||||
- Return empty bytes with end-of-chunk marker in empty stream reader. (`#3186 <https://github.com/aio-libs/aiohttp/pull/3186>`_)
|
||||
- Accept ``CIMultiDictProxy`` instances for ``headers`` argument in ``web.Response``
|
||||
constructor. (`#3207 <https://github.com/aio-libs/aiohttp/pull/3207>`_)
|
||||
- Don't uppercase HTTP method in parser (`#3233 <https://github.com/aio-libs/aiohttp/pull/3233>`_)
|
||||
- Make method match regexp RFC-7230 compliant (`#3235 <https://github.com/aio-libs/aiohttp/pull/3235>`_)
|
||||
- Add ``app.pre_frozen`` state to properly handle startup signals in sub-applications. (`#3237 <https://github.com/aio-libs/aiohttp/pull/3237>`_)
|
||||
- Enhanced parsing and validation of helpers.BasicAuth.decode. (`#3239 <https://github.com/aio-libs/aiohttp/pull/3239>`_)
|
||||
- Change imports from collections module in preparation for 3.8. (`#3258 <https://github.com/aio-libs/aiohttp/pull/3258>`_)
|
||||
- Ensure Host header is added first to ClientRequest to better replicate browser (`#3265 <https://github.com/aio-libs/aiohttp/pull/3265>`_)
|
||||
- Fix forward compatibility with Python 3.8: importing ABCs directly from the collections module will not be supported anymore. (`#3273 <https://github.com/aio-libs/aiohttp/pull/3273>`_)
|
||||
- Keep the query string by `normalize_path_middleware`. (`#3278 <https://github.com/aio-libs/aiohttp/pull/3278>`_)
|
||||
- Fix missing parameter ``raise_for_status`` for aiohttp.request() (`#3290 <https://github.com/aio-libs/aiohttp/pull/3290>`_)
|
||||
- Bracket IPv6 addresses in the HOST header (`#3304 <https://github.com/aio-libs/aiohttp/pull/3304>`_)
|
||||
- Fix default message for server ping and pong frames. (`#3308 <https://github.com/aio-libs/aiohttp/pull/3308>`_)
|
||||
- Fix tests/test_connector.py typo and tests/autobahn/server.py duplicate loop def. (`#3337 <https://github.com/aio-libs/aiohttp/pull/3337>`_)
|
||||
- Fix false-negative indicator end_of_HTTP_chunk in StreamReader.readchunk function (`#3361 <https://github.com/aio-libs/aiohttp/pull/3361>`_)
|
||||
- Release HTTP response before raising status exception (`#3364 <https://github.com/aio-libs/aiohttp/pull/3364>`_)
|
||||
- Fix task cancellation when ``sendfile()`` syscall is used by static file handling. (`#3383 <https://github.com/aio-libs/aiohttp/pull/3383>`_)
|
||||
- Fix stack trace for ``asyncio.TimeoutError`` which was not logged, when it is caught
|
||||
in the handler. (`#3414 <https://github.com/aio-libs/aiohttp/pull/3414>`_)
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Improve documentation of ``Application.make_handler`` parameters. (`#3152 <https://github.com/aio-libs/aiohttp/pull/3152>`_)
|
||||
- Fix BaseRequest.raw_headers doc. (`#3215 <https://github.com/aio-libs/aiohttp/pull/3215>`_)
|
||||
- Fix typo in TypeError exception reason in ``web.Application._handle`` (`#3229 <https://github.com/aio-libs/aiohttp/pull/3229>`_)
|
||||
- Make server access log format placeholder %b documentation reflect
|
||||
behavior and docstring. (`#3307 <https://github.com/aio-libs/aiohttp/pull/3307>`_)
|
||||
|
||||
|
||||
Deprecations and Removals
|
||||
-------------------------
|
||||
|
||||
- Deprecate modification of ``session.requote_redirect_url`` (`#2278 <https://github.com/aio-libs/aiohttp/pull/2278>`_)
|
||||
- Deprecate ``stream.unread_data()`` (`#3260 <https://github.com/aio-libs/aiohttp/pull/3260>`_)
|
||||
- Deprecated use of boolean in ``resp.enable_compression()`` (`#3318 <https://github.com/aio-libs/aiohttp/pull/3318>`_)
|
||||
- Encourage creation of aiohttp public objects inside a coroutine (`#3331 <https://github.com/aio-libs/aiohttp/pull/3331>`_)
|
||||
- Drop dead ``Connection.detach()`` and ``Connection.writer``. Both methods were broken
|
||||
for more than 2 years. (`#3358 <https://github.com/aio-libs/aiohttp/pull/3358>`_)
|
||||
- Deprecate ``app.loop``, ``request.loop``, ``client.loop`` and ``connector.loop`` properties. (`#3374 <https://github.com/aio-libs/aiohttp/pull/3374>`_)
|
||||
- Deprecate explicit debug argument. Use asyncio debug mode instead. (`#3381 <https://github.com/aio-libs/aiohttp/pull/3381>`_)
|
||||
- Deprecate body parameter in HTTPException (and derived classes) constructor. (`#3385 <https://github.com/aio-libs/aiohttp/pull/3385>`_)
|
||||
- Deprecate bare connector close, use ``async with connector:`` and ``await connector.close()`` instead. (`#3417 <https://github.com/aio-libs/aiohttp/pull/3417>`_)
|
||||
- Deprecate obsolete ``read_timeout`` and ``conn_timeout`` in ``ClientSession`` constructor. (`#3438 <https://github.com/aio-libs/aiohttp/pull/3438>`_)
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- #3341, #3351
|
||||
|
@ -1,124 +0,0 @@
|
||||
aiohttp-3.5.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
aiohttp-3.5.4.dist-info/LICENSE.txt,sha256=b9UkPpLdf5jsacesN3co50kFcJ_1J6W_mNbQJjwE9bY,11332
|
||||
aiohttp-3.5.4.dist-info/METADATA,sha256=vpBjLbRZ9Tbi4DEj6aDUlGbj-HJPHa8Wihktdh4Z9U0,16950
|
||||
aiohttp-3.5.4.dist-info/RECORD,,
|
||||
aiohttp-3.5.4.dist-info/WHEEL,sha256=NGBd8VpwAMkmGKuUIURJaMXNI6PaAo_v5wy1RzFtRN4,106
|
||||
aiohttp-3.5.4.dist-info/top_level.txt,sha256=iv-JIaacmTl-hSho3QmphcKnbRRYx1st47yjz_178Ro,8
|
||||
aiohttp/__init__.py,sha256=GdkiBfeUQa38wScKQYLH4mRL-20MqARHC0ljV6Naf8w,4948
|
||||
aiohttp/__pycache__/__init__.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/abc.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/base_protocol.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_proto.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_reqrep.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_ws.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/connector.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/cookiejar.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/formdata.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/frozenlist.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/hdrs.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/helpers.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_parser.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_websocket.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_writer.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/locks.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/log.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/multipart.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/payload.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/payload_streamer.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/pytest_plugin.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/resolver.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/signals.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/streams.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/tcp_helpers.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/test_utils.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/tracing.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/typedefs.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_app.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_fileresponse.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_log.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_middlewares.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_protocol.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_request.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_response.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_routedef.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_runner.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_server.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_urldispatcher.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_ws.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/worker.cpython-36.pyc,,
|
||||
aiohttp/_cparser.pxd,sha256=tgw30SL6kQSczzGMlMhx2Cuhf_O8P8ZPimVCb85xILc,3959
|
||||
aiohttp/_find_header.c,sha256=lWc5w3UZiVd3ni60DuFDSSPzsaQUhAQcERDGBOqeML8,189932
|
||||
aiohttp/_find_header.h,sha256=5oOgQ85nF6V7rpU8NhyE5vyGkTo1Cgf1GIYrtxSTzQI,170
|
||||
aiohttp/_find_header.pxd,sha256=0GfwFCPN2zxEKTO1_MA5sYq2UfzsG8kcV3aTqvwlz3g,68
|
||||
aiohttp/_frozenlist.c,sha256=TGMrV7V3PPs6wAktCttiCr_8p2Qn8uRQb7hFFag9x6A,287339
|
||||
aiohttp/_frozenlist.cp36-win_amd64.pyd,sha256=9JUCj2BYRIghlufCf0SAmKzWsu4js27eI0xZLUfrVEw,61440
|
||||
aiohttp/_frozenlist.pyx,sha256=BD8LcERExsWdo4qzuuQ84f-L_pHVzkUQO0lEAOe3Fog,2605
|
||||
aiohttp/_headers.pxi,sha256=XgJL5FQRwL4uZQfegYShPclsErUlvG_xuMHs7dp_2-o,2027
|
||||
aiohttp/_helpers.c,sha256=Kf2ro8IvT0TTxfB_P1yPBEZXYi597J9-Pc6a1HW_m34,207049
|
||||
aiohttp/_helpers.cp36-win_amd64.pyd,sha256=qd3DgclMuKf3cMVTEusoYVVdutfgTiYNxSVp0WVvQ8k,46080
|
||||
aiohttp/_helpers.pyi,sha256=mJRb5YdG8DxYbPfVddGRGmi93qqaJM30L1qFpgSKQuA,204
|
||||
aiohttp/_helpers.pyx,sha256=XeLbNft5X_4ifi8QB8i6TyrRuayijMSO3IDHeSA89uM,1049
|
||||
aiohttp/_http_parser.c,sha256=RsN44f-VDf-s6Pdhpeowlqu_tQK6qieHVdM9JoWB_No,994100
|
||||
aiohttp/_http_parser.cp36-win_amd64.pyd,sha256=bmU4boNpDPaQkrImibWgMwJDyUsLH1LqcZzGY3K7NbA,270336
|
||||
aiohttp/_http_parser.pyx,sha256=qAeXR88_UXU2ontoLIq7hg7M2KHjY982iJeH_u7aXXs,28672
|
||||
aiohttp/_http_writer.c,sha256=koVxrMta9W_hOkYK_8S4UD2zjnZo_T-umufxwePAhTc,205822
|
||||
aiohttp/_http_writer.cp36-win_amd64.pyd,sha256=i-iBsVTcStCakBdONEnWMM6QMbRIhFEYTYNRDplP-8s,38912
|
||||
aiohttp/_http_writer.pyx,sha256=vnanyXytNqyi6oqxELg5ARJ8LhtB8mDGxNfz6DdvH6E,4193
|
||||
aiohttp/_websocket.c,sha256=JVNi7H1-CxOO1Upw5b9b_IA1IKLp9B95_H8gZhhNkvg,135136
|
||||
aiohttp/_websocket.cp36-win_amd64.pyd,sha256=RrJYhQnL14kjT7Q5GvqsoVAtdpg683K52S_gZ0lcOWc,27648
|
||||
aiohttp/_websocket.pyx,sha256=tJfygcVwKF_Xb6Pg48a6t50YO2xY4Rg0Wj7LcJJMi-U,1559
|
||||
aiohttp/abc.py,sha256=lsf2bz-9KtqLhtI-e-tmgp3ynziMypYyEHvwOnFg7lQ,5392
|
||||
aiohttp/base_protocol.py,sha256=kv6AbDw8ZQOyB9Hm2bOaPZyXcAbUUwFOO2lbAmArpfw,2644
|
||||
aiohttp/client.py,sha256=hXh0WgGqhl80gVDlkuzgrHVaCxxkg_A9_mrhOkdSb-s,42549
|
||||
aiohttp/client_exceptions.py,sha256=3e7SWwDXDhUO5npOhwgdL6K8tXMTdVyv58rjQboY4Yo,7547
|
||||
aiohttp/client_proto.py,sha256=l1bLzhVx8hHOuS8nBPH6wNU15S-P6z_OMtpx_tPRi54,8001
|
||||
aiohttp/client_reqrep.py,sha256=LUhjuCGyJs55LcH_Sr3AMcAhS1XlcCPM73rc8C3_GV0,35793
|
||||
aiohttp/client_ws.py,sha256=AQlj-peBA0mGyra1t38sWlfV28MEM0SAATRXp1TsF9I,10694
|
||||
aiohttp/connector.py,sha256=AORmJFz8WLuAjca5O582FKCC74f6emuXdZfhWzvPpx4,39556
|
||||
aiohttp/cookiejar.py,sha256=ghkcBC9JhqKFz3InpJ4l2_stXLVv6qORX1303vepQUI,11268
|
||||
aiohttp/formdata.py,sha256=VZCo9kmDb50lQUcRMDfAH3d5lnRxBq_AX38ge8vFI00,5807
|
||||
aiohttp/frozenlist.py,sha256=I4zR368wRHXp402Z3f5lhd5i48b6A66MhHncW1JGkb4,1781
|
||||
aiohttp/frozenlist.pyi,sha256=fkQEKqDR6nOjXDx2cXvfCcetoMQQdzjXs2uoA7uVaP4,1431
|
||||
aiohttp/hdrs.py,sha256=iaXnHXOR_Dx0rvVkvmIZhc-7Egf2ByuSDI9tqskS0kQ,3449
|
||||
aiohttp/helpers.py,sha256=q_AZMU7hOJBvtTklhQpwa1DTH3uR5h2ZA0vLlsVGSQs,22633
|
||||
aiohttp/http.py,sha256=mYXbwDI8bF9D1RShF0EGtVTx7OgIyksbmKR4b_4RgBo,1385
|
||||
aiohttp/http_exceptions.py,sha256=yb2XryY_kktgiADcYn1nS0Dm-RVhhy0J6R0qfg-JyWo,2358
|
||||
aiohttp/http_parser.py,sha256=v9csKsBv-rmOir1ikRBcDJDAaPMsFen1HoP8_Viz6xE,27912
|
||||
aiohttp/http_websocket.py,sha256=GpysCWVOOQyRzvLSq0IHhVG0goWSnv5Rmwf91uUwowI,24594
|
||||
aiohttp/http_writer.py,sha256=XhGCqy_lzdLyxIzjQ_ufPFfJKTTWx1sb6YZWvrOFUPA,5239
|
||||
aiohttp/locks.py,sha256=l-cW8wUbIkHaovghT7gpY8Yp5Vlo-u2G7_CR5xQqEQ8,1234
|
||||
aiohttp/log.py,sha256=kOWU6EcyBQESISm27vc8dVEz_h9zxozLa5WCya1RzhQ,325
|
||||
aiohttp/multipart.py,sha256=h76ZKaEdP2moxWK0qNydR7zYMgGMoyqkkRssTmrtx1A,32277
|
||||
aiohttp/payload.py,sha256=QjzdcLJ89GGqFSN_SdMgEvw_Id4UEXZ9mL_2fAGF4gk,14027
|
||||
aiohttp/payload_streamer.py,sha256=ZNWaWwAxOIricwfjH4-YrkCqehowVizM6fJ_JVDR480,2103
|
||||
aiohttp/py.typed,sha256=E84IaZyFwfLqvXjOVW4LS6WH7QOaKEFpNh9TFyzHNQc,6
|
||||
aiohttp/pytest_plugin.py,sha256=8KOUt8KXu_3NkPQ8DYwgqKfdAvVZ--zHnm0EQiKFPkI,10332
|
||||
aiohttp/resolver.py,sha256=pRF91jOjTNuCll5TMRjTe1OxnGZK4wjAggYLgvzXkGQ,3626
|
||||
aiohttp/signals.py,sha256=_ge2XQXBDWHoyCI4E-nXC-sOEJGVrJm0zYGHH0E5woQ,948
|
||||
aiohttp/signals.pyi,sha256=mrEA9Ve08W22L_yI8_F7PkdQUjid_VsL3o9tcC0Ud0E,325
|
||||
aiohttp/streams.py,sha256=i1Q7_RzolpEQ63AkalkeeSHsMPOaHAfjnwlxvRmYi-k,20371
|
||||
aiohttp/tcp_helpers.py,sha256=1WVYM2C-HZQpgcksTyadRsl2_WeuXh_ECUxCcwji5d8,1631
|
||||
aiohttp/test_utils.py,sha256=0a0034sQM72grdRxjTnYpHtkUvMwstshfc9jVPXsZ1U,20525
|
||||
aiohttp/tracing.py,sha256=yfOJWzRQgRdDcdjsDLqPul3anYyVFhztDeyoM01oIq8,12662
|
||||
aiohttp/typedefs.py,sha256=6HXEWJNZGUuNewFQUjSkCzKP8rQVZSKqfdNnIgofZWs,1259
|
||||
aiohttp/web.py,sha256=2edP5uK2BU6wTXAWzGp2lgYq_CyU3vzLaQa0I_Ehg_0,15121
|
||||
aiohttp/web_app.py,sha256=vKuHVhH9d-Qg5Pg1A8MbaZPeJttkSsghpuo2JYvUJks,17212
|
||||
aiohttp/web_exceptions.py,sha256=-CQI325lMa9W-1WeJ2RlHApOOQ74ctHd6OyeKG_EyT4,10079
|
||||
aiohttp/web_fileresponse.py,sha256=0Oln1kTqD80EhftG2jqVbsuSLr0Gbjpuk4T3D06fFjk,12712
|
||||
aiohttp/web_log.py,sha256=J33FXqV36hWcyk8YfFNXDj3SI40uoOQzEX2Fhni7bzc,8269
|
||||
aiohttp/web_middlewares.py,sha256=BY05dLo9rsRZttRmjDUHEokiHQLzW_ffENZL9q-Grf4,4188
|
||||
aiohttp/web_protocol.py,sha256=q0zEVHMSLdmUw_KdI6zVeOj_k3lLZWMj4PJHo8h9c54,21394
|
||||
aiohttp/web_request.py,sha256=M8ARRuEso-V7G675-xWY-lqLBGDmBVRGPujaufKZGuo,25234
|
||||
aiohttp/web_response.py,sha256=nmldFBqLLaCECoaYUw54-2BVHB6Xz6XgGMK0O5ymrjo,25511
|
||||
aiohttp/web_routedef.py,sha256=jQ8Y0hDHYuMBTtsuo17qjkQLBMoacbkh4zaUdwSJJ8s,6077
|
||||
aiohttp/web_runner.py,sha256=_LUDpAc6vDOWfNJ-DBj3NZPtID0gBPH6JeMXtGSt4OU,10088
|
||||
aiohttp/web_server.py,sha256=527MjryEIqWArFHMJlEABg3TcZgYtyJIFHY19Yvf3AI,2165
|
||||
aiohttp/web_urldispatcher.py,sha256=x-O0Tqxn6xqMdQ5Qrg0hxIli-DbOfxLEDpgX_j_FGQU,38788
|
||||
aiohttp/web_ws.py,sha256=7UpGsVFZw_YtpJOWPLeDnGmL6PtirxAkc8r-pGUQbt0,17082
|
||||
aiohttp/worker.py,sha256=hekSLWLEJVrHrIrZ3dQga7Jzgtx_Cf3ZW7Zfd1J1G3A,8178
|
661
venv/Lib/site-packages/aiohttp-3.6.3.dist-info/METADATA
Normal file
661
venv/Lib/site-packages/aiohttp-3.6.3.dist-info/METADATA
Normal file
@ -0,0 +1,661 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: aiohttp
|
||||
Version: 3.6.3
|
||||
Summary: Async http client/server framework (asyncio)
|
||||
Home-page: https://github.com/aio-libs/aiohttp
|
||||
Author: Nikolay Kim
|
||||
Author-email: fafhrd91@gmail.com
|
||||
Maintainer: Nikolay Kim <fafhrd91@gmail.com>, Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||
Maintainer-email: aio-libs@googlegroups.com
|
||||
License: Apache 2
|
||||
Project-URL: Chat: Gitter, https://gitter.im/aio-libs/Lobby
|
||||
Project-URL: CI: AppVeyor, https://ci.appveyor.com/project/aio-libs/aiohttp
|
||||
Project-URL: CI: Circle, https://circleci.com/gh/aio-libs/aiohttp
|
||||
Project-URL: CI: Shippable, https://app.shippable.com/github/aio-libs/aiohttp
|
||||
Project-URL: CI: Travis, https://travis-ci.com/aio-libs/aiohttp
|
||||
Project-URL: Coverage: codecov, https://codecov.io/github/aio-libs/aiohttp
|
||||
Project-URL: Docs: RTD, https://docs.aiohttp.org
|
||||
Project-URL: GitHub: issues, https://github.com/aio-libs/aiohttp/issues
|
||||
Project-URL: GitHub: repo, https://github.com/aio-libs/aiohttp
|
||||
Platform: UNKNOWN
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Topic :: Internet :: WWW/HTTP
|
||||
Classifier: Framework :: AsyncIO
|
||||
Requires-Python: >=3.5.3
|
||||
Requires-Dist: attrs (>=17.3.0)
|
||||
Requires-Dist: chardet (<4.0,>=2.0)
|
||||
Requires-Dist: multidict (<5.0,>=4.5)
|
||||
Requires-Dist: async-timeout (<4.0,>=3.0)
|
||||
Requires-Dist: yarl (<1.6.0,>=1.0)
|
||||
Requires-Dist: idna-ssl (>=1.0) ; python_version < "3.7"
|
||||
Requires-Dist: typing-extensions (>=3.6.5) ; python_version < "3.7"
|
||||
Provides-Extra: speedups
|
||||
Requires-Dist: aiodns ; extra == 'speedups'
|
||||
Requires-Dist: brotlipy ; extra == 'speedups'
|
||||
Requires-Dist: cchardet ; extra == 'speedups'
|
||||
|
||||
==================================
|
||||
Async http client/server framework
|
||||
==================================
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png
|
||||
:height: 64px
|
||||
:width: 64px
|
||||
:alt: aiohttp logo
|
||||
|
||||
|
|
||||
|
||||
.. image:: https://travis-ci.com/aio-libs/aiohttp.svg?branch=master
|
||||
:target: https://travis-ci.com/aio-libs/aiohttp
|
||||
:align: right
|
||||
:alt: Travis status for master branch
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/tnddy9k6pphl8w7k/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/aio-libs/aiohttp
|
||||
:align: right
|
||||
:alt: AppVeyor status for master branch
|
||||
|
||||
.. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/aio-libs/aiohttp
|
||||
:alt: codecov.io status for master branch
|
||||
|
||||
.. image:: https://badge.fury.io/py/aiohttp.svg
|
||||
:target: https://pypi.org/project/aiohttp
|
||||
:alt: Latest PyPI package version
|
||||
|
||||
.. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest
|
||||
:target: https://docs.aiohttp.org/
|
||||
:alt: Latest Read The Docs
|
||||
|
||||
.. image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
:target: https://gitter.im/aio-libs/Lobby
|
||||
:alt: Chat on Gitter
|
||||
|
||||
Key Features
|
||||
============
|
||||
|
||||
- Supports both client and server side of HTTP protocol.
|
||||
- Supports both client and server Web-Sockets out-of-the-box and avoids
|
||||
Callback Hell.
|
||||
- Provides Web-server with middlewares and pluggable routing.
|
||||
|
||||
|
||||
Getting started
|
||||
===============
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
To get something from the web:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
|
||||
async def fetch(session, url):
|
||||
async with session.get(url) as response:
|
||||
return await response.text()
|
||||
|
||||
async def main():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
html = await fetch(session, 'http://python.org')
|
||||
print(html)
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
An example using a simple server:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# examples/server_simple.py
|
||||
from aiohttp import web
|
||||
|
||||
async def handle(request):
|
||||
name = request.match_info.get('name', "Anonymous")
|
||||
text = "Hello, " + name
|
||||
return web.Response(text=text)
|
||||
|
||||
async def wshandle(request):
|
||||
ws = web.WebSocketResponse()
|
||||
await ws.prepare(request)
|
||||
|
||||
async for msg in ws:
|
||||
if msg.type == web.WSMsgType.text:
|
||||
await ws.send_str("Hello, {}".format(msg.data))
|
||||
elif msg.type == web.WSMsgType.binary:
|
||||
await ws.send_bytes(msg.data)
|
||||
elif msg.type == web.WSMsgType.close:
|
||||
break
|
||||
|
||||
return ws
|
||||
|
||||
|
||||
app = web.Application()
|
||||
app.add_routes([web.get('/', handle),
|
||||
web.get('/echo', wshandle),
|
||||
web.get('/{name}', handle)])
|
||||
|
||||
if __name__ == '__main__':
|
||||
web.run_app(app)
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
https://aiohttp.readthedocs.io/
|
||||
|
||||
|
||||
Demos
|
||||
=====
|
||||
|
||||
https://github.com/aio-libs/aiohttp-demos
|
||||
|
||||
|
||||
External links
|
||||
==============
|
||||
|
||||
* `Third party libraries
|
||||
<http://aiohttp.readthedocs.io/en/latest/third_party.html>`_
|
||||
* `Built with aiohttp
|
||||
<http://aiohttp.readthedocs.io/en/latest/built_with.html>`_
|
||||
* `Powered by aiohttp
|
||||
<http://aiohttp.readthedocs.io/en/latest/powered_by.html>`_
|
||||
|
||||
Feel free to make a Pull Request for adding your link to these pages!
|
||||
|
||||
|
||||
Communication channels
|
||||
======================
|
||||
|
||||
*aio-libs* google group: https://groups.google.com/forum/#!forum/aio-libs
|
||||
|
||||
Feel free to post your questions and ideas here.
|
||||
|
||||
*gitter chat* https://gitter.im/aio-libs/Lobby
|
||||
|
||||
We support `Stack Overflow
|
||||
<https://stackoverflow.com/questions/tagged/aiohttp>`_.
|
||||
Please add *aiohttp* tag to your question there.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Python >= 3.5.3
|
||||
- async-timeout_
|
||||
- attrs_
|
||||
- chardet_
|
||||
- multidict_
|
||||
- yarl_
|
||||
|
||||
Optionally you may install the cChardet_ and aiodns_ libraries (highly
|
||||
recommended for sake of speed).
|
||||
|
||||
.. _chardet: https://pypi.python.org/pypi/chardet
|
||||
.. _aiodns: https://pypi.python.org/pypi/aiodns
|
||||
.. _attrs: https://github.com/python-attrs/attrs
|
||||
.. _multidict: https://pypi.python.org/pypi/multidict
|
||||
.. _yarl: https://pypi.python.org/pypi/yarl
|
||||
.. _async-timeout: https://pypi.python.org/pypi/async_timeout
|
||||
.. _cChardet: https://pypi.python.org/pypi/cchardet
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
``aiohttp`` is offered under the Apache 2 license.
|
||||
|
||||
|
||||
Keepsafe
|
||||
========
|
||||
|
||||
The aiohttp community would like to thank Keepsafe
|
||||
(https://www.getkeepsafe.com) for its support in the early days of
|
||||
the project.
|
||||
|
||||
|
||||
Source code
|
||||
===========
|
||||
|
||||
The latest developer version is available in a GitHub repository:
|
||||
https://github.com/aio-libs/aiohttp
|
||||
|
||||
Benchmarks
|
||||
==========
|
||||
|
||||
If you are interested in efficiency, the AsyncIO community maintains a
|
||||
list of benchmarks on the official wiki:
|
||||
https://github.com/python/asyncio/wiki/Benchmarks
|
||||
|
||||
=========
|
||||
Changelog
|
||||
=========
|
||||
|
||||
..
|
||||
You should *NOT* be adding new change log entries to this file, this
|
||||
file is managed by towncrier. You *may* edit previous change logs to
|
||||
fix problems like typo corrections or such.
|
||||
To add a new change log entry, please see
|
||||
https://pip.pypa.io/en/latest/development/#adding-a-news-entry
|
||||
we named the news folder "changes".
|
||||
|
||||
WARNING: Don't drop the next directive!
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
3.6.3 (2020-10-12)
|
||||
==================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Pin yarl to ``<1.6.0`` to avoid buggy behavior that will be fixed by the next aiohttp
|
||||
release.
|
||||
|
||||
3.6.2 (2019-10-09)
|
||||
==================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Made exceptions pickleable. Also changed the repr of some exceptions.
|
||||
`#4077 <https://github.com/aio-libs/aiohttp/issues/4077>`_
|
||||
- Use ``Iterable`` type hint instead of ``Sequence`` for ``Application`` *middleware*
|
||||
parameter. `#4125 <https://github.com/aio-libs/aiohttp/issues/4125>`_
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Reset the ``sock_read`` timeout each time data is received for a
|
||||
``aiohttp.ClientResponse``. `#3808
|
||||
<https://github.com/aio-libs/aiohttp/issues/3808>`_
|
||||
- Fix handling of expired cookies so they are not stored in CookieJar.
|
||||
`#4063 <https://github.com/aio-libs/aiohttp/issues/4063>`_
|
||||
- Fix misleading message in the string representation of ``ClientConnectorError``;
|
||||
``self.ssl == None`` means default SSL context, not SSL disabled `#4097
|
||||
<https://github.com/aio-libs/aiohttp/issues/4097>`_
|
||||
- Don't clobber HTTP status when using FileResponse.
|
||||
`#4106 <https://github.com/aio-libs/aiohttp/issues/4106>`_
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Added minimal required logging configuration to logging documentation.
|
||||
`#2469 <https://github.com/aio-libs/aiohttp/issues/2469>`_
|
||||
- Update docs to reflect proxy support.
|
||||
`#4100 <https://github.com/aio-libs/aiohttp/issues/4100>`_
|
||||
- Fix typo in code example in testing docs.
|
||||
`#4108 <https://github.com/aio-libs/aiohttp/issues/4108>`_
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- `#4102 <https://github.com/aio-libs/aiohttp/issues/4102>`_
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.6.1 (2019-09-19)
|
||||
==================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Compatibility with Python 3.8.
|
||||
`#4056 <https://github.com/aio-libs/aiohttp/issues/4056>`_
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- correct some exception string format
|
||||
`#4068 <https://github.com/aio-libs/aiohttp/issues/4068>`_
|
||||
- Emit a warning when ``ssl.OP_NO_COMPRESSION`` is
|
||||
unavailable because the runtime is built against
|
||||
an outdated OpenSSL.
|
||||
`#4052 <https://github.com/aio-libs/aiohttp/issues/4052>`_
|
||||
- Update multidict requirement to >= 4.5
|
||||
`#4057 <https://github.com/aio-libs/aiohttp/issues/4057>`_
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Provide pytest-aiohttp namespace for pytest fixtures in docs.
|
||||
`#3723 <https://github.com/aio-libs/aiohttp/issues/3723>`_
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.6.0 (2019-09-06)
|
||||
==================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Add support for Named Pipes (Site and Connector) under Windows. This feature requires
|
||||
Proactor event loop to work. `#3629
|
||||
<https://github.com/aio-libs/aiohttp/issues/3629>`_
|
||||
- Removed ``Transfer-Encoding: chunked`` header from websocket responses to be
|
||||
compatible with more http proxy servers. `#3798
|
||||
<https://github.com/aio-libs/aiohttp/issues/3798>`_
|
||||
- Accept non-GET request for starting websocket handshake on server side.
|
||||
`#3980 <https://github.com/aio-libs/aiohttp/issues/3980>`_
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Raise a ClientResponseError instead of an AssertionError for a blank
|
||||
HTTP Reason Phrase.
|
||||
`#3532 <https://github.com/aio-libs/aiohttp/issues/3532>`_
|
||||
- Fix an issue where cookies would sometimes not be set during a redirect.
|
||||
`#3576 <https://github.com/aio-libs/aiohttp/issues/3576>`_
|
||||
- Change normalize_path_middleware to use 308 redirect instead of 301.
|
||||
|
||||
This behavior should prevent clients from being unable to use PUT/POST
|
||||
methods on endpoints that are redirected because of a trailing slash.
|
||||
`#3579 <https://github.com/aio-libs/aiohttp/issues/3579>`_
|
||||
- Drop the processed task from ``all_tasks()`` list early. It prevents logging about a
|
||||
task with unhandled exception when the server is used in conjunction with
|
||||
``asyncio.run()``. `#3587 <https://github.com/aio-libs/aiohttp/issues/3587>`_
|
||||
- ``Signal`` type annotation changed from ``Signal[Callable[['TraceConfig'],
|
||||
Awaitable[None]]]`` to ``Signal[Callable[ClientSession, SimpleNamespace, ...]``.
|
||||
`#3595 <https://github.com/aio-libs/aiohttp/issues/3595>`_
|
||||
- Use sanitized URL as Location header in redirects
|
||||
`#3614 <https://github.com/aio-libs/aiohttp/issues/3614>`_
|
||||
- Improve typing annotations for multipart.py along with changes required
|
||||
by mypy in files that references multipart.py.
|
||||
`#3621 <https://github.com/aio-libs/aiohttp/issues/3621>`_
|
||||
- Close session created inside ``aiohttp.request`` when unhandled exception occurs
|
||||
`#3628 <https://github.com/aio-libs/aiohttp/issues/3628>`_
|
||||
- Cleanup per-chunk data in generic data read. Memory leak fixed.
|
||||
`#3631 <https://github.com/aio-libs/aiohttp/issues/3631>`_
|
||||
- Use correct type for add_view and family
|
||||
`#3633 <https://github.com/aio-libs/aiohttp/issues/3633>`_
|
||||
- Fix _keepalive field in __slots__ of ``RequestHandler``.
|
||||
`#3644 <https://github.com/aio-libs/aiohttp/issues/3644>`_
|
||||
- Properly handle ConnectionResetError, to silence the "Cannot write to closing
|
||||
transport" exception when clients disconnect uncleanly.
|
||||
`#3648 <https://github.com/aio-libs/aiohttp/issues/3648>`_
|
||||
- Suppress pytest warnings due to ``test_utils`` classes
|
||||
`#3660 <https://github.com/aio-libs/aiohttp/issues/3660>`_
|
||||
- Fix overshadowing of overlapped sub-application prefixes.
|
||||
`#3701 <https://github.com/aio-libs/aiohttp/issues/3701>`_
|
||||
- Fixed return type annotation for WSMessage.json()
|
||||
`#3720 <https://github.com/aio-libs/aiohttp/issues/3720>`_
|
||||
- Properly expose TooManyRedirects publicly as documented.
|
||||
`#3818 <https://github.com/aio-libs/aiohttp/issues/3818>`_
|
||||
- Fix missing brackets for IPv6 in proxy CONNECT request
|
||||
`#3841 <https://github.com/aio-libs/aiohttp/issues/3841>`_
|
||||
- Make the signature of ``aiohttp.test_utils.TestClient.request`` match
|
||||
``asyncio.ClientSession.request`` according to the docs `#3852
|
||||
<https://github.com/aio-libs/aiohttp/issues/3852>`_
|
||||
- Use correct style for re-exported imports, makes mypy ``--strict`` mode happy.
|
||||
`#3868 <https://github.com/aio-libs/aiohttp/issues/3868>`_
|
||||
- Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of
|
||||
View `#3880 <https://github.com/aio-libs/aiohttp/issues/3880>`_
|
||||
- Made cython HTTP parser set Reason-Phrase of the response to an empty string if it is
|
||||
missing. `#3906 <https://github.com/aio-libs/aiohttp/issues/3906>`_
|
||||
- Add URL to the string representation of ClientResponseError.
|
||||
`#3959 <https://github.com/aio-libs/aiohttp/issues/3959>`_
|
||||
- Accept ``istr`` keys in ``LooseHeaders`` type hints.
|
||||
`#3976 <https://github.com/aio-libs/aiohttp/issues/3976>`_
|
||||
- Fixed race conditions in _resolve_host caching and throttling when tracing is enabled.
|
||||
`#4013 <https://github.com/aio-libs/aiohttp/issues/4013>`_
|
||||
- For URLs like "unix://localhost/..." set Host HTTP header to "localhost" instead of
|
||||
"localhost:None". `#4039 <https://github.com/aio-libs/aiohttp/issues/4039>`_
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Modify documentation for Background Tasks to remove deprecated usage of event loop.
|
||||
`#3526 <https://github.com/aio-libs/aiohttp/issues/3526>`_
|
||||
- use ``if __name__ == '__main__':`` in server examples.
|
||||
`#3775 <https://github.com/aio-libs/aiohttp/issues/3775>`_
|
||||
- Update documentation reference to the default access logger.
|
||||
`#3783 <https://github.com/aio-libs/aiohttp/issues/3783>`_
|
||||
- Improve documentation for ``web.BaseRequest.path`` and ``web.BaseRequest.raw_path``.
|
||||
`#3791 <https://github.com/aio-libs/aiohttp/issues/3791>`_
|
||||
- Removed deprecation warning in tracing example docs
|
||||
`#3964 <https://github.com/aio-libs/aiohttp/issues/3964>`_
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.5.4 (2019-01-12)
|
||||
==================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix stream ``.read()`` / ``.readany()`` / ``.iter_any()`` which used to return a
|
||||
partial content only in case of compressed content
|
||||
`#3525 <https://github.com/aio-libs/aiohttp/issues/3525>`_
|
||||
|
||||
|
||||
3.5.3 (2019-01-10)
|
||||
==================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix type stubs for ``aiohttp.web.run_app(access_log=True)`` and fix edge case of
|
||||
``access_log=True`` and the event loop being in debug mode. `#3504
|
||||
<https://github.com/aio-libs/aiohttp/issues/3504>`_
|
||||
- Fix ``aiohttp.ClientTimeout`` type annotations to accept ``None`` for fields
|
||||
`#3511 <https://github.com/aio-libs/aiohttp/issues/3511>`_
|
||||
- Send custom per-request cookies even if session jar is empty
|
||||
`#3515 <https://github.com/aio-libs/aiohttp/issues/3515>`_
|
||||
- Restore Linux binary wheels publishing on PyPI
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.5.2 (2019-01-08)
|
||||
==================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- ``FileResponse`` from ``web_fileresponse.py`` uses a ``ThreadPoolExecutor`` to work
|
||||
with files asynchronously. I/O based payloads from ``payload.py`` uses a
|
||||
``ThreadPoolExecutor`` to work with I/O objects asynchronously. `#3313
|
||||
<https://github.com/aio-libs/aiohttp/issues/3313>`_
|
||||
- Internal Server Errors in plain text if the browser does not support HTML.
|
||||
`#3483 <https://github.com/aio-libs/aiohttp/issues/3483>`_
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Preserve MultipartWriter parts headers on write. Refactor the way how
|
||||
``Payload.headers`` are handled. Payload instances now always have headers and
|
||||
Content-Type defined. Fix Payload Content-Disposition header reset after initial
|
||||
creation. `#3035 <https://github.com/aio-libs/aiohttp/issues/3035>`_
|
||||
- Log suppressed exceptions in ``GunicornWebWorker``.
|
||||
`#3464 <https://github.com/aio-libs/aiohttp/issues/3464>`_
|
||||
- Remove wildcard imports.
|
||||
`#3468 <https://github.com/aio-libs/aiohttp/issues/3468>`_
|
||||
- Use the same task for app initialization and web server handling in gunicorn workers.
|
||||
It allows to use Python3.7 context vars smoothly.
|
||||
`#3471 <https://github.com/aio-libs/aiohttp/issues/3471>`_
|
||||
- Fix handling of chunked+gzipped response when first chunk does not give uncompressed
|
||||
data `#3477 <https://github.com/aio-libs/aiohttp/issues/3477>`_
|
||||
- Replace ``collections.MutableMapping`` with ``collections.abc.MutableMapping`` to
|
||||
avoid a deprecation warning. `#3480
|
||||
<https://github.com/aio-libs/aiohttp/issues/3480>`_
|
||||
- ``Payload.size`` type annotation changed from ``Optional[float]`` to
|
||||
``Optional[int]``. `#3484 <https://github.com/aio-libs/aiohttp/issues/3484>`_
|
||||
- Ignore done tasks when cancels pending activities on ``web.run_app`` finalization.
|
||||
`#3497 <https://github.com/aio-libs/aiohttp/issues/3497>`_
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Add documentation for ``aiohttp.web.HTTPException``.
|
||||
`#3490 <https://github.com/aio-libs/aiohttp/issues/3490>`_
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- `#3487 <https://github.com/aio-libs/aiohttp/issues/3487>`_
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
3.5.1 (2018-12-24)
|
||||
====================
|
||||
|
||||
- Fix a regression about ``ClientSession._requote_redirect_url`` modification in debug
|
||||
mode.
|
||||
|
||||
3.5.0 (2018-12-22)
|
||||
====================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- The library type annotations are checked in strict mode now.
|
||||
- Add support for setting cookies for individual request (`#2387
|
||||
<https://github.com/aio-libs/aiohttp/pull/2387>`_)
|
||||
- Application.add_domain implementation (`#2809
|
||||
<https://github.com/aio-libs/aiohttp/pull/2809>`_)
|
||||
- The default ``app`` in the request returned by ``test_utils.make_mocked_request`` can
|
||||
now have objects assigned to it and retrieved using the ``[]`` operator. (`#3174
|
||||
<https://github.com/aio-libs/aiohttp/pull/3174>`_)
|
||||
- Make ``request.url`` accessible when transport is closed. (`#3177
|
||||
<https://github.com/aio-libs/aiohttp/pull/3177>`_)
|
||||
- Add ``zlib_executor_size`` argument to ``Response`` constructor to allow compression
|
||||
to run in a background executor to avoid blocking the main thread and potentially
|
||||
triggering health check failures. (`#3205
|
||||
<https://github.com/aio-libs/aiohttp/pull/3205>`_)
|
||||
- Enable users to set ``ClientTimeout`` in ``aiohttp.request`` (`#3213
|
||||
<https://github.com/aio-libs/aiohttp/pull/3213>`_)
|
||||
- Don't raise a warning if ``NETRC`` environment variable is not set and ``~/.netrc``
|
||||
file doesn't exist. (`#3267 <https://github.com/aio-libs/aiohttp/pull/3267>`_)
|
||||
- Add default logging handler to web.run_app If the ``Application.debug``` flag is set
|
||||
and the default logger ``aiohttp.access`` is used, access logs will now be output
|
||||
using a *stderr* ``StreamHandler`` if no handlers are attached. Furthermore, if the
|
||||
default logger has no log level set, the log level will be set to ``DEBUG``. (`#3324
|
||||
<https://github.com/aio-libs/aiohttp/pull/3324>`_)
|
||||
- Add method argument to ``session.ws_connect()``. Sometimes server API requires a
|
||||
different HTTP method for WebSocket connection establishment. For example, ``Docker
|
||||
exec`` needs POST. (`#3378 <https://github.com/aio-libs/aiohttp/pull/3378>`_)
|
||||
- Create a task per request handling. (`#3406
|
||||
<https://github.com/aio-libs/aiohttp/pull/3406>`_)
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Enable passing ``access_log_class`` via ``handler_args`` (`#3158
|
||||
<https://github.com/aio-libs/aiohttp/pull/3158>`_)
|
||||
- Return empty bytes with end-of-chunk marker in empty stream reader. (`#3186
|
||||
<https://github.com/aio-libs/aiohttp/pull/3186>`_)
|
||||
- Accept ``CIMultiDictProxy`` instances for ``headers`` argument in ``web.Response``
|
||||
constructor. (`#3207 <https://github.com/aio-libs/aiohttp/pull/3207>`_)
|
||||
- Don't uppercase HTTP method in parser (`#3233
|
||||
<https://github.com/aio-libs/aiohttp/pull/3233>`_)
|
||||
- Make method match regexp RFC-7230 compliant (`#3235
|
||||
<https://github.com/aio-libs/aiohttp/pull/3235>`_)
|
||||
- Add ``app.pre_frozen`` state to properly handle startup signals in
|
||||
sub-applications. (`#3237 <https://github.com/aio-libs/aiohttp/pull/3237>`_)
|
||||
- Enhanced parsing and validation of helpers.BasicAuth.decode. (`#3239
|
||||
<https://github.com/aio-libs/aiohttp/pull/3239>`_)
|
||||
- Change imports from collections module in preparation for 3.8. (`#3258
|
||||
<https://github.com/aio-libs/aiohttp/pull/3258>`_)
|
||||
- Ensure Host header is added first to ClientRequest to better replicate browser (`#3265
|
||||
<https://github.com/aio-libs/aiohttp/pull/3265>`_)
|
||||
- Fix forward compatibility with Python 3.8: importing ABCs directly from the
|
||||
collections module will not be supported anymore. (`#3273
|
||||
<https://github.com/aio-libs/aiohttp/pull/3273>`_)
|
||||
- Keep the query string by ``normalize_path_middleware``. (`#3278
|
||||
<https://github.com/aio-libs/aiohttp/pull/3278>`_)
|
||||
- Fix missing parameter ``raise_for_status`` for aiohttp.request() (`#3290
|
||||
<https://github.com/aio-libs/aiohttp/pull/3290>`_)
|
||||
- Bracket IPv6 addresses in the HOST header (`#3304
|
||||
<https://github.com/aio-libs/aiohttp/pull/3304>`_)
|
||||
- Fix default message for server ping and pong frames. (`#3308
|
||||
<https://github.com/aio-libs/aiohttp/pull/3308>`_)
|
||||
- Fix tests/test_connector.py typo and tests/autobahn/server.py duplicate loop
|
||||
def. (`#3337 <https://github.com/aio-libs/aiohttp/pull/3337>`_)
|
||||
- Fix false-negative indicator end_of_HTTP_chunk in StreamReader.readchunk function
|
||||
(`#3361 <https://github.com/aio-libs/aiohttp/pull/3361>`_)
|
||||
- Release HTTP response before raising status exception (`#3364
|
||||
<https://github.com/aio-libs/aiohttp/pull/3364>`_)
|
||||
- Fix task cancellation when ``sendfile()`` syscall is used by static file
|
||||
handling. (`#3383 <https://github.com/aio-libs/aiohttp/pull/3383>`_)
|
||||
- Fix stack trace for ``asyncio.TimeoutError`` which was not logged, when it is caught
|
||||
in the handler. (`#3414 <https://github.com/aio-libs/aiohttp/pull/3414>`_)
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Improve documentation of ``Application.make_handler`` parameters. (`#3152
|
||||
<https://github.com/aio-libs/aiohttp/pull/3152>`_)
|
||||
- Fix BaseRequest.raw_headers doc. (`#3215
|
||||
<https://github.com/aio-libs/aiohttp/pull/3215>`_)
|
||||
- Fix typo in TypeError exception reason in ``web.Application._handle`` (`#3229
|
||||
<https://github.com/aio-libs/aiohttp/pull/3229>`_)
|
||||
- Make server access log format placeholder %b documentation reflect
|
||||
behavior and docstring. (`#3307 <https://github.com/aio-libs/aiohttp/pull/3307>`_)
|
||||
|
||||
|
||||
Deprecations and Removals
|
||||
-------------------------
|
||||
|
||||
- Deprecate modification of ``session.requote_redirect_url`` (`#2278
|
||||
<https://github.com/aio-libs/aiohttp/pull/2278>`_)
|
||||
- Deprecate ``stream.unread_data()`` (`#3260
|
||||
<https://github.com/aio-libs/aiohttp/pull/3260>`_)
|
||||
- Deprecated use of boolean in ``resp.enable_compression()`` (`#3318
|
||||
<https://github.com/aio-libs/aiohttp/pull/3318>`_)
|
||||
- Encourage creation of aiohttp public objects inside a coroutine (`#3331
|
||||
<https://github.com/aio-libs/aiohttp/pull/3331>`_)
|
||||
- Drop dead ``Connection.detach()`` and ``Connection.writer``. Both methods were broken
|
||||
for more than 2 years. (`#3358 <https://github.com/aio-libs/aiohttp/pull/3358>`_)
|
||||
- Deprecate ``app.loop``, ``request.loop``, ``client.loop`` and ``connector.loop``
|
||||
properties. (`#3374 <https://github.com/aio-libs/aiohttp/pull/3374>`_)
|
||||
- Deprecate explicit debug argument. Use asyncio debug mode instead. (`#3381
|
||||
<https://github.com/aio-libs/aiohttp/pull/3381>`_)
|
||||
- Deprecate body parameter in HTTPException (and derived classes) constructor. (`#3385
|
||||
<https://github.com/aio-libs/aiohttp/pull/3385>`_)
|
||||
- Deprecate bare connector close, use ``async with connector:`` and ``await
|
||||
connector.close()`` instead. (`#3417
|
||||
<https://github.com/aio-libs/aiohttp/pull/3417>`_)
|
||||
- Deprecate obsolete ``read_timeout`` and ``conn_timeout`` in ``ClientSession``
|
||||
constructor. (`#3438 <https://github.com/aio-libs/aiohttp/pull/3438>`_)
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- #3341, #3351
|
||||
|
124
venv/Lib/site-packages/aiohttp-3.6.3.dist-info/RECORD
Normal file
124
venv/Lib/site-packages/aiohttp-3.6.3.dist-info/RECORD
Normal file
@ -0,0 +1,124 @@
|
||||
aiohttp-3.6.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
aiohttp-3.6.3.dist-info/LICENSE.txt,sha256=atcq6P9K6Td0Wq4oBfNDqYf6o6YGrHLGCfLUj3GZspQ,11533
|
||||
aiohttp-3.6.3.dist-info/METADATA,sha256=UmObIpkmeVqZFB1rwDUEbIzmKMrVaEaEfDZulA48d_g,24570
|
||||
aiohttp-3.6.3.dist-info/RECORD,,
|
||||
aiohttp-3.6.3.dist-info/WHEEL,sha256=SktxJNdVgf2GQ0Rnj47KhGrFXFhp4j6ROtWy0UXB1eM,106
|
||||
aiohttp-3.6.3.dist-info/top_level.txt,sha256=iv-JIaacmTl-hSho3QmphcKnbRRYx1st47yjz_178Ro,8
|
||||
aiohttp/__init__.py,sha256=LagwdvgQ1g_JFcWIC-PjM8StM1gLulnzbjJ1UncMXoI,8427
|
||||
aiohttp/__pycache__/__init__.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/abc.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/base_protocol.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_proto.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_reqrep.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/client_ws.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/connector.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/cookiejar.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/formdata.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/frozenlist.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/hdrs.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/helpers.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_parser.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_websocket.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/http_writer.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/locks.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/log.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/multipart.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/payload.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/payload_streamer.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/pytest_plugin.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/resolver.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/signals.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/streams.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/tcp_helpers.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/test_utils.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/tracing.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/typedefs.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_app.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_exceptions.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_fileresponse.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_log.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_middlewares.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_protocol.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_request.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_response.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_routedef.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_runner.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_server.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_urldispatcher.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/web_ws.cpython-36.pyc,,
|
||||
aiohttp/__pycache__/worker.cpython-36.pyc,,
|
||||
aiohttp/_cparser.pxd,sha256=xvsLl13ZXXyHGyb2Us7WsLncndQrxhyGB4KXnvbsRtQ,4099
|
||||
aiohttp/_find_header.c,sha256=MOZn07_ot-UcOdQBpYAWQmyigqLvMwkqa_7l4M7D1dI,199932
|
||||
aiohttp/_find_header.h,sha256=HistyxY7K3xEJ53Y5xEfwrDVDkfcV0zQ9mkzMgzi_jo,184
|
||||
aiohttp/_find_header.pxd,sha256=BFUSmxhemBtblqxzjzH3x03FfxaWlTyuAIOz8YZ5_nM,70
|
||||
aiohttp/_frozenlist.c,sha256=-vfgzV6cNjUykuqt1kkWDiT2U92BR2zhL9b9yDiiodg,288943
|
||||
aiohttp/_frozenlist.cp36-win_amd64.pyd,sha256=ChZp9r6iFxKYd5M_zgBVSnfuG69razOy5oZNxQ_mfyo,69120
|
||||
aiohttp/_frozenlist.pyx,sha256=SB851KmtWpiJ2ZB05Tpo4855VkCyRtgMs843Wz8kFeg,2713
|
||||
aiohttp/_headers.pxi,sha256=PxiakDsuEs0O94eHRlPcerO24TqPAxc0BtX86XZL4gw,2111
|
||||
aiohttp/_helpers.c,sha256=sQcHpEGAX3jEvA8jujh4_D_fev9cRjMAc5CySqtHYrg,208657
|
||||
aiohttp/_helpers.cp36-win_amd64.pyd,sha256=vaRlMUUMLYsjE0c8OyK-IYIhYr3U-V6_2O3PJCrpcfc,50176
|
||||
aiohttp/_helpers.pyi,sha256=C6Q4W8EwElvD1gF1siRGMVG7evEX8fWWstZHL1BbsDA,212
|
||||
aiohttp/_helpers.pyx,sha256=tgl7fZh0QMT6cjf4jSJ8iaO6DdQD3GON2-SH4N5_ETg,1084
|
||||
aiohttp/_http_parser.c,sha256=W1sETtDrrBdnBiSOpqaDcO9DcE9zhyLjPTq4WKIK0bc,997494
|
||||
aiohttp/_http_parser.cp36-win_amd64.pyd,sha256=GQaatWLpRa9ldsKnE7Dg20DkDJZBjsg_v0fbSR2YUo0,248320
|
||||
aiohttp/_http_parser.pyx,sha256=C2XxooYRput7XPQzbaGMDrtvJtmhWa58SDPytyuAwGk,29577
|
||||
aiohttp/_http_writer.c,sha256=-wuBZwiaUXEy1Zj-R5BD5igH7cUg_CYb5ZvYMsh8vzo,211620
|
||||
aiohttp/_http_writer.cp36-win_amd64.pyd,sha256=yxFOMEepS8vykxlCNgXRJL-PeaDQhuhdw7pU3yryUGI,44032
|
||||
aiohttp/_http_writer.pyx,sha256=TzCawCBLMe7w9eX2SEcUcLYySwkFfrfjaEYHS0Uvjtg,4353
|
||||
aiohttp/_websocket.c,sha256=JrG6bXW3OR8sfxl5V1Q3VTXvGBbFTYgzgdbhQHr3LGI,136606
|
||||
aiohttp/_websocket.cp36-win_amd64.pyd,sha256=BoTx06YtxrQWEGuQrGXey7sg5ZU4Fy40TMUv7UIu8H0,29184
|
||||
aiohttp/_websocket.pyx,sha256=Ig8jXl_wkAXPugEWS0oPYo0-BnL8zT7uBG6BrYqVXdA,1613
|
||||
aiohttp/abc.py,sha256=s3wtDI3os8uX4FdQbsvJwr67cFGhylif0mR5k2SKY04,5600
|
||||
aiohttp/base_protocol.py,sha256=5PJImwc0iX8kR3VjZn1D_SAeL-6JKERi87iGHEYjJQ4,2744
|
||||
aiohttp/client.py,sha256=DYv-h8V2wljt4hRmPDmU2czk9zSlSn8zua9MgssSEiY,45130
|
||||
aiohttp/client_exceptions.py,sha256=RCbzCGw_HcaqnL4AHf3nol32xH_2xu1hrYbLNgpjHqk,8786
|
||||
aiohttp/client_proto.py,sha256=XDXJ0G9RW8m80wHahzjgp4T5S3Rf6LSYks9Q9MajSQg,8276
|
||||
aiohttp/client_reqrep.py,sha256=zf6GFaDYvpy50HZ4GntrT8flcc6B4HfwnlHw_yYdGMw,37064
|
||||
aiohttp/client_ws.py,sha256=OUkkw9RwRHRmAakBibE6c63VLMWGVgoyRadoC22wtNY,10995
|
||||
aiohttp/connector.py,sha256=pbq2XHrujiyQXbIhzXQK6E1zrzRYedzt8xlGNmvbQcM,43672
|
||||
aiohttp/cookiejar.py,sha256=lNwvnGX3BjIDU4btE50AUsBQditLXzJhsPPUMZo-dkI,12249
|
||||
aiohttp/formdata.py,sha256=1yNFnS6O0wUrIL4_V66-DwyjS3nWVd0JiPIjWKbTZTs,5957
|
||||
aiohttp/frozenlist.py,sha256=PSElO5biFCVHyVEr6-hXy7--cDaHAxaWDrsFxESHsFc,1853
|
||||
aiohttp/frozenlist.pyi,sha256=z-EGiL4Q5MTe1wxDZINsIhqh4Eb0oT9Xn0X_Rt7C9ns,1512
|
||||
aiohttp/hdrs.py,sha256=PmN2SUiMmwiC0TMEEMSFfwirUpnrzy3jwUhniPGFlmc,3549
|
||||
aiohttp/helpers.py,sha256=yAdG1c-axo7-Vsf3CRaEqb7hU5Ej-FpUgZowGA76f_U,23613
|
||||
aiohttp/http.py,sha256=H9xNqvagxteFvx2R7AeYiGfze7uR6VKF5IsUAITr7d4,2183
|
||||
aiohttp/http_exceptions.py,sha256=Oby70EpyDmwpsb4DpCFYXw-sa856HmWv8IjeHlWWlJo,2771
|
||||
aiohttp/http_parser.py,sha256=Ttk5BSX11cXMaFJmquzd1oNkZbnodghQvBgdUGdQxnE,28676
|
||||
aiohttp/http_websocket.py,sha256=KmHznrwSjtpUgxbFafBg1MaAaCpxGxoK0IL8wDKg9f8,25400
|
||||
aiohttp/http_writer.py,sha256=VBMPy_AaB7m_keycuu05SCN2S3GVVyY8UCHG-W86Y1w,5411
|
||||
aiohttp/locks.py,sha256=6DiJHW1eQKXypu1eWXZT3_amPhFBK-jnxdI-_BpYICk,1278
|
||||
aiohttp/log.py,sha256=qAQMjI6XpX3MOAZATN4HcG0tIceSreR54orlYZaoJ0A,333
|
||||
aiohttp/multipart.py,sha256=RPXfp5GMauxW19nbBaLAkzgUFKTQ9eMo4XtZ7ItGyo4,33740
|
||||
aiohttp/payload.py,sha256=lCF_pZvwyBKJGk4OOLYEQhtxUwOW8rsFF0pxisvfBps,14483
|
||||
aiohttp/payload_streamer.py,sha256=7koj4FVujDGriDIOes48XPp5BK9tsWYyTxJG-3aNaHc,2177
|
||||
aiohttp/py.typed,sha256=E84IaZyFwfLqvXjOVW4LS6WH7QOaKEFpNh9TFyzHNQc,6
|
||||
aiohttp/pytest_plugin.py,sha256=1_XNSrZS-czuaNVt4qvRQs-GbIIl8DaLykGpoDlZfhU,11187
|
||||
aiohttp/resolver.py,sha256=mQvusmMHpS0JekvnX7R1y4aqQ7BIIv3FIkxO5wgv2xQ,3738
|
||||
aiohttp/signals.py,sha256=I_QAX1S7VbN7KDnNO6CSnAzhzx42AYh2Dto_FC9DQ3k,982
|
||||
aiohttp/signals.pyi,sha256=pg4KElFcxBNFU-OQpTe2x-7qKJ79bAlemgqE-yaciiU,341
|
||||
aiohttp/streams.py,sha256=EPM7T5_aJLOXlBTIEeFapIQ1O33KsHTvT-wWH3X0QvQ,21093
|
||||
aiohttp/tcp_helpers.py,sha256=q9fHztjKbR57sCc4zWoo89QDW88pLT0OpcdHLGcV3Fo,1694
|
||||
aiohttp/test_utils.py,sha256=_GjrPdE_9v0SxzbM4Tmt8vst-KJPwL2ILM_Rl1jHhi4,21530
|
||||
aiohttp/tracing.py,sha256=GGhlQDrx5AVwFt33Zl4DvBIoFcR7sXAsgXNxvkd2Uus,13740
|
||||
aiohttp/typedefs.py,sha256=o4R9uAySHxTzedIfX3UPbD0a5TnD5inc_M-h_4qyC4U,1377
|
||||
aiohttp/web.py,sha256=KQXp0C__KpeX8nYM3FWl-eoMAmj9LZIbx7YeI39pQco,19940
|
||||
aiohttp/web_app.py,sha256=dHOhoDoakwdrya0cc6Jl6K723MKGmd_M5LxH3wDeGQI,17779
|
||||
aiohttp/web_exceptions.py,sha256=CQvslnHcpFnreO-qNjnKOWQev7ZvlTG6jfV14NQwb1Q,10519
|
||||
aiohttp/web_fileresponse.py,sha256=TftBNfbgowCQ0L5Iud-dewCAnXq5tIyP-8iZ-KrSHw8,13118
|
||||
aiohttp/web_log.py,sha256=gOR8iLbhjeAUwGL-21qD31kA0HlYSNhpdX6eNwJ-3Uo,8490
|
||||
aiohttp/web_middlewares.py,sha256=jATe_igeeoyBoWKBDW_ISOOzFKvxSoLJE1QPTqZPWGc,4310
|
||||
aiohttp/web_protocol.py,sha256=Zol5oVApIE12NDLBV_W1oKW8AN-sGdBfC0RFMI050U0,22791
|
||||
aiohttp/web_request.py,sha256=xzvj84uGe5Uuug1b4iKWZl8uko_0TpzYKa00POke_NM,26526
|
||||
aiohttp/web_response.py,sha256=CEx04E7NLNg6mfgTjT0QPS9vJuglbw3UQvwob6Qeb7c,26202
|
||||
aiohttp/web_routedef.py,sha256=5QCl85zQml2qoj7bkC9XMoK4stBVuUoiq_0uefxifjc,6293
|
||||
aiohttp/web_runner.py,sha256=ArW4NjMJ24Fv68Ez-9hPL1WNzVygDYEWJ4aIfzOMKz8,11479
|
||||
aiohttp/web_server.py,sha256=P826xDCDs4VgeksMam8OHKm_VzprXuOpsJrysqj3CVg,2222
|
||||
aiohttp/web_urldispatcher.py,sha256=8uhNNXlHd2WJfJ4wcyQ1UxoRM1VUyWWwQhK-TPrM_GM,40043
|
||||
aiohttp/web_ws.py,sha256=mAU6Ln3AbMZeXjUZSSA5MmE39hTajJIMxBE0xnq-4Tc,17414
|
||||
aiohttp/worker.py,sha256=yatPZxpUOp9CzDA05Jb2UWi0eo2PgGWlQm4lIFCRCSY,8420
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.32.3)
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp36-cp36m-win_amd64
|
||||
|
@ -1,110 +1,118 @@
|
||||
__version__ = '3.5.4'
|
||||
__version__ = '3.6.3'
|
||||
|
||||
from typing import Tuple # noqa
|
||||
|
||||
from . import hdrs
|
||||
from . import hdrs as hdrs
|
||||
from .client import BaseConnector as BaseConnector
|
||||
from .client import ClientConnectionError as ClientConnectionError
|
||||
from .client import (
|
||||
BaseConnector,
|
||||
ClientConnectionError,
|
||||
ClientConnectorCertificateError,
|
||||
ClientConnectorError,
|
||||
ClientConnectorSSLError,
|
||||
ClientError,
|
||||
ClientHttpProxyError,
|
||||
ClientOSError,
|
||||
ClientPayloadError,
|
||||
ClientProxyConnectionError,
|
||||
ClientResponse,
|
||||
ClientRequest,
|
||||
ClientResponseError,
|
||||
ClientSSLError,
|
||||
ClientSession,
|
||||
ClientTimeout,
|
||||
ClientWebSocketResponse,
|
||||
ContentTypeError,
|
||||
Fingerprint,
|
||||
InvalidURL,
|
||||
RequestInfo,
|
||||
ServerConnectionError,
|
||||
ServerDisconnectedError,
|
||||
ServerFingerprintMismatch,
|
||||
ServerTimeoutError,
|
||||
TCPConnector,
|
||||
UnixConnector,
|
||||
WSServerHandshakeError,
|
||||
request
|
||||
ClientConnectorCertificateError as ClientConnectorCertificateError,
|
||||
)
|
||||
|
||||
from .cookiejar import CookieJar, DummyCookieJar
|
||||
from .formdata import FormData
|
||||
from .helpers import BasicAuth, ChainMapProxy
|
||||
from .http import (
|
||||
HttpVersion,
|
||||
HttpVersion10,
|
||||
HttpVersion11,
|
||||
WSMsgType,
|
||||
WSCloseCode,
|
||||
WSMessage,
|
||||
WebSocketError
|
||||
)
|
||||
|
||||
from .client import ClientConnectorError as ClientConnectorError
|
||||
from .client import ClientConnectorSSLError as ClientConnectorSSLError
|
||||
from .client import ClientError as ClientError
|
||||
from .client import ClientHttpProxyError as ClientHttpProxyError
|
||||
from .client import ClientOSError as ClientOSError
|
||||
from .client import ClientPayloadError as ClientPayloadError
|
||||
from .client import ClientProxyConnectionError as ClientProxyConnectionError
|
||||
from .client import ClientRequest as ClientRequest
|
||||
from .client import ClientResponse as ClientResponse
|
||||
from .client import ClientResponseError as ClientResponseError
|
||||
from .client import ClientSession as ClientSession
|
||||
from .client import ClientSSLError as ClientSSLError
|
||||
from .client import ClientTimeout as ClientTimeout
|
||||
from .client import ClientWebSocketResponse as ClientWebSocketResponse
|
||||
from .client import ContentTypeError as ContentTypeError
|
||||
from .client import Fingerprint as Fingerprint
|
||||
from .client import InvalidURL as InvalidURL
|
||||
from .client import NamedPipeConnector as NamedPipeConnector
|
||||
from .client import RequestInfo as RequestInfo
|
||||
from .client import ServerConnectionError as ServerConnectionError
|
||||
from .client import ServerDisconnectedError as ServerDisconnectedError
|
||||
from .client import ServerFingerprintMismatch as ServerFingerprintMismatch
|
||||
from .client import ServerTimeoutError as ServerTimeoutError
|
||||
from .client import TCPConnector as TCPConnector
|
||||
from .client import TooManyRedirects as TooManyRedirects
|
||||
from .client import UnixConnector as UnixConnector
|
||||
from .client import WSServerHandshakeError as WSServerHandshakeError
|
||||
from .client import request as request
|
||||
from .cookiejar import CookieJar as CookieJar
|
||||
from .cookiejar import DummyCookieJar as DummyCookieJar
|
||||
from .formdata import FormData as FormData
|
||||
from .helpers import BasicAuth as BasicAuth
|
||||
from .helpers import ChainMapProxy as ChainMapProxy
|
||||
from .http import HttpVersion as HttpVersion
|
||||
from .http import HttpVersion10 as HttpVersion10
|
||||
from .http import HttpVersion11 as HttpVersion11
|
||||
from .http import WebSocketError as WebSocketError
|
||||
from .http import WSCloseCode as WSCloseCode
|
||||
from .http import WSMessage as WSMessage
|
||||
from .http import WSMsgType as WSMsgType
|
||||
from .multipart import (
|
||||
BadContentDispositionHeader,
|
||||
BadContentDispositionParam,
|
||||
BodyPartReader,
|
||||
MultipartReader,
|
||||
MultipartWriter,
|
||||
content_disposition_filename,
|
||||
parse_content_disposition
|
||||
BadContentDispositionHeader as BadContentDispositionHeader,
|
||||
)
|
||||
|
||||
from .payload import (
|
||||
AsyncIterablePayload,
|
||||
BufferedReaderPayload,
|
||||
BytesIOPayload,
|
||||
BytesPayload,
|
||||
IOBasePayload,
|
||||
JsonPayload,
|
||||
PAYLOAD_REGISTRY,
|
||||
Payload,
|
||||
StringIOPayload,
|
||||
StringPayload,
|
||||
TextIOPayload,
|
||||
get_payload,
|
||||
payload_type
|
||||
from .multipart import BadContentDispositionParam as BadContentDispositionParam
|
||||
from .multipart import BodyPartReader as BodyPartReader
|
||||
from .multipart import MultipartReader as MultipartReader
|
||||
from .multipart import MultipartWriter as MultipartWriter
|
||||
from .multipart import (
|
||||
content_disposition_filename as content_disposition_filename,
|
||||
)
|
||||
|
||||
from .payload_streamer import streamer
|
||||
|
||||
from .resolver import AsyncResolver, DefaultResolver, ThreadedResolver
|
||||
|
||||
from .signals import Signal
|
||||
|
||||
from .streams import (
|
||||
DataQueue,
|
||||
EMPTY_PAYLOAD,
|
||||
EofStream,
|
||||
FlowControlDataQueue,
|
||||
StreamReader
|
||||
)
|
||||
|
||||
from .multipart import parse_content_disposition as parse_content_disposition
|
||||
from .payload import PAYLOAD_REGISTRY as PAYLOAD_REGISTRY
|
||||
from .payload import AsyncIterablePayload as AsyncIterablePayload
|
||||
from .payload import BufferedReaderPayload as BufferedReaderPayload
|
||||
from .payload import BytesIOPayload as BytesIOPayload
|
||||
from .payload import BytesPayload as BytesPayload
|
||||
from .payload import IOBasePayload as IOBasePayload
|
||||
from .payload import JsonPayload as JsonPayload
|
||||
from .payload import Payload as Payload
|
||||
from .payload import StringIOPayload as StringIOPayload
|
||||
from .payload import StringPayload as StringPayload
|
||||
from .payload import TextIOPayload as TextIOPayload
|
||||
from .payload import get_payload as get_payload
|
||||
from .payload import payload_type as payload_type
|
||||
from .payload_streamer import streamer as streamer
|
||||
from .resolver import AsyncResolver as AsyncResolver
|
||||
from .resolver import DefaultResolver as DefaultResolver
|
||||
from .resolver import ThreadedResolver as ThreadedResolver
|
||||
from .signals import Signal as Signal
|
||||
from .streams import EMPTY_PAYLOAD as EMPTY_PAYLOAD
|
||||
from .streams import DataQueue as DataQueue
|
||||
from .streams import EofStream as EofStream
|
||||
from .streams import FlowControlDataQueue as FlowControlDataQueue
|
||||
from .streams import StreamReader as StreamReader
|
||||
from .tracing import TraceConfig as TraceConfig
|
||||
from .tracing import (
|
||||
TraceConfig,
|
||||
TraceConnectionCreateEndParams,
|
||||
TraceConnectionCreateStartParams,
|
||||
TraceConnectionQueuedEndParams,
|
||||
TraceConnectionQueuedStartParams,
|
||||
TraceConnectionReuseconnParams,
|
||||
TraceDnsCacheHitParams,
|
||||
TraceDnsCacheMissParams,
|
||||
TraceDnsResolveHostEndParams,
|
||||
TraceDnsResolveHostStartParams,
|
||||
TraceRequestChunkSentParams,
|
||||
TraceRequestEndParams,
|
||||
TraceRequestExceptionParams,
|
||||
TraceRequestRedirectParams,
|
||||
TraceRequestStartParams,
|
||||
TraceResponseChunkReceivedParams
|
||||
TraceConnectionCreateEndParams as TraceConnectionCreateEndParams,
|
||||
)
|
||||
from .tracing import (
|
||||
TraceConnectionCreateStartParams as TraceConnectionCreateStartParams,
|
||||
)
|
||||
from .tracing import (
|
||||
TraceConnectionQueuedEndParams as TraceConnectionQueuedEndParams,
|
||||
)
|
||||
from .tracing import (
|
||||
TraceConnectionQueuedStartParams as TraceConnectionQueuedStartParams,
|
||||
)
|
||||
from .tracing import (
|
||||
TraceConnectionReuseconnParams as TraceConnectionReuseconnParams,
|
||||
)
|
||||
from .tracing import TraceDnsCacheHitParams as TraceDnsCacheHitParams
|
||||
from .tracing import TraceDnsCacheMissParams as TraceDnsCacheMissParams
|
||||
from .tracing import (
|
||||
TraceDnsResolveHostEndParams as TraceDnsResolveHostEndParams,
|
||||
)
|
||||
from .tracing import (
|
||||
TraceDnsResolveHostStartParams as TraceDnsResolveHostStartParams,
|
||||
)
|
||||
from .tracing import TraceRequestChunkSentParams as TraceRequestChunkSentParams
|
||||
from .tracing import TraceRequestEndParams as TraceRequestEndParams
|
||||
from .tracing import TraceRequestExceptionParams as TraceRequestExceptionParams
|
||||
from .tracing import TraceRequestRedirectParams as TraceRequestRedirectParams
|
||||
from .tracing import TraceRequestStartParams as TraceRequestStartParams
|
||||
from .tracing import (
|
||||
TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams,
|
||||
)
|
||||
|
||||
__all__ = (
|
||||
@ -136,7 +144,9 @@ __all__ = (
|
||||
'ServerFingerprintMismatch',
|
||||
'ServerTimeoutError',
|
||||
'TCPConnector',
|
||||
'TooManyRedirects',
|
||||
'UnixConnector',
|
||||
'NamedPipeConnector',
|
||||
'WSServerHandshakeError',
|
||||
'request',
|
||||
# cookiejar
|
||||
|
@ -1,16 +1,4 @@
|
||||
/* Generated by Cython 0.29.2 */
|
||||
|
||||
/* BEGIN: Cython Metadata
|
||||
{
|
||||
"distutils": {
|
||||
"name": "aiohttp._frozenlist",
|
||||
"sources": [
|
||||
"aiohttp/_frozenlist.pyx"
|
||||
]
|
||||
},
|
||||
"module_name": "aiohttp._frozenlist"
|
||||
}
|
||||
END: Cython Metadata */
|
||||
/* Generated by Cython 0.29.13 */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
@ -19,9 +7,9 @@ END: Cython Metadata */
|
||||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||
#else
|
||||
#define CYTHON_ABI "0_29_2"
|
||||
#define CYTHON_HEX_VERSION 0x001D02F0
|
||||
#define CYTHON_FUTURE_DIVISION 0
|
||||
#define CYTHON_ABI "0_29_13"
|
||||
#define CYTHON_HEX_VERSION 0x001D0DF0
|
||||
#define CYTHON_FUTURE_DIVISION 1
|
||||
#include <stddef.h>
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
|
||||
@ -322,8 +310,13 @@ END: Cython Metadata */
|
||||
#define __Pyx_DefaultClassType PyClass_Type
|
||||
#else
|
||||
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
|
||||
#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#else
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#endif
|
||||
#define __Pyx_DefaultClassType PyType_Type
|
||||
#endif
|
||||
#ifndef Py_TPFLAGS_CHECKTYPES
|
||||
@ -358,26 +351,6 @@ END: Cython Metadata */
|
||||
#else
|
||||
#define __Pyx_PyFastCFunction_Check(func) 0
|
||||
#endif
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
|
||||
#define PyObject_Malloc(s) PyMem_Malloc(s)
|
||||
#define PyObject_Free(p) PyMem_Free(p)
|
||||
@ -410,7 +383,7 @@ END: Cython Metadata */
|
||||
typedef int Py_tss_t;
|
||||
static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) {
|
||||
*key = PyThread_create_key();
|
||||
return 0; // PyThread_create_key reports success always
|
||||
return 0;
|
||||
}
|
||||
static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) {
|
||||
Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t));
|
||||
@ -433,7 +406,7 @@ static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) {
|
||||
static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
||||
return PyThread_get_key_value(*key);
|
||||
}
|
||||
#endif // TSS (Thread Specific Storage) API
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized)
|
||||
#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n))
|
||||
#else
|
||||
@ -632,7 +605,8 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc
|
||||
const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
|
||||
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8)
|
||||
#define __PYX_DEFAULT_STRING_ENCODING ""
|
||||
#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
|
||||
#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
|
||||
@ -1023,7 +997,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* k
|
||||
#define __Pyx_PyFunction_FastCall(func, args, nargs)\
|
||||
__Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL)
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs);
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs);
|
||||
#else
|
||||
#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs)
|
||||
#endif
|
||||
@ -1089,18 +1063,18 @@ static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t
|
||||
#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
|
||||
(likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ?\
|
||||
__Pyx__PyList_PopIndex(L, py_ix, ix) : (\
|
||||
(unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
(unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
__Pyx__PyObject_PopIndex(L, py_ix)))
|
||||
#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
|
||||
__Pyx_fits_Py_ssize_t(ix, type, is_signed) ?\
|
||||
__Pyx__PyList_PopIndex(L, py_ix, ix) : (\
|
||||
(unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
(unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
__Pyx__PyObject_PopIndex(L, py_ix)))
|
||||
#else
|
||||
#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)\
|
||||
__Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)
|
||||
#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
|
||||
(unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
(unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
|
||||
__Pyx__PyObject_PopIndex(L, py_ix))
|
||||
#endif
|
||||
|
||||
@ -1135,6 +1109,32 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *);
|
||||
/* GetAttr3.proto */
|
||||
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *);
|
||||
|
||||
/* PyDictVersioning.proto */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1)
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version);
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
|
||||
/* GetModuleGlobalName.proto */
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
#define __Pyx_GetModuleGlobalName(var, name) {\
|
||||
@ -1298,9 +1298,9 @@ static const char __pyx_k_aiohttp__frozenlist[] = "aiohttp._frozenlist";
|
||||
static const char __pyx_k_pyx_unpickle_FrozenList[] = "__pyx_unpickle_FrozenList";
|
||||
static const char __pyx_k_Cannot_modify_frozen_list[] = "Cannot modify frozen list.";
|
||||
static const char __pyx_k_Incompatible_checksums_s_vs_0x94[] = "Incompatible checksums (%s vs 0x949a143 = (_items, frozen))";
|
||||
static PyObject *__pyx_kp_s_Cannot_modify_frozen_list;
|
||||
static PyObject *__pyx_kp_u_Cannot_modify_frozen_list;
|
||||
static PyObject *__pyx_n_s_FrozenList;
|
||||
static PyObject *__pyx_kp_s_FrozenList_frozen_r;
|
||||
static PyObject *__pyx_kp_u_FrozenList_frozen_r;
|
||||
static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x94;
|
||||
static PyObject *__pyx_n_s_MutableSequence;
|
||||
static PyObject *__pyx_n_s_PickleError;
|
||||
@ -3427,7 +3427,7 @@ static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(struct
|
||||
*
|
||||
*/
|
||||
__Pyx_XDECREF(__pyx_r);
|
||||
__pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_FrozenList_frozen_r, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 104, __pyx_L1_error)
|
||||
__pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_FrozenList_frozen_r, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 104, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_t_2);
|
||||
__pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 104, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_t_3);
|
||||
@ -3963,7 +3963,7 @@ static PyObject *__pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(CYTHO
|
||||
__Pyx_INCREF(__pyx_n_s_PickleError);
|
||||
__Pyx_GIVEREF(__pyx_n_s_PickleError);
|
||||
PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError);
|
||||
__pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, -1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
__pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_t_3);
|
||||
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
|
||||
__pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
@ -4472,6 +4472,9 @@ static PyTypeObject __pyx_type_7aiohttp_11_frozenlist_FrozenList = {
|
||||
#if PY_VERSION_HEX >= 0x030400a1
|
||||
0, /*tp_finalize*/
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x030800b1
|
||||
0, /*tp_vectorcall*/
|
||||
#endif
|
||||
};
|
||||
|
||||
static PyMethodDef __pyx_methods[] = {
|
||||
@ -4520,9 +4523,9 @@ static struct PyModuleDef __pyx_moduledef = {
|
||||
#endif
|
||||
|
||||
static __Pyx_StringTabEntry __pyx_string_tab[] = {
|
||||
{&__pyx_kp_s_Cannot_modify_frozen_list, __pyx_k_Cannot_modify_frozen_list, sizeof(__pyx_k_Cannot_modify_frozen_list), 0, 0, 1, 0},
|
||||
{&__pyx_kp_u_Cannot_modify_frozen_list, __pyx_k_Cannot_modify_frozen_list, sizeof(__pyx_k_Cannot_modify_frozen_list), 0, 1, 0, 0},
|
||||
{&__pyx_n_s_FrozenList, __pyx_k_FrozenList, sizeof(__pyx_k_FrozenList), 0, 0, 1, 1},
|
||||
{&__pyx_kp_s_FrozenList_frozen_r, __pyx_k_FrozenList_frozen_r, sizeof(__pyx_k_FrozenList_frozen_r), 0, 0, 1, 0},
|
||||
{&__pyx_kp_u_FrozenList_frozen_r, __pyx_k_FrozenList_frozen_r, sizeof(__pyx_k_FrozenList_frozen_r), 0, 1, 0, 0},
|
||||
{&__pyx_kp_s_Incompatible_checksums_s_vs_0x94, __pyx_k_Incompatible_checksums_s_vs_0x94, sizeof(__pyx_k_Incompatible_checksums_s_vs_0x94), 0, 0, 1, 0},
|
||||
{&__pyx_n_s_MutableSequence, __pyx_k_MutableSequence, sizeof(__pyx_k_MutableSequence), 0, 0, 1, 1},
|
||||
{&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1},
|
||||
@ -4584,7 +4587,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
|
||||
*
|
||||
* cdef inline object _fast_len(self):
|
||||
*/
|
||||
__pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_Cannot_modify_frozen_list); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 19, __pyx_L1_error)
|
||||
__pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_Cannot_modify_frozen_list); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 19, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_tuple_);
|
||||
__Pyx_GIVEREF(__pyx_tuple_);
|
||||
|
||||
@ -4659,7 +4662,9 @@ static int __Pyx_modinit_type_init_code(void) {
|
||||
__pyx_vtable_7aiohttp_11_frozenlist_FrozenList._check_frozen = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen;
|
||||
__pyx_vtable_7aiohttp_11_frozenlist_FrozenList._fast_len = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len;
|
||||
if (PyType_Ready(&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error)
|
||||
#if PY_VERSION_HEX < 0x030800B1
|
||||
__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_print = 0;
|
||||
#endif
|
||||
if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_dictoffset && __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro == PyObject_GenericGetAttr)) {
|
||||
__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro = __Pyx_PyObject_GenericGetAttr;
|
||||
}
|
||||
@ -4859,10 +4864,9 @@ if (!__Pyx_RefNanny) {
|
||||
__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_d);
|
||||
__pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
#if CYTHON_COMPILING_IN_PYPY
|
||||
Py_INCREF(__pyx_b);
|
||||
#endif
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_cython_runtime);
|
||||
if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error);
|
||||
/*--- Initialize various global constants etc. ---*/
|
||||
if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
@ -4881,9 +4885,9 @@ if (!__Pyx_RefNanny) {
|
||||
}
|
||||
#endif
|
||||
/*--- Builtin init code ---*/
|
||||
if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error;
|
||||
/*--- Constants init code ---*/
|
||||
if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error;
|
||||
/*--- Global type/function init code ---*/
|
||||
(void)__Pyx_modinit_global_init_code();
|
||||
(void)__Pyx_modinit_variable_export_code();
|
||||
@ -4907,7 +4911,7 @@ if (!__Pyx_RefNanny) {
|
||||
__Pyx_INCREF(__pyx_n_s_MutableSequence);
|
||||
__Pyx_GIVEREF(__pyx_n_s_MutableSequence);
|
||||
PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_MutableSequence);
|
||||
__pyx_t_2 = __Pyx_Import(__pyx_n_s_collections_abc, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
__pyx_t_2 = __Pyx_Import(__pyx_n_s_collections_abc, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_t_2);
|
||||
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
|
||||
__pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_MutableSequence); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
@ -5514,7 +5518,7 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args
|
||||
return result;
|
||||
}
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) {
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) {
|
||||
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
|
||||
PyObject *globals = PyFunction_GET_GLOBALS(func);
|
||||
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
|
||||
@ -5585,12 +5589,12 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, kwdefs, closure);
|
||||
#else
|
||||
result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, closure);
|
||||
#endif
|
||||
@ -6005,6 +6009,32 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject
|
||||
return (likely(r)) ? r : __Pyx_GetAttr3Default(d);
|
||||
}
|
||||
|
||||
/* PyDictVersioning */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) {
|
||||
PyObject **dictptr = NULL;
|
||||
Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset;
|
||||
if (offset) {
|
||||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj);
|
||||
#else
|
||||
dictptr = _PyObject_GetDictPtr(obj);
|
||||
#endif
|
||||
}
|
||||
return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
|
||||
}
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
|
||||
return 0;
|
||||
return obj_dict_version == __Pyx_get_object_dict_version(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* GetModuleGlobalName */
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value)
|
||||
|
Binary file not shown.
@ -1,16 +1,4 @@
|
||||
/* Generated by Cython 0.29.2 */
|
||||
|
||||
/* BEGIN: Cython Metadata
|
||||
{
|
||||
"distutils": {
|
||||
"name": "aiohttp._helpers",
|
||||
"sources": [
|
||||
"aiohttp/_helpers.pyx"
|
||||
]
|
||||
},
|
||||
"module_name": "aiohttp._helpers"
|
||||
}
|
||||
END: Cython Metadata */
|
||||
/* Generated by Cython 0.29.13 */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
@ -19,9 +7,9 @@ END: Cython Metadata */
|
||||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||
#else
|
||||
#define CYTHON_ABI "0_29_2"
|
||||
#define CYTHON_HEX_VERSION 0x001D02F0
|
||||
#define CYTHON_FUTURE_DIVISION 0
|
||||
#define CYTHON_ABI "0_29_13"
|
||||
#define CYTHON_HEX_VERSION 0x001D0DF0
|
||||
#define CYTHON_FUTURE_DIVISION 1
|
||||
#include <stddef.h>
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
|
||||
@ -322,8 +310,13 @@ END: Cython Metadata */
|
||||
#define __Pyx_DefaultClassType PyClass_Type
|
||||
#else
|
||||
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
|
||||
#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#else
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#endif
|
||||
#define __Pyx_DefaultClassType PyType_Type
|
||||
#endif
|
||||
#ifndef Py_TPFLAGS_CHECKTYPES
|
||||
@ -358,26 +351,6 @@ END: Cython Metadata */
|
||||
#else
|
||||
#define __Pyx_PyFastCFunction_Check(func) 0
|
||||
#endif
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
|
||||
#define PyObject_Malloc(s) PyMem_Malloc(s)
|
||||
#define PyObject_Free(p) PyMem_Free(p)
|
||||
@ -410,7 +383,7 @@ END: Cython Metadata */
|
||||
typedef int Py_tss_t;
|
||||
static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) {
|
||||
*key = PyThread_create_key();
|
||||
return 0; // PyThread_create_key reports success always
|
||||
return 0;
|
||||
}
|
||||
static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) {
|
||||
Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t));
|
||||
@ -433,7 +406,7 @@ static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) {
|
||||
static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
||||
return PyThread_get_key_value(*key);
|
||||
}
|
||||
#endif // TSS (Thread Specific Storage) API
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized)
|
||||
#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n))
|
||||
#else
|
||||
@ -632,7 +605,8 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc
|
||||
const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
|
||||
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8)
|
||||
#define __PYX_DEFAULT_STRING_ENCODING ""
|
||||
#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
|
||||
#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
|
||||
@ -1016,7 +990,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObje
|
||||
#define __Pyx_PyFunction_FastCall(func, args, nargs)\
|
||||
__Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL)
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs);
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs);
|
||||
#else
|
||||
#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs)
|
||||
#endif
|
||||
@ -1086,6 +1060,32 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *);
|
||||
/* GetAttr3.proto */
|
||||
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *);
|
||||
|
||||
/* PyDictVersioning.proto */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1)
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version);
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
|
||||
/* GetModuleGlobalName.proto */
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
#define __Pyx_GetModuleGlobalName(var, name) {\
|
||||
@ -1254,7 +1254,7 @@ static PyObject *__pyx_n_s_pyx_unpickle_reify;
|
||||
static PyObject *__pyx_n_s_reduce;
|
||||
static PyObject *__pyx_n_s_reduce_cython;
|
||||
static PyObject *__pyx_n_s_reduce_ex;
|
||||
static PyObject *__pyx_kp_s_reified_property_is_read_only;
|
||||
static PyObject *__pyx_kp_u_reified_property_is_read_only;
|
||||
static PyObject *__pyx_n_s_reify;
|
||||
static PyObject *__pyx_n_s_setstate;
|
||||
static PyObject *__pyx_n_s_setstate_cython;
|
||||
@ -1657,12 +1657,12 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers_5reify_2__get__(struct __pyx_obj_7a
|
||||
*/
|
||||
}
|
||||
__pyx_L3_error:;
|
||||
__Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
|
||||
__Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
|
||||
|
||||
/* "aiohttp/_helpers.pyx":29
|
||||
* inst._cache[self.name] = val
|
||||
@ -2250,7 +2250,7 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED
|
||||
__Pyx_INCREF(__pyx_n_s_PickleError);
|
||||
__Pyx_GIVEREF(__pyx_n_s_PickleError);
|
||||
PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError);
|
||||
__pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, -1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
__pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_t_3);
|
||||
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
|
||||
__pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error)
|
||||
@ -2676,6 +2676,9 @@ static PyTypeObject __pyx_type_7aiohttp_8_helpers_reify = {
|
||||
#if PY_VERSION_HEX >= 0x030400a1
|
||||
0, /*tp_finalize*/
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x030800b1
|
||||
0, /*tp_vectorcall*/
|
||||
#endif
|
||||
};
|
||||
|
||||
static PyMethodDef __pyx_methods[] = {
|
||||
@ -2748,7 +2751,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
|
||||
{&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1},
|
||||
{&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1},
|
||||
{&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1},
|
||||
{&__pyx_kp_s_reified_property_is_read_only, __pyx_k_reified_property_is_read_only, sizeof(__pyx_k_reified_property_is_read_only), 0, 0, 1, 0},
|
||||
{&__pyx_kp_u_reified_property_is_read_only, __pyx_k_reified_property_is_read_only, sizeof(__pyx_k_reified_property_is_read_only), 0, 1, 0, 0},
|
||||
{&__pyx_n_s_reify, __pyx_k_reify, sizeof(__pyx_k_reify), 0, 0, 1, 1},
|
||||
{&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1},
|
||||
{&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1},
|
||||
@ -2775,7 +2778,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
|
||||
* def __set__(self, inst, value):
|
||||
* raise AttributeError("reified property is read-only") # <<<<<<<<<<<<<<
|
||||
*/
|
||||
__pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_reified_property_is_read_only); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 35, __pyx_L1_error)
|
||||
__pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_reified_property_is_read_only); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 35, __pyx_L1_error)
|
||||
__Pyx_GOTREF(__pyx_tuple_);
|
||||
__Pyx_GIVEREF(__pyx_tuple_);
|
||||
|
||||
@ -2840,7 +2843,9 @@ static int __Pyx_modinit_type_init_code(void) {
|
||||
__Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0);
|
||||
/*--- Type init code ---*/
|
||||
if (PyType_Ready(&__pyx_type_7aiohttp_8_helpers_reify) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
#if PY_VERSION_HEX < 0x030800B1
|
||||
__pyx_type_7aiohttp_8_helpers_reify.tp_print = 0;
|
||||
#endif
|
||||
if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_8_helpers_reify.tp_dictoffset && __pyx_type_7aiohttp_8_helpers_reify.tp_getattro == PyObject_GenericGetAttr)) {
|
||||
__pyx_type_7aiohttp_8_helpers_reify.tp_getattro = __Pyx_PyObject_GenericGetAttr;
|
||||
}
|
||||
@ -3038,10 +3043,9 @@ if (!__Pyx_RefNanny) {
|
||||
__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_d);
|
||||
__pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
#if CYTHON_COMPILING_IN_PYPY
|
||||
Py_INCREF(__pyx_b);
|
||||
#endif
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_cython_runtime);
|
||||
if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error);
|
||||
/*--- Initialize various global constants etc. ---*/
|
||||
if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
@ -3060,9 +3064,9 @@ if (!__Pyx_RefNanny) {
|
||||
}
|
||||
#endif
|
||||
/*--- Builtin init code ---*/
|
||||
if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error;
|
||||
/*--- Constants init code ---*/
|
||||
if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error;
|
||||
/*--- Global type/function init code ---*/
|
||||
(void)__Pyx_modinit_global_init_code();
|
||||
(void)__Pyx_modinit_variable_export_code();
|
||||
@ -3633,7 +3637,7 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args
|
||||
return result;
|
||||
}
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) {
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) {
|
||||
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
|
||||
PyObject *globals = PyFunction_GET_GLOBALS(func);
|
||||
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
|
||||
@ -3704,12 +3708,12 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, kwdefs, closure);
|
||||
#else
|
||||
result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, closure);
|
||||
#endif
|
||||
@ -4041,6 +4045,32 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject
|
||||
return (likely(r)) ? r : __Pyx_GetAttr3Default(d);
|
||||
}
|
||||
|
||||
/* PyDictVersioning */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) {
|
||||
PyObject **dictptr = NULL;
|
||||
Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset;
|
||||
if (offset) {
|
||||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj);
|
||||
#else
|
||||
dictptr = _PyObject_GetDictPtr(obj);
|
||||
#endif
|
||||
}
|
||||
return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
|
||||
}
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
|
||||
return 0;
|
||||
return obj_dict_version == __Pyx_get_object_dict_version(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* GetModuleGlobalName */
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value)
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -576,7 +576,8 @@ cdef class HttpResponseParser(HttpParser):
|
||||
if self._buf:
|
||||
self._reason = self._buf.decode('utf-8', 'surrogateescape')
|
||||
PyByteArray_Resize(self._buf, 0)
|
||||
|
||||
else:
|
||||
self._reason = self._reason or ''
|
||||
|
||||
cdef int cb_on_message_begin(cparser.http_parser* parser) except -1:
|
||||
cdef HttpParser pyparser = <HttpParser>parser.data
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -123,28 +123,28 @@ def _serialize_headers(str status_line, headers):
|
||||
try:
|
||||
if _write_str(&writer, status_line) < 0:
|
||||
raise
|
||||
if _write_byte(&writer, '\r') < 0:
|
||||
if _write_byte(&writer, b'\r') < 0:
|
||||
raise
|
||||
if _write_byte(&writer, '\n') < 0:
|
||||
if _write_byte(&writer, b'\n') < 0:
|
||||
raise
|
||||
|
||||
for key, val in headers.items():
|
||||
if _write_str(&writer, to_str(key)) < 0:
|
||||
raise
|
||||
if _write_byte(&writer, ':') < 0:
|
||||
if _write_byte(&writer, b':') < 0:
|
||||
raise
|
||||
if _write_byte(&writer, ' ') < 0:
|
||||
if _write_byte(&writer, b' ') < 0:
|
||||
raise
|
||||
if _write_str(&writer, to_str(val)) < 0:
|
||||
raise
|
||||
if _write_byte(&writer, '\r') < 0:
|
||||
if _write_byte(&writer, b'\r') < 0:
|
||||
raise
|
||||
if _write_byte(&writer, '\n') < 0:
|
||||
if _write_byte(&writer, b'\n') < 0:
|
||||
raise
|
||||
|
||||
if _write_byte(&writer, '\r') < 0:
|
||||
if _write_byte(&writer, b'\r') < 0:
|
||||
raise
|
||||
if _write_byte(&writer, '\n') < 0:
|
||||
if _write_byte(&writer, b'\n') < 0:
|
||||
raise
|
||||
|
||||
return PyBytes_FromStringAndSize(writer.buf, writer.pos)
|
||||
|
@ -1,17 +1,4 @@
|
||||
/* Generated by Cython 0.29.2 */
|
||||
|
||||
/* BEGIN: Cython Metadata
|
||||
{
|
||||
"distutils": {
|
||||
"depends": [],
|
||||
"name": "aiohttp._websocket",
|
||||
"sources": [
|
||||
"aiohttp/_websocket.pyx"
|
||||
]
|
||||
},
|
||||
"module_name": "aiohttp._websocket"
|
||||
}
|
||||
END: Cython Metadata */
|
||||
/* Generated by Cython 0.29.13 */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
@ -20,9 +7,9 @@ END: Cython Metadata */
|
||||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||
#else
|
||||
#define CYTHON_ABI "0_29_2"
|
||||
#define CYTHON_HEX_VERSION 0x001D02F0
|
||||
#define CYTHON_FUTURE_DIVISION 0
|
||||
#define CYTHON_ABI "0_29_13"
|
||||
#define CYTHON_HEX_VERSION 0x001D0DF0
|
||||
#define CYTHON_FUTURE_DIVISION 1
|
||||
#include <stddef.h>
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
|
||||
@ -323,8 +310,13 @@ END: Cython Metadata */
|
||||
#define __Pyx_DefaultClassType PyClass_Type
|
||||
#else
|
||||
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
|
||||
#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#else
|
||||
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
|
||||
PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
|
||||
#endif
|
||||
#define __Pyx_DefaultClassType PyType_Type
|
||||
#endif
|
||||
#ifndef Py_TPFLAGS_CHECKTYPES
|
||||
@ -359,26 +351,6 @@ END: Cython Metadata */
|
||||
#else
|
||||
#define __Pyx_PyFastCFunction_Check(func) 0
|
||||
#endif
|
||||
#if CYTHON_USE_DICT_VERSIONS
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
|
||||
#define PyObject_Malloc(s) PyMem_Malloc(s)
|
||||
#define PyObject_Free(p) PyMem_Free(p)
|
||||
@ -411,7 +383,7 @@ END: Cython Metadata */
|
||||
typedef int Py_tss_t;
|
||||
static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) {
|
||||
*key = PyThread_create_key();
|
||||
return 0; // PyThread_create_key reports success always
|
||||
return 0;
|
||||
}
|
||||
static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) {
|
||||
Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t));
|
||||
@ -434,7 +406,7 @@ static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) {
|
||||
static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
||||
return PyThread_get_key_value(*key);
|
||||
}
|
||||
#endif // TSS (Thread Specific Storage) API
|
||||
#endif
|
||||
#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized)
|
||||
#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n))
|
||||
#else
|
||||
@ -637,7 +609,8 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc
|
||||
const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
|
||||
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0
|
||||
#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8)
|
||||
#define __PYX_DEFAULT_STRING_ENCODING ""
|
||||
#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
|
||||
#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
|
||||
@ -938,7 +911,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObje
|
||||
#define __Pyx_PyFunction_FastCall(func, args, nargs)\
|
||||
__Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL)
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs);
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs);
|
||||
#else
|
||||
#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs)
|
||||
#endif
|
||||
@ -982,6 +955,32 @@ enum __Pyx_ImportType_CheckSize {
|
||||
static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size);
|
||||
#endif
|
||||
|
||||
/* PyDictVersioning.proto */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1)
|
||||
#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
|
||||
(version_var) = __PYX_GET_DICT_VERSION(dict);\
|
||||
(cache_var) = (value);
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
|
||||
static PY_UINT64_T __pyx_dict_version = 0;\
|
||||
static PyObject *__pyx_dict_cached_value = NULL;\
|
||||
if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
|
||||
(VAR) = __pyx_dict_cached_value;\
|
||||
} else {\
|
||||
(VAR) = __pyx_dict_cached_value = (LOOKUP);\
|
||||
__pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
|
||||
}\
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj);
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version);
|
||||
#else
|
||||
#define __PYX_GET_DICT_VERSION(dict) (0)
|
||||
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
|
||||
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP);
|
||||
#endif
|
||||
|
||||
/* PyThreadStateGet.proto */
|
||||
#if CYTHON_FAST_THREAD_STATE
|
||||
#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate;
|
||||
@ -1946,10 +1945,9 @@ if (!__Pyx_RefNanny) {
|
||||
__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_d);
|
||||
__pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
#if CYTHON_COMPILING_IN_PYPY
|
||||
Py_INCREF(__pyx_b);
|
||||
#endif
|
||||
__pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
Py_INCREF(__pyx_cython_runtime);
|
||||
if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error);
|
||||
/*--- Initialize various global constants etc. ---*/
|
||||
if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
@ -1968,9 +1966,9 @@ if (!__Pyx_RefNanny) {
|
||||
}
|
||||
#endif
|
||||
/*--- Builtin init code ---*/
|
||||
if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error;
|
||||
/*--- Constants init code ---*/
|
||||
if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||
if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error;
|
||||
/*--- Global type/function init code ---*/
|
||||
(void)__Pyx_modinit_global_init_code();
|
||||
(void)__Pyx_modinit_variable_export_code();
|
||||
@ -2272,7 +2270,7 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args
|
||||
return result;
|
||||
}
|
||||
#if 1 || PY_VERSION_HEX < 0x030600B1
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) {
|
||||
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) {
|
||||
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
|
||||
PyObject *globals = PyFunction_GET_GLOBALS(func);
|
||||
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
|
||||
@ -2343,12 +2341,12 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, kwdefs, closure);
|
||||
#else
|
||||
result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL,
|
||||
args, nargs,
|
||||
args, (int)nargs,
|
||||
k, (int)nk,
|
||||
d, (int)nd, closure);
|
||||
#endif
|
||||
@ -2501,6 +2499,32 @@ bad:
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PyDictVersioning */
|
||||
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
|
||||
}
|
||||
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) {
|
||||
PyObject **dictptr = NULL;
|
||||
Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset;
|
||||
if (offset) {
|
||||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj);
|
||||
#else
|
||||
dictptr = _PyObject_GetDictPtr(obj);
|
||||
#endif
|
||||
}
|
||||
return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
|
||||
}
|
||||
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) {
|
||||
PyObject *dict = Py_TYPE(obj)->tp_dict;
|
||||
if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
|
||||
return 0;
|
||||
return obj_dict_version == __Pyx_get_object_dict_version(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PyErrFetchRestore */
|
||||
#if CYTHON_FAST_THREAD_STATE
|
||||
static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
|
||||
|
Binary file not shown.
@ -6,7 +6,7 @@ from .tcp_helpers import tcp_nodelay
|
||||
|
||||
class BaseProtocol(asyncio.Protocol):
|
||||
__slots__ = ('_loop', '_paused', '_drain_waiter',
|
||||
'_connection_lost', 'transport')
|
||||
'_connection_lost', '_reading_paused', 'transport')
|
||||
|
||||
def __init__(self, loop: asyncio.AbstractEventLoop) -> None:
|
||||
self._loop = loop # type: asyncio.AbstractEventLoop
|
||||
|
@ -31,36 +31,45 @@ from yarl import URL
|
||||
|
||||
from . import hdrs, http, payload
|
||||
from .abc import AbstractCookieJar
|
||||
from .client_exceptions import ClientConnectionError as ClientConnectionError
|
||||
from .client_exceptions import (
|
||||
ClientConnectionError,
|
||||
ClientConnectorCertificateError,
|
||||
ClientConnectorError,
|
||||
ClientConnectorSSLError,
|
||||
ClientError,
|
||||
ClientHttpProxyError,
|
||||
ClientOSError,
|
||||
ClientPayloadError,
|
||||
ClientProxyConnectionError,
|
||||
ClientResponseError,
|
||||
ClientSSLError,
|
||||
ContentTypeError,
|
||||
InvalidURL,
|
||||
ServerConnectionError,
|
||||
ServerDisconnectedError,
|
||||
ServerFingerprintMismatch,
|
||||
ServerTimeoutError,
|
||||
TooManyRedirects,
|
||||
WSServerHandshakeError,
|
||||
ClientConnectorCertificateError as ClientConnectorCertificateError,
|
||||
)
|
||||
from .client_reqrep import (
|
||||
ClientRequest,
|
||||
ClientResponse,
|
||||
Fingerprint,
|
||||
RequestInfo,
|
||||
_merge_ssl_params,
|
||||
from .client_exceptions import ClientConnectorError as ClientConnectorError
|
||||
from .client_exceptions import (
|
||||
ClientConnectorSSLError as ClientConnectorSSLError,
|
||||
)
|
||||
from .client_ws import ClientWebSocketResponse
|
||||
from .connector import BaseConnector, TCPConnector, UnixConnector
|
||||
from .client_exceptions import ClientError as ClientError
|
||||
from .client_exceptions import ClientHttpProxyError as ClientHttpProxyError
|
||||
from .client_exceptions import ClientOSError as ClientOSError
|
||||
from .client_exceptions import ClientPayloadError as ClientPayloadError
|
||||
from .client_exceptions import (
|
||||
ClientProxyConnectionError as ClientProxyConnectionError,
|
||||
)
|
||||
from .client_exceptions import ClientResponseError as ClientResponseError
|
||||
from .client_exceptions import ClientSSLError as ClientSSLError
|
||||
from .client_exceptions import ContentTypeError as ContentTypeError
|
||||
from .client_exceptions import InvalidURL as InvalidURL
|
||||
from .client_exceptions import ServerConnectionError as ServerConnectionError
|
||||
from .client_exceptions import (
|
||||
ServerDisconnectedError as ServerDisconnectedError,
|
||||
)
|
||||
from .client_exceptions import (
|
||||
ServerFingerprintMismatch as ServerFingerprintMismatch,
|
||||
)
|
||||
from .client_exceptions import ServerTimeoutError as ServerTimeoutError
|
||||
from .client_exceptions import TooManyRedirects as TooManyRedirects
|
||||
from .client_exceptions import WSServerHandshakeError as WSServerHandshakeError
|
||||
from .client_reqrep import ClientRequest as ClientRequest
|
||||
from .client_reqrep import ClientResponse as ClientResponse
|
||||
from .client_reqrep import Fingerprint as Fingerprint
|
||||
from .client_reqrep import RequestInfo as RequestInfo
|
||||
from .client_reqrep import _merge_ssl_params
|
||||
from .client_ws import ClientWebSocketResponse as ClientWebSocketResponse
|
||||
from .connector import BaseConnector as BaseConnector
|
||||
from .connector import NamedPipeConnector as NamedPipeConnector
|
||||
from .connector import TCPConnector as TCPConnector
|
||||
from .connector import UnixConnector as UnixConnector
|
||||
from .cookiejar import CookieJar
|
||||
from .helpers import (
|
||||
DEBUG,
|
||||
@ -114,6 +123,7 @@ __all__ = (
|
||||
'BaseConnector',
|
||||
'TCPConnector',
|
||||
'UnixConnector',
|
||||
'NamedPipeConnector',
|
||||
# client_ws
|
||||
'ClientWebSocketResponse',
|
||||
# client
|
||||
@ -170,7 +180,6 @@ class ClientSession:
|
||||
'_ws_response_class', '_trace_configs'])
|
||||
|
||||
_source_traceback = None
|
||||
_connector = None
|
||||
|
||||
def __init__(self, *, connector: Optional[BaseConnector]=None,
|
||||
loop: Optional[asyncio.AbstractEventLoop]=None,
|
||||
@ -219,7 +228,7 @@ class ClientSession:
|
||||
if cookies is not None:
|
||||
self._cookie_jar.update_cookies(cookies)
|
||||
|
||||
self._connector = connector # type: BaseConnector
|
||||
self._connector = connector # type: Optional[BaseConnector]
|
||||
self._connector_owner = connector_owner
|
||||
self._default_auth = auth
|
||||
self._version = version
|
||||
@ -256,10 +265,10 @@ class ClientSession:
|
||||
|
||||
# Convert to list of tuples
|
||||
if headers:
|
||||
headers = CIMultiDict(headers)
|
||||
real_headers = CIMultiDict(headers) # type: CIMultiDict[str]
|
||||
else:
|
||||
headers = CIMultiDict()
|
||||
self._default_headers = headers
|
||||
real_headers = CIMultiDict()
|
||||
self._default_headers = real_headers # type: CIMultiDict[str]
|
||||
if skip_auto_headers is not None:
|
||||
self._skip_auto_headers = frozenset([istr(i)
|
||||
for i in skip_auto_headers])
|
||||
@ -434,16 +443,14 @@ class ClientSession:
|
||||
"with AUTH argument or credentials "
|
||||
"encoded in URL")
|
||||
|
||||
session_cookies = self._cookie_jar.filter_cookies(url)
|
||||
all_cookies = self._cookie_jar.filter_cookies(url)
|
||||
|
||||
if cookies is not None:
|
||||
tmp_cookie_jar = CookieJar()
|
||||
tmp_cookie_jar.update_cookies(cookies)
|
||||
req_cookies = tmp_cookie_jar.filter_cookies(url)
|
||||
if req_cookies:
|
||||
session_cookies.load(req_cookies)
|
||||
|
||||
cookies = session_cookies
|
||||
all_cookies.load(req_cookies)
|
||||
|
||||
if proxy is not None:
|
||||
proxy = URL(proxy)
|
||||
@ -457,7 +464,7 @@ class ClientSession:
|
||||
req = self._request_class(
|
||||
method, url, params=params, headers=headers,
|
||||
skip_auto_headers=skip_headers, data=data,
|
||||
cookies=cookies, auth=auth, version=version,
|
||||
cookies=all_cookies, auth=auth, version=version,
|
||||
compress=compress, chunked=chunked,
|
||||
expect100=expect100, loop=self._loop,
|
||||
response_class=self._response_class,
|
||||
@ -1040,8 +1047,13 @@ class _SessionRequestContextManager:
|
||||
self._session = session
|
||||
|
||||
async def __aenter__(self) -> ClientResponse:
|
||||
self._resp = await self._coro
|
||||
return self._resp
|
||||
try:
|
||||
self._resp = await self._coro
|
||||
except BaseException:
|
||||
await self._session.close()
|
||||
raise
|
||||
else:
|
||||
return self._resp
|
||||
|
||||
async def __aexit__(self,
|
||||
exc_type: Optional[Type[BaseException]],
|
||||
|
@ -72,8 +72,21 @@ class ClientResponseError(ClientError):
|
||||
self.message = message
|
||||
self.headers = headers
|
||||
self.history = history
|
||||
self.args = (request_info, history)
|
||||
|
||||
super().__init__("%s, message='%s'" % (self.status, message))
|
||||
def __str__(self) -> str:
|
||||
return ("%s, message=%r, url=%r" %
|
||||
(self.status, self.message, self.request_info.real_url))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
args = "%r, %r" % (self.request_info, self.history)
|
||||
if self.status != 0:
|
||||
args += ", status=%r" % (self.status,)
|
||||
if self.message != '':
|
||||
args += ", message=%r" % (self.message,)
|
||||
if self.headers is not None:
|
||||
args += ", headers=%r" % (self.headers,)
|
||||
return "%s(%s)" % (type(self).__name__, args)
|
||||
|
||||
@property
|
||||
def code(self) -> int:
|
||||
@ -130,6 +143,7 @@ class ClientConnectorError(ClientOSError):
|
||||
self._conn_key = connection_key
|
||||
self._os_error = os_error
|
||||
super().__init__(os_error.errno, os_error.strerror)
|
||||
self.args = (connection_key, os_error)
|
||||
|
||||
@property
|
||||
def os_error(self) -> OSError:
|
||||
@ -148,8 +162,12 @@ class ClientConnectorError(ClientOSError):
|
||||
return self._conn_key.ssl
|
||||
|
||||
def __str__(self) -> str:
|
||||
return ('Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} [{1}]'
|
||||
.format(self, self.strerror))
|
||||
return ('Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]'
|
||||
.format(self, self.ssl if self.ssl is not None else 'default',
|
||||
self.strerror))
|
||||
|
||||
# OSError.__reduce__ does too much black magick
|
||||
__reduce__ = BaseException.__reduce__
|
||||
|
||||
|
||||
class ClientProxyConnectionError(ClientConnectorError):
|
||||
@ -169,6 +187,10 @@ class ServerDisconnectedError(ServerConnectionError):
|
||||
|
||||
def __init__(self, message: Optional[str]=None) -> None:
|
||||
self.message = message
|
||||
if message is None:
|
||||
self.args = ()
|
||||
else:
|
||||
self.args = (message,)
|
||||
|
||||
|
||||
class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
|
||||
@ -184,9 +206,10 @@ class ServerFingerprintMismatch(ServerConnectionError):
|
||||
self.got = got
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.args = (expected, got, host, port)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return '<{} expected={} got={} host={} port={}>'.format(
|
||||
return '<{} expected={!r} got={!r} host={!r} port={!r}>'.format(
|
||||
self.__class__.__name__, self.expected, self.got,
|
||||
self.host, self.port)
|
||||
|
||||
@ -245,6 +268,7 @@ class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore
|
||||
ConnectionKey, certificate_error: Exception) -> None:
|
||||
self._conn_key = connection_key
|
||||
self._certificate_error = certificate_error
|
||||
self.args = (connection_key, certificate_error)
|
||||
|
||||
@property
|
||||
def certificate_error(self) -> Exception:
|
||||
|
@ -176,6 +176,8 @@ class ResponseHandler(BaseProtocol,
|
||||
self._payload.set_exception(exc)
|
||||
|
||||
def data_received(self, data: bytes) -> None:
|
||||
self._reschedule_timeout()
|
||||
|
||||
if not data:
|
||||
return
|
||||
|
||||
|
@ -220,7 +220,6 @@ class ClientRequest:
|
||||
body = b''
|
||||
auth = None
|
||||
response = None
|
||||
response_class = None
|
||||
|
||||
_writer = None # async task for streaming data
|
||||
_continue = None # waiter future for '100 Continue' response
|
||||
@ -367,7 +366,7 @@ class ClientRequest:
|
||||
netloc = cast(str, self.url.raw_host)
|
||||
if helpers.is_ipv6_address(netloc):
|
||||
netloc = '[{}]'.format(netloc)
|
||||
if not self.url.is_default_port():
|
||||
if self.url.port is not None and not self.url.is_default_port():
|
||||
netloc += ':' + str(self.url.port)
|
||||
self.headers[hdrs.HOST] = netloc
|
||||
|
||||
@ -413,7 +412,7 @@ class ClientRequest:
|
||||
if isinstance(value, Morsel):
|
||||
# Preserve coded_value
|
||||
mrsl_val = value.get(value.key, Morsel())
|
||||
mrsl_val.set(value.key, value.value, value.coded_value) # type: ignore # noqa
|
||||
mrsl_val.set(value.key, value.value, value.coded_value)
|
||||
c[name] = mrsl_val
|
||||
else:
|
||||
c[name] = value # type: ignore
|
||||
@ -580,7 +579,11 @@ class ClientRequest:
|
||||
# - not CONNECT proxy must send absolute form URI
|
||||
# - most common is origin form URI
|
||||
if self.method == hdrs.METH_CONNECT:
|
||||
path = '{}:{}'.format(self.url.raw_host, self.url.port)
|
||||
connect_host = self.url.raw_host
|
||||
assert connect_host is not None
|
||||
if helpers.is_ipv6_address(connect_host):
|
||||
connect_host = '[{}]'.format(connect_host)
|
||||
path = '{}:{}'.format(connect_host, self.url.port)
|
||||
elif self.proxy and not self.is_ssl():
|
||||
path = str(self.url)
|
||||
else:
|
||||
@ -932,7 +935,8 @@ class ClientResponse(HeadersMixin):
|
||||
|
||||
def raise_for_status(self) -> None:
|
||||
if 400 <= self.status:
|
||||
assert self.reason # always not None for started response
|
||||
# reason should always be not None for a started response
|
||||
assert self.reason is not None
|
||||
self.release()
|
||||
raise ClientResponseError(
|
||||
self.request_info,
|
||||
|
@ -64,7 +64,8 @@ except ImportError: # pragma: no cover
|
||||
SSLContext = object # type: ignore
|
||||
|
||||
|
||||
__all__ = ('BaseConnector', 'TCPConnector', 'UnixConnector')
|
||||
__all__ = ('BaseConnector', 'TCPConnector', 'UnixConnector',
|
||||
'NamedPipeConnector')
|
||||
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
@ -716,7 +717,7 @@ class TCPConnector(BaseConnector):
|
||||
family: int=0,
|
||||
ssl_context: Optional[SSLContext]=None,
|
||||
ssl: Union[None, bool, Fingerprint, SSLContext]=None,
|
||||
local_addr: Optional[str]=None,
|
||||
local_addr: Optional[Tuple[str, int]]=None,
|
||||
resolver: Optional[AbstractResolver]=None,
|
||||
keepalive_timeout: Union[None, float, object]=sentinel,
|
||||
force_close: bool=False,
|
||||
@ -797,24 +798,28 @@ class TCPConnector(BaseConnector):
|
||||
|
||||
if (key in self._cached_hosts) and \
|
||||
(not self._cached_hosts.expired(key)):
|
||||
# get result early, before any await (#4014)
|
||||
result = self._cached_hosts.next_addrs(key)
|
||||
|
||||
if traces:
|
||||
for trace in traces:
|
||||
await trace.send_dns_cache_hit(host)
|
||||
|
||||
return self._cached_hosts.next_addrs(key)
|
||||
return result
|
||||
|
||||
if key in self._throttle_dns_events:
|
||||
# get event early, before any await (#4014)
|
||||
event = self._throttle_dns_events[key]
|
||||
if traces:
|
||||
for trace in traces:
|
||||
await trace.send_dns_cache_hit(host)
|
||||
await self._throttle_dns_events[key].wait()
|
||||
await event.wait()
|
||||
else:
|
||||
# update dict early, before any await (#4014)
|
||||
self._throttle_dns_events[key] = \
|
||||
EventResultOrError(self._loop)
|
||||
if traces:
|
||||
for trace in traces:
|
||||
await trace.send_dns_cache_miss(host)
|
||||
self._throttle_dns_events[key] = \
|
||||
EventResultOrError(self._loop)
|
||||
try:
|
||||
|
||||
if traces:
|
||||
@ -864,7 +869,16 @@ class TCPConnector(BaseConnector):
|
||||
sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
sslcontext.options |= ssl.OP_NO_SSLv2
|
||||
sslcontext.options |= ssl.OP_NO_SSLv3
|
||||
sslcontext.options |= ssl.OP_NO_COMPRESSION
|
||||
try:
|
||||
sslcontext.options |= ssl.OP_NO_COMPRESSION
|
||||
except AttributeError as attr_err:
|
||||
warnings.warn(
|
||||
'{!s}: The Python interpreter is compiled '
|
||||
'against OpenSSL < 1.0.0. Ref: '
|
||||
'https://docs.python.org/3/library/ssl.html'
|
||||
'#ssl.OP_NO_COMPRESSION'.
|
||||
format(attr_err),
|
||||
)
|
||||
sslcontext.set_default_verify_paths()
|
||||
return sslcontext
|
||||
|
||||
@ -919,9 +933,7 @@ class TCPConnector(BaseConnector):
|
||||
**kwargs: Any) -> Tuple[asyncio.Transport, ResponseHandler]:
|
||||
try:
|
||||
with CeilTimeout(timeout.sock_connect):
|
||||
return cast(
|
||||
Tuple[asyncio.Transport, ResponseHandler],
|
||||
await self._loop.create_connection(*args, **kwargs))
|
||||
return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa
|
||||
except cert_errors as exc:
|
||||
raise ClientConnectorCertificateError(
|
||||
req.connection_key, exc) from exc
|
||||
@ -1126,3 +1138,56 @@ class UnixConnector(BaseConnector):
|
||||
raise ClientConnectorError(req.connection_key, exc) from exc
|
||||
|
||||
return cast(ResponseHandler, proto)
|
||||
|
||||
|
||||
class NamedPipeConnector(BaseConnector):
|
||||
"""Named pipe connector.
|
||||
|
||||
Only supported by the proactor event loop.
|
||||
See also: https://docs.python.org/3.7/library/asyncio-eventloop.html
|
||||
|
||||
path - Windows named pipe path.
|
||||
keepalive_timeout - (optional) Keep-alive timeout.
|
||||
force_close - Set to True to force close and do reconnect
|
||||
after each request (and between redirects).
|
||||
limit - The total number of simultaneous connections.
|
||||
limit_per_host - Number of simultaneous connections to one host.
|
||||
loop - Optional event loop.
|
||||
"""
|
||||
|
||||
def __init__(self, path: str, force_close: bool=False,
|
||||
keepalive_timeout: Union[object, float, None]=sentinel,
|
||||
limit: int=100, limit_per_host: int=0,
|
||||
loop: Optional[asyncio.AbstractEventLoop]=None) -> None:
|
||||
super().__init__(force_close=force_close,
|
||||
keepalive_timeout=keepalive_timeout,
|
||||
limit=limit, limit_per_host=limit_per_host, loop=loop)
|
||||
if not isinstance(self._loop, asyncio.ProactorEventLoop): # type: ignore # noqa
|
||||
raise RuntimeError("Named Pipes only available in proactor "
|
||||
"loop under windows")
|
||||
self._path = path
|
||||
|
||||
@property
|
||||
def path(self) -> str:
|
||||
"""Path to the named pipe."""
|
||||
return self._path
|
||||
|
||||
async def _create_connection(self, req: 'ClientRequest',
|
||||
traces: List['Trace'],
|
||||
timeout: 'ClientTimeout') -> ResponseHandler:
|
||||
try:
|
||||
with CeilTimeout(timeout.sock_connect):
|
||||
_, proto = await self._loop.create_pipe_connection( # type: ignore # noqa
|
||||
self._factory, self._path
|
||||
)
|
||||
# the drain is required so that the connection_made is called
|
||||
# and transport is set otherwise it is not set before the
|
||||
# `assert conn.transport is not None`
|
||||
# in client.py's _request method
|
||||
await asyncio.sleep(0)
|
||||
# other option is to manually set transport like
|
||||
# `proto.transport = trans`
|
||||
except OSError as exc:
|
||||
raise ClientConnectorError(req.connection_key, exc) from exc
|
||||
|
||||
return cast(ResponseHandler, proto)
|
||||
|
@ -6,7 +6,6 @@ import pickle
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from http.cookies import BaseCookie, Morsel, SimpleCookie # noqa
|
||||
from math import ceil
|
||||
from typing import ( # noqa
|
||||
DefaultDict,
|
||||
Dict,
|
||||
@ -23,7 +22,7 @@ from typing import ( # noqa
|
||||
from yarl import URL
|
||||
|
||||
from .abc import AbstractCookieJar
|
||||
from .helpers import is_ip_address
|
||||
from .helpers import is_ip_address, next_whole_second
|
||||
from .typedefs import LooseCookies, PathLike
|
||||
|
||||
__all__ = ('CookieJar', 'DummyCookieJar')
|
||||
@ -48,7 +47,8 @@ class CookieJar(AbstractCookieJar):
|
||||
|
||||
DATE_YEAR_RE = re.compile(r"(\d{2,4})")
|
||||
|
||||
MAX_TIME = 2051215261.0 # so far in future (2035-01-01)
|
||||
MAX_TIME = datetime.datetime.max.replace(
|
||||
tzinfo=datetime.timezone.utc)
|
||||
|
||||
def __init__(self, *, unsafe: bool=False,
|
||||
loop: Optional[asyncio.AbstractEventLoop]=None) -> None:
|
||||
@ -56,8 +56,8 @@ class CookieJar(AbstractCookieJar):
|
||||
self._cookies = defaultdict(SimpleCookie) #type: DefaultDict[str, SimpleCookie] # noqa
|
||||
self._host_only_cookies = set() # type: Set[Tuple[str, str]]
|
||||
self._unsafe = unsafe
|
||||
self._next_expiration = ceil(self._loop.time())
|
||||
self._expirations = {} # type: Dict[Tuple[str, str], int]
|
||||
self._next_expiration = next_whole_second()
|
||||
self._expirations = {} # type: Dict[Tuple[str, str], datetime.datetime] # noqa: E501
|
||||
|
||||
def save(self, file_path: PathLike) -> None:
|
||||
file_path = pathlib.Path(file_path)
|
||||
@ -72,7 +72,7 @@ class CookieJar(AbstractCookieJar):
|
||||
def clear(self) -> None:
|
||||
self._cookies.clear()
|
||||
self._host_only_cookies.clear()
|
||||
self._next_expiration = ceil(self._loop.time())
|
||||
self._next_expiration = next_whole_second()
|
||||
self._expirations.clear()
|
||||
|
||||
def __iter__(self) -> 'Iterator[Morsel[str]]':
|
||||
@ -84,7 +84,7 @@ class CookieJar(AbstractCookieJar):
|
||||
return sum(1 for i in self)
|
||||
|
||||
def _do_expiration(self) -> None:
|
||||
now = self._loop.time()
|
||||
now = datetime.datetime.now(datetime.timezone.utc)
|
||||
if self._next_expiration > now:
|
||||
return
|
||||
if not self._expirations:
|
||||
@ -103,12 +103,16 @@ class CookieJar(AbstractCookieJar):
|
||||
for key in to_del:
|
||||
del expirations[key]
|
||||
|
||||
self._next_expiration = ceil(next_expiration)
|
||||
try:
|
||||
self._next_expiration = (next_expiration.replace(microsecond=0) +
|
||||
datetime.timedelta(seconds=1))
|
||||
except OverflowError:
|
||||
self._next_expiration = self.MAX_TIME
|
||||
|
||||
def _expire_cookie(self, when: float, domain: str, name: str) -> None:
|
||||
iwhen = int(when)
|
||||
self._next_expiration = min(self._next_expiration, iwhen)
|
||||
self._expirations[(domain, name)] = iwhen
|
||||
def _expire_cookie(self, when: datetime.datetime, domain: str, name: str
|
||||
) -> None:
|
||||
self._next_expiration = min(self._next_expiration, when)
|
||||
self._expirations[(domain, name)] = when
|
||||
|
||||
def update_cookies(self,
|
||||
cookies: LooseCookies,
|
||||
@ -166,7 +170,13 @@ class CookieJar(AbstractCookieJar):
|
||||
if max_age:
|
||||
try:
|
||||
delta_seconds = int(max_age)
|
||||
self._expire_cookie(self._loop.time() + delta_seconds,
|
||||
try:
|
||||
max_age_expiration = (
|
||||
datetime.datetime.now(datetime.timezone.utc) +
|
||||
datetime.timedelta(seconds=delta_seconds))
|
||||
except OverflowError:
|
||||
max_age_expiration = self.MAX_TIME
|
||||
self._expire_cookie(max_age_expiration,
|
||||
domain, name)
|
||||
except ValueError:
|
||||
cookie["max-age"] = ""
|
||||
@ -176,7 +186,7 @@ class CookieJar(AbstractCookieJar):
|
||||
if expires:
|
||||
expire_time = self._parse_date(expires)
|
||||
if expire_time:
|
||||
self._expire_cookie(expire_time.timestamp(),
|
||||
self._expire_cookie(expire_time,
|
||||
domain, name)
|
||||
else:
|
||||
cookie["expires"] = ""
|
||||
@ -299,6 +309,7 @@ class CookieJar(AbstractCookieJar):
|
||||
month_match = cls.DATE_MONTH_RE.match(token)
|
||||
if month_match:
|
||||
found_month = True
|
||||
assert month_match.lastindex is not None
|
||||
month = month_match.lastindex
|
||||
continue
|
||||
|
||||
|
@ -1,5 +1,14 @@
|
||||
from typing import (Generic, Iterable, Iterator, List, MutableSequence,
|
||||
Optional, TypeVar, Union, overload)
|
||||
from typing import (
|
||||
Generic,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
MutableSequence,
|
||||
Optional,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
_T = TypeVar('_T')
|
||||
_Arg = Union[List[_T], Iterable[_T]]
|
||||
@ -7,7 +16,7 @@ _Arg = Union[List[_T], Iterable[_T]]
|
||||
|
||||
class FrozenList(MutableSequence[_T], Generic[_T]):
|
||||
|
||||
def __init__(self, items: Optional[_Arg[_T]]=None) -> None: ...
|
||||
def __init__(self, items: Optional[_Arg[_T]]=...) -> None: ...
|
||||
|
||||
@property
|
||||
def frozen(self) -> bool: ...
|
||||
|
@ -4,6 +4,7 @@ import asyncio
|
||||
import base64
|
||||
import binascii
|
||||
import cgi
|
||||
import datetime
|
||||
import functools
|
||||
import inspect
|
||||
import netrc
|
||||
@ -52,6 +53,7 @@ __all__ = ('BasicAuth', 'ChainMapProxy')
|
||||
|
||||
PY_36 = sys.version_info >= (3, 6)
|
||||
PY_37 = sys.version_info >= (3, 7)
|
||||
PY_38 = sys.version_info >= (3, 8)
|
||||
|
||||
if not PY_37:
|
||||
import idna_ssl
|
||||
@ -66,7 +68,7 @@ except ImportError:
|
||||
def all_tasks(
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
) -> Set['asyncio.Task[Any]']:
|
||||
tasks = list(asyncio.Task.all_tasks(loop)) # type: ignore
|
||||
tasks = list(asyncio.Task.all_tasks(loop))
|
||||
return {t for t in tasks if not t.done()}
|
||||
|
||||
|
||||
@ -257,7 +259,7 @@ def current_task(loop: Optional[asyncio.AbstractEventLoop]=None) -> asyncio.Task
|
||||
if PY_37:
|
||||
return asyncio.current_task(loop=loop) # type: ignore
|
||||
else:
|
||||
return asyncio.Task.current_task(loop=loop) # type: ignore
|
||||
return asyncio.Task.current_task(loop=loop)
|
||||
|
||||
|
||||
def get_running_loop(
|
||||
@ -428,7 +430,7 @@ _ipv6_regexb = re.compile(_ipv6_pattern.encode('ascii'), flags=re.IGNORECASE)
|
||||
|
||||
def _is_ip_address(
|
||||
regex: Pattern[str], regexb: Pattern[bytes],
|
||||
host: Optional[Union[str, bytes]])-> bool:
|
||||
host: Optional[Union[str, bytes]]) -> bool:
|
||||
if host is None:
|
||||
return False
|
||||
if isinstance(host, str):
|
||||
@ -449,8 +451,17 @@ def is_ip_address(
|
||||
return is_ipv4_address(host) or is_ipv6_address(host)
|
||||
|
||||
|
||||
_cached_current_datetime = None
|
||||
_cached_formatted_datetime = None
|
||||
def next_whole_second() -> datetime.datetime:
|
||||
"""Return current time rounded up to the next whole second."""
|
||||
return (
|
||||
datetime.datetime.now(
|
||||
datetime.timezone.utc).replace(microsecond=0) +
|
||||
datetime.timedelta(seconds=0)
|
||||
)
|
||||
|
||||
|
||||
_cached_current_datetime = None # type: Optional[int]
|
||||
_cached_formatted_datetime = ""
|
||||
|
||||
|
||||
def rfc822_formatted_time() -> str:
|
||||
@ -467,12 +478,12 @@ def rfc822_formatted_time() -> str:
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
|
||||
|
||||
year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now) # type: ignore # noqa
|
||||
year, month, day, hh, mm, ss, wd, *tail = time.gmtime(now)
|
||||
_cached_formatted_datetime = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
|
||||
_weekdayname[wd], day, _monthname[month], year, hh, mm, ss
|
||||
)
|
||||
_cached_current_datetime = now
|
||||
return _cached_formatted_datetime # type: ignore
|
||||
return _cached_formatted_datetime
|
||||
|
||||
|
||||
def _weakref_handle(info): # type: ignore
|
||||
|
@ -3,34 +3,28 @@ import sys
|
||||
from typing import Mapping, Tuple # noqa
|
||||
|
||||
from . import __version__
|
||||
from .http_exceptions import HttpProcessingError
|
||||
from .http_parser import (
|
||||
HeadersParser,
|
||||
HttpParser,
|
||||
HttpRequestParser,
|
||||
HttpResponseParser,
|
||||
RawRequestMessage,
|
||||
RawResponseMessage,
|
||||
)
|
||||
from .http_websocket import (
|
||||
WS_CLOSED_MESSAGE,
|
||||
WS_CLOSING_MESSAGE,
|
||||
WS_KEY,
|
||||
WebSocketError,
|
||||
WebSocketReader,
|
||||
WebSocketWriter,
|
||||
WSCloseCode,
|
||||
WSMessage,
|
||||
WSMsgType,
|
||||
ws_ext_gen,
|
||||
ws_ext_parse,
|
||||
)
|
||||
from .http_writer import (
|
||||
HttpVersion,
|
||||
HttpVersion10,
|
||||
HttpVersion11,
|
||||
StreamWriter,
|
||||
)
|
||||
from .http_exceptions import HttpProcessingError as HttpProcessingError
|
||||
from .http_parser import HeadersParser as HeadersParser
|
||||
from .http_parser import HttpParser as HttpParser
|
||||
from .http_parser import HttpRequestParser as HttpRequestParser
|
||||
from .http_parser import HttpResponseParser as HttpResponseParser
|
||||
from .http_parser import RawRequestMessage as RawRequestMessage
|
||||
from .http_parser import RawResponseMessage as RawResponseMessage
|
||||
from .http_websocket import WS_CLOSED_MESSAGE as WS_CLOSED_MESSAGE
|
||||
from .http_websocket import WS_CLOSING_MESSAGE as WS_CLOSING_MESSAGE
|
||||
from .http_websocket import WS_KEY as WS_KEY
|
||||
from .http_websocket import WebSocketError as WebSocketError
|
||||
from .http_websocket import WebSocketReader as WebSocketReader
|
||||
from .http_websocket import WebSocketWriter as WebSocketWriter
|
||||
from .http_websocket import WSCloseCode as WSCloseCode
|
||||
from .http_websocket import WSMessage as WSMessage
|
||||
from .http_websocket import WSMsgType as WSMsgType
|
||||
from .http_websocket import ws_ext_gen as ws_ext_gen
|
||||
from .http_websocket import ws_ext_parse as ws_ext_parse
|
||||
from .http_writer import HttpVersion as HttpVersion
|
||||
from .http_writer import HttpVersion10 as HttpVersion10
|
||||
from .http_writer import HttpVersion11 as HttpVersion11
|
||||
from .http_writer import StreamWriter as StreamWriter
|
||||
|
||||
__all__ = (
|
||||
'HttpProcessingError', 'RESPONSES', 'SERVER_SOFTWARE',
|
||||
|
@ -31,7 +31,11 @@ class HttpProcessingError(Exception):
|
||||
self.headers = headers
|
||||
self.message = message
|
||||
|
||||
super().__init__("%s, message='%s'" % (self.code, message))
|
||||
def __str__(self) -> str:
|
||||
return "%s, message=%r" % (self.code, self.message)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<%s: %s>" % (self.__class__.__name__, self)
|
||||
|
||||
|
||||
class BadHttpMessage(HttpProcessingError):
|
||||
@ -42,6 +46,7 @@ class BadHttpMessage(HttpProcessingError):
|
||||
def __init__(self, message: str, *,
|
||||
headers: Optional[_CIMultiDict]=None) -> None:
|
||||
super().__init__(message=message, headers=headers)
|
||||
self.args = (message,)
|
||||
|
||||
|
||||
class HttpBadRequest(BadHttpMessage):
|
||||
@ -74,6 +79,7 @@ class LineTooLong(BadHttpMessage):
|
||||
super().__init__(
|
||||
"Got more than %s bytes (%s) when reading %s." % (
|
||||
limit, actual_size, line))
|
||||
self.args = (line, limit, actual_size)
|
||||
|
||||
|
||||
class InvalidHeader(BadHttpMessage):
|
||||
@ -83,16 +89,20 @@ class InvalidHeader(BadHttpMessage):
|
||||
hdr = hdr.decode('utf-8', 'surrogateescape')
|
||||
super().__init__('Invalid HTTP Header: {}'.format(hdr))
|
||||
self.hdr = hdr
|
||||
self.args = (hdr,)
|
||||
|
||||
|
||||
class BadStatusLine(BadHttpMessage):
|
||||
|
||||
def __init__(self, line: str='') -> None:
|
||||
if not line:
|
||||
if not isinstance(line, str):
|
||||
line = repr(line)
|
||||
self.args = line,
|
||||
self.args = (line,)
|
||||
self.line = line
|
||||
|
||||
__str__ = Exception.__str__
|
||||
__repr__ = Exception.__repr__
|
||||
|
||||
|
||||
class InvalidURLError(BadHttpMessage):
|
||||
pass
|
||||
|
@ -82,8 +82,8 @@ _WSMessageBase = collections.namedtuple('_WSMessageBase',
|
||||
|
||||
class WSMessage(_WSMessageBase):
|
||||
|
||||
def json(self, *, # type: ignore
|
||||
loads: Callable[[Any], Any]=json.loads) -> None:
|
||||
def json(self, *,
|
||||
loads: Callable[[Any], Any]=json.loads) -> Any:
|
||||
"""Return parsed JSON data.
|
||||
|
||||
.. versionadded:: 0.22
|
||||
@ -100,7 +100,10 @@ class WebSocketError(Exception):
|
||||
|
||||
def __init__(self, code: int, message: str) -> None:
|
||||
self.code = code
|
||||
super().__init__(message)
|
||||
super().__init__(code, message)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.args[1]
|
||||
|
||||
|
||||
class WSHandshakeError(Exception):
|
||||
@ -365,9 +368,12 @@ class WebSocketReader:
|
||||
left = len(self._decompressobj.unconsumed_tail)
|
||||
raise WebSocketError(
|
||||
WSCloseCode.MESSAGE_TOO_BIG,
|
||||
"Decompressed message size exceeds limit {}".
|
||||
format(self._max_msg_size + left,
|
||||
self._max_msg_size))
|
||||
"Decompressed message size {} exceeds limit {}"
|
||||
.format(
|
||||
self._max_msg_size + left,
|
||||
self._max_msg_size
|
||||
)
|
||||
)
|
||||
else:
|
||||
payload_merged = bytes(self._partial)
|
||||
|
||||
|
@ -19,7 +19,6 @@ from typing import ( # noqa
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
from urllib.parse import parse_qsl, unquote, urlencode
|
||||
|
||||
@ -195,21 +194,26 @@ def content_disposition_filename(params: Mapping[str, str],
|
||||
|
||||
|
||||
class MultipartResponseWrapper:
|
||||
"""Wrapper around the MultipartBodyReader.
|
||||
"""Wrapper around the MultipartReader.
|
||||
|
||||
It takes care about
|
||||
underlying connection and close it when it needs in.
|
||||
"""
|
||||
|
||||
def __init__(self, resp: 'ClientResponse', stream: Any) -> None:
|
||||
# TODO: add strong annotation to stream
|
||||
def __init__(
|
||||
self,
|
||||
resp: 'ClientResponse',
|
||||
stream: 'MultipartReader',
|
||||
) -> None:
|
||||
self.resp = resp
|
||||
self.stream = stream
|
||||
|
||||
def __aiter__(self) -> 'MultipartResponseWrapper':
|
||||
return self
|
||||
|
||||
async def __anext__(self) -> Any:
|
||||
async def __anext__(
|
||||
self,
|
||||
) -> Union['MultipartReader', 'BodyPartReader']:
|
||||
part = await self.next()
|
||||
if part is None:
|
||||
raise StopAsyncIteration # NOQA
|
||||
@ -219,7 +223,9 @@ class MultipartResponseWrapper:
|
||||
"""Returns True when all response data had been read."""
|
||||
return self.resp.content.at_eof()
|
||||
|
||||
async def next(self) -> Any:
|
||||
async def next(
|
||||
self,
|
||||
) -> Optional[Union['MultipartReader', 'BodyPartReader']]:
|
||||
"""Emits next multipart reader object."""
|
||||
item = await self.stream.next()
|
||||
if self.stream.at_eof():
|
||||
@ -238,7 +244,7 @@ class BodyPartReader:
|
||||
chunk_size = 8192
|
||||
|
||||
def __init__(self, boundary: bytes,
|
||||
headers: Mapping[str, Optional[str]],
|
||||
headers: 'CIMultiDictProxy[str]',
|
||||
content: StreamReader) -> None:
|
||||
self.headers = headers
|
||||
self._boundary = boundary
|
||||
@ -256,19 +262,19 @@ class BodyPartReader:
|
||||
def __aiter__(self) -> 'BodyPartReader':
|
||||
return self
|
||||
|
||||
async def __anext__(self) -> Any:
|
||||
async def __anext__(self) -> bytes:
|
||||
part = await self.next()
|
||||
if part is None:
|
||||
raise StopAsyncIteration # NOQA
|
||||
return part
|
||||
|
||||
async def next(self) -> Any:
|
||||
async def next(self) -> Optional[bytes]:
|
||||
item = await self.read()
|
||||
if not item:
|
||||
return None
|
||||
return item
|
||||
|
||||
async def read(self, *, decode: bool=False) -> Any:
|
||||
async def read(self, *, decode: bool=False) -> bytes:
|
||||
"""Reads body part data.
|
||||
|
||||
decode: Decodes data following by encoding
|
||||
@ -392,7 +398,9 @@ class BodyPartReader:
|
||||
encoding = encoding or self.get_charset(default='utf-8')
|
||||
return data.decode(encoding)
|
||||
|
||||
async def json(self, *, encoding: Optional[str]=None) -> Any:
|
||||
async def json(self,
|
||||
*,
|
||||
encoding: Optional[str]=None) -> Optional[Dict[str, Any]]:
|
||||
"""Like read(), but assumes that body parts contains JSON data."""
|
||||
data = await self.read(decode=True)
|
||||
if not data:
|
||||
@ -431,7 +439,7 @@ class BodyPartReader:
|
||||
return data
|
||||
|
||||
def _decode_content(self, data: bytes) -> bytes:
|
||||
encoding = cast(str, self.headers[CONTENT_ENCODING]).lower()
|
||||
encoding = self.headers.get(CONTENT_ENCODING, '').lower()
|
||||
|
||||
if encoding == 'deflate':
|
||||
return zlib.decompress(data, -zlib.MAX_WBITS)
|
||||
@ -443,7 +451,7 @@ class BodyPartReader:
|
||||
raise RuntimeError('unknown content encoding: {}'.format(encoding))
|
||||
|
||||
def _decode_content_transfer(self, data: bytes) -> bytes:
|
||||
encoding = cast(str, self.headers[CONTENT_TRANSFER_ENCODING]).lower()
|
||||
encoding = self.headers.get(CONTENT_TRANSFER_ENCODING, '').lower()
|
||||
|
||||
if encoding == 'base64':
|
||||
return base64.b64decode(data)
|
||||
@ -521,7 +529,7 @@ class MultipartReader:
|
||||
self.headers = headers
|
||||
self._boundary = ('--' + self._get_boundary()).encode()
|
||||
self._content = content
|
||||
self._last_part = None
|
||||
self._last_part = None # type: Optional[Union['MultipartReader', BodyPartReader]] # noqa
|
||||
self._at_eof = False
|
||||
self._at_bof = True
|
||||
self._unread = [] # type: List[bytes]
|
||||
@ -529,14 +537,19 @@ class MultipartReader:
|
||||
def __aiter__(self) -> 'MultipartReader':
|
||||
return self
|
||||
|
||||
async def __anext__(self) -> Any:
|
||||
async def __anext__(
|
||||
self,
|
||||
) -> Union['MultipartReader', BodyPartReader]:
|
||||
part = await self.next()
|
||||
if part is None:
|
||||
raise StopAsyncIteration # NOQA
|
||||
return part
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response: 'ClientResponse') -> Any:
|
||||
def from_response(
|
||||
cls,
|
||||
response: 'ClientResponse',
|
||||
) -> MultipartResponseWrapper:
|
||||
"""Constructs reader instance from HTTP response.
|
||||
|
||||
:param response: :class:`~aiohttp.client.ClientResponse` instance
|
||||
@ -551,11 +564,13 @@ class MultipartReader:
|
||||
"""
|
||||
return self._at_eof
|
||||
|
||||
async def next(self) -> Any:
|
||||
async def next(
|
||||
self,
|
||||
) -> Optional[Union['MultipartReader', BodyPartReader]]:
|
||||
"""Emits the next multipart body part."""
|
||||
# So, if we're at BOF, we need to skip till the boundary.
|
||||
if self._at_eof:
|
||||
return
|
||||
return None
|
||||
await self._maybe_release_last_part()
|
||||
if self._at_bof:
|
||||
await self._read_until_first_boundary()
|
||||
@ -563,7 +578,7 @@ class MultipartReader:
|
||||
else:
|
||||
await self._read_boundary()
|
||||
if self._at_eof: # we just read the last boundary, nothing to do there
|
||||
return
|
||||
return None
|
||||
self._last_part = await self.fetch_next_part()
|
||||
return self._last_part
|
||||
|
||||
@ -575,12 +590,17 @@ class MultipartReader:
|
||||
break
|
||||
await item.release()
|
||||
|
||||
async def fetch_next_part(self) -> Any:
|
||||
async def fetch_next_part(
|
||||
self,
|
||||
) -> Union['MultipartReader', BodyPartReader]:
|
||||
"""Returns the next body part reader."""
|
||||
headers = await self._read_headers()
|
||||
return self._get_part_reader(headers)
|
||||
|
||||
def _get_part_reader(self, headers: 'CIMultiDictProxy[str]') -> Any:
|
||||
def _get_part_reader(
|
||||
self,
|
||||
headers: 'CIMultiDictProxy[str]',
|
||||
) -> Union['MultipartReader', BodyPartReader]:
|
||||
"""Dispatches the response by the `Content-Type` header, returning
|
||||
suitable reader instance.
|
||||
|
||||
@ -718,6 +738,9 @@ class MultipartWriter(Payload):
|
||||
def __len__(self) -> int:
|
||||
return len(self._parts)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return True
|
||||
|
||||
_valid_tchar_regex = re.compile(br"\A[!#$%&'*+\-.^_`|~\w]+\Z")
|
||||
_invalid_qdtext_char_regex = re.compile(br"[\x00-\x08\x0A-\x1F\x7F]")
|
||||
|
||||
@ -760,7 +783,7 @@ class MultipartWriter(Payload):
|
||||
def append(
|
||||
self,
|
||||
obj: Any,
|
||||
headers: Optional['MultiMapping[str]']=None
|
||||
headers: Optional[MultiMapping[str]]=None
|
||||
) -> Payload:
|
||||
if headers is None:
|
||||
headers = CIMultiDict()
|
||||
@ -779,7 +802,10 @@ class MultipartWriter(Payload):
|
||||
def append_payload(self, payload: Payload) -> Payload:
|
||||
"""Adds a new body part to multipart writer."""
|
||||
# compression
|
||||
encoding = payload.headers.get(CONTENT_ENCODING, '').lower() # type: Optional[str] # noqa
|
||||
encoding = payload.headers.get(
|
||||
CONTENT_ENCODING,
|
||||
'',
|
||||
).lower() # type: Optional[str]
|
||||
if encoding and encoding not in ('deflate', 'gzip', 'identity'):
|
||||
raise RuntimeError('unknown content encoding: {}'.format(encoding))
|
||||
if encoding == 'identity':
|
||||
@ -787,7 +813,9 @@ class MultipartWriter(Payload):
|
||||
|
||||
# te encoding
|
||||
te_encoding = payload.headers.get(
|
||||
CONTENT_TRANSFER_ENCODING, '').lower() # type: Optional[str] # noqa
|
||||
CONTENT_TRANSFER_ENCODING,
|
||||
'',
|
||||
).lower() # type: Optional[str]
|
||||
if te_encoding not in ('', 'base64', 'quoted-printable', 'binary'):
|
||||
raise RuntimeError('unknown content transfer encoding: {}'
|
||||
''.format(te_encoding))
|
||||
@ -805,7 +833,7 @@ class MultipartWriter(Payload):
|
||||
def append_json(
|
||||
self,
|
||||
obj: Any,
|
||||
headers: Optional['MultiMapping[str]']=None
|
||||
headers: Optional[MultiMapping[str]]=None
|
||||
) -> Payload:
|
||||
"""Helper to append JSON part."""
|
||||
if headers is None:
|
||||
@ -817,7 +845,7 @@ class MultipartWriter(Payload):
|
||||
self,
|
||||
obj: Union[Sequence[Tuple[str, str]],
|
||||
Mapping[str, str]],
|
||||
headers: Optional['MultiMapping[str]']=None
|
||||
headers: Optional[MultiMapping[str]]=None
|
||||
) -> Payload:
|
||||
"""Helper to append form urlencoded part."""
|
||||
assert isinstance(obj, (Sequence, Mapping))
|
||||
@ -836,9 +864,6 @@ class MultipartWriter(Payload):
|
||||
@property
|
||||
def size(self) -> Optional[int]:
|
||||
"""Size of the payload."""
|
||||
if not self._parts:
|
||||
return 0
|
||||
|
||||
total = 0
|
||||
for part, encoding, te_encoding in self._parts:
|
||||
if encoding or te_encoding or part.size is None:
|
||||
@ -856,9 +881,6 @@ class MultipartWriter(Payload):
|
||||
async def write(self, writer: Any,
|
||||
close_boundary: bool=True) -> None:
|
||||
"""Write body."""
|
||||
if not self._parts:
|
||||
return
|
||||
|
||||
for part, encoding, te_encoding in self._parts:
|
||||
await writer.write(b'--' + self._boundary + b'\r\n')
|
||||
await writer.write(part._binary_headers)
|
||||
|
@ -207,7 +207,7 @@ class BytesPayload(Payload):
|
||||
*args: Any,
|
||||
**kwargs: Any) -> None:
|
||||
if not isinstance(value, (bytes, bytearray, memoryview)):
|
||||
raise TypeError("value argument must be byte-ish, not (!r)"
|
||||
raise TypeError("value argument must be byte-ish, not {!r}"
|
||||
.format(type(value)))
|
||||
|
||||
if 'content_type' not in kwargs:
|
||||
|
@ -5,7 +5,7 @@ from collections.abc import Callable
|
||||
|
||||
import pytest
|
||||
|
||||
from aiohttp.helpers import isasyncgenfunction
|
||||
from aiohttp.helpers import PY_37, isasyncgenfunction
|
||||
from aiohttp.web import Application
|
||||
|
||||
from .test_utils import (
|
||||
@ -161,7 +161,8 @@ def pytest_pyfunc_call(pyfuncitem): # type: ignore
|
||||
"""
|
||||
fast = pyfuncitem.config.getoption("--aiohttp-fast")
|
||||
if asyncio.iscoroutinefunction(pyfuncitem.function):
|
||||
existing_loop = pyfuncitem.funcargs.get('loop', None)
|
||||
existing_loop = pyfuncitem.funcargs.get('proactor_loop')\
|
||||
or pyfuncitem.funcargs.get('loop', None)
|
||||
with _runtime_warning_context():
|
||||
with _passthrough_loop_context(existing_loop, fast=fast) as _loop:
|
||||
testargs = {arg: pyfuncitem.funcargs[arg]
|
||||
@ -216,6 +217,20 @@ def loop(loop_factory, fast, loop_debug): # type: ignore
|
||||
yield _loop
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def proactor_loop(): # type: ignore
|
||||
if not PY_37:
|
||||
policy = asyncio.get_event_loop_policy()
|
||||
policy._loop_factory = asyncio.ProactorEventLoop # type: ignore
|
||||
else:
|
||||
policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore
|
||||
asyncio.set_event_loop_policy(policy)
|
||||
|
||||
with loop_context(policy.new_event_loop) as _loop:
|
||||
asyncio.set_event_loop(_loop)
|
||||
yield _loop
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def unused_port(aiohttp_unused_port): # type: ignore # pragma: no cover
|
||||
warnings.warn("Deprecated, use aiohttp_unused_port fixture instead",
|
||||
|
@ -2,7 +2,6 @@ from typing import Any, Generic, TypeVar
|
||||
|
||||
from aiohttp.frozenlist import FrozenList
|
||||
|
||||
|
||||
__all__ = ('Signal',)
|
||||
|
||||
|
||||
|
@ -13,7 +13,6 @@ try: # pragma: no cover
|
||||
except ImportError:
|
||||
from typing_extensions import Deque # noqa
|
||||
|
||||
|
||||
__all__ = (
|
||||
'EMPTY_PAYLOAD', 'EofStream', 'StreamReader', 'DataQueue',
|
||||
'FlowControlDataQueue')
|
||||
@ -122,8 +121,8 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
self._buffer = collections.deque() # type: Deque[bytes]
|
||||
self._buffer_offset = 0
|
||||
self._eof = False
|
||||
self._waiter = None # type: Optional[asyncio.Future[bool]]
|
||||
self._eof_waiter = None # type: Optional[asyncio.Future[bool]]
|
||||
self._waiter = None # type: Optional[asyncio.Future[None]]
|
||||
self._eof_waiter = None # type: Optional[asyncio.Future[None]]
|
||||
self._exception = None # type: Optional[BaseException]
|
||||
self._timer = timer
|
||||
self._eof_callbacks = [] # type: List[Callable[[], None]]
|
||||
@ -156,8 +155,8 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
|
||||
waiter = self._eof_waiter
|
||||
if waiter is not None:
|
||||
set_exception(waiter, exc)
|
||||
self._eof_waiter = None
|
||||
set_exception(waiter, exc)
|
||||
|
||||
def on_eof(self, callback: Callable[[], None]) -> None:
|
||||
if self._eof:
|
||||
@ -174,12 +173,12 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
self._waiter = None
|
||||
set_result(waiter, True)
|
||||
set_result(waiter, None)
|
||||
|
||||
waiter = self._eof_waiter
|
||||
if waiter is not None:
|
||||
self._eof_waiter = None
|
||||
set_result(waiter, True)
|
||||
set_result(waiter, None)
|
||||
|
||||
for cb in self._eof_callbacks:
|
||||
try:
|
||||
@ -240,7 +239,7 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
self._waiter = None
|
||||
set_result(waiter, False)
|
||||
set_result(waiter, None)
|
||||
|
||||
if (self._size > self._high_water and
|
||||
not self._protocol._reading_paused):
|
||||
@ -279,7 +278,7 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
self._waiter = None
|
||||
set_result(waiter, False)
|
||||
set_result(waiter, None)
|
||||
|
||||
async def _wait(self, func_name: str) -> None:
|
||||
# StreamReader uses a future to link the protocol feed_data() method
|
||||
@ -388,31 +387,29 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
of the data corresponds to the end of a HTTP chunk , otherwise it is
|
||||
always False.
|
||||
"""
|
||||
if self._exception is not None:
|
||||
raise self._exception
|
||||
while True:
|
||||
if self._exception is not None:
|
||||
raise self._exception
|
||||
|
||||
if not self._buffer and not self._eof:
|
||||
if (self._http_chunk_splits and
|
||||
self._cursor == self._http_chunk_splits[0]):
|
||||
# end of http chunk without available data
|
||||
self._http_chunk_splits = self._http_chunk_splits[1:]
|
||||
return (b"", True)
|
||||
await self._wait('readchunk')
|
||||
|
||||
if not self._buffer and not self._http_chunk_splits:
|
||||
# end of file
|
||||
return (b"", False)
|
||||
elif self._http_chunk_splits is not None:
|
||||
while self._http_chunk_splits:
|
||||
pos = self._http_chunk_splits[0]
|
||||
self._http_chunk_splits = self._http_chunk_splits[1:]
|
||||
pos = self._http_chunk_splits.pop(0)
|
||||
if pos == self._cursor:
|
||||
return (b"", True)
|
||||
if pos > self._cursor:
|
||||
return (self._read_nowait(pos-self._cursor), True)
|
||||
return (self._read_nowait(-1), False)
|
||||
else:
|
||||
return (self._read_nowait_chunk(-1), False)
|
||||
internal_logger.warning('Skipping HTTP chunk end due to data '
|
||||
'consumption beyond chunk boundary')
|
||||
|
||||
if self._buffer:
|
||||
return (self._read_nowait_chunk(-1), False)
|
||||
# return (self._read_nowait(-1), False)
|
||||
|
||||
if self._eof:
|
||||
# Special case for signifying EOF.
|
||||
# (b'', True) is not a final return value actually.
|
||||
return (b'', False)
|
||||
|
||||
await self._wait('readchunk')
|
||||
|
||||
async def readexactly(self, n: int) -> bytes:
|
||||
if self._exception is not None:
|
||||
@ -423,7 +420,7 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
block = await self.read(n)
|
||||
if not block:
|
||||
partial = b''.join(blocks)
|
||||
raise asyncio.streams.IncompleteReadError(
|
||||
raise asyncio.IncompleteReadError(
|
||||
partial, len(partial) + n)
|
||||
blocks.append(block)
|
||||
n -= len(block)
|
||||
@ -462,11 +459,17 @@ class StreamReader(AsyncStreamReaderMixin):
|
||||
self._size -= len(data)
|
||||
self._cursor += len(data)
|
||||
|
||||
chunk_splits = self._http_chunk_splits
|
||||
# Prevent memory leak: drop useless chunk splits
|
||||
while chunk_splits and chunk_splits[0] < self._cursor:
|
||||
chunk_splits.pop(0)
|
||||
|
||||
if self._size < self._low_water and self._protocol._reading_paused:
|
||||
self._protocol.resume_reading()
|
||||
return data
|
||||
|
||||
def _read_nowait(self, n: int) -> bytes:
|
||||
""" Read not more than n bytes, or whole buffer is n == -1 """
|
||||
chunks = []
|
||||
|
||||
while self._buffer:
|
||||
@ -522,7 +525,7 @@ class EmptyStreamReader(AsyncStreamReaderMixin):
|
||||
return (b'', True)
|
||||
|
||||
async def readexactly(self, n: int) -> bytes:
|
||||
raise asyncio.streams.IncompleteReadError(b'', n)
|
||||
raise asyncio.IncompleteReadError(b'', n)
|
||||
|
||||
def read_nowait(self) -> bytes:
|
||||
return b''
|
||||
@ -537,7 +540,7 @@ class DataQueue(Generic[_T]):
|
||||
def __init__(self, loop: asyncio.AbstractEventLoop) -> None:
|
||||
self._loop = loop
|
||||
self._eof = False
|
||||
self._waiter = None # type: Optional[asyncio.Future[bool]]
|
||||
self._waiter = None # type: Optional[asyncio.Future[None]]
|
||||
self._exception = None # type: Optional[BaseException]
|
||||
self._size = 0
|
||||
self._buffer = collections.deque() # type: Deque[Tuple[_T, int]]
|
||||
@ -560,8 +563,8 @@ class DataQueue(Generic[_T]):
|
||||
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
set_exception(waiter, exc)
|
||||
self._waiter = None
|
||||
set_exception(waiter, exc)
|
||||
|
||||
def feed_data(self, data: _T, size: int=0) -> None:
|
||||
self._size += size
|
||||
@ -570,7 +573,7 @@ class DataQueue(Generic[_T]):
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
self._waiter = None
|
||||
set_result(waiter, True)
|
||||
set_result(waiter, None)
|
||||
|
||||
def feed_eof(self) -> None:
|
||||
self._eof = True
|
||||
@ -578,7 +581,7 @@ class DataQueue(Generic[_T]):
|
||||
waiter = self._waiter
|
||||
if waiter is not None:
|
||||
self._waiter = None
|
||||
set_result(waiter, False)
|
||||
set_result(waiter, None)
|
||||
|
||||
async def read(self) -> _T:
|
||||
if not self._buffer and not self._eof:
|
||||
|
@ -4,6 +4,7 @@ import asyncio
|
||||
import contextlib
|
||||
import functools
|
||||
import gc
|
||||
import inspect
|
||||
import socket
|
||||
import sys
|
||||
import unittest
|
||||
@ -74,6 +75,8 @@ def unused_port() -> int:
|
||||
|
||||
|
||||
class BaseTestServer(ABC):
|
||||
__test__ = False
|
||||
|
||||
def __init__(self,
|
||||
*,
|
||||
scheme: Union[str, object]=sentinel,
|
||||
@ -230,6 +233,7 @@ class TestClient:
|
||||
To write functional tests for aiohttp based servers.
|
||||
|
||||
"""
|
||||
__test__ = False
|
||||
|
||||
def __init__(self, server: BaseTestServer, *,
|
||||
cookie_jar: Optional[AbstractCookieJar]=None,
|
||||
@ -282,15 +286,8 @@ class TestClient:
|
||||
def make_url(self, path: str) -> URL:
|
||||
return self._server.make_url(path)
|
||||
|
||||
async def request(self, method: str, path: str,
|
||||
**kwargs: Any) -> ClientResponse:
|
||||
"""Routes a request to tested http server.
|
||||
|
||||
The interface is identical to aiohttp.ClientSession.request,
|
||||
except the loop kwarg is overridden by the instance used by the
|
||||
test server.
|
||||
|
||||
"""
|
||||
async def _request(self, method: str, path: str,
|
||||
**kwargs: Any) -> ClientResponse:
|
||||
resp = await self._session.request(
|
||||
method, self.make_url(path), **kwargs
|
||||
)
|
||||
@ -298,46 +295,59 @@ class TestClient:
|
||||
self._responses.append(resp)
|
||||
return resp
|
||||
|
||||
def request(self, method: str, path: str,
|
||||
**kwargs: Any) -> _RequestContextManager:
|
||||
"""Routes a request to tested http server.
|
||||
|
||||
The interface is identical to aiohttp.ClientSession.request,
|
||||
except the loop kwarg is overridden by the instance used by the
|
||||
test server.
|
||||
|
||||
"""
|
||||
return _RequestContextManager(
|
||||
self._request(method, path, **kwargs)
|
||||
)
|
||||
|
||||
def get(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP GET request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_GET, path, **kwargs)
|
||||
self._request(hdrs.METH_GET, path, **kwargs)
|
||||
)
|
||||
|
||||
def post(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP POST request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_POST, path, **kwargs)
|
||||
self._request(hdrs.METH_POST, path, **kwargs)
|
||||
)
|
||||
|
||||
def options(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP OPTIONS request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_OPTIONS, path, **kwargs)
|
||||
self._request(hdrs.METH_OPTIONS, path, **kwargs)
|
||||
)
|
||||
|
||||
def head(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP HEAD request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_HEAD, path, **kwargs)
|
||||
self._request(hdrs.METH_HEAD, path, **kwargs)
|
||||
)
|
||||
|
||||
def put(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP PUT request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_PUT, path, **kwargs)
|
||||
self._request(hdrs.METH_PUT, path, **kwargs)
|
||||
)
|
||||
|
||||
def patch(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP PATCH request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_PATCH, path, **kwargs)
|
||||
self._request(hdrs.METH_PATCH, path, **kwargs)
|
||||
)
|
||||
|
||||
def delete(self, path: str, **kwargs: Any) -> _RequestContextManager:
|
||||
"""Perform an HTTP PATCH request."""
|
||||
return _RequestContextManager(
|
||||
self.request(hdrs.METH_DELETE, path, **kwargs)
|
||||
self._request(hdrs.METH_DELETE, path, **kwargs)
|
||||
)
|
||||
|
||||
def ws_connect(self, path: str, **kwargs: Any) -> _WSRequestContextManager:
|
||||
@ -650,10 +660,11 @@ def make_mocked_request(method: str, path: str,
|
||||
def make_mocked_coro(return_value: Any=sentinel,
|
||||
raise_exception: Any=sentinel) -> Any:
|
||||
"""Creates a coroutine mock."""
|
||||
@asyncio.coroutine
|
||||
def mock_coro(*args: Any, **kwargs: Any) -> Any:
|
||||
async def mock_coro(*args: Any, **kwargs: Any) -> Any:
|
||||
if raise_exception is not sentinel:
|
||||
raise raise_exception
|
||||
return return_value
|
||||
if not inspect.isawaitable(return_value):
|
||||
return return_value
|
||||
await return_value
|
||||
|
||||
return mock.Mock(wraps=mock_coro)
|
||||
|
@ -1,5 +1,5 @@
|
||||
from types import SimpleNamespace
|
||||
from typing import TYPE_CHECKING, Awaitable, Callable, Type
|
||||
from typing import TYPE_CHECKING, Awaitable, Callable, Type, Union
|
||||
|
||||
import attr
|
||||
from multidict import CIMultiDict # noqa
|
||||
@ -11,7 +11,25 @@ from .signals import Signal
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from .client import ClientSession # noqa
|
||||
|
||||
_Signal = Signal[Callable[['TraceConfig'], Awaitable[None]]]
|
||||
_SignalArgs = Union[
|
||||
'TraceRequestStartParams',
|
||||
'TraceRequestEndParams',
|
||||
'TraceRequestExceptionParams',
|
||||
'TraceConnectionQueuedStartParams',
|
||||
'TraceConnectionQueuedEndParams',
|
||||
'TraceConnectionCreateStartParams',
|
||||
'TraceConnectionCreateEndParams',
|
||||
'TraceConnectionReuseconnParams',
|
||||
'TraceDnsResolveHostStartParams',
|
||||
'TraceDnsResolveHostEndParams',
|
||||
'TraceDnsCacheHitParams',
|
||||
'TraceDnsCacheMissParams',
|
||||
'TraceRequestRedirectParams',
|
||||
'TraceRequestChunkSentParams',
|
||||
'TraceResponseChunkReceivedParams',
|
||||
]
|
||||
_Signal = Signal[Callable[[ClientSession, SimpleNamespace, _SignalArgs],
|
||||
Awaitable[None]]]
|
||||
else:
|
||||
_Signal = Signal
|
||||
|
||||
|
@ -12,7 +12,13 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy
|
||||
from multidict import (
|
||||
CIMultiDict,
|
||||
CIMultiDictProxy,
|
||||
MultiDict,
|
||||
MultiDictProxy,
|
||||
istr,
|
||||
)
|
||||
from yarl import URL
|
||||
|
||||
DEFAULT_JSON_ENCODER = json.dumps
|
||||
@ -33,7 +39,8 @@ else:
|
||||
Byteish = Union[bytes, bytearray, memoryview]
|
||||
JSONEncoder = Callable[[Any], str]
|
||||
JSONDecoder = Callable[[str], Any]
|
||||
LooseHeaders = Union[Mapping[str, str], _CIMultiDict, _CIMultiDictProxy]
|
||||
LooseHeaders = Union[Mapping[Union[str, istr], str], _CIMultiDict,
|
||||
_CIMultiDictProxy]
|
||||
RawHeaders = Tuple[Tuple[bytes, bytes], ...]
|
||||
StrOrURL = Union[str, URL]
|
||||
LooseCookies = Union[Iterable[Tuple[str, 'BaseCookie[str]']],
|
||||
|
@ -10,121 +10,138 @@ from typing import Any, Awaitable, Callable, List, Optional, Type, Union, cast
|
||||
from .abc import AbstractAccessLogger
|
||||
from .helpers import all_tasks
|
||||
from .log import access_logger
|
||||
from .web_app import Application, CleanupError
|
||||
from .web_app import Application as Application
|
||||
from .web_app import CleanupError as CleanupError
|
||||
from .web_exceptions import HTTPAccepted as HTTPAccepted
|
||||
from .web_exceptions import HTTPBadGateway as HTTPBadGateway
|
||||
from .web_exceptions import HTTPBadRequest as HTTPBadRequest
|
||||
from .web_exceptions import HTTPClientError as HTTPClientError
|
||||
from .web_exceptions import HTTPConflict as HTTPConflict
|
||||
from .web_exceptions import HTTPCreated as HTTPCreated
|
||||
from .web_exceptions import HTTPError as HTTPError
|
||||
from .web_exceptions import HTTPException as HTTPException
|
||||
from .web_exceptions import HTTPExpectationFailed as HTTPExpectationFailed
|
||||
from .web_exceptions import HTTPFailedDependency as HTTPFailedDependency
|
||||
from .web_exceptions import HTTPForbidden as HTTPForbidden
|
||||
from .web_exceptions import HTTPFound as HTTPFound
|
||||
from .web_exceptions import HTTPGatewayTimeout as HTTPGatewayTimeout
|
||||
from .web_exceptions import HTTPGone as HTTPGone
|
||||
from .web_exceptions import HTTPInsufficientStorage as HTTPInsufficientStorage
|
||||
from .web_exceptions import HTTPInternalServerError as HTTPInternalServerError
|
||||
from .web_exceptions import HTTPLengthRequired as HTTPLengthRequired
|
||||
from .web_exceptions import HTTPMethodNotAllowed as HTTPMethodNotAllowed
|
||||
from .web_exceptions import HTTPMisdirectedRequest as HTTPMisdirectedRequest
|
||||
from .web_exceptions import HTTPMovedPermanently as HTTPMovedPermanently
|
||||
from .web_exceptions import HTTPMultipleChoices as HTTPMultipleChoices
|
||||
from .web_exceptions import (
|
||||
HTTPAccepted,
|
||||
HTTPBadGateway,
|
||||
HTTPBadRequest,
|
||||
HTTPClientError,
|
||||
HTTPConflict,
|
||||
HTTPCreated,
|
||||
HTTPError,
|
||||
HTTPException,
|
||||
HTTPExpectationFailed,
|
||||
HTTPFailedDependency,
|
||||
HTTPForbidden,
|
||||
HTTPFound,
|
||||
HTTPGatewayTimeout,
|
||||
HTTPGone,
|
||||
HTTPInsufficientStorage,
|
||||
HTTPInternalServerError,
|
||||
HTTPLengthRequired,
|
||||
HTTPMethodNotAllowed,
|
||||
HTTPMisdirectedRequest,
|
||||
HTTPMovedPermanently,
|
||||
HTTPMultipleChoices,
|
||||
HTTPNetworkAuthenticationRequired,
|
||||
HTTPNoContent,
|
||||
HTTPNonAuthoritativeInformation,
|
||||
HTTPNotAcceptable,
|
||||
HTTPNotExtended,
|
||||
HTTPNotFound,
|
||||
HTTPNotImplemented,
|
||||
HTTPNotModified,
|
||||
HTTPOk,
|
||||
HTTPPartialContent,
|
||||
HTTPPaymentRequired,
|
||||
HTTPPermanentRedirect,
|
||||
HTTPPreconditionFailed,
|
||||
HTTPPreconditionRequired,
|
||||
HTTPProxyAuthenticationRequired,
|
||||
HTTPRedirection,
|
||||
HTTPRequestEntityTooLarge,
|
||||
HTTPRequestHeaderFieldsTooLarge,
|
||||
HTTPRequestRangeNotSatisfiable,
|
||||
HTTPRequestTimeout,
|
||||
HTTPRequestURITooLong,
|
||||
HTTPResetContent,
|
||||
HTTPSeeOther,
|
||||
HTTPServerError,
|
||||
HTTPServiceUnavailable,
|
||||
HTTPSuccessful,
|
||||
HTTPTemporaryRedirect,
|
||||
HTTPTooManyRequests,
|
||||
HTTPUnauthorized,
|
||||
HTTPUnavailableForLegalReasons,
|
||||
HTTPUnprocessableEntity,
|
||||
HTTPUnsupportedMediaType,
|
||||
HTTPUpgradeRequired,
|
||||
HTTPUseProxy,
|
||||
HTTPVariantAlsoNegotiates,
|
||||
HTTPVersionNotSupported,
|
||||
HTTPNetworkAuthenticationRequired as HTTPNetworkAuthenticationRequired,
|
||||
)
|
||||
from .web_fileresponse import FileResponse
|
||||
from .web_exceptions import HTTPNoContent as HTTPNoContent
|
||||
from .web_exceptions import (
|
||||
HTTPNonAuthoritativeInformation as HTTPNonAuthoritativeInformation,
|
||||
)
|
||||
from .web_exceptions import HTTPNotAcceptable as HTTPNotAcceptable
|
||||
from .web_exceptions import HTTPNotExtended as HTTPNotExtended
|
||||
from .web_exceptions import HTTPNotFound as HTTPNotFound
|
||||
from .web_exceptions import HTTPNotImplemented as HTTPNotImplemented
|
||||
from .web_exceptions import HTTPNotModified as HTTPNotModified
|
||||
from .web_exceptions import HTTPOk as HTTPOk
|
||||
from .web_exceptions import HTTPPartialContent as HTTPPartialContent
|
||||
from .web_exceptions import HTTPPaymentRequired as HTTPPaymentRequired
|
||||
from .web_exceptions import HTTPPermanentRedirect as HTTPPermanentRedirect
|
||||
from .web_exceptions import HTTPPreconditionFailed as HTTPPreconditionFailed
|
||||
from .web_exceptions import (
|
||||
HTTPPreconditionRequired as HTTPPreconditionRequired,
|
||||
)
|
||||
from .web_exceptions import (
|
||||
HTTPProxyAuthenticationRequired as HTTPProxyAuthenticationRequired,
|
||||
)
|
||||
from .web_exceptions import HTTPRedirection as HTTPRedirection
|
||||
from .web_exceptions import (
|
||||
HTTPRequestEntityTooLarge as HTTPRequestEntityTooLarge,
|
||||
)
|
||||
from .web_exceptions import (
|
||||
HTTPRequestHeaderFieldsTooLarge as HTTPRequestHeaderFieldsTooLarge,
|
||||
)
|
||||
from .web_exceptions import (
|
||||
HTTPRequestRangeNotSatisfiable as HTTPRequestRangeNotSatisfiable,
|
||||
)
|
||||
from .web_exceptions import HTTPRequestTimeout as HTTPRequestTimeout
|
||||
from .web_exceptions import HTTPRequestURITooLong as HTTPRequestURITooLong
|
||||
from .web_exceptions import HTTPResetContent as HTTPResetContent
|
||||
from .web_exceptions import HTTPSeeOther as HTTPSeeOther
|
||||
from .web_exceptions import HTTPServerError as HTTPServerError
|
||||
from .web_exceptions import HTTPServiceUnavailable as HTTPServiceUnavailable
|
||||
from .web_exceptions import HTTPSuccessful as HTTPSuccessful
|
||||
from .web_exceptions import HTTPTemporaryRedirect as HTTPTemporaryRedirect
|
||||
from .web_exceptions import HTTPTooManyRequests as HTTPTooManyRequests
|
||||
from .web_exceptions import HTTPUnauthorized as HTTPUnauthorized
|
||||
from .web_exceptions import (
|
||||
HTTPUnavailableForLegalReasons as HTTPUnavailableForLegalReasons,
|
||||
)
|
||||
from .web_exceptions import HTTPUnprocessableEntity as HTTPUnprocessableEntity
|
||||
from .web_exceptions import (
|
||||
HTTPUnsupportedMediaType as HTTPUnsupportedMediaType,
|
||||
)
|
||||
from .web_exceptions import HTTPUpgradeRequired as HTTPUpgradeRequired
|
||||
from .web_exceptions import HTTPUseProxy as HTTPUseProxy
|
||||
from .web_exceptions import (
|
||||
HTTPVariantAlsoNegotiates as HTTPVariantAlsoNegotiates,
|
||||
)
|
||||
from .web_exceptions import HTTPVersionNotSupported as HTTPVersionNotSupported
|
||||
from .web_fileresponse import FileResponse as FileResponse
|
||||
from .web_log import AccessLogger
|
||||
from .web_middlewares import middleware, normalize_path_middleware
|
||||
from .web_protocol import (
|
||||
PayloadAccessError,
|
||||
RequestHandler,
|
||||
RequestPayloadError,
|
||||
from .web_middlewares import middleware as middleware
|
||||
from .web_middlewares import (
|
||||
normalize_path_middleware as normalize_path_middleware,
|
||||
)
|
||||
from .web_request import BaseRequest, FileField, Request
|
||||
from .web_response import (
|
||||
ContentCoding,
|
||||
Response,
|
||||
StreamResponse,
|
||||
json_response,
|
||||
)
|
||||
from .web_routedef import (
|
||||
AbstractRouteDef,
|
||||
RouteDef,
|
||||
RouteTableDef,
|
||||
StaticDef,
|
||||
delete,
|
||||
get,
|
||||
head,
|
||||
options,
|
||||
patch,
|
||||
post,
|
||||
put,
|
||||
route,
|
||||
static,
|
||||
view,
|
||||
)
|
||||
from .web_runner import (
|
||||
AppRunner,
|
||||
BaseRunner,
|
||||
BaseSite,
|
||||
GracefulExit,
|
||||
ServerRunner,
|
||||
SockSite,
|
||||
TCPSite,
|
||||
UnixSite,
|
||||
)
|
||||
from .web_server import Server
|
||||
from .web_urldispatcher import (
|
||||
AbstractResource,
|
||||
AbstractRoute,
|
||||
DynamicResource,
|
||||
PlainResource,
|
||||
Resource,
|
||||
ResourceRoute,
|
||||
StaticResource,
|
||||
UrlDispatcher,
|
||||
UrlMappingMatchInfo,
|
||||
View,
|
||||
)
|
||||
from .web_ws import WebSocketReady, WebSocketResponse, WSMsgType
|
||||
from .web_protocol import PayloadAccessError as PayloadAccessError
|
||||
from .web_protocol import RequestHandler as RequestHandler
|
||||
from .web_protocol import RequestPayloadError as RequestPayloadError
|
||||
from .web_request import BaseRequest as BaseRequest
|
||||
from .web_request import FileField as FileField
|
||||
from .web_request import Request as Request
|
||||
from .web_response import ContentCoding as ContentCoding
|
||||
from .web_response import Response as Response
|
||||
from .web_response import StreamResponse as StreamResponse
|
||||
from .web_response import json_response as json_response
|
||||
from .web_routedef import AbstractRouteDef as AbstractRouteDef
|
||||
from .web_routedef import RouteDef as RouteDef
|
||||
from .web_routedef import RouteTableDef as RouteTableDef
|
||||
from .web_routedef import StaticDef as StaticDef
|
||||
from .web_routedef import delete as delete
|
||||
from .web_routedef import get as get
|
||||
from .web_routedef import head as head
|
||||
from .web_routedef import options as options
|
||||
from .web_routedef import patch as patch
|
||||
from .web_routedef import post as post
|
||||
from .web_routedef import put as put
|
||||
from .web_routedef import route as route
|
||||
from .web_routedef import static as static
|
||||
from .web_routedef import view as view
|
||||
from .web_runner import AppRunner as AppRunner
|
||||
from .web_runner import BaseRunner as BaseRunner
|
||||
from .web_runner import BaseSite as BaseSite
|
||||
from .web_runner import GracefulExit as GracefulExit
|
||||
from .web_runner import NamedPipeSite as NamedPipeSite
|
||||
from .web_runner import ServerRunner as ServerRunner
|
||||
from .web_runner import SockSite as SockSite
|
||||
from .web_runner import TCPSite as TCPSite
|
||||
from .web_runner import UnixSite as UnixSite
|
||||
from .web_server import Server as Server
|
||||
from .web_urldispatcher import AbstractResource as AbstractResource
|
||||
from .web_urldispatcher import AbstractRoute as AbstractRoute
|
||||
from .web_urldispatcher import DynamicResource as DynamicResource
|
||||
from .web_urldispatcher import PlainResource as PlainResource
|
||||
from .web_urldispatcher import Resource as Resource
|
||||
from .web_urldispatcher import ResourceRoute as ResourceRoute
|
||||
from .web_urldispatcher import StaticResource as StaticResource
|
||||
from .web_urldispatcher import UrlDispatcher as UrlDispatcher
|
||||
from .web_urldispatcher import UrlMappingMatchInfo as UrlMappingMatchInfo
|
||||
from .web_urldispatcher import View as View
|
||||
from .web_ws import WebSocketReady as WebSocketReady
|
||||
from .web_ws import WebSocketResponse as WebSocketResponse
|
||||
from .web_ws import WSMsgType as WSMsgType
|
||||
|
||||
__all__ = (
|
||||
# web_app
|
||||
@ -230,6 +247,7 @@ __all__ = (
|
||||
'SockSite',
|
||||
'TCPSite',
|
||||
'UnixSite',
|
||||
'NamedPipeSite',
|
||||
# web_server
|
||||
'Server',
|
||||
# web_urldispatcher
|
||||
|
@ -88,7 +88,7 @@ class Application(MutableMapping[str, Any]):
|
||||
def __init__(self, *,
|
||||
logger: logging.Logger=web_logger,
|
||||
router: Optional[UrlDispatcher]=None,
|
||||
middlewares: Sequence[_Middleware]=(),
|
||||
middlewares: Iterable[_Middleware]=(),
|
||||
handler_args: Mapping[str, Any]=None,
|
||||
client_max_size: int=1024**2,
|
||||
loop: Optional[asyncio.AbstractEventLoop]=None,
|
||||
@ -466,6 +466,9 @@ class Application(MutableMapping[str, Any]):
|
||||
def __repr__(self) -> str:
|
||||
return "<Application 0x{:x}>".format(id(self))
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class CleanupError(RuntimeError):
|
||||
@property
|
||||
|
@ -1,6 +1,8 @@
|
||||
import warnings
|
||||
from typing import Any, Dict, Iterable, List, Optional, Set # noqa
|
||||
|
||||
from yarl import URL
|
||||
|
||||
from .typedefs import LooseHeaders, StrOrURL
|
||||
from .web_response import Response
|
||||
|
||||
@ -161,7 +163,7 @@ class _HTTPMove(HTTPRedirection):
|
||||
raise ValueError("HTTP redirects need a location to redirect to.")
|
||||
super().__init__(headers=headers, reason=reason,
|
||||
body=body, text=text, content_type=content_type)
|
||||
self.headers['Location'] = str(location)
|
||||
self.headers['Location'] = str(URL(location))
|
||||
self.location = location
|
||||
|
||||
|
||||
|
@ -24,7 +24,6 @@ from .log import server_logger
|
||||
from .typedefs import LooseHeaders
|
||||
from .web_exceptions import (
|
||||
HTTPNotModified,
|
||||
HTTPOk,
|
||||
HTTPPartialContent,
|
||||
HTTPPreconditionFailed,
|
||||
HTTPRequestRangeNotSatisfiable,
|
||||
@ -245,7 +244,7 @@ class FileResponse(StreamResponse):
|
||||
encoding = 'gzip' if gzip else None
|
||||
should_set_ct = False
|
||||
|
||||
status = HTTPOk.status_code
|
||||
status = self._status
|
||||
file_size = st.st_size
|
||||
count = file_size
|
||||
|
||||
@ -318,8 +317,8 @@ class FileResponse(StreamResponse):
|
||||
status = HTTPPartialContent.status_code
|
||||
# Even though you are sending the whole file, you should still
|
||||
# return a HTTP 206 for a Range request.
|
||||
self.set_status(status)
|
||||
|
||||
self.set_status(status)
|
||||
if should_set_ct:
|
||||
self.content_type = ct # type: ignore
|
||||
if encoding:
|
||||
@ -337,8 +336,11 @@ class FileResponse(StreamResponse):
|
||||
self.headers[hdrs.CONTENT_RANGE] = 'bytes {0}-{1}/{2}'.format(
|
||||
real_start, real_start + count - 1, file_size)
|
||||
|
||||
with (await loop.run_in_executor(None, filepath.open, 'rb')) as fobj:
|
||||
if start: # be aware that start could be None or int=0 here.
|
||||
await loop.run_in_executor(None, fobj.seek, start)
|
||||
fobj = await loop.run_in_executor(None, filepath.open, 'rb')
|
||||
if start: # be aware that start could be None or int=0 here.
|
||||
await loop.run_in_executor(None, fobj.seek, start)
|
||||
|
||||
try:
|
||||
return await self._sendfile(request, fobj, count)
|
||||
finally:
|
||||
await loop.run_in_executor(None, fobj.close)
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
import os
|
||||
import re
|
||||
from collections import namedtuple
|
||||
from typing import Callable, Dict, Iterable, List, Tuple # noqa
|
||||
from typing import Any, Callable, Dict, Iterable, List, Tuple # noqa
|
||||
|
||||
from .abc import AbstractAccessLogger
|
||||
from .web_request import BaseRequest
|
||||
@ -226,9 +226,9 @@ class AccessLogger(AbstractAccessLogger):
|
||||
extra[key] = value
|
||||
else:
|
||||
k1, k2 = key
|
||||
dct = extra.get(k1, {})
|
||||
dct[k2] = value # type: ignore
|
||||
extra[k1] = dct # type: ignore
|
||||
dct = extra.get(k1, {}) # type: Any
|
||||
dct[k2] = value
|
||||
extra[k1] = dct
|
||||
|
||||
self.logger.info(self._log_format % tuple(values), extra=extra)
|
||||
except Exception:
|
||||
|
@ -1,7 +1,7 @@
|
||||
import re
|
||||
from typing import TYPE_CHECKING, Awaitable, Callable, Tuple, Type, TypeVar
|
||||
|
||||
from .web_exceptions import HTTPMovedPermanently, _HTTPMove
|
||||
from .web_exceptions import HTTPPermanentRedirect, _HTTPMove
|
||||
from .web_request import Request
|
||||
from .web_response import StreamResponse
|
||||
from .web_urldispatcher import SystemRoute
|
||||
@ -42,7 +42,7 @@ _Middleware = Callable[[Request, _Handler], Awaitable[StreamResponse]]
|
||||
def normalize_path_middleware(
|
||||
*, append_slash: bool=True, remove_slash: bool=False,
|
||||
merge_slashes: bool=True,
|
||||
redirect_class: Type[_HTTPMove]=HTTPMovedPermanently) -> _Middleware:
|
||||
redirect_class: Type[_HTTPMove]=HTTPPermanentRedirect) -> _Middleware:
|
||||
"""
|
||||
Middleware factory which produces a middleware that normalizes
|
||||
the path of a request. By normalizing it means:
|
||||
|
@ -107,7 +107,7 @@ class RequestHandler(BaseProtocol):
|
||||
"""
|
||||
KEEPALIVE_RESCHEDULE_DELAY = 1
|
||||
|
||||
__slots__ = ('_request_count', '_keep_alive', '_manager',
|
||||
__slots__ = ('_request_count', '_keepalive', '_manager',
|
||||
'_request_handler', '_request_factory', '_tcp_keepalive',
|
||||
'_keepalive_time', '_keepalive_handle', '_keepalive_timeout',
|
||||
'_lingering_time', '_messages', '_message_tail',
|
||||
@ -411,14 +411,14 @@ class RequestHandler(BaseProtocol):
|
||||
request = self._request_factory(
|
||||
message, payload, self, writer, handler)
|
||||
try:
|
||||
# a new task is used for copy context vars (#3406)
|
||||
task = self._loop.create_task(
|
||||
self._request_handler(request))
|
||||
try:
|
||||
# a new task is used for copy context vars (#3406)
|
||||
task = self._loop.create_task(
|
||||
self._request_handler(request))
|
||||
resp = await task
|
||||
except HTTPException as exc:
|
||||
resp = exc
|
||||
except asyncio.CancelledError:
|
||||
except (asyncio.CancelledError, ConnectionError):
|
||||
self.log_debug('Ignored premature client disconnection')
|
||||
break
|
||||
except asyncio.TimeoutError as exc:
|
||||
@ -435,6 +435,9 @@ class RequestHandler(BaseProtocol):
|
||||
"please raise the exception instead",
|
||||
DeprecationWarning)
|
||||
|
||||
# Drop the processed task from asyncio.Task.all_tasks() early
|
||||
del task
|
||||
|
||||
if self.debug:
|
||||
if not isinstance(resp, StreamResponse):
|
||||
if resp is None:
|
||||
@ -444,8 +447,22 @@ class RequestHandler(BaseProtocol):
|
||||
raise RuntimeError("Web-handler should return "
|
||||
"a response instance, "
|
||||
"got {!r}".format(resp))
|
||||
await resp.prepare(request)
|
||||
await resp.write_eof()
|
||||
try:
|
||||
prepare_meth = resp.prepare
|
||||
except AttributeError:
|
||||
if resp is None:
|
||||
raise RuntimeError("Missing return "
|
||||
"statement on request handler")
|
||||
else:
|
||||
raise RuntimeError("Web-handler should return "
|
||||
"a response instance, "
|
||||
"got {!r}".format(resp))
|
||||
try:
|
||||
await prepare_meth(request)
|
||||
await resp.write_eof()
|
||||
except ConnectionError:
|
||||
self.log_debug('Ignored premature client disconnection 2')
|
||||
break
|
||||
|
||||
# notify server about keep-alive
|
||||
self._keepalive = bool(resp.keep_alive)
|
||||
|
@ -32,7 +32,7 @@ from . import hdrs
|
||||
from .abc import AbstractStreamWriter
|
||||
from .helpers import DEBUG, ChainMapProxy, HeadersMixin, reify, sentinel
|
||||
from .http_parser import RawRequestMessage
|
||||
from .multipart import MultipartReader
|
||||
from .multipart import BodyPartReader, MultipartReader
|
||||
from .streams import EmptyStreamReader, StreamReader
|
||||
from .typedefs import (
|
||||
DEFAULT_JSON_DECODER,
|
||||
@ -611,41 +611,49 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin):
|
||||
field = await multipart.next()
|
||||
while field is not None:
|
||||
size = 0
|
||||
content_type = field.headers.get(hdrs.CONTENT_TYPE)
|
||||
field_ct = field.headers.get(hdrs.CONTENT_TYPE)
|
||||
|
||||
if field.filename:
|
||||
# store file in temp file
|
||||
tmp = tempfile.TemporaryFile()
|
||||
chunk = await field.read_chunk(size=2**16)
|
||||
while chunk:
|
||||
chunk = field.decode(chunk)
|
||||
tmp.write(chunk)
|
||||
size += len(chunk)
|
||||
if isinstance(field, BodyPartReader):
|
||||
if field.filename and field_ct:
|
||||
# store file in temp file
|
||||
tmp = tempfile.TemporaryFile()
|
||||
chunk = await field.read_chunk(size=2**16)
|
||||
while chunk:
|
||||
chunk = field.decode(chunk)
|
||||
tmp.write(chunk)
|
||||
size += len(chunk)
|
||||
if 0 < max_size < size:
|
||||
raise HTTPRequestEntityTooLarge(
|
||||
max_size=max_size,
|
||||
actual_size=size
|
||||
)
|
||||
chunk = await field.read_chunk(size=2**16)
|
||||
tmp.seek(0)
|
||||
|
||||
ff = FileField(field.name, field.filename,
|
||||
cast(io.BufferedReader, tmp),
|
||||
field_ct, field.headers)
|
||||
out.add(field.name, ff)
|
||||
else:
|
||||
# deal with ordinary data
|
||||
value = await field.read(decode=True)
|
||||
if field_ct is None or \
|
||||
field_ct.startswith('text/'):
|
||||
charset = field.get_charset(default='utf-8')
|
||||
out.add(field.name, value.decode(charset))
|
||||
else:
|
||||
out.add(field.name, value)
|
||||
size += len(value)
|
||||
if 0 < max_size < size:
|
||||
raise HTTPRequestEntityTooLarge(
|
||||
max_size=max_size,
|
||||
actual_size=size
|
||||
)
|
||||
chunk = await field.read_chunk(size=2**16)
|
||||
tmp.seek(0)
|
||||
|
||||
ff = FileField(field.name, field.filename,
|
||||
cast(io.BufferedReader, tmp),
|
||||
content_type, field.headers)
|
||||
out.add(field.name, ff)
|
||||
else:
|
||||
value = await field.read(decode=True)
|
||||
if content_type is None or \
|
||||
content_type.startswith('text/'):
|
||||
charset = field.get_charset(default='utf-8')
|
||||
value = value.decode(charset)
|
||||
out.add(field.name, value)
|
||||
size += len(value)
|
||||
if 0 < max_size < size:
|
||||
raise HTTPRequestEntityTooLarge(
|
||||
max_size=max_size,
|
||||
actual_size=size
|
||||
)
|
||||
raise ValueError(
|
||||
'To decode nested multipart you need '
|
||||
'to use custom reader',
|
||||
)
|
||||
|
||||
field = await multipart.next()
|
||||
else:
|
||||
@ -670,6 +678,9 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin):
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return id(self) == id(other)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return True
|
||||
|
||||
async def _prepare_hook(self, response: StreamResponse) -> None:
|
||||
return
|
||||
|
||||
|
@ -81,7 +81,7 @@ class StreamResponse(BaseClass, HeadersMixin):
|
||||
if headers is not None:
|
||||
self._headers = CIMultiDict(headers) # type: CIMultiDict[str]
|
||||
else:
|
||||
self._headers = CIMultiDict() # type: CIMultiDict[str]
|
||||
self._headers = CIMultiDict()
|
||||
|
||||
self.set_status(status, reason)
|
||||
|
||||
|
@ -10,6 +10,7 @@ from typing import (
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Type,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
@ -40,7 +41,7 @@ class AbstractRouteDef(abc.ABC):
|
||||
|
||||
|
||||
_SimpleHandler = Callable[[Request], Awaitable[StreamResponse]]
|
||||
_HandlerType = Union[AbstractView, _SimpleHandler]
|
||||
_HandlerType = Union[Type[AbstractView], _SimpleHandler]
|
||||
|
||||
|
||||
@attr.s(frozen=True, repr=False, slots=True)
|
||||
@ -120,7 +121,7 @@ def delete(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef:
|
||||
return route(hdrs.METH_DELETE, path, handler, **kwargs)
|
||||
|
||||
|
||||
def view(path: str, handler: AbstractView, **kwargs: Any) -> RouteDef:
|
||||
def view(path: str, handler: Type[AbstractView], **kwargs: Any) -> RouteDef:
|
||||
return route(hdrs.METH_ANY, path, handler, **kwargs)
|
||||
|
||||
|
||||
|
@ -15,8 +15,8 @@ except ImportError:
|
||||
SSLContext = object # type: ignore
|
||||
|
||||
|
||||
__all__ = ('BaseSite', 'TCPSite', 'UnixSite', 'SockSite', 'BaseRunner',
|
||||
'AppRunner', 'ServerRunner', 'GracefulExit')
|
||||
__all__ = ('BaseSite', 'TCPSite', 'UnixSite', 'NamedPipeSite', 'SockSite',
|
||||
'BaseRunner', 'AppRunner', 'ServerRunner', 'GracefulExit')
|
||||
|
||||
|
||||
class GracefulExit(SystemExit):
|
||||
@ -58,7 +58,9 @@ class BaseSite(ABC):
|
||||
self._runner._unreg_site(self)
|
||||
return # not started yet
|
||||
self._server.close()
|
||||
await self._server.wait_closed()
|
||||
# named pipes do not have wait_closed property
|
||||
if hasattr(self._server, 'wait_closed'):
|
||||
await self._server.wait_closed()
|
||||
await self._runner.shutdown()
|
||||
assert self._runner.server
|
||||
await self._runner.server.shutdown(self._shutdown_timeout)
|
||||
@ -95,7 +97,7 @@ class TCPSite(BaseSite):
|
||||
loop = asyncio.get_event_loop()
|
||||
server = self._runner.server
|
||||
assert server is not None
|
||||
self._server = await loop.create_server(
|
||||
self._server = await loop.create_server( # type: ignore
|
||||
server, self._host, self._port,
|
||||
ssl=self._ssl_context, backlog=self._backlog,
|
||||
reuse_address=self._reuse_address,
|
||||
@ -128,6 +130,33 @@ class UnixSite(BaseSite):
|
||||
ssl=self._ssl_context, backlog=self._backlog)
|
||||
|
||||
|
||||
class NamedPipeSite(BaseSite):
|
||||
__slots__ = ('_path', )
|
||||
|
||||
def __init__(self, runner: 'BaseRunner', path: str, *,
|
||||
shutdown_timeout: float=60.0) -> None:
|
||||
loop = asyncio.get_event_loop()
|
||||
if not isinstance(loop, asyncio.ProactorEventLoop): # type: ignore
|
||||
raise RuntimeError("Named Pipes only available in proactor"
|
||||
"loop under windows")
|
||||
super().__init__(runner, shutdown_timeout=shutdown_timeout)
|
||||
self._path = path
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._path
|
||||
|
||||
async def start(self) -> None:
|
||||
await super().start()
|
||||
loop = asyncio.get_event_loop()
|
||||
server = self._runner.server
|
||||
assert server is not None
|
||||
_server = await loop.start_serving_pipe( # type: ignore
|
||||
server, self._path
|
||||
)
|
||||
self._server = _server[0]
|
||||
|
||||
|
||||
class SockSite(BaseSite):
|
||||
__slots__ = ('_sock', '_name')
|
||||
|
||||
@ -155,7 +184,7 @@ class SockSite(BaseSite):
|
||||
loop = asyncio.get_event_loop()
|
||||
server = self._runner.server
|
||||
assert server is not None
|
||||
self._server = await loop.create_server(
|
||||
self._server = await loop.create_server( # type: ignore
|
||||
server, sock=self._sock,
|
||||
ssl=self._ssl_context, backlog=self._backlog)
|
||||
|
||||
|
@ -27,6 +27,7 @@ from typing import ( # noqa
|
||||
Set,
|
||||
Sized,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
@ -123,7 +124,7 @@ class AbstractResource(Sized, Iterable['AbstractRoute']):
|
||||
class AbstractRoute(abc.ABC):
|
||||
|
||||
def __init__(self, method: str,
|
||||
handler: Union[_WebHandler, AbstractView], *,
|
||||
handler: Union[_WebHandler, Type[AbstractView]], *,
|
||||
expect_handler: _ExpectHandler=None,
|
||||
resource: AbstractResource=None) -> None:
|
||||
|
||||
@ -154,8 +155,8 @@ class AbstractRoute(abc.ABC):
|
||||
async def handler_wrapper(request: Request) -> StreamResponse:
|
||||
result = old_handler(request)
|
||||
if asyncio.iscoroutine(result):
|
||||
result = await result
|
||||
return result
|
||||
return await result
|
||||
return result # type: ignore
|
||||
old_handler = handler
|
||||
handler = handler_wrapper
|
||||
|
||||
@ -296,7 +297,7 @@ class Resource(AbstractResource):
|
||||
self._routes = [] # type: List[ResourceRoute]
|
||||
|
||||
def add_route(self, method: str,
|
||||
handler: Union[AbstractView, _WebHandler], *,
|
||||
handler: Union[Type[AbstractView], _WebHandler], *,
|
||||
expect_handler: Optional[_ExpectHandler]=None
|
||||
) -> 'ResourceRoute':
|
||||
|
||||
@ -500,7 +501,7 @@ class StaticResource(PrefixResource):
|
||||
expect_handler: Optional[_ExpectHandler]=None,
|
||||
chunk_size: int=256 * 1024,
|
||||
show_index: bool=False, follow_symlinks: bool=False,
|
||||
append_version: bool=False)-> None:
|
||||
append_version: bool=False) -> None:
|
||||
super().__init__(prefix, name=name)
|
||||
try:
|
||||
directory = Path(directory)
|
||||
@ -698,7 +699,8 @@ class PrefixedSubAppResource(PrefixResource):
|
||||
'prefix': self._prefix}
|
||||
|
||||
async def resolve(self, request: Request) -> _Resolve:
|
||||
if not request.url.raw_path.startswith(self._prefix):
|
||||
if not request.url.raw_path.startswith(self._prefix + '/') and \
|
||||
request.url.raw_path != self._prefix:
|
||||
return None, set()
|
||||
match_info = await self._app.router.resolve(request)
|
||||
match_info.add_app(self._app)
|
||||
@ -825,7 +827,7 @@ class ResourceRoute(AbstractRoute):
|
||||
"""A route with resource"""
|
||||
|
||||
def __init__(self, method: str,
|
||||
handler: Union[_WebHandler, AbstractView],
|
||||
handler: Union[_WebHandler, Type[AbstractView]],
|
||||
resource: AbstractResource, *,
|
||||
expect_handler: Optional[_ExpectHandler]=None) -> None:
|
||||
super().__init__(method, handler, expect_handler=expect_handler,
|
||||
@ -1025,7 +1027,7 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]):
|
||||
return resource
|
||||
|
||||
def add_route(self, method: str, path: str,
|
||||
handler: Union[_WebHandler, AbstractView],
|
||||
handler: Union[_WebHandler, Type[AbstractView]],
|
||||
*, name: Optional[str]=None,
|
||||
expect_handler: Optional[_ExpectHandler]=None
|
||||
) -> AbstractRoute:
|
||||
@ -1112,7 +1114,7 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]):
|
||||
"""
|
||||
return self.add_route(hdrs.METH_DELETE, path, handler, **kwargs)
|
||||
|
||||
def add_view(self, path: str, handler: AbstractView,
|
||||
def add_view(self, path: str, handler: Type[AbstractView],
|
||||
**kwargs: Any) -> AbstractRoute:
|
||||
"""
|
||||
Shortcut for add_route with ANY methods for a class-based view
|
||||
|
@ -20,14 +20,13 @@ from .http import (
|
||||
WebSocketReader,
|
||||
WebSocketWriter,
|
||||
WSMessage,
|
||||
WSMsgType,
|
||||
ws_ext_gen,
|
||||
ws_ext_parse,
|
||||
)
|
||||
from .http import WSMsgType as WSMsgType
|
||||
from .http import ws_ext_gen, ws_ext_parse
|
||||
from .log import ws_logger
|
||||
from .streams import EofStream, FlowControlDataQueue
|
||||
from .typedefs import JSONDecoder, JSONEncoder
|
||||
from .web_exceptions import HTTPBadRequest, HTTPException, HTTPMethodNotAllowed
|
||||
from .web_exceptions import HTTPBadRequest, HTTPException
|
||||
from .web_request import BaseRequest
|
||||
from .web_response import StreamResponse
|
||||
|
||||
@ -47,6 +46,8 @@ class WebSocketReady:
|
||||
|
||||
class WebSocketResponse(StreamResponse):
|
||||
|
||||
_length_check = False
|
||||
|
||||
def __init__(self, *,
|
||||
timeout: float=10.0, receive_timeout: Optional[float]=None,
|
||||
autoclose: bool=True, autoping: bool=True,
|
||||
@ -129,8 +130,6 @@ class WebSocketResponse(StreamResponse):
|
||||
bool,
|
||||
bool]:
|
||||
headers = request.headers
|
||||
if request.method != hdrs.METH_GET:
|
||||
raise HTTPMethodNotAllowed(request.method, [hdrs.METH_GET])
|
||||
if 'websocket' != headers.get(hdrs.UPGRADE, '').lower().strip():
|
||||
raise HTTPBadRequest(
|
||||
text=('No WebSocket UPGRADE hdr: {}\n Can '
|
||||
@ -179,7 +178,6 @@ class WebSocketResponse(StreamResponse):
|
||||
response_headers = CIMultiDict( # type: ignore
|
||||
{hdrs.UPGRADE: 'websocket',
|
||||
hdrs.CONNECTION: 'upgrade',
|
||||
hdrs.TRANSFER_ENCODING: 'chunked',
|
||||
hdrs.SEC_WEBSOCKET_ACCEPT: accept_val})
|
||||
|
||||
notakeover = False
|
||||
|
@ -1,10 +1,12 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import sys
|
||||
|
||||
from functools import partial
|
||||
|
||||
from . import converters, exceptions, filters, validators
|
||||
from . import converters, exceptions, filters, setters, validators
|
||||
from ._config import get_run_validators, set_run_validators
|
||||
from ._funcs import asdict, assoc, astuple, evolve, has
|
||||
from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types
|
||||
from ._make import (
|
||||
NOTHING,
|
||||
Attribute,
|
||||
@ -19,7 +21,7 @@ from ._make import (
|
||||
from ._version_info import VersionInfo
|
||||
|
||||
|
||||
__version__ = "19.3.0"
|
||||
__version__ = "20.3.0"
|
||||
__version_info__ = VersionInfo._from_version_string(__version__)
|
||||
|
||||
__title__ = "attrs"
|
||||
@ -39,7 +41,6 @@ s = attributes = attrs
|
||||
ib = attr = attrib
|
||||
dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Attribute",
|
||||
"Factory",
|
||||
@ -61,8 +62,15 @@ __all__ = [
|
||||
"has",
|
||||
"ib",
|
||||
"make_class",
|
||||
"resolve_types",
|
||||
"s",
|
||||
"set_run_validators",
|
||||
"setters",
|
||||
"validate",
|
||||
"validators",
|
||||
]
|
||||
|
||||
if sys.version_info[:2] >= (3, 6):
|
||||
from ._next_gen import define, field, frozen, mutable
|
||||
|
||||
__all__.extend((define, field, frozen, mutable))
|
||||
|
@ -18,6 +18,7 @@ from typing import (
|
||||
from . import exceptions as exceptions
|
||||
from . import filters as filters
|
||||
from . import converters as converters
|
||||
from . import setters as setters
|
||||
from . import validators as validators
|
||||
|
||||
from ._version_info import VersionInfo
|
||||
@ -37,20 +38,26 @@ _T = TypeVar("_T")
|
||||
_C = TypeVar("_C", bound=type)
|
||||
|
||||
_ValidatorType = Callable[[Any, Attribute[_T], _T], Any]
|
||||
_ConverterType = Callable[[Any], _T]
|
||||
_ConverterType = Callable[[Any], Any]
|
||||
_FilterType = Callable[[Attribute[_T], _T], bool]
|
||||
_ReprType = Callable[[Any], str]
|
||||
_ReprArgType = Union[bool, _ReprType]
|
||||
# FIXME: in reality, if multiple validators are passed they must be in a list or tuple,
|
||||
# but those are invariant and so would prevent subtypes of _ValidatorType from working
|
||||
# when passed in a list or tuple.
|
||||
_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any]
|
||||
_OnSetAttrArgType = Union[
|
||||
_OnSetAttrType, List[_OnSetAttrType], setters._NoOpType
|
||||
]
|
||||
_FieldTransformer = Callable[[type, List[Attribute]], List[Attribute]]
|
||||
# FIXME: in reality, if multiple validators are passed they must be in a list
|
||||
# or tuple, but those are invariant and so would prevent subtypes of
|
||||
# _ValidatorType from working when passed in a list or tuple.
|
||||
_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
|
||||
|
||||
# _make --
|
||||
|
||||
NOTHING: object
|
||||
|
||||
# NOTE: Factory lies about its return type to make this possible: `x: List[int] = Factory(list)`
|
||||
# NOTE: Factory lies about its return type to make this possible:
|
||||
# `x: List[int] # = Factory(list)`
|
||||
# Work around mypy issue #4554 in the common case by using an overload.
|
||||
@overload
|
||||
def Factory(factory: Callable[[], _T]) -> _T: ...
|
||||
@ -70,16 +77,17 @@ class Attribute(Generic[_T]):
|
||||
order: bool
|
||||
hash: Optional[bool]
|
||||
init: bool
|
||||
converter: Optional[_ConverterType[_T]]
|
||||
converter: Optional[_ConverterType]
|
||||
metadata: Dict[Any, Any]
|
||||
type: Optional[Type[_T]]
|
||||
kw_only: bool
|
||||
on_setattr: _OnSetAttrType
|
||||
|
||||
# NOTE: We had several choices for the annotation to use for type arg:
|
||||
# 1) Type[_T]
|
||||
# - Pros: Handles simple cases correctly
|
||||
# - Cons: Might produce less informative errors in the case of conflicting TypeVars
|
||||
# e.g. `attr.ib(default='bad', type=int)`
|
||||
# - Cons: Might produce less informative errors in the case of conflicting
|
||||
# TypeVars e.g. `attr.ib(default='bad', type=int)`
|
||||
# 2) Callable[..., _T]
|
||||
# - Pros: Better error messages than #1 for conflicting TypeVars
|
||||
# - Cons: Terrible error messages for validator checks.
|
||||
@ -97,7 +105,8 @@ class Attribute(Generic[_T]):
|
||||
# This makes this type of assignments possible:
|
||||
# x: int = attr(8)
|
||||
#
|
||||
# This form catches explicit None or no default but with no other arguments returns Any.
|
||||
# This form catches explicit None or no default but with no other arguments
|
||||
# returns Any.
|
||||
@overload
|
||||
def attrib(
|
||||
default: None = ...,
|
||||
@ -113,9 +122,11 @@ def attrib(
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
# This form catches an explicit None or no default and infers the type from the other arguments.
|
||||
# This form catches an explicit None or no default and infers the type from the
|
||||
# other arguments.
|
||||
@overload
|
||||
def attrib(
|
||||
default: None = ...,
|
||||
@ -126,11 +137,12 @@ def attrib(
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
type: Optional[Type[_T]] = ...,
|
||||
converter: Optional[_ConverterType[_T]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form catches an explicit default argument.
|
||||
@ -144,11 +156,12 @@ def attrib(
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
type: Optional[Type[_T]] = ...,
|
||||
converter: Optional[_ConverterType[_T]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||
@ -162,11 +175,83 @@ def attrib(
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
type: object = ...,
|
||||
converter: Optional[_ConverterType[_T]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def field(
|
||||
*,
|
||||
default: None = ...,
|
||||
validator: None = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
converter: None = ...,
|
||||
factory: None = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
# This form catches an explicit None or no default and infers the type from the
|
||||
# other arguments.
|
||||
@overload
|
||||
def field(
|
||||
*,
|
||||
default: None = ...,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form catches an explicit default argument.
|
||||
@overload
|
||||
def field(
|
||||
*,
|
||||
default: _T,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||
@overload
|
||||
def field(
|
||||
*,
|
||||
default: Optional[_T] = ...,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def attrs(
|
||||
@ -187,6 +272,11 @@ def attrs(
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
auto_detect: bool = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
) -> _C: ...
|
||||
@overload
|
||||
def attrs(
|
||||
@ -207,7 +297,61 @@ def attrs(
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
auto_detect: bool = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
) -> Callable[[_C], _C]: ...
|
||||
@overload
|
||||
def define(
|
||||
maybe_cls: _C,
|
||||
*,
|
||||
these: Optional[Dict[str, Any]] = ...,
|
||||
repr: bool = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
slots: bool = ...,
|
||||
frozen: bool = ...,
|
||||
weakref_slot: bool = ...,
|
||||
str: bool = ...,
|
||||
auto_attribs: bool = ...,
|
||||
kw_only: bool = ...,
|
||||
cache_hash: bool = ...,
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
auto_detect: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
) -> _C: ...
|
||||
@overload
|
||||
def define(
|
||||
maybe_cls: None = ...,
|
||||
*,
|
||||
these: Optional[Dict[str, Any]] = ...,
|
||||
repr: bool = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
init: bool = ...,
|
||||
slots: bool = ...,
|
||||
frozen: bool = ...,
|
||||
weakref_slot: bool = ...,
|
||||
str: bool = ...,
|
||||
auto_attribs: bool = ...,
|
||||
kw_only: bool = ...,
|
||||
cache_hash: bool = ...,
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
auto_detect: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
) -> Callable[[_C], _C]: ...
|
||||
|
||||
mutable = define
|
||||
frozen = define # they differ only in their defaults
|
||||
|
||||
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||
class _Fields(Tuple[Attribute[Any], ...]):
|
||||
@ -216,9 +360,15 @@ class _Fields(Tuple[Attribute[Any], ...]):
|
||||
def fields(cls: type) -> _Fields: ...
|
||||
def fields_dict(cls: type) -> Dict[str, Attribute[Any]]: ...
|
||||
def validate(inst: Any) -> None: ...
|
||||
def resolve_types(
|
||||
cls: _C,
|
||||
globalns: Optional[Dict[str, Any]] = ...,
|
||||
localns: Optional[Dict[str, Any]] = ...,
|
||||
) -> _C: ...
|
||||
|
||||
# TODO: add support for returning a proper attrs class from the mypy plugin
|
||||
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', [attr.ib()])` is valid
|
||||
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo',
|
||||
# [attr.ib()])` is valid
|
||||
def make_class(
|
||||
name: str,
|
||||
attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
|
||||
@ -238,12 +388,16 @@ def make_class(
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[bool] = ...,
|
||||
order: Optional[bool] = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
) -> type: ...
|
||||
|
||||
# _funcs --
|
||||
|
||||
# TODO: add support for returning TypedDict from the mypy plugin
|
||||
# FIXME: asdict/astuple do not honor their factory args. waiting on one of these:
|
||||
# FIXME: asdict/astuple do not honor their factory args. Waiting on one of
|
||||
# these:
|
||||
# https://github.com/python/mypy/issues/4236
|
||||
# https://github.com/python/typing/issues/253
|
||||
def asdict(
|
||||
@ -252,6 +406,7 @@ def asdict(
|
||||
filter: Optional[_FilterType[Any]] = ...,
|
||||
dict_factory: Type[Mapping[Any, Any]] = ...,
|
||||
retain_collection_types: bool = ...,
|
||||
value_serializer: Optional[Callable[[type, Attribute, Any], Any]] = ...,
|
||||
) -> Dict[str, Any]: ...
|
||||
|
||||
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||
|
@ -19,9 +19,10 @@ else:
|
||||
|
||||
|
||||
if PY2:
|
||||
from UserDict import IterableUserDict
|
||||
from collections import Mapping, Sequence
|
||||
|
||||
from UserDict import IterableUserDict
|
||||
|
||||
# We 'bundle' isclass instead of using inspect as importing inspect is
|
||||
# fairly expensive (order of 10-15 ms for a modern machine in 2016)
|
||||
def isclass(klass):
|
||||
@ -90,7 +91,7 @@ if PY2:
|
||||
res.data.update(d) # We blocked update, so we have to do it like this.
|
||||
return res
|
||||
|
||||
def just_warn(*args, **kw): # pragma: nocover
|
||||
def just_warn(*args, **kw): # pragma: no cover
|
||||
"""
|
||||
We only warn on Python 3 because we are not aware of any concrete
|
||||
consequences of not setting the cell on Python 2.
|
||||
@ -131,7 +132,7 @@ def make_set_closure_cell():
|
||||
"""
|
||||
# pypy makes this easy. (It also supports the logic below, but
|
||||
# why not do the easy/fast thing?)
|
||||
if PYPY: # pragma: no cover
|
||||
if PYPY:
|
||||
|
||||
def set_closure_cell(cell, value):
|
||||
cell.__setstate__((value,))
|
||||
|
@ -13,6 +13,7 @@ def asdict(
|
||||
filter=None,
|
||||
dict_factory=dict,
|
||||
retain_collection_types=False,
|
||||
value_serializer=None,
|
||||
):
|
||||
"""
|
||||
Return the ``attrs`` attribute values of *inst* as a dict.
|
||||
@ -32,6 +33,10 @@ def asdict(
|
||||
:param bool retain_collection_types: Do not convert to ``list`` when
|
||||
encountering an attribute whose type is ``tuple`` or ``set``. Only
|
||||
meaningful if ``recurse`` is ``True``.
|
||||
:param Optional[callable] value_serializer: A hook that is called for every
|
||||
attribute or dict key/value. It receives the current instance, field
|
||||
and value and must return the (updated) value. The hook is run *after*
|
||||
the optional *filter* has been applied.
|
||||
|
||||
:rtype: return type of *dict_factory*
|
||||
|
||||
@ -40,6 +45,7 @@ def asdict(
|
||||
|
||||
.. versionadded:: 16.0.0 *dict_factory*
|
||||
.. versionadded:: 16.1.0 *retain_collection_types*
|
||||
.. versionadded:: 20.3.0 *value_serializer*
|
||||
"""
|
||||
attrs = fields(inst.__class__)
|
||||
rv = dict_factory()
|
||||
@ -47,17 +53,30 @@ def asdict(
|
||||
v = getattr(inst, a.name)
|
||||
if filter is not None and not filter(a, v):
|
||||
continue
|
||||
|
||||
if value_serializer is not None:
|
||||
v = value_serializer(inst, a, v)
|
||||
|
||||
if recurse is True:
|
||||
if has(v.__class__):
|
||||
rv[a.name] = asdict(
|
||||
v, True, filter, dict_factory, retain_collection_types
|
||||
v,
|
||||
True,
|
||||
filter,
|
||||
dict_factory,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
)
|
||||
elif isinstance(v, (tuple, list, set)):
|
||||
elif isinstance(v, (tuple, list, set, frozenset)):
|
||||
cf = v.__class__ if retain_collection_types is True else list
|
||||
rv[a.name] = cf(
|
||||
[
|
||||
_asdict_anything(
|
||||
i, filter, dict_factory, retain_collection_types
|
||||
i,
|
||||
filter,
|
||||
dict_factory,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
)
|
||||
for i in v
|
||||
]
|
||||
@ -67,10 +86,18 @@ def asdict(
|
||||
rv[a.name] = df(
|
||||
(
|
||||
_asdict_anything(
|
||||
kk, filter, df, retain_collection_types
|
||||
kk,
|
||||
filter,
|
||||
df,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
),
|
||||
_asdict_anything(
|
||||
vv, filter, df, retain_collection_types
|
||||
vv,
|
||||
filter,
|
||||
df,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
),
|
||||
)
|
||||
for kk, vv in iteritems(v)
|
||||
@ -82,19 +109,36 @@ def asdict(
|
||||
return rv
|
||||
|
||||
|
||||
def _asdict_anything(val, filter, dict_factory, retain_collection_types):
|
||||
def _asdict_anything(
|
||||
val,
|
||||
filter,
|
||||
dict_factory,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
):
|
||||
"""
|
||||
``asdict`` only works on attrs instances, this works on anything.
|
||||
"""
|
||||
if getattr(val.__class__, "__attrs_attrs__", None) is not None:
|
||||
# Attrs class.
|
||||
rv = asdict(val, True, filter, dict_factory, retain_collection_types)
|
||||
elif isinstance(val, (tuple, list, set)):
|
||||
rv = asdict(
|
||||
val,
|
||||
True,
|
||||
filter,
|
||||
dict_factory,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
)
|
||||
elif isinstance(val, (tuple, list, set, frozenset)):
|
||||
cf = val.__class__ if retain_collection_types is True else list
|
||||
rv = cf(
|
||||
[
|
||||
_asdict_anything(
|
||||
i, filter, dict_factory, retain_collection_types
|
||||
i,
|
||||
filter,
|
||||
dict_factory,
|
||||
retain_collection_types,
|
||||
value_serializer,
|
||||
)
|
||||
for i in val
|
||||
]
|
||||
@ -103,13 +147,20 @@ def _asdict_anything(val, filter, dict_factory, retain_collection_types):
|
||||
df = dict_factory
|
||||
rv = df(
|
||||
(
|
||||
_asdict_anything(kk, filter, df, retain_collection_types),
|
||||
_asdict_anything(vv, filter, df, retain_collection_types),
|
||||
_asdict_anything(
|
||||
kk, filter, df, retain_collection_types, value_serializer
|
||||
),
|
||||
_asdict_anything(
|
||||
vv, filter, df, retain_collection_types, value_serializer
|
||||
),
|
||||
)
|
||||
for kk, vv in iteritems(val)
|
||||
)
|
||||
else:
|
||||
rv = val
|
||||
if value_serializer is not None:
|
||||
rv = value_serializer(None, None, rv)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
@ -164,7 +215,7 @@ def astuple(
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
)
|
||||
elif isinstance(v, (tuple, list, set)):
|
||||
elif isinstance(v, (tuple, list, set, frozenset)):
|
||||
cf = v.__class__ if retain is True else list
|
||||
rv.append(
|
||||
cf(
|
||||
@ -209,6 +260,7 @@ def astuple(
|
||||
rv.append(v)
|
||||
else:
|
||||
rv.append(v)
|
||||
|
||||
return rv if tuple_factory is list else tuple_factory(rv)
|
||||
|
||||
|
||||
@ -287,4 +339,52 @@ def evolve(inst, **changes):
|
||||
init_name = attr_name if attr_name[0] != "_" else attr_name[1:]
|
||||
if init_name not in changes:
|
||||
changes[init_name] = getattr(inst, attr_name)
|
||||
|
||||
return cls(**changes)
|
||||
|
||||
|
||||
def resolve_types(cls, globalns=None, localns=None):
|
||||
"""
|
||||
Resolve any strings and forward annotations in type annotations.
|
||||
|
||||
This is only required if you need concrete types in `Attribute`'s *type*
|
||||
field. In other words, you don't need to resolve your types if you only
|
||||
use them for static type checking.
|
||||
|
||||
With no arguments, names will be looked up in the module in which the class
|
||||
was created. If this is not what you want, e.g. if the name only exists
|
||||
inside a method, you may pass *globalns* or *localns* to specify other
|
||||
dictionaries in which to look up these names. See the docs of
|
||||
`typing.get_type_hints` for more details.
|
||||
|
||||
:param type cls: Class to resolve.
|
||||
:param Optional[dict] globalns: Dictionary containing global variables.
|
||||
:param Optional[dict] localns: Dictionary containing local variables.
|
||||
|
||||
:raise TypeError: If *cls* is not a class.
|
||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
||||
class.
|
||||
:raise NameError: If types cannot be resolved because of missing variables.
|
||||
|
||||
:returns: *cls* so you can use this function also as a class decorator.
|
||||
Please note that you have to apply it **after** `attr.s`. That means
|
||||
the decorator has to come in the line **before** `attr.s`.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
try:
|
||||
# Since calling get_type_hints is expensive we cache whether we've
|
||||
# done it already.
|
||||
cls.__attrs_types_resolved__
|
||||
except AttributeError:
|
||||
import typing
|
||||
|
||||
hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)
|
||||
for field in fields(cls):
|
||||
if field.name in hints:
|
||||
# Since fields have been frozen we must work around it.
|
||||
_obj_setattr(field, "type", hints[field.name])
|
||||
cls.__attrs_types_resolved__ = True
|
||||
|
||||
# Return the class so you can use it as a decorator too.
|
||||
return cls
|
||||
|
File diff suppressed because it is too large
Load Diff
160
venv/Lib/site-packages/attr/_next_gen.py
Normal file
160
venv/Lib/site-packages/attr/_next_gen.py
Normal file
@ -0,0 +1,160 @@
|
||||
"""
|
||||
This is a Python 3.6 and later-only, keyword-only, and **provisional** API that
|
||||
calls `attr.s` with different default values.
|
||||
|
||||
Provisional APIs that shall become "import attrs" one glorious day.
|
||||
"""
|
||||
|
||||
from functools import partial
|
||||
|
||||
from attr.exceptions import UnannotatedAttributeError
|
||||
|
||||
from . import setters
|
||||
from ._make import NOTHING, _frozen_setattrs, attrib, attrs
|
||||
|
||||
|
||||
def define(
|
||||
maybe_cls=None,
|
||||
*,
|
||||
these=None,
|
||||
repr=None,
|
||||
hash=None,
|
||||
init=None,
|
||||
slots=True,
|
||||
frozen=False,
|
||||
weakref_slot=True,
|
||||
str=False,
|
||||
auto_attribs=None,
|
||||
kw_only=False,
|
||||
cache_hash=False,
|
||||
auto_exc=True,
|
||||
eq=None,
|
||||
order=False,
|
||||
auto_detect=True,
|
||||
getstate_setstate=None,
|
||||
on_setattr=None,
|
||||
field_transformer=None,
|
||||
):
|
||||
r"""
|
||||
The only behavioral differences are the handling of the *auto_attribs*
|
||||
option:
|
||||
|
||||
:param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
|
||||
exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
|
||||
|
||||
1. If all attributes are annotated and no `attr.ib` is found, it assumes
|
||||
*auto_attribs=True*.
|
||||
2. Otherwise it assumes *auto_attribs=False* and tries to collect
|
||||
`attr.ib`\ s.
|
||||
|
||||
and that mutable classes (``frozen=False``) validate on ``__setattr__``.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
|
||||
def do_it(cls, auto_attribs):
|
||||
return attrs(
|
||||
maybe_cls=cls,
|
||||
these=these,
|
||||
repr=repr,
|
||||
hash=hash,
|
||||
init=init,
|
||||
slots=slots,
|
||||
frozen=frozen,
|
||||
weakref_slot=weakref_slot,
|
||||
str=str,
|
||||
auto_attribs=auto_attribs,
|
||||
kw_only=kw_only,
|
||||
cache_hash=cache_hash,
|
||||
auto_exc=auto_exc,
|
||||
eq=eq,
|
||||
order=order,
|
||||
auto_detect=auto_detect,
|
||||
collect_by_mro=True,
|
||||
getstate_setstate=getstate_setstate,
|
||||
on_setattr=on_setattr,
|
||||
field_transformer=field_transformer,
|
||||
)
|
||||
|
||||
def wrap(cls):
|
||||
"""
|
||||
Making this a wrapper ensures this code runs during class creation.
|
||||
|
||||
We also ensure that frozen-ness of classes is inherited.
|
||||
"""
|
||||
nonlocal frozen, on_setattr
|
||||
|
||||
had_on_setattr = on_setattr not in (None, setters.NO_OP)
|
||||
|
||||
# By default, mutable classes validate on setattr.
|
||||
if frozen is False and on_setattr is None:
|
||||
on_setattr = setters.validate
|
||||
|
||||
# However, if we subclass a frozen class, we inherit the immutability
|
||||
# and disable on_setattr.
|
||||
for base_cls in cls.__bases__:
|
||||
if base_cls.__setattr__ is _frozen_setattrs:
|
||||
if had_on_setattr:
|
||||
raise ValueError(
|
||||
"Frozen classes can't use on_setattr "
|
||||
"(frozen-ness was inherited)."
|
||||
)
|
||||
|
||||
on_setattr = setters.NO_OP
|
||||
break
|
||||
|
||||
if auto_attribs is not None:
|
||||
return do_it(cls, auto_attribs)
|
||||
|
||||
try:
|
||||
return do_it(cls, True)
|
||||
except UnannotatedAttributeError:
|
||||
return do_it(cls, False)
|
||||
|
||||
# maybe_cls's type depends on the usage of the decorator. It's a class
|
||||
# if it's used as `@attrs` but ``None`` if used as `@attrs()`.
|
||||
if maybe_cls is None:
|
||||
return wrap
|
||||
else:
|
||||
return wrap(maybe_cls)
|
||||
|
||||
|
||||
mutable = define
|
||||
frozen = partial(define, frozen=True, on_setattr=None)
|
||||
|
||||
|
||||
def field(
|
||||
*,
|
||||
default=NOTHING,
|
||||
validator=None,
|
||||
repr=True,
|
||||
hash=None,
|
||||
init=True,
|
||||
metadata=None,
|
||||
converter=None,
|
||||
factory=None,
|
||||
kw_only=False,
|
||||
eq=None,
|
||||
order=None,
|
||||
on_setattr=None,
|
||||
):
|
||||
"""
|
||||
Identical to `attr.ib`, except keyword-only and with some arguments
|
||||
removed.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
return attrib(
|
||||
default=default,
|
||||
validator=validator,
|
||||
repr=repr,
|
||||
hash=hash,
|
||||
init=init,
|
||||
metadata=metadata,
|
||||
converter=converter,
|
||||
factory=factory,
|
||||
kw_only=kw_only,
|
||||
eq=eq,
|
||||
order=order,
|
||||
on_setattr=on_setattr,
|
||||
)
|
@ -4,7 +4,14 @@ Commonly useful converters.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from ._make import NOTHING, Factory
|
||||
from ._make import NOTHING, Factory, pipe
|
||||
|
||||
|
||||
__all__ = [
|
||||
"pipe",
|
||||
"optional",
|
||||
"default_if_none",
|
||||
]
|
||||
|
||||
|
||||
def optional(converter):
|
||||
|
@ -3,10 +3,9 @@ from . import _ConverterType
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
def optional(
|
||||
converter: _ConverterType[_T]
|
||||
) -> _ConverterType[Optional[_T]]: ...
|
||||
def pipe(*validators: _ConverterType) -> _ConverterType: ...
|
||||
def optional(converter: _ConverterType) -> _ConverterType: ...
|
||||
@overload
|
||||
def default_if_none(default: _T) -> _ConverterType[_T]: ...
|
||||
def default_if_none(default: _T) -> _ConverterType: ...
|
||||
@overload
|
||||
def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType[_T]: ...
|
||||
def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ...
|
||||
|
@ -1,20 +1,37 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
|
||||
class FrozenInstanceError(AttributeError):
|
||||
class FrozenError(AttributeError):
|
||||
"""
|
||||
A frozen/immutable instance has been attempted to be modified.
|
||||
A frozen/immutable instance or attribute haave been attempted to be
|
||||
modified.
|
||||
|
||||
It mirrors the behavior of ``namedtuples`` by using the same error message
|
||||
and subclassing `AttributeError`.
|
||||
|
||||
.. versionadded:: 16.1.0
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
|
||||
msg = "can't set attribute"
|
||||
args = [msg]
|
||||
|
||||
|
||||
class FrozenInstanceError(FrozenError):
|
||||
"""
|
||||
A frozen instance has been attempted to be modified.
|
||||
|
||||
.. versionadded:: 16.1.0
|
||||
"""
|
||||
|
||||
|
||||
class FrozenAttributeError(FrozenError):
|
||||
"""
|
||||
A frozen attribute has been attempted to be modified.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
|
||||
|
||||
class AttrsAttributeNotFoundError(ValueError):
|
||||
"""
|
||||
An ``attrs`` function couldn't find an attribute that the user asked for.
|
||||
@ -51,7 +68,8 @@ class UnannotatedAttributeError(RuntimeError):
|
||||
|
||||
class PythonTooOldError(RuntimeError):
|
||||
"""
|
||||
An ``attrs`` feature requiring a more recent python version has been used.
|
||||
It was attempted to use an ``attrs`` feature that requires a newer Python
|
||||
version.
|
||||
|
||||
.. versionadded:: 18.2.0
|
||||
"""
|
||||
|
@ -1,8 +1,10 @@
|
||||
from typing import Any
|
||||
|
||||
class FrozenInstanceError(AttributeError):
|
||||
class FrozenError(AttributeError):
|
||||
msg: str = ...
|
||||
|
||||
class FrozenInstanceError(FrozenError): ...
|
||||
class FrozenAttributeError(FrozenError): ...
|
||||
class AttrsAttributeNotFoundError(ValueError): ...
|
||||
class NotAnAttrsClassError(ValueError): ...
|
||||
class DefaultAlreadySetError(RuntimeError): ...
|
||||
|
77
venv/Lib/site-packages/attr/setters.py
Normal file
77
venv/Lib/site-packages/attr/setters.py
Normal file
@ -0,0 +1,77 @@
|
||||
"""
|
||||
Commonly used hooks for on_setattr.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from . import _config
|
||||
from .exceptions import FrozenAttributeError
|
||||
|
||||
|
||||
def pipe(*setters):
|
||||
"""
|
||||
Run all *setters* and return the return value of the last one.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
|
||||
def wrapped_pipe(instance, attrib, new_value):
|
||||
rv = new_value
|
||||
|
||||
for setter in setters:
|
||||
rv = setter(instance, attrib, rv)
|
||||
|
||||
return rv
|
||||
|
||||
return wrapped_pipe
|
||||
|
||||
|
||||
def frozen(_, __, ___):
|
||||
"""
|
||||
Prevent an attribute to be modified.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
raise FrozenAttributeError()
|
||||
|
||||
|
||||
def validate(instance, attrib, new_value):
|
||||
"""
|
||||
Run *attrib*'s validator on *new_value* if it has one.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
if _config._run_validators is False:
|
||||
return new_value
|
||||
|
||||
v = attrib.validator
|
||||
if not v:
|
||||
return new_value
|
||||
|
||||
v(instance, attrib, new_value)
|
||||
|
||||
return new_value
|
||||
|
||||
|
||||
def convert(instance, attrib, new_value):
|
||||
"""
|
||||
Run *attrib*'s converter -- if it has one -- on *new_value* and return the
|
||||
result.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
||||
c = attrib.converter
|
||||
if c:
|
||||
return c(new_value)
|
||||
|
||||
return new_value
|
||||
|
||||
|
||||
NO_OP = object()
|
||||
"""
|
||||
Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
|
||||
|
||||
Does not work in `pipe` or within lists.
|
||||
|
||||
.. versionadded:: 20.1.0
|
||||
"""
|
18
venv/Lib/site-packages/attr/setters.pyi
Normal file
18
venv/Lib/site-packages/attr/setters.pyi
Normal file
@ -0,0 +1,18 @@
|
||||
from . import _OnSetAttrType, Attribute
|
||||
from typing import TypeVar, Any, NewType, NoReturn, cast
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
def frozen(
|
||||
instance: Any, attribute: Attribute, new_value: Any
|
||||
) -> NoReturn: ...
|
||||
def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ...
|
||||
def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ...
|
||||
|
||||
# convert is allowed to return Any, because they can be chained using pipe.
|
||||
def convert(
|
||||
instance: Any, attribute: Attribute[Any], new_value: Any
|
||||
) -> Any: ...
|
||||
|
||||
_NoOpType = NewType("_NoOpType", object)
|
||||
NO_OP: _NoOpType
|
@ -67,7 +67,7 @@ def instance_of(type):
|
||||
return _InstanceOfValidator(type)
|
||||
|
||||
|
||||
@attrs(repr=False, frozen=True)
|
||||
@attrs(repr=False, frozen=True, slots=True)
|
||||
class _MatchesReValidator(object):
|
||||
regex = attrib()
|
||||
flags = attrib()
|
||||
@ -171,7 +171,8 @@ def provides(interface):
|
||||
performed using ``interface.providedBy(value)`` (see `zope.interface
|
||||
<https://zopeinterface.readthedocs.io/en/latest/>`_).
|
||||
|
||||
:param zope.interface.Interface interface: The interface to check for.
|
||||
:param interface: The interface to check for.
|
||||
:type interface: ``zope.interface.Interface``
|
||||
|
||||
:raises TypeError: With a human readable error message, the attribute
|
||||
(of type `attr.Attribute`), the expected interface, and the
|
||||
|
@ -1,33 +0,0 @@
|
||||
attr/__init__.py,sha256=ONaI-ZEGOIC7IDqH2HANgesnOxPE1m0GIRRYPPsXEHk,1349
|
||||
attr/__init__.pyi,sha256=fOnMRTF00b5J23PYPF74u66UVhVzzm0KYVxzmVXHPw0,8257
|
||||
attr/__pycache__/__init__.cpython-36.pyc,,
|
||||
attr/__pycache__/_compat.cpython-36.pyc,,
|
||||
attr/__pycache__/_config.cpython-36.pyc,,
|
||||
attr/__pycache__/_funcs.cpython-36.pyc,,
|
||||
attr/__pycache__/_make.cpython-36.pyc,,
|
||||
attr/__pycache__/_version_info.cpython-36.pyc,,
|
||||
attr/__pycache__/converters.cpython-36.pyc,,
|
||||
attr/__pycache__/exceptions.cpython-36.pyc,,
|
||||
attr/__pycache__/filters.cpython-36.pyc,,
|
||||
attr/__pycache__/validators.cpython-36.pyc,,
|
||||
attr/_compat.py,sha256=-pJtdtqgCg0K6rH_BWf3wKuTum58GD-WWPclQQ2SUaU,7326
|
||||
attr/_config.py,sha256=_KvW0mQdH2PYjHc0YfIUaV_o2pVfM7ziMEYTxwmEhOA,514
|
||||
attr/_funcs.py,sha256=unAJfNGSTOzxyFzkj7Rs3O1bfsQodmXyir9uZKen-vY,9696
|
||||
attr/_make.py,sha256=HhjGhFEbnxPKuUb9hFmAjXoQGpekniw1IEF3_Z-vwCc,70807
|
||||
attr/_version_info.py,sha256=azMi1lNelb3cJvvYUMXsXVbUANkRzbD5IEiaXVpeVr4,2162
|
||||
attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209
|
||||
attr/converters.py,sha256=5QJRYSXE8G7PW0289y_SPwvvZIcw-nJIuBlfYVdB4BQ,2141
|
||||
attr/converters.pyi,sha256=wAhCoOT1MFV8t323rpD87O7bxQ8CYLTPiBQd-29BieI,351
|
||||
attr/exceptions.py,sha256=hbhOa3b4W8_mRrbj3FsMTR4Bt5xzbJs5xaFTWn8s6h4,1635
|
||||
attr/exceptions.pyi,sha256=4zuaJyl2axxWbqnZgxo_2oTpPNbyowEw3A4hqV5PmAc,458
|
||||
attr/filters.py,sha256=weDxwATsa69T_0bPVjiM1fGsciAMQmwhY5G8Jm5BxuI,1098
|
||||
attr/filters.pyi,sha256=xDpmKQlFdssgxGa5tsl1ADh_3zwAwAT4vUhd8h-8-Tk,214
|
||||
attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
attr/validators.py,sha256=8AsxgdDgh3sGPseiUIMPGcTr6PvaDYfH3AK46tsvs8U,11460
|
||||
attr/validators.pyi,sha256=vZgsJqUwrJevh4v_Hd7_RSXqDrBctE6-3AEZ7uYKodo,1868
|
||||
attrs-19.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
attrs-19.3.0.dist-info/LICENSE,sha256=v2WaKLSSQGAvVrvfSQy-LsUJsVuY-Z17GaUsdA4yeGM,1082
|
||||
attrs-19.3.0.dist-info/METADATA,sha256=WmnjYy_TftebL3pewXyGEaD4TZRrLUEHk3frEkAtqL0,9022
|
||||
attrs-19.3.0.dist-info/RECORD,,
|
||||
attrs-19.3.0.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
|
||||
attrs-19.3.0.dist-info/top_level.txt,sha256=tlRYMddkRlKPqJ96wP2_j9uEsmcNHgD2SbuWd4CzGVU,5
|
11
venv/Lib/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst
Normal file
11
venv/Lib/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst
Normal file
@ -0,0 +1,11 @@
|
||||
Credits
|
||||
=======
|
||||
|
||||
``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_.
|
||||
|
||||
The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_.
|
||||
|
||||
A full list of contributors can be found in `GitHub's overview <https://github.com/python-attrs/attrs/graphs/contributors>`_.
|
||||
|
||||
It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.io/>`_ and aspires to fix some of it clunkiness and unfortunate decisions.
|
||||
Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `subclassing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay?
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: attrs
|
||||
Version: 19.3.0
|
||||
Version: 20.3.0
|
||||
Summary: Classes Without Boilerplate
|
||||
Home-page: https://www.attrs.org/
|
||||
Author: Hynek Schlawack
|
||||
@ -11,6 +11,8 @@ License: MIT
|
||||
Project-URL: Documentation, https://www.attrs.org/
|
||||
Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues
|
||||
Project-URL: Source Code, https://github.com/python-attrs/attrs
|
||||
Project-URL: Funding, https://github.com/sponsors/hynek
|
||||
Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi
|
||||
Keywords: class,attribute,boilerplate
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
@ -22,43 +24,43 @@ Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Description-Content-Type: text/x-rst
|
||||
Provides-Extra: azure-pipelines
|
||||
Requires-Dist: coverage ; extra == 'azure-pipelines'
|
||||
Requires-Dist: hypothesis ; extra == 'azure-pipelines'
|
||||
Requires-Dist: pympler ; extra == 'azure-pipelines'
|
||||
Requires-Dist: pytest (>=4.3.0) ; extra == 'azure-pipelines'
|
||||
Requires-Dist: six ; extra == 'azure-pipelines'
|
||||
Requires-Dist: zope.interface ; extra == 'azure-pipelines'
|
||||
Requires-Dist: pytest-azurepipelines ; extra == 'azure-pipelines'
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: coverage ; extra == 'dev'
|
||||
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'dev'
|
||||
Requires-Dist: hypothesis ; extra == 'dev'
|
||||
Requires-Dist: pympler ; extra == 'dev'
|
||||
Requires-Dist: pytest (>=4.3.0) ; extra == 'dev'
|
||||
Requires-Dist: six ; extra == 'dev'
|
||||
Requires-Dist: zope.interface ; extra == 'dev'
|
||||
Requires-Dist: furo ; extra == 'dev'
|
||||
Requires-Dist: sphinx ; extra == 'dev'
|
||||
Requires-Dist: pre-commit ; extra == 'dev'
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: furo ; extra == 'docs'
|
||||
Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: zope.interface ; extra == 'docs'
|
||||
Provides-Extra: tests
|
||||
Requires-Dist: coverage ; extra == 'tests'
|
||||
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests'
|
||||
Requires-Dist: hypothesis ; extra == 'tests'
|
||||
Requires-Dist: pympler ; extra == 'tests'
|
||||
Requires-Dist: pytest (>=4.3.0) ; extra == 'tests'
|
||||
Requires-Dist: six ; extra == 'tests'
|
||||
Requires-Dist: zope.interface ; extra == 'tests'
|
||||
Provides-Extra: tests_no_zope
|
||||
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope'
|
||||
Requires-Dist: hypothesis ; extra == 'tests_no_zope'
|
||||
Requires-Dist: pympler ; extra == 'tests_no_zope'
|
||||
Requires-Dist: pytest (>=4.3.0) ; extra == 'tests_no_zope'
|
||||
Requires-Dist: six ; extra == 'tests_no_zope'
|
||||
|
||||
.. image:: https://www.attrs.org/en/latest/_static/attrs_logo.png
|
||||
:alt: attrs Logo
|
||||
@ -71,8 +73,8 @@ Requires-Dist: zope.interface ; extra == 'tests'
|
||||
:target: https://www.attrs.org/en/stable/?badge=stable
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://attrs.visualstudio.com/attrs/_apis/build/status/python-attrs.attrs?branchName=master
|
||||
:target: https://attrs.visualstudio.com/attrs/_build/latest?definitionId=1&branchName=master
|
||||
.. image:: https://github.com/python-attrs/attrs/workflows/CI/badge.svg?branch=master
|
||||
:target: https://github.com/python-attrs/attrs/actions?workflow=CI
|
||||
:alt: CI Status
|
||||
|
||||
.. image:: https://codecov.io/github/python-attrs/attrs/branch/master/graph/badge.svg
|
||||
@ -89,7 +91,7 @@ Requires-Dist: zope.interface ; extra == 'tests'
|
||||
|
||||
Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
|
||||
|
||||
.. -spiel-end-
|
||||
.. teaser-end
|
||||
|
||||
For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
|
||||
|
||||
@ -147,44 +149,18 @@ Which in turn encourages you to write *small classes* that do `one thing well <h
|
||||
Never again violate the `single responsibility principle <https://en.wikipedia.org/wiki/Single_responsibility_principle>`_ just because implementing ``__init__`` et al is a painful drag.
|
||||
|
||||
|
||||
.. -testimonials-
|
||||
|
||||
Testimonials
|
||||
============
|
||||
|
||||
**Amber Hawkie Brown**, Twisted Release Manager and Computer Owl:
|
||||
|
||||
Writing a fully-functional class using attrs takes me less time than writing this testimonial.
|
||||
|
||||
|
||||
**Glyph Lefkowitz**, creator of `Twisted <https://twistedmatrix.com/>`_, `Automat <https://pypi.org/project/Automat/>`_, and other open source software, in `The One Python Library Everyone Needs <https://glyph.twistedmatrix.com/2016/08/attrs.html>`_:
|
||||
|
||||
I’m looking forward to is being able to program in Python-with-attrs everywhere.
|
||||
It exerts a subtle, but positive, design influence in all the codebases I’ve see it used in.
|
||||
|
||||
|
||||
**Kenneth Reitz**, creator of `Requests <https://github.com/psf/requests>`_ (`on paper no less <https://twitter.com/hynek/status/866817877650751488>`_!):
|
||||
|
||||
attrs—classes for humans. I like it.
|
||||
|
||||
|
||||
**Łukasz Langa**, creator of `Black <https://github.com/psf/black>`_, prolific Python core developer, and release manager for Python 3.8 and 3.9:
|
||||
|
||||
I'm increasingly digging your attr.ocity. Good job!
|
||||
|
||||
|
||||
.. -end-
|
||||
|
||||
.. -project-information-
|
||||
.. -getting-help-
|
||||
|
||||
Getting Help
|
||||
============
|
||||
|
||||
Please use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ to get help.
|
||||
|
||||
Answering questions of your fellow developers is also great way to help the project!
|
||||
Answering questions of your fellow developers is also a great way to help the project!
|
||||
|
||||
|
||||
.. -project-information-
|
||||
|
||||
Project Information
|
||||
===================
|
||||
|
||||
@ -192,7 +168,7 @@ Project Information
|
||||
its documentation lives at `Read the Docs <https://www.attrs.org/>`_,
|
||||
the code on `GitHub <https://github.com/python-attrs/attrs>`_,
|
||||
and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
|
||||
It’s rigorously tested on Python 2.7, 3.4+, and PyPy.
|
||||
It’s rigorously tested on Python 2.7, 3.5+, and PyPy.
|
||||
|
||||
We collect information on **third-party extensions** in our `wiki <https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs>`_.
|
||||
Feel free to browse and add your own!
|
||||
@ -200,17 +176,53 @@ Feel free to browse and add your own!
|
||||
If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide <https://www.attrs.org/en/latest/contributing.html>`_ to get you started!
|
||||
|
||||
|
||||
``attrs`` for Enterprise
|
||||
------------------------
|
||||
|
||||
Available as part of the Tidelift Subscription.
|
||||
|
||||
The maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.
|
||||
Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
|
||||
`Learn more. <https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
|
||||
|
||||
|
||||
Release Information
|
||||
===================
|
||||
|
||||
19.3.0 (2019-10-15)
|
||||
20.3.0 (2020-11-05)
|
||||
-------------------
|
||||
|
||||
Backward-incompatible Changes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ``attr.define()``, ``attr.frozen()``, ``attr.mutable()``, and ``attr.field()`` remain **provisional**.
|
||||
|
||||
This release does **not** change change anything about them and they are already used widely in production though.
|
||||
|
||||
If you wish to use them together with mypy, you can simply drop `this plugin <https://gist.github.com/hynek/1e3844d0c99e479e716169034b5fa963#file-attrs_ng_plugin-py>`_ into your project.
|
||||
|
||||
Feel free to provide feedback to them in the linked issue #668.
|
||||
|
||||
We will release the ``attrs`` namespace once we have the feeling that the APIs have properly settled.
|
||||
`#668 <https://github.com/python-attrs/attrs/issues/668>`_
|
||||
|
||||
|
||||
Changes
|
||||
^^^^^^^
|
||||
|
||||
- Fixed ``auto_attribs`` usage when default values cannot be compared directly with ``==``, such as ``numpy`` arrays.
|
||||
`#585 <https://github.com/python-attrs/attrs/issues/585>`_
|
||||
- ``attr.s()`` now has a *field_transformer* hook that is called for all ``Attribute``\ s and returns a (modified or updated) list of ``Attribute`` instances.
|
||||
``attr.asdict()`` has a *value_serializer* hook that can change the way values are converted.
|
||||
Both hooks are meant to help with data (de-)serialization workflows.
|
||||
`#653 <https://github.com/python-attrs/attrs/issues/653>`_
|
||||
- ``kw_only=True`` now works on Python 2.
|
||||
`#700 <https://github.com/python-attrs/attrs/issues/700>`_
|
||||
- ``raise from`` now works on frozen classes on PyPy.
|
||||
`#703 <https://github.com/python-attrs/attrs/issues/703>`_,
|
||||
`#712 <https://github.com/python-attrs/attrs/issues/712>`_
|
||||
- ``attr.asdict()`` and ``attr.astuple()`` now treat ``frozenset``\ s like ``set``\ s with regards to the *retain_collection_types* argument.
|
||||
`#704 <https://github.com/python-attrs/attrs/issues/704>`_
|
||||
- The type stubs for ``attr.s()`` and ``attr.make_class()`` are not missing the *collect_by_mro* argument anymore.
|
||||
`#711 <https://github.com/python-attrs/attrs/issues/711>`_
|
||||
|
||||
`Full changelog <https://www.attrs.org/en/stable/changelog.html>`_.
|
||||
|
39
venv/Lib/site-packages/attrs-20.3.0.dist-info/RECORD
Normal file
39
venv/Lib/site-packages/attrs-20.3.0.dist-info/RECORD
Normal file
@ -0,0 +1,39 @@
|
||||
attr/__init__.py,sha256=70KmZOgz2sUvtRTC_IuXEeN2ttOyBWHn4XA59aqGXPs,1568
|
||||
attr/__init__.pyi,sha256=ca_4sg7z0e_EL7ehy-flXVGAju5PBX2hVo51dUmPMi0,12986
|
||||
attr/__pycache__/__init__.cpython-36.pyc,,
|
||||
attr/__pycache__/_compat.cpython-36.pyc,,
|
||||
attr/__pycache__/_config.cpython-36.pyc,,
|
||||
attr/__pycache__/_funcs.cpython-36.pyc,,
|
||||
attr/__pycache__/_make.cpython-36.pyc,,
|
||||
attr/__pycache__/_next_gen.cpython-36.pyc,,
|
||||
attr/__pycache__/_version_info.cpython-36.pyc,,
|
||||
attr/__pycache__/converters.cpython-36.pyc,,
|
||||
attr/__pycache__/exceptions.cpython-36.pyc,,
|
||||
attr/__pycache__/filters.cpython-36.pyc,,
|
||||
attr/__pycache__/setters.cpython-36.pyc,,
|
||||
attr/__pycache__/validators.cpython-36.pyc,,
|
||||
attr/_compat.py,sha256=rZhpP09xbyWSzMv796XQbryIr21oReJFvA70G3lrHxg,7308
|
||||
attr/_config.py,sha256=_KvW0mQdH2PYjHc0YfIUaV_o2pVfM7ziMEYTxwmEhOA,514
|
||||
attr/_funcs.py,sha256=PvFQlflEswO_qIR2sUr4a4x8ggQpEoDKe3YKM2rLJu4,13081
|
||||
attr/_make.py,sha256=61XB4-SHQpFbWbStGWotTTbzVT2m49DUovRgnxpMqmU,88313
|
||||
attr/_next_gen.py,sha256=x6TU2rVOXmFmrNNvkfshJsxyRbAAK0wDI4SJV2OI97c,4138
|
||||
attr/_version_info.py,sha256=azMi1lNelb3cJvvYUMXsXVbUANkRzbD5IEiaXVpeVr4,2162
|
||||
attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209
|
||||
attr/converters.py,sha256=CaK6iLtEMmemrqU8LQ1D2nWtbo9dGPAv4UaZ0rFzhOA,2214
|
||||
attr/converters.pyi,sha256=fVGSfawF3NMy2EBApkC7dAwMuujWCHnGEnnAgsbkVpg,380
|
||||
attr/exceptions.py,sha256=gmlET97ikqdQVvy7Ff9p7zVvqc2SsNtTd-r30pva1GE,1950
|
||||
attr/exceptions.pyi,sha256=zZq8bCUnKAy9mDtBEw42ZhPhAUIHoTKedDQInJD883M,539
|
||||
attr/filters.py,sha256=weDxwATsa69T_0bPVjiM1fGsciAMQmwhY5G8Jm5BxuI,1098
|
||||
attr/filters.pyi,sha256=xDpmKQlFdssgxGa5tsl1ADh_3zwAwAT4vUhd8h-8-Tk,214
|
||||
attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
attr/setters.py,sha256=0ElzHwdVK3dsYcQi2CXkFvhx8fNxUI5OVhw8SWeaKmA,1434
|
||||
attr/setters.pyi,sha256=SYr6adhx4f0dSkmmBICg6eK8WMev5jT-KJQJTdul078,567
|
||||
attr/validators.py,sha256=6DBx1jt4oZxx1ppvx6JWqm9-UAsYpXC4HTwxJilCeRg,11497
|
||||
attr/validators.pyi,sha256=vZgsJqUwrJevh4v_Hd7_RSXqDrBctE6-3AEZ7uYKodo,1868
|
||||
attrs-20.3.0.dist-info/AUTHORS.rst,sha256=wsqCNbGz_mklcJrt54APIZHZpoTIJLkXqEhhn4Nd8hc,752
|
||||
attrs-20.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
attrs-20.3.0.dist-info/LICENSE,sha256=v2WaKLSSQGAvVrvfSQy-LsUJsVuY-Z17GaUsdA4yeGM,1082
|
||||
attrs-20.3.0.dist-info/METADATA,sha256=2XTmALrRRbIZj9J8pJgpKYnyATu_NAL8vfUnqRFpE5w,10220
|
||||
attrs-20.3.0.dist-info/RECORD,,
|
||||
attrs-20.3.0.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
|
||||
attrs-20.3.0.dist-info/top_level.txt,sha256=tlRYMddkRlKPqJ96wP2_j9uEsmcNHgD2SbuWd4CzGVU,5
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.32.2)
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
@ -1,26 +0,0 @@
|
||||
|
||||
Except when otherwise stated (look for LICENSE files in directories or
|
||||
information at the beginning of each file) all software and
|
||||
documentation is licensed as follows:
|
||||
|
||||
The MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
@ -1,37 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: cffi
|
||||
Version: 1.14.0
|
||||
Summary: Foreign Function Interface for Python calling C code.
|
||||
Home-page: http://cffi.readthedocs.org
|
||||
Author: Armin Rigo, Maciej Fijalkowski
|
||||
Author-email: python-cffi@googlegroups.com
|
||||
License: MIT
|
||||
Platform: UNKNOWN
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Requires-Dist: pycparser
|
||||
|
||||
|
||||
CFFI
|
||||
====
|
||||
|
||||
Foreign Function Interface for Python calling C code.
|
||||
Please see the `Documentation <http://cffi.readthedocs.org/>`_.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
`Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
_cffi_backend.cp36-win_amd64.pyd,sha256=Fl9fNCxcVgweZH6L64L1BE1akXg3VPw4uvmSXtUuKQ0,180736
|
||||
cffi-1.14.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
cffi-1.14.0.dist-info/LICENSE,sha256=esEZUOct9bRcUXFqeyLnuzSzJNZ_Bl4pOBUt1HLEgV8,1320
|
||||
cffi-1.14.0.dist-info/METADATA,sha256=tZUQbfePzTlM58vXdkcDc1ID5OsPswm6VNj3Ds5VzRU,1191
|
||||
cffi-1.14.0.dist-info/RECORD,,
|
||||
cffi-1.14.0.dist-info/WHEEL,sha256=Mp7cNSJkwOccBZaxEtyYhlze1HXRCLLX3tIlVLTix2E,106
|
||||
cffi-1.14.0.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76
|
||||
cffi-1.14.0.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19
|
||||
cffi/__init__.py,sha256=rt03V1G6kc9Hk9MFKivO7NokqmXzEGBtiEVMEoD3erk,527
|
||||
cffi/__pycache__/__init__.cpython-36.pyc,,
|
||||
cffi/__pycache__/api.cpython-36.pyc,,
|
||||
cffi/__pycache__/backend_ctypes.cpython-36.pyc,,
|
||||
cffi/__pycache__/cffi_opcode.cpython-36.pyc,,
|
||||
cffi/__pycache__/commontypes.cpython-36.pyc,,
|
||||
cffi/__pycache__/cparser.cpython-36.pyc,,
|
||||
cffi/__pycache__/error.cpython-36.pyc,,
|
||||
cffi/__pycache__/ffiplatform.cpython-36.pyc,,
|
||||
cffi/__pycache__/lock.cpython-36.pyc,,
|
||||
cffi/__pycache__/model.cpython-36.pyc,,
|
||||
cffi/__pycache__/pkgconfig.cpython-36.pyc,,
|
||||
cffi/__pycache__/recompiler.cpython-36.pyc,,
|
||||
cffi/__pycache__/setuptools_ext.cpython-36.pyc,,
|
||||
cffi/__pycache__/vengine_cpy.cpython-36.pyc,,
|
||||
cffi/__pycache__/vengine_gen.cpython-36.pyc,,
|
||||
cffi/__pycache__/verifier.cpython-36.pyc,,
|
||||
cffi/_cffi_errors.h,sha256=INd0GxZQna8TTRYNOOr9_iFy0FZa84I_KH1qlmPgulQ,4003
|
||||
cffi/_cffi_include.h,sha256=SZmeKYOZhH9yEe9YQko2yqFar_GPhzlbbZXIQdKvPxg,13838
|
||||
cffi/_embedding.h,sha256=ESJSMS67PytRAu1ZQsNpYYOpAKzwSO4H9yR6vQBDVK0,17931
|
||||
cffi/api.py,sha256=Xs_dAN5x1ehfnn_F9ZTdA3Ce0bmPrqeIOkO4Ya1tfbQ,43029
|
||||
cffi/backend_ctypes.py,sha256=BHN3q2giL2_Y8wMDST2CIcc_qoMrs65qV9Ob5JvxBZ4,43575
|
||||
cffi/cffi_opcode.py,sha256=57P2NHLZkuTWueZybu5iosWljb6ocQmUXzGrCplrnyE,5911
|
||||
cffi/commontypes.py,sha256=mEZD4g0qtadnv6O6CEXvMQaJ1K6SRbG5S1h4YvVZHOU,2769
|
||||
cffi/cparser.py,sha256=Jbm7NYmhQky0W6_VvYy-HLZnv3kdrKCw5HkpqLAijH4,43034
|
||||
cffi/error.py,sha256=Bka7fSV22aIglTQDPIDfpnxTc1aWZLMQdQOJY-h_PUA,908
|
||||
cffi/ffiplatform.py,sha256=qioydJeC63dEvrQ3ht5_BPmSs7wzzzuWnZAJtfhic7I,4173
|
||||
cffi/lock.py,sha256=vnbsel7392Ib8gGBifIfAfc7MHteSwd3nP725pvc25Q,777
|
||||
cffi/model.py,sha256=m6ExPe_NyemlW1cPV-RkptNv9MDQGEey9MDQAoOu-XQ,22296
|
||||
cffi/parse_c_type.h,sha256=fKYNqWNX5f9kZNNhbXcRLTOlpRGRhh8eCLyHmTXIZnQ,6157
|
||||
cffi/pkgconfig.py,sha256=9zDcDf0XKIJaxFHLg7e-W8-Xb8Yq5hdhqH7kLg-ugRo,4495
|
||||
cffi/recompiler.py,sha256=G3SqywHi2evVNV_nkHbNmbtHqg-WHLgBn8Silyo028o,64769
|
||||
cffi/setuptools_ext.py,sha256=gtA1z8ujS8As3ysDUFrN4rNzw-02_M9kRrQveVNzfW0,9065
|
||||
cffi/vengine_cpy.py,sha256=a-0zG9XdGF0aEkH01KeGLszETCGNt-PCuI6II-8TxBg,44390
|
||||
cffi/vengine_gen.py,sha256=ZR3d1bEpeAM123Xev9SZeL8pYHdghYD3f3wpk2idr64,27351
|
||||
cffi/verifier.py,sha256=La8rdbEkvdvbqAHDzTk5lsNUvdkqB_GcFnO7wXI6Mgk,11513
|
@ -1,3 +0,0 @@
|
||||
[distutils.setup_keywords]
|
||||
cffi_modules = cffi.setuptools_ext:cffi_modules
|
||||
|
@ -1,2 +0,0 @@
|
||||
_cffi_backend
|
||||
cffi
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user