Initial commit

This commit is contained in:
René Mathieu
2026-01-17 13:49:51 +01:00
commit 0fef8d96c5
1897 changed files with 396119 additions and 0 deletions

BIN
dist/.DS_Store vendored Executable file

Binary file not shown.

View File

@@ -0,0 +1 @@
Versions/Current/Python

View File

@@ -0,0 +1 @@
Versions/Current/Resources

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>Python</string>
<key>CFBundleGetInfoString</key>
<string>Python Runtime and Library</string>
<key>CFBundleIdentifier</key>
<string>org.python.python</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Python</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.13.3, (c) 2001-2024 Python Software Foundation.</string>
<key>CFBundleLongVersionString</key>
<string>3.13.3, (c) 2001-2024 Python Software Foundation.</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>3.13.3</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Resources/Info.plist</key>
<data>
uzcQGc+DYX34OBsw4BTyyvFmNyc=
</data>
</dict>
<key>files2</key>
<dict>
<key>Resources/Info.plist</key>
<dict>
<key>hash2</key>
<data>
LdTNemLO189g3KPIksYuzf6WR17A2iDRvDbOP2f1n00=
</data>
</dict>
<key>include/python3.13/pyconfig.h</key>
<dict>
<key>hash2</key>
<data>
ABn4/w321BqCH+SX4hsbKD0PYg8u5fmvAVt5nQg2S9g=
</data>
</dict>
<key>lib/python3.13/config-3.13-darwin/Makefile</key>
<dict>
<key>hash2</key>
<data>
jGHpvAlEuaS1SBDCxU3N8ncn3kjR5gH8LgCRmMA5Dqc=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
3.13

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
libmpdec.4.0.0.dylib

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

91
dist/dicom2pacs.app/Contents/Info.plist vendored Executable file
View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>DICOM zu PACS</string>
<key>CFBundleExecutable</key>
<string>dicom2pacs</string>
<key>CFBundleGetInfoString</key>
<string>DICOM Dateien zu Orthanc PACS hochladen</string>
<key>CFBundleIconFile</key>
<string>Logo.icns</string>
<key>CFBundleIdentifier</key>
<string>com.dicom2pacs.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>dicom2pacs</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>LSHasLocalizedDisplayName</key>
<false/>
<key>NSAppleScriptEnabled</key>
<false/>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright not specified</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>PyMainFileNames</key>
<array>
<string>__boot__</string>
</array>
<key>PyOptions</key>
<dict>
<key>alias</key>
<false/>
<key>argv_emulation</key>
<false/>
<key>emulate_shell_environment</key>
<false/>
<key>no_chdir</key>
<false/>
<key>prefer_ppc</key>
<false/>
<key>site_packages</key>
<false/>
<key>use_faulthandler</key>
<false/>
<key>use_pythonpath</key>
<false/>
<key>verbose</key>
<false/>
</dict>
<key>PyResourcePackages</key>
<array/>
<key>PyRuntimeLocations</key>
<array>
<string>@executable_path/../Frameworks/Python.framework/Versions/3.13/Python</string>
</array>
<key>PythonInfoDict</key>
<dict>
<key>PythonExecutable</key>
<string>/Users/rene/scripts/läuft 2026/venv/bin/python</string>
<key>PythonLongVersion</key>
<string>3.13.3 (main, Apr 8 2025, 13:54:08) [Clang 16.0.0 (clang-1600.0.26.6)]</string>
<key>PythonShortVersion</key>
<string>3.1</string>
<key>py2app</key>
<dict>
<key>alias</key>
<false/>
<key>template</key>
<string>app</string>
<key>version</key>
<string>0.28.9</string>
</dict>
</dict>
</dict>
</plist>

BIN
dist/dicom2pacs.app/Contents/MacOS/dicom2pacs vendored Executable file

Binary file not shown.

BIN
dist/dicom2pacs.app/Contents/MacOS/python vendored Executable file

Binary file not shown.

1
dist/dicom2pacs.app/Contents/PkgInfo vendored Executable file
View File

@@ -0,0 +1 @@
APPL????

Binary file not shown.

View File

@@ -0,0 +1,130 @@
def _reset_sys_path():
# Clear generic sys.path[0]
import os
import sys
resources = os.environ["RESOURCEPATH"]
while sys.path[0] == resources:
del sys.path[0]
_reset_sys_path()
def _chdir_resource():
import os
os.chdir(os.environ["RESOURCEPATH"])
_chdir_resource()
def _disable_linecache():
import linecache
def fake_getline(*args, **kwargs):
return ""
linecache.orig_getline = linecache.getline
linecache.getline = fake_getline
_disable_linecache()
import re
import sys
cookie_re = re.compile(rb"coding[:=]\s*([-\w.]+)")
if sys.version_info[0] == 2:
default_encoding = "ascii"
else:
default_encoding = "utf-8"
def guess_encoding(fp):
for _i in range(2):
ln = fp.readline()
m = cookie_re.search(ln)
if m is not None:
return m.group(1).decode("ascii")
return default_encoding
def _run():
global __file__
import os
import site # noqa: F401
sys.frozen = "macosx_app"
base = os.environ["RESOURCEPATH"]
argv0 = os.path.basename(os.environ["ARGVZERO"])
script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) # noqa: F821
path = os.path.join(base, script)
sys.argv[0] = __file__ = path
if sys.version_info[0] == 2:
with open(path, "rU") as fp:
source = fp.read() + "\n"
else:
with open(path, "rb") as fp:
encoding = guess_encoding(fp)
with open(path, "r", encoding=encoding) as fp:
source = fp.read() + "\n"
BOM = b"\xef\xbb\xbf".decode("utf-8")
if source.startswith(BOM):
source = source[1:]
exec(compile(source, path, "exec"), globals(), globals())
def _setup_ctypes():
import os
from ctypes.macholib import dyld
frameworks = os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")
dyld.DEFAULT_FRAMEWORK_FALLBACK.insert(0, frameworks)
dyld.DEFAULT_LIBRARY_FALLBACK.insert(0, frameworks)
_setup_ctypes()
def _boot_multiprocessing():
import sys
import multiprocessing.spawn
orig_get_command_line = multiprocessing.spawn.get_command_line
def wrapped_get_command_line(**kwargs):
orig_frozen = sys.frozen
del sys.frozen
try:
return orig_get_command_line(**kwargs)
finally:
sys.frozen = orig_frozen
multiprocessing.spawn.get_command_line = wrapped_get_command_line
_boot_multiprocessing()
def _setup_openssl():
import os
resourcepath = os.environ["RESOURCEPATH"]
os.environ["SSL_CERT_FILE"] = os.path.join(
resourcepath, "openssl.ca", "cert.pem")
os.environ["SSL_CERT_DIR"] = os.path.join(
resourcepath, "openssl.ca", "certs")
_setup_openssl()
DEFAULT_SCRIPT='dicom2pacs.py'
SCRIPT_MAP={}
_run()

View File

@@ -0,0 +1,19 @@
#!/bin/sh
#
# This is the default apptemplate error script
#
echo "Launch error"
if [ -n "$2" ]; then
echo "An unexpected error has occurred during execution of the main script"
echo ""
echo "$2: $3"
echo ""
fi
echo "See the py2app website for debugging launch issues"
echo ""
echo "ERRORURL: https://py2app.readthedocs.io/en/latest/debugging.html"
exit

Binary file not shown.

View File

@@ -0,0 +1,225 @@
import sys
import os
import asyncio
from gui import GUI
import file_management
import threading
import dicom_processing
import shutil
import network_utils
from tkinter import filedialog
import tkinter as tk
# Konfigurationsvariablen
HOME_DIRECTORY = os.path.expanduser('~')
TRANSFER_FOLDER = os.path.join(HOME_DIRECTORY, 'Downloads/D2OTrans')
AUSGABE_DATEI = os.path.join(HOME_DIRECTORY, 't2o_modality.txt')
name = None
vorname = None
geburtsdatum = None
patienten_id = None
CONFIG_PATH = os.path.join(HOME_DIRECTORY, '.dicom2pacs.conf')
# Standardkonfigurationswerte
DEFAULT_CONFIG = {
'server_url': 'http://192.168.188.23:8042/instances',
'server_username': 'orthanc',
'server_pw': 'Praxis'
}
def save_default_config():
"""Speichert die Standardkonfiguration in der Konfigurationsdatei."""
try:
with open(CONFIG_PATH, 'w', encoding='utf-8') as config_file:
for key, value in DEFAULT_CONFIG.items():
config_file.write(f'{key}={value}\n')
except Exception as e:
print(f"Fehler beim Speichern der Standardkonfiguration: {e}")
def load_config():
"""Lädt die Konfiguration aus der Konfigurationsdatei. Erstellt die Datei mit Standardwerten, falls nicht vorhanden."""
config = {}
try:
with open(CONFIG_PATH, 'r', encoding='utf-8') as config_file:
for line in config_file:
line = line.strip()
if not line or line.startswith('#'): # Überspringe leere Zeilen und Kommentare
continue
if '=' in line:
key, value = line.split('=', 1)
config[key.strip()] = value.strip()
except FileNotFoundError:
print("Konfigurationsdatei nicht gefunden. Erstelle eine mit Standardwerten.")
save_default_config()
config = DEFAULT_CONFIG.copy() # Verwende Kopie der Standardwerte
except Exception as e:
print(f"Fehler beim Laden der Konfiguration: {e}")
print("Verwende Standardwerte.")
config = DEFAULT_CONFIG.copy()
return config
config = load_config()
server_url = config.get('server_url')
server_username = config.get('server_username')
server_pw = config.get('server_pw')
loop = asyncio.new_event_loop() # Initialisiere loop hier
# Erstelle den Event-Loop für asynchronen Code
def start_asyncio_loop():
global loop # Verweise auf die globale Variable loop
asyncio.set_event_loop(loop)
loop.run_forever()
asyncio_thread = threading.Thread(target=start_asyncio_loop, daemon=True)
asyncio_thread.start()
async def on_folder_selected_coro(folder_path, gui):
print("on_folder_selected gestartet")
await get_patientfiles(folder_path, gui)
upload_files = file_management.get_files_in_folder(TRANSFER_FOLDER)
if upload_files == 'no_transfer_folder':
results, folder_path = gui.ask_for_more("Bisher keine Bilder ausgewählt.\nAndere Orte durchsuchen?")
if results is False:
gui.on_app_close()
else:
if folder_path:
await get_patientfiles(folder_path, gui)
else:
file_paths = upload_files
print(file_paths)
if not file_paths or len(file_paths) == 0:
gui.start_animation("Keine Dateien zum Hochladen gefunden")
print("Keine Dateien zum Hochladen gefunden")
gui.on_app_close()
return
if not server_url:
gui.start_animation("FEHLER: Server-URL nicht konfiguriert")
print("FEHLER: Server-URL nicht konfiguriert")
gui.on_app_close()
return
availability = await network_utils.check_server_availability(server_url)
if availability:
print("Server ist verfügbar. Dateien werden hochgeladen.")
# Hier wird die Funktion upload_single_file asynchron aufgerufen
# In dicom_processing.process_dicom_files
gui.start_animation("Lade DICOM Dateien zum PACS Server hoch")
print(f"Starte Upload von {len(file_paths)} Dateien...")
uploaded_count, failed_count = await network_utils.upload_multiple_files(file_paths, server_url, server_username, server_pw, gui.upload_success, gui.upload_progress)
gui.stop_animation()
if failed_count == 0:
gui.start_animation("Bilddaten Im PACS erfolgreich eingelesen!")
await asyncio.sleep(3)
else:
gui.start_animation(f"Upload abgeschlossen: {uploaded_count}/{len(file_paths)} Dateien hochgeladen")
await asyncio.sleep(5) # Mehr Zeit, damit Benutzer die Meldung lesen kann
shutil.rmtree(TRANSFER_FOLDER)
print(f"Transferordner {TRANSFER_FOLDER} wurde gelöscht.")
gui.on_app_close()
else:
gui.start_animation("PACS SERVER NICHT ERREICHBAR")
print("Server ist nicht verfügbar.")
print("on_folder_selected abgeschlossen") # Debugging-Ausgabe
async def get_patientfiles(folder_path, gui):
print("Debugging-Ausgabe vor der Suche") # Debugging-Ausgabe
gui.hint_label.pack_forget()
while True:
gui.disable_browse_button()
gui.start_animation("Suche nach DICOM Dateien") # Starte die Suchanimation
print(folder_path)
files_found = file_management.find_dicom_files(folder_path)
if files_found == 'non_found':
gui.stop_animation()
results, folder_path = gui.ask_for_more("In diesem Ordner wurde keine Bilddaten gefunden.\nAndere Orte durchsuchen?")
if not results: # Wenn der Benutzer 'Nein' auswählt
break
else:
dicom_files, total_files = files_found
print(dicom_files)
gui.stop_animation() # Erhalte Dateien und Anzahl
print(f"Dicom-Dateien gefunden: {total_files}")
gui.start_animation("Kopiere DICOM Dateien in den Transfer Ordner")
await file_management.copy_dicom_files(dicom_files, folder_path, TRANSFER_FOLDER, gui.update_progress)
gui.stop_animation()
print(f"Dicom-Dateien wurden nach {TRANSFER_FOLDER} kopiert.")
current_dat_folder = file_management.get_latest_dat_folder(TRANSFER_FOLDER)
if not current_dat_folder:
gui.stop_animation()
gui.start_animation("FEHLER: Transferordner nicht gefunden")
print("FEHLER: Transferordner nicht gefunden")
break
gui.start_animation("Patienten ID wird mit Tomedo ID aktualisiert")
dicom_processing.update_patient_id_in_transfer_folder(current_dat_folder, patienten_id)
print("ID wurde aktualisiert")
gui.stop_animation()
print("Erstelle Ausgabedatei")
acq_date, modality = dicom_processing.extract_modality(current_dat_folder)
if acq_date and modality:
file_management.write_to_file(acq_date, modality, AUSGABE_DATEI)
else:
print("Warnung: Konnte Modality-Daten nicht extrahieren")
# Verarbeite die kopierten DICOM-Dateien synchron
await dicom_processing.process_dicom_files(current_dat_folder, gui, name, vorname, geburtsdatum, server_url, server_username, server_pw)
gui.stop_animation()
gui.enable_browse_button()
file_management.eject_cd_if_volume_path(folder_path)
results, new_folder_path = gui.ask_for_more("Sollen mehr Bilddaten für den Patienten eingelesen werden?")
print(f"Dialogergebnis: {results}")
if results and new_folder_path: # Wenn der Benutzer 'Ja' auswählt
gui.reset_progress(total_files)
folder_path = new_folder_path
if not results: # Wenn der Benutzer 'Nein' auswählt
break
def main():
global config, name, vorname, geburtsdatum, patienten_id
# Argumente prüfen
if len(sys.argv) != 5:
print("Bitte genau vier Argumente angeben: Name, Vorname, Geburtsdatum, Patienten_ID")
sys.exit(1)
# Argumente zuweisen
_, name, vorname, geburtsdatum, patienten_id = sys.argv
print(f"Name: {name}, Vorname: {vorname}, Geburtsdatum: {geburtsdatum}, Patienten_ID: {patienten_id}")
config = load_config() # Stellen Sie sicher, dass config geladen wird, bevor GUI initiiert wird
gui = GUI(None, TRANSFER_FOLDER, lambda: None, config)
# Definiere den Callback nach der Erstellung der GUI-Instanz
def on_folder_selected_callback(folder):
# Plane die Coroutine im asyncio Event-Loop
asyncio.run_coroutine_threadsafe(on_folder_selected_coro(folder, gui), loop)
# Setze den Callback in der GUI-Instanz
gui.on_folder_selected = on_folder_selected_callback
# Funktion, die überprüft, ob eine CD eingelegt ist, und diese verarbeitet
def check_cd_and_select():
cd_path = file_management.check_for_cd_at_start()
if cd_path:
print(f"CD gefunden: {cd_path}")
gui.root.after(100, lambda: on_folder_selected_callback(cd_path))
else:
print("Keine CD gefunden, bitte Ordner manuell auswählen.")
# Stelle sicher, dass on_app_close als Methode der GUI-Klasse definiert ist
gui.root.protocol("WM_DELETE_WINDOW", gui.on_app_close)
# Überprüfe, ob eine CD eingelegt ist, bevor die GUI vollständig gestartet wird
# Überprüfe die Einstellung und führe ggf. die CD-Überprüfung aus
if config.get('check_for_cd', '0') == '1':
check_cd_and_select()
# Starte die GUI
gui.start()
if __name__ == "__main__":
main()

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
"""Utilities for asyncio-friendly file handling."""
from . import tempfile
from .threadpool import (
open,
stderr,
stderr_bytes,
stdin,
stdin_bytes,
stdout,
stdout_bytes,
)
__all__ = [
"open",
"tempfile",
"stdin",
"stdout",
"stderr",
"stdin_bytes",
"stdout_bytes",
"stderr_bytes",
]

View File

@@ -0,0 +1,79 @@
from asyncio import get_running_loop
from collections.abc import Awaitable
from contextlib import AbstractAsyncContextManager
from functools import partial, wraps
def wrap(func):
@wraps(func)
async def run(*args, loop=None, executor=None, **kwargs):
if loop is None:
loop = get_running_loop()
pfunc = partial(func, *args, **kwargs)
return await loop.run_in_executor(executor, pfunc)
return run
class AsyncBase:
def __init__(self, file, loop, executor):
self._file = file
self._executor = executor
self._ref_loop = loop
@property
def _loop(self):
return self._ref_loop or get_running_loop()
def __aiter__(self):
"""We are our own iterator."""
return self
def __repr__(self):
return super().__repr__() + " wrapping " + repr(self._file)
async def __anext__(self):
"""Simulate normal file iteration."""
if line := await self.readline():
return line
raise StopAsyncIteration
class AsyncIndirectBase(AsyncBase):
def __init__(self, name, loop, executor, indirect):
self._indirect = indirect
self._name = name
super().__init__(None, loop, executor)
@property
def _file(self):
return self._indirect()
@_file.setter
def _file(self, v):
pass # discard writes
class AiofilesContextManager(Awaitable, AbstractAsyncContextManager):
"""An adjusted async context manager for aiofiles."""
__slots__ = ("_coro", "_obj")
def __init__(self, coro):
self._coro = coro
self._obj = None
def __await__(self):
if self._obj is None:
self._obj = yield from self._coro.__await__()
return self._obj
async def __aenter__(self):
return await self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await get_running_loop().run_in_executor(
None, self._obj._file.__exit__, exc_type, exc_val, exc_tb
)
self._obj = None

View File

@@ -0,0 +1,61 @@
"""Async executor versions of file functions from the os module."""
import os
from . import ospath as path
from .base import wrap
__all__ = [
"path",
"stat",
"rename",
"renames",
"replace",
"remove",
"unlink",
"mkdir",
"makedirs",
"rmdir",
"removedirs",
"symlink",
"readlink",
"listdir",
"scandir",
"access",
"wrap",
"getcwd",
]
access = wrap(os.access)
getcwd = wrap(os.getcwd)
listdir = wrap(os.listdir)
makedirs = wrap(os.makedirs)
mkdir = wrap(os.mkdir)
readlink = wrap(os.readlink)
remove = wrap(os.remove)
removedirs = wrap(os.removedirs)
rename = wrap(os.rename)
renames = wrap(os.renames)
replace = wrap(os.replace)
rmdir = wrap(os.rmdir)
scandir = wrap(os.scandir)
stat = wrap(os.stat)
symlink = wrap(os.symlink)
unlink = wrap(os.unlink)
if hasattr(os, "link"):
__all__ += ["link"]
link = wrap(os.link)
if hasattr(os, "sendfile"):
__all__ += ["sendfile"]
sendfile = wrap(os.sendfile)
if hasattr(os, "statvfs"):
__all__ += ["statvfs"]
statvfs = wrap(os.statvfs)

View File

@@ -0,0 +1,37 @@
"""Async executor versions of file functions from the os.path module."""
from os import path
from .base import wrap
__all__ = [
"abspath",
"getatime",
"getctime",
"getmtime",
"getsize",
"exists",
"isdir",
"isfile",
"islink",
"ismount",
"samefile",
"sameopenfile",
]
abspath = wrap(path.abspath)
getatime = wrap(path.getatime)
getctime = wrap(path.getctime)
getmtime = wrap(path.getmtime)
getsize = wrap(path.getsize)
exists = wrap(path.exists)
isdir = wrap(path.isdir)
isfile = wrap(path.isfile)
islink = wrap(path.islink)
ismount = wrap(path.ismount)
samefile = wrap(path.samefile)
sameopenfile = wrap(path.sameopenfile)

View File

@@ -0,0 +1,357 @@
import asyncio
import sys
from functools import partial, singledispatch
from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOBase
from tempfile import NamedTemporaryFile as syncNamedTemporaryFile
from tempfile import SpooledTemporaryFile as syncSpooledTemporaryFile
from tempfile import TemporaryDirectory as syncTemporaryDirectory
from tempfile import TemporaryFile as syncTemporaryFile
from tempfile import _TemporaryFileWrapper as syncTemporaryFileWrapper
from ..base import AiofilesContextManager
from ..threadpool.binary import AsyncBufferedIOBase, AsyncBufferedReader, AsyncFileIO
from ..threadpool.text import AsyncTextIOWrapper
from .temptypes import AsyncSpooledTemporaryFile, AsyncTemporaryDirectory
__all__ = [
"NamedTemporaryFile",
"TemporaryFile",
"SpooledTemporaryFile",
"TemporaryDirectory",
]
# ================================================================
# Public methods for async open and return of temp file/directory
# objects with async interface
# ================================================================
if sys.version_info >= (3, 12):
def NamedTemporaryFile(
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
delete=True,
delete_on_close=True,
loop=None,
executor=None,
):
"""Async open a named temporary file"""
return AiofilesContextManager(
_temporary_file(
named=True,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
delete=delete,
delete_on_close=delete_on_close,
loop=loop,
executor=executor,
)
)
else:
def NamedTemporaryFile(
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
delete=True,
loop=None,
executor=None,
):
"""Async open a named temporary file"""
return AiofilesContextManager(
_temporary_file(
named=True,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
delete=delete,
loop=loop,
executor=executor,
)
)
def TemporaryFile(
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
loop=None,
executor=None,
):
"""Async open an unnamed temporary file"""
return AiofilesContextManager(
_temporary_file(
named=False,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
loop=loop,
executor=executor,
)
)
def SpooledTemporaryFile(
max_size=0,
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
loop=None,
executor=None,
):
"""Async open a spooled temporary file"""
return AiofilesContextManager(
_spooled_temporary_file(
max_size=max_size,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
loop=loop,
executor=executor,
)
)
def TemporaryDirectory(suffix=None, prefix=None, dir=None, loop=None, executor=None):
"""Async open a temporary directory"""
return AiofilesContextManagerTempDir(
_temporary_directory(
suffix=suffix, prefix=prefix, dir=dir, loop=loop, executor=executor
)
)
# =========================================================
# Internal coroutines to open new temp files/directories
# =========================================================
if sys.version_info >= (3, 12):
async def _temporary_file(
named=True,
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
delete=True,
delete_on_close=True,
loop=None,
executor=None,
max_size=0,
):
"""Async method to open a temporary file with async interface"""
if loop is None:
loop = asyncio.get_running_loop()
if named:
cb = partial(
syncNamedTemporaryFile,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
delete=delete,
delete_on_close=delete_on_close,
)
else:
cb = partial(
syncTemporaryFile,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
)
f = await loop.run_in_executor(executor, cb)
# Wrap based on type of underlying IO object
if type(f) is syncTemporaryFileWrapper:
# _TemporaryFileWrapper was used (named files)
result = wrap(f.file, f, loop=loop, executor=executor)
result._closer = f._closer
return result
# IO object was returned directly without wrapper
return wrap(f, f, loop=loop, executor=executor)
else:
async def _temporary_file(
named=True,
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
delete=True,
loop=None,
executor=None,
max_size=0,
):
"""Async method to open a temporary file with async interface"""
if loop is None:
loop = asyncio.get_running_loop()
if named:
cb = partial(
syncNamedTemporaryFile,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
delete=delete,
)
else:
cb = partial(
syncTemporaryFile,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
)
f = await loop.run_in_executor(executor, cb)
# Wrap based on type of underlying IO object
if type(f) is syncTemporaryFileWrapper:
# _TemporaryFileWrapper was used (named files)
result = wrap(f.file, f, loop=loop, executor=executor)
# add delete property
result.delete = f.delete
return result
# IO object was returned directly without wrapper
return wrap(f, f, loop=loop, executor=executor)
async def _spooled_temporary_file(
max_size=0,
mode="w+b",
buffering=-1,
encoding=None,
newline=None,
suffix=None,
prefix=None,
dir=None,
loop=None,
executor=None,
):
"""Open a spooled temporary file with async interface"""
if loop is None:
loop = asyncio.get_running_loop()
cb = partial(
syncSpooledTemporaryFile,
max_size=max_size,
mode=mode,
buffering=buffering,
encoding=encoding,
newline=newline,
suffix=suffix,
prefix=prefix,
dir=dir,
)
f = await loop.run_in_executor(executor, cb)
# Single interface provided by SpooledTemporaryFile for all modes
return AsyncSpooledTemporaryFile(f, loop=loop, executor=executor)
async def _temporary_directory(
suffix=None, prefix=None, dir=None, loop=None, executor=None
):
"""Async method to open a temporary directory with async interface"""
if loop is None:
loop = asyncio.get_running_loop()
cb = partial(syncTemporaryDirectory, suffix, prefix, dir)
f = await loop.run_in_executor(executor, cb)
return AsyncTemporaryDirectory(f, loop=loop, executor=executor)
class AiofilesContextManagerTempDir(AiofilesContextManager):
"""With returns the directory location, not the object (matching sync lib)"""
async def __aenter__(self):
self._obj = await self._coro
return self._obj.name
@singledispatch
def wrap(base_io_obj, file, *, loop=None, executor=None):
"""Wrap the object with interface based on type of underlying IO"""
msg = f"Unsupported IO type: {base_io_obj}"
raise TypeError(msg)
@wrap.register(TextIOBase)
def _(base_io_obj, file, *, loop=None, executor=None):
return AsyncTextIOWrapper(file, loop=loop, executor=executor)
@wrap.register(BufferedWriter)
def _(base_io_obj, file, *, loop=None, executor=None):
return AsyncBufferedIOBase(file, loop=loop, executor=executor)
@wrap.register(BufferedReader)
@wrap.register(BufferedRandom)
def _(base_io_obj, file, *, loop=None, executor=None):
return AsyncBufferedReader(file, loop=loop, executor=executor)
@wrap.register(FileIO)
def _(base_io_obj, file, *, loop=None, executor=None):
return AsyncFileIO(file, loop=loop, executor=executor)

View File

@@ -0,0 +1,70 @@
"""Async wrappers for spooled temp files and temp directory objects"""
from functools import partial
from ..base import AsyncBase
from ..threadpool.utils import (
cond_delegate_to_executor,
delegate_to_executor,
proxy_property_directly,
)
@delegate_to_executor("fileno", "rollover")
@cond_delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"readline",
"readlines",
"seek",
"tell",
"truncate",
)
@proxy_property_directly("closed", "encoding", "mode", "name", "newlines")
class AsyncSpooledTemporaryFile(AsyncBase):
"""Async wrapper for SpooledTemporaryFile class"""
async def _check(self):
if self._file._rolled:
return
max_size = self._file._max_size
if max_size and self._file.tell() > max_size:
await self.rollover()
async def write(self, s):
"""Implementation to anticipate rollover"""
if self._file._rolled:
cb = partial(self._file.write, s)
return await self._loop.run_in_executor(self._executor, cb)
file = self._file._file # reference underlying base IO object
rv = file.write(s)
await self._check()
return rv
async def writelines(self, iterable):
"""Implementation to anticipate rollover"""
if self._file._rolled:
cb = partial(self._file.writelines, iterable)
return await self._loop.run_in_executor(self._executor, cb)
file = self._file._file # reference underlying base IO object
rv = file.writelines(iterable)
await self._check()
return rv
@delegate_to_executor("cleanup")
@proxy_property_directly("name")
class AsyncTemporaryDirectory:
"""Async wrapper for TemporaryDirectory class"""
def __init__(self, file, loop, executor):
self._file = file
self._loop = loop
self._executor = executor
async def close(self):
await self.cleanup()

View File

@@ -0,0 +1,141 @@
"""Handle files using a thread pool executor."""
import asyncio
import sys
from functools import partial, singledispatch
from io import (
BufferedIOBase,
BufferedRandom,
BufferedReader,
BufferedWriter,
FileIO,
TextIOBase,
)
from ..base import AiofilesContextManager
from .binary import (
AsyncBufferedIOBase,
AsyncBufferedReader,
AsyncFileIO,
AsyncIndirectBufferedIOBase,
)
from .text import AsyncTextIndirectIOWrapper, AsyncTextIOWrapper
sync_open = open
__all__ = (
"open",
"stdin",
"stdout",
"stderr",
"stdin_bytes",
"stdout_bytes",
"stderr_bytes",
)
def open(
file,
mode="r",
buffering=-1,
encoding=None,
errors=None,
newline=None,
closefd=True,
opener=None,
*,
loop=None,
executor=None,
):
return AiofilesContextManager(
_open(
file,
mode=mode,
buffering=buffering,
encoding=encoding,
errors=errors,
newline=newline,
closefd=closefd,
opener=opener,
loop=loop,
executor=executor,
)
)
async def _open(
file,
mode="r",
buffering=-1,
encoding=None,
errors=None,
newline=None,
closefd=True,
opener=None,
*,
loop=None,
executor=None,
):
"""Open an asyncio file."""
if loop is None:
loop = asyncio.get_running_loop()
cb = partial(
sync_open,
file,
mode=mode,
buffering=buffering,
encoding=encoding,
errors=errors,
newline=newline,
closefd=closefd,
opener=opener,
)
f = await loop.run_in_executor(executor, cb)
return wrap(f, loop=loop, executor=executor)
@singledispatch
def wrap(file, *, loop=None, executor=None):
msg = f"Unsupported io type: {file}."
raise TypeError(msg)
@wrap.register(TextIOBase)
def _(file, *, loop=None, executor=None):
return AsyncTextIOWrapper(file, loop=loop, executor=executor)
@wrap.register(BufferedWriter)
@wrap.register(BufferedIOBase)
def _(file, *, loop=None, executor=None):
return AsyncBufferedIOBase(file, loop=loop, executor=executor)
@wrap.register(BufferedReader)
@wrap.register(BufferedRandom)
def _(file, *, loop=None, executor=None):
return AsyncBufferedReader(file, loop=loop, executor=executor)
@wrap.register(FileIO)
def _(file, *, loop=None, executor=None):
return AsyncFileIO(file, loop=loop, executor=executor)
stdin = AsyncTextIndirectIOWrapper("sys.stdin", None, None, indirect=lambda: sys.stdin)
stdout = AsyncTextIndirectIOWrapper(
"sys.stdout", None, None, indirect=lambda: sys.stdout
)
stderr = AsyncTextIndirectIOWrapper(
"sys.stderr", None, None, indirect=lambda: sys.stderr
)
stdin_bytes = AsyncIndirectBufferedIOBase(
"sys.stdin.buffer", None, None, indirect=lambda: sys.stdin.buffer
)
stdout_bytes = AsyncIndirectBufferedIOBase(
"sys.stdout.buffer", None, None, indirect=lambda: sys.stdout.buffer
)
stderr_bytes = AsyncIndirectBufferedIOBase(
"sys.stderr.buffer", None, None, indirect=lambda: sys.stderr.buffer
)

View File

@@ -0,0 +1,104 @@
from ..base import AsyncBase, AsyncIndirectBase
from .utils import delegate_to_executor, proxy_method_directly, proxy_property_directly
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"read1",
"readinto",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"writable",
"write",
"writelines",
)
@proxy_method_directly("detach", "fileno", "readable")
@proxy_property_directly("closed", "raw", "name", "mode")
class AsyncBufferedIOBase(AsyncBase):
"""The asyncio executor version of io.BufferedWriter and BufferedIOBase."""
@delegate_to_executor("peek")
class AsyncBufferedReader(AsyncBufferedIOBase):
"""The asyncio executor version of io.BufferedReader and Random."""
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"readall",
"readinto",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"writable",
"write",
"writelines",
)
@proxy_method_directly("fileno", "readable")
@proxy_property_directly("closed", "name", "mode")
class AsyncFileIO(AsyncBase):
"""The asyncio executor version of io.FileIO."""
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"read1",
"readinto",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"writable",
"write",
"writelines",
)
@proxy_method_directly("detach", "fileno", "readable")
@proxy_property_directly("closed", "raw", "name", "mode")
class AsyncIndirectBufferedIOBase(AsyncIndirectBase):
"""The indirect asyncio executor version of io.BufferedWriter and BufferedIOBase."""
@delegate_to_executor("peek")
class AsyncIndirectBufferedReader(AsyncIndirectBufferedIOBase):
"""The indirect asyncio executor version of io.BufferedReader and Random."""
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"readall",
"readinto",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"writable",
"write",
"writelines",
)
@proxy_method_directly("fileno", "readable")
@proxy_property_directly("closed", "name", "mode")
class AsyncIndirectFileIO(AsyncIndirectBase):
"""The indirect asyncio executor version of io.FileIO."""

View File

@@ -0,0 +1,64 @@
from ..base import AsyncBase, AsyncIndirectBase
from .utils import delegate_to_executor, proxy_method_directly, proxy_property_directly
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"readable",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"write",
"writable",
"writelines",
)
@proxy_method_directly("detach", "fileno", "readable")
@proxy_property_directly(
"buffer",
"closed",
"encoding",
"errors",
"line_buffering",
"newlines",
"name",
"mode",
)
class AsyncTextIOWrapper(AsyncBase):
"""The asyncio executor version of io.TextIOWrapper."""
@delegate_to_executor(
"close",
"flush",
"isatty",
"read",
"readable",
"readline",
"readlines",
"seek",
"seekable",
"tell",
"truncate",
"write",
"writable",
"writelines",
)
@proxy_method_directly("detach", "fileno", "readable")
@proxy_property_directly(
"buffer",
"closed",
"encoding",
"errors",
"line_buffering",
"newlines",
"name",
"mode",
)
class AsyncTextIndirectIOWrapper(AsyncIndirectBase):
"""The indirect asyncio executor version of io.TextIOWrapper."""

View File

@@ -0,0 +1,71 @@
import functools
def delegate_to_executor(*attrs):
def cls_builder(cls):
for attr_name in attrs:
setattr(cls, attr_name, _make_delegate_method(attr_name))
return cls
return cls_builder
def proxy_method_directly(*attrs):
def cls_builder(cls):
for attr_name in attrs:
setattr(cls, attr_name, _make_proxy_method(attr_name))
return cls
return cls_builder
def proxy_property_directly(*attrs):
def cls_builder(cls):
for attr_name in attrs:
setattr(cls, attr_name, _make_proxy_property(attr_name))
return cls
return cls_builder
def cond_delegate_to_executor(*attrs):
def cls_builder(cls):
for attr_name in attrs:
setattr(cls, attr_name, _make_cond_delegate_method(attr_name))
return cls
return cls_builder
def _make_delegate_method(attr_name):
async def method(self, *args, **kwargs):
cb = functools.partial(getattr(self._file, attr_name), *args, **kwargs)
return await self._loop.run_in_executor(self._executor, cb)
return method
def _make_proxy_method(attr_name):
def method(self, *args, **kwargs):
return getattr(self._file, attr_name)(*args, **kwargs)
return method
def _make_proxy_property(attr_name):
def proxy_property(self):
return getattr(self._file, attr_name)
return property(proxy_property)
def _make_cond_delegate_method(attr_name):
"""For spooled temp files, delegate only if rolled to file object"""
async def method(self, *args, **kwargs):
if self._file._rolled:
cb = functools.partial(getattr(self._file, attr_name), *args, **kwargs)
return await self._loop.run_in_executor(self._executor, cb)
return getattr(self._file, attr_name)(*args, **kwargs)
return method

View File

@@ -0,0 +1 @@
5276d46021e0e0d7577e0c9155800cbf62932d60a50783fec42aefb63febedec /Users/runner/work/aiohttp/aiohttp/aiohttp/_cparser.pxd

View File

@@ -0,0 +1 @@
d067f01423cddb3c442933b5fcc039b18ab651fcec1bc91c577693aafc25cf78 /Users/runner/work/aiohttp/aiohttp/aiohttp/_find_header.pxd

View File

@@ -0,0 +1 @@
f9823c608638b8a77fec1c2bd28dc5c043f08c775ec59e7e262dd74b4ebb7384 /Users/runner/work/aiohttp/aiohttp/aiohttp/_http_parser.pyx

View File

@@ -0,0 +1 @@
56514404ce87a15bfc6b400026d73a270165b2fdbe70313cfa007de29ddd7e14 /Users/runner/work/aiohttp/aiohttp/aiohttp/_http_writer.pyx

View File

@@ -0,0 +1 @@
dab8f933203eeb245d60f856e542a45b888d5a110094620e4811f90f816628d1 /Users/runner/work/aiohttp/aiohttp/aiohttp/hdrs.py

View File

@@ -0,0 +1,278 @@
__version__ = "3.13.3"
from typing import TYPE_CHECKING, Tuple
from . import hdrs as hdrs
from .client import (
BaseConnector,
ClientConnectionError,
ClientConnectionResetError,
ClientConnectorCertificateError,
ClientConnectorDNSError,
ClientConnectorError,
ClientConnectorSSLError,
ClientError,
ClientHttpProxyError,
ClientOSError,
ClientPayloadError,
ClientProxyConnectionError,
ClientRequest,
ClientResponse,
ClientResponseError,
ClientSession,
ClientSSLError,
ClientTimeout,
ClientWebSocketResponse,
ClientWSTimeout,
ConnectionTimeoutError,
ContentTypeError,
Fingerprint,
InvalidURL,
InvalidUrlClientError,
InvalidUrlRedirectClientError,
NamedPipeConnector,
NonHttpUrlClientError,
NonHttpUrlRedirectClientError,
RedirectClientError,
RequestInfo,
ServerConnectionError,
ServerDisconnectedError,
ServerFingerprintMismatch,
ServerTimeoutError,
SocketTimeoutError,
TCPConnector,
TooManyRedirects,
UnixConnector,
WSMessageTypeError,
WSServerHandshakeError,
request,
)
from .client_middleware_digest_auth import DigestAuthMiddleware
from .client_middlewares import ClientHandlerType, ClientMiddlewareType
from .compression_utils import set_zlib_backend
from .connector import (
AddrInfoType as AddrInfoType,
SocketFactoryType as SocketFactoryType,
)
from .cookiejar import CookieJar as CookieJar, DummyCookieJar as DummyCookieJar
from .formdata import FormData as FormData
from .helpers import BasicAuth, ChainMapProxy, ETag
from .http import (
HttpVersion as HttpVersion,
HttpVersion10 as HttpVersion10,
HttpVersion11 as HttpVersion11,
WebSocketError as WebSocketError,
WSCloseCode as WSCloseCode,
WSMessage as WSMessage,
WSMsgType as WSMsgType,
)
from .multipart import (
BadContentDispositionHeader as BadContentDispositionHeader,
BadContentDispositionParam as BadContentDispositionParam,
BodyPartReader as BodyPartReader,
MultipartReader as MultipartReader,
MultipartWriter as MultipartWriter,
content_disposition_filename as content_disposition_filename,
parse_content_disposition as parse_content_disposition,
)
from .payload import (
PAYLOAD_REGISTRY as PAYLOAD_REGISTRY,
AsyncIterablePayload as AsyncIterablePayload,
BufferedReaderPayload as BufferedReaderPayload,
BytesIOPayload as BytesIOPayload,
BytesPayload as BytesPayload,
IOBasePayload as IOBasePayload,
JsonPayload as JsonPayload,
Payload as Payload,
StringIOPayload as StringIOPayload,
StringPayload as StringPayload,
TextIOPayload as TextIOPayload,
get_payload as get_payload,
payload_type as payload_type,
)
from .payload_streamer import streamer as streamer
from .resolver import (
AsyncResolver as AsyncResolver,
DefaultResolver as DefaultResolver,
ThreadedResolver as ThreadedResolver,
)
from .streams import (
EMPTY_PAYLOAD as EMPTY_PAYLOAD,
DataQueue as DataQueue,
EofStream as EofStream,
FlowControlDataQueue as FlowControlDataQueue,
StreamReader as StreamReader,
)
from .tracing import (
TraceConfig as TraceConfig,
TraceConnectionCreateEndParams as TraceConnectionCreateEndParams,
TraceConnectionCreateStartParams as TraceConnectionCreateStartParams,
TraceConnectionQueuedEndParams as TraceConnectionQueuedEndParams,
TraceConnectionQueuedStartParams as TraceConnectionQueuedStartParams,
TraceConnectionReuseconnParams as TraceConnectionReuseconnParams,
TraceDnsCacheHitParams as TraceDnsCacheHitParams,
TraceDnsCacheMissParams as TraceDnsCacheMissParams,
TraceDnsResolveHostEndParams as TraceDnsResolveHostEndParams,
TraceDnsResolveHostStartParams as TraceDnsResolveHostStartParams,
TraceRequestChunkSentParams as TraceRequestChunkSentParams,
TraceRequestEndParams as TraceRequestEndParams,
TraceRequestExceptionParams as TraceRequestExceptionParams,
TraceRequestHeadersSentParams as TraceRequestHeadersSentParams,
TraceRequestRedirectParams as TraceRequestRedirectParams,
TraceRequestStartParams as TraceRequestStartParams,
TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams,
)
if TYPE_CHECKING:
# At runtime these are lazy-loaded at the bottom of the file.
from .worker import (
GunicornUVLoopWebWorker as GunicornUVLoopWebWorker,
GunicornWebWorker as GunicornWebWorker,
)
__all__: Tuple[str, ...] = (
"hdrs",
# client
"AddrInfoType",
"BaseConnector",
"ClientConnectionError",
"ClientConnectionResetError",
"ClientConnectorCertificateError",
"ClientConnectorDNSError",
"ClientConnectorError",
"ClientConnectorSSLError",
"ClientError",
"ClientHttpProxyError",
"ClientOSError",
"ClientPayloadError",
"ClientProxyConnectionError",
"ClientResponse",
"ClientRequest",
"ClientResponseError",
"ClientSSLError",
"ClientSession",
"ClientTimeout",
"ClientWebSocketResponse",
"ClientWSTimeout",
"ConnectionTimeoutError",
"ContentTypeError",
"Fingerprint",
"FlowControlDataQueue",
"InvalidURL",
"InvalidUrlClientError",
"InvalidUrlRedirectClientError",
"NonHttpUrlClientError",
"NonHttpUrlRedirectClientError",
"RedirectClientError",
"RequestInfo",
"ServerConnectionError",
"ServerDisconnectedError",
"ServerFingerprintMismatch",
"ServerTimeoutError",
"SocketFactoryType",
"SocketTimeoutError",
"TCPConnector",
"TooManyRedirects",
"UnixConnector",
"NamedPipeConnector",
"WSServerHandshakeError",
"request",
# client_middleware
"ClientMiddlewareType",
"ClientHandlerType",
# cookiejar
"CookieJar",
"DummyCookieJar",
# formdata
"FormData",
# helpers
"BasicAuth",
"ChainMapProxy",
"DigestAuthMiddleware",
"ETag",
"set_zlib_backend",
# http
"HttpVersion",
"HttpVersion10",
"HttpVersion11",
"WSMsgType",
"WSCloseCode",
"WSMessage",
"WebSocketError",
# multipart
"BadContentDispositionHeader",
"BadContentDispositionParam",
"BodyPartReader",
"MultipartReader",
"MultipartWriter",
"content_disposition_filename",
"parse_content_disposition",
# payload
"AsyncIterablePayload",
"BufferedReaderPayload",
"BytesIOPayload",
"BytesPayload",
"IOBasePayload",
"JsonPayload",
"PAYLOAD_REGISTRY",
"Payload",
"StringIOPayload",
"StringPayload",
"TextIOPayload",
"get_payload",
"payload_type",
# payload_streamer
"streamer",
# resolver
"AsyncResolver",
"DefaultResolver",
"ThreadedResolver",
# streams
"DataQueue",
"EMPTY_PAYLOAD",
"EofStream",
"StreamReader",
# tracing
"TraceConfig",
"TraceConnectionCreateEndParams",
"TraceConnectionCreateStartParams",
"TraceConnectionQueuedEndParams",
"TraceConnectionQueuedStartParams",
"TraceConnectionReuseconnParams",
"TraceDnsCacheHitParams",
"TraceDnsCacheMissParams",
"TraceDnsResolveHostEndParams",
"TraceDnsResolveHostStartParams",
"TraceRequestChunkSentParams",
"TraceRequestEndParams",
"TraceRequestExceptionParams",
"TraceRequestHeadersSentParams",
"TraceRequestRedirectParams",
"TraceRequestStartParams",
"TraceResponseChunkReceivedParams",
# workers (imported lazily with __getattr__)
"GunicornUVLoopWebWorker",
"GunicornWebWorker",
"WSMessageTypeError",
)
def __dir__() -> Tuple[str, ...]:
return __all__ + ("__doc__",)
def __getattr__(name: str) -> object:
global GunicornUVLoopWebWorker, GunicornWebWorker
# Importing gunicorn takes a long time (>100ms), so only import if actually needed.
if name in ("GunicornUVLoopWebWorker", "GunicornWebWorker"):
try:
from .worker import GunicornUVLoopWebWorker as guv, GunicornWebWorker as gw
except ImportError:
return None
GunicornUVLoopWebWorker = guv # type: ignore[misc]
GunicornWebWorker = gw # type: ignore[misc]
return guv if name == "GunicornUVLoopWebWorker" else gw
raise AttributeError(f"module {__name__} has no attribute {name}")

Some files were not shown because too many files have changed in this diff Show More