patchright 1.48.0__py3-none-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- patchright/__init__.py +5 -0
- patchright/__main__.py +18 -0
- patchright/_impl/__init__.py +0 -0
- patchright/_impl/__pyinstaller/__init__.py +20 -0
- patchright/_impl/__pyinstaller/hook-playwright.async_api.py +17 -0
- patchright/_impl/__pyinstaller/hook-playwright.sync_api.py +17 -0
- patchright/_impl/_accessibility.py +50 -0
- patchright/_impl/_api_structures.py +271 -0
- patchright/_impl/_artifact.py +45 -0
- patchright/_impl/_assertions.py +779 -0
- patchright/_impl/_async_base.py +92 -0
- patchright/_impl/_browser.py +243 -0
- patchright/_impl/_browser_context.py +724 -0
- patchright/_impl/_browser_type.py +264 -0
- patchright/_impl/_cdp_session.py +21 -0
- patchright/_impl/_clock.py +57 -0
- patchright/_impl/_connection.py +554 -0
- patchright/_impl/_console_message.py +45 -0
- patchright/_impl/_dialog.py +40 -0
- patchright/_impl/_download.py +50 -0
- patchright/_impl/_driver.py +26 -0
- patchright/_impl/_element_handle.py +376 -0
- patchright/_impl/_errors.py +44 -0
- patchright/_impl/_event_context_manager.py +20 -0
- patchright/_impl/_fetch.py +511 -0
- patchright/_impl/_file_chooser.py +43 -0
- patchright/_impl/_frame.py +755 -0
- patchright/_impl/_glob.py +51 -0
- patchright/_impl/_greenlets.py +39 -0
- patchright/_impl/_har_router.py +99 -0
- patchright/_impl/_helper.py +421 -0
- patchright/_impl/_impl_to_api_mapping.py +123 -0
- patchright/_impl/_input.py +71 -0
- patchright/_impl/_js_handle.py +234 -0
- patchright/_impl/_json_pipe.py +56 -0
- patchright/_impl/_local_utils.py +73 -0
- patchright/_impl/_locator.py +784 -0
- patchright/_impl/_map.py +19 -0
- patchright/_impl/_network.py +934 -0
- patchright/_impl/_object_factory.py +91 -0
- patchright/_impl/_page.py +1446 -0
- patchright/_impl/_path_utils.py +11 -0
- patchright/_impl/_playwright.py +51 -0
- patchright/_impl/_selectors.py +62 -0
- patchright/_impl/_set_input_files_helpers.py +135 -0
- patchright/_impl/_str_utils.py +57 -0
- patchright/_impl/_stream.py +32 -0
- patchright/_impl/_sync_base.py +134 -0
- patchright/_impl/_tracing.py +103 -0
- patchright/_impl/_transport.py +150 -0
- patchright/_impl/_video.py +57 -0
- patchright/_impl/_waiter.py +142 -0
- patchright/_impl/_web_error.py +22 -0
- patchright/_impl/_writable_stream.py +27 -0
- patchright/_repo_version.py +12 -0
- patchright/async_api/__init__.py +177 -0
- patchright/async_api/_context_manager.py +39 -0
- patchright/async_api/_generated.py +19960 -0
- patchright/driver/LICENSE +2174 -0
- patchright/driver/README.md +1 -0
- patchright/driver/node.exe +0 -0
- patchright/driver/package/README.md +3 -0
- patchright/driver/package/ThirdPartyNotices.txt +1548 -0
- patchright/driver/package/api.json +1 -0
- patchright/driver/package/bin/PrintDeps.exe +0 -0
- patchright/driver/package/bin/README.md +2 -0
- patchright/driver/package/bin/install_media_pack.ps1 +5 -0
- patchright/driver/package/bin/reinstall_chrome_beta_linux.sh +40 -0
- patchright/driver/package/bin/reinstall_chrome_beta_mac.sh +13 -0
- patchright/driver/package/bin/reinstall_chrome_beta_win.ps1 +24 -0
- patchright/driver/package/bin/reinstall_chrome_stable_linux.sh +40 -0
- patchright/driver/package/bin/reinstall_chrome_stable_mac.sh +12 -0
- patchright/driver/package/bin/reinstall_chrome_stable_win.ps1 +24 -0
- patchright/driver/package/bin/reinstall_msedge_beta_linux.sh +40 -0
- patchright/driver/package/bin/reinstall_msedge_beta_mac.sh +11 -0
- patchright/driver/package/bin/reinstall_msedge_beta_win.ps1 +23 -0
- patchright/driver/package/bin/reinstall_msedge_dev_linux.sh +40 -0
- patchright/driver/package/bin/reinstall_msedge_dev_mac.sh +11 -0
- patchright/driver/package/bin/reinstall_msedge_dev_win.ps1 +23 -0
- patchright/driver/package/bin/reinstall_msedge_stable_linux.sh +40 -0
- patchright/driver/package/bin/reinstall_msedge_stable_mac.sh +11 -0
- patchright/driver/package/bin/reinstall_msedge_stable_win.ps1 +24 -0
- patchright/driver/package/browsers.json +57 -0
- patchright/driver/package/cli.js +18 -0
- patchright/driver/package/index.d.ts +17 -0
- patchright/driver/package/index.js +33 -0
- patchright/driver/package/index.mjs +28 -0
- patchright/driver/package/lib/androidServerImpl.js +69 -0
- patchright/driver/package/lib/browserServerImpl.js +92 -0
- patchright/driver/package/lib/cli/driver.js +95 -0
- patchright/driver/package/lib/cli/program.js +587 -0
- patchright/driver/package/lib/cli/programWithTestStub.js +67 -0
- patchright/driver/package/lib/client/accessibility.js +50 -0
- patchright/driver/package/lib/client/android.js +473 -0
- patchright/driver/package/lib/client/api.js +285 -0
- patchright/driver/package/lib/client/artifact.js +79 -0
- patchright/driver/package/lib/client/browser.js +145 -0
- patchright/driver/package/lib/client/browserContext.js +559 -0
- patchright/driver/package/lib/client/browserType.js +241 -0
- patchright/driver/package/lib/client/cdpSession.js +53 -0
- patchright/driver/package/lib/client/channelOwner.js +235 -0
- patchright/driver/package/lib/client/clientHelper.js +57 -0
- patchright/driver/package/lib/client/clientInstrumentation.js +50 -0
- patchright/driver/package/lib/client/clock.js +68 -0
- patchright/driver/package/lib/client/connection.js +333 -0
- patchright/driver/package/lib/client/consoleMessage.js +55 -0
- patchright/driver/package/lib/client/coverage.js +41 -0
- patchright/driver/package/lib/client/dialog.js +57 -0
- patchright/driver/package/lib/client/download.js +62 -0
- patchright/driver/package/lib/client/electron.js +135 -0
- patchright/driver/package/lib/client/elementHandle.js +321 -0
- patchright/driver/package/lib/client/errors.js +77 -0
- patchright/driver/package/lib/client/eventEmitter.js +314 -0
- patchright/driver/package/lib/client/events.js +94 -0
- patchright/driver/package/lib/client/fetch.js +391 -0
- patchright/driver/package/lib/client/fileChooser.js +45 -0
- patchright/driver/package/lib/client/frame.js +504 -0
- patchright/driver/package/lib/client/harRouter.js +99 -0
- patchright/driver/package/lib/client/input.js +111 -0
- patchright/driver/package/lib/client/jsHandle.js +121 -0
- patchright/driver/package/lib/client/jsonPipe.js +35 -0
- patchright/driver/package/lib/client/localUtils.js +36 -0
- patchright/driver/package/lib/client/locator.js +441 -0
- patchright/driver/package/lib/client/network.js +762 -0
- patchright/driver/package/lib/client/page.js +746 -0
- patchright/driver/package/lib/client/playwright.js +80 -0
- patchright/driver/package/lib/client/selectors.js +67 -0
- patchright/driver/package/lib/client/stream.js +54 -0
- patchright/driver/package/lib/client/tracing.js +134 -0
- patchright/driver/package/lib/client/types.js +24 -0
- patchright/driver/package/lib/client/video.js +51 -0
- patchright/driver/package/lib/client/waiter.js +158 -0
- patchright/driver/package/lib/client/webError.js +37 -0
- patchright/driver/package/lib/client/worker.js +71 -0
- patchright/driver/package/lib/client/writableStream.js +54 -0
- patchright/driver/package/lib/common/socksProxy.js +569 -0
- patchright/driver/package/lib/common/timeoutSettings.js +73 -0
- patchright/driver/package/lib/common/types.js +5 -0
- patchright/driver/package/lib/generated/clockSource.js +7 -0
- patchright/driver/package/lib/generated/consoleApiSource.js +7 -0
- patchright/driver/package/lib/generated/injectedScriptSource.js +7 -0
- patchright/driver/package/lib/generated/pollingRecorderSource.js +7 -0
- patchright/driver/package/lib/generated/utilityScriptSource.js +7 -0
- patchright/driver/package/lib/generated/webSocketMockSource.js +7 -0
- patchright/driver/package/lib/image_tools/colorUtils.js +98 -0
- patchright/driver/package/lib/image_tools/compare.js +108 -0
- patchright/driver/package/lib/image_tools/imageChannel.js +70 -0
- patchright/driver/package/lib/image_tools/stats.js +102 -0
- patchright/driver/package/lib/inProcessFactory.js +54 -0
- patchright/driver/package/lib/inprocess.js +20 -0
- patchright/driver/package/lib/outofprocess.js +67 -0
- patchright/driver/package/lib/protocol/debug.js +27 -0
- patchright/driver/package/lib/protocol/serializers.js +173 -0
- patchright/driver/package/lib/protocol/transport.js +82 -0
- patchright/driver/package/lib/protocol/validator.js +2759 -0
- patchright/driver/package/lib/protocol/validatorPrimitives.js +139 -0
- patchright/driver/package/lib/remote/playwrightConnection.js +274 -0
- patchright/driver/package/lib/remote/playwrightServer.js +110 -0
- patchright/driver/package/lib/server/accessibility.js +62 -0
- patchright/driver/package/lib/server/android/android.js +441 -0
- patchright/driver/package/lib/server/android/backendAdb.js +172 -0
- patchright/driver/package/lib/server/artifact.js +104 -0
- patchright/driver/package/lib/server/bidi/bidiBrowser.js +311 -0
- patchright/driver/package/lib/server/bidi/bidiChromium.js +124 -0
- patchright/driver/package/lib/server/bidi/bidiConnection.js +206 -0
- patchright/driver/package/lib/server/bidi/bidiExecutionContext.js +159 -0
- patchright/driver/package/lib/server/bidi/bidiFirefox.js +104 -0
- patchright/driver/package/lib/server/bidi/bidiInput.js +158 -0
- patchright/driver/package/lib/server/bidi/bidiNetworkManager.js +338 -0
- patchright/driver/package/lib/server/bidi/bidiOverCdp.js +103 -0
- patchright/driver/package/lib/server/bidi/bidiPage.js +529 -0
- patchright/driver/package/lib/server/bidi/bidiPdf.js +140 -0
- patchright/driver/package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
- patchright/driver/package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
- patchright/driver/package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
- patchright/driver/package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
- patchright/driver/package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
- patchright/driver/package/lib/server/browser.js +148 -0
- patchright/driver/package/lib/server/browserContext.js +666 -0
- patchright/driver/package/lib/server/browserType.js +335 -0
- patchright/driver/package/lib/server/chromium/appIcon.png +0 -0
- patchright/driver/package/lib/server/chromium/chromium.js +350 -0
- patchright/driver/package/lib/server/chromium/chromiumSwitches.js +36 -0
- patchright/driver/package/lib/server/chromium/crAccessibility.js +237 -0
- patchright/driver/package/lib/server/chromium/crBrowser.js +522 -0
- patchright/driver/package/lib/server/chromium/crConnection.js +228 -0
- patchright/driver/package/lib/server/chromium/crCoverage.js +246 -0
- patchright/driver/package/lib/server/chromium/crDevTools.js +104 -0
- patchright/driver/package/lib/server/chromium/crDragDrop.js +143 -0
- patchright/driver/package/lib/server/chromium/crExecutionContext.js +149 -0
- patchright/driver/package/lib/server/chromium/crInput.js +171 -0
- patchright/driver/package/lib/server/chromium/crNetworkManager.js +809 -0
- patchright/driver/package/lib/server/chromium/crPage.js +1235 -0
- patchright/driver/package/lib/server/chromium/crPdf.js +153 -0
- patchright/driver/package/lib/server/chromium/crProtocolHelper.js +133 -0
- patchright/driver/package/lib/server/chromium/crServiceWorker.js +111 -0
- patchright/driver/package/lib/server/chromium/defaultFontFamilies.js +145 -0
- patchright/driver/package/lib/server/chromium/videoRecorder.js +155 -0
- patchright/driver/package/lib/server/clock.js +133 -0
- patchright/driver/package/lib/server/codegen/csharp.js +299 -0
- patchright/driver/package/lib/server/codegen/java.js +235 -0
- patchright/driver/package/lib/server/codegen/javascript.js +223 -0
- patchright/driver/package/lib/server/codegen/jsonl.js +47 -0
- patchright/driver/package/lib/server/codegen/language.js +88 -0
- patchright/driver/package/lib/server/codegen/languages.js +30 -0
- patchright/driver/package/lib/server/codegen/python.js +265 -0
- patchright/driver/package/lib/server/codegen/types.js +5 -0
- patchright/driver/package/lib/server/console.js +57 -0
- patchright/driver/package/lib/server/cookieStore.js +185 -0
- patchright/driver/package/lib/server/debugController.js +234 -0
- patchright/driver/package/lib/server/debugger.js +132 -0
- patchright/driver/package/lib/server/deviceDescriptors.js +26 -0
- patchright/driver/package/lib/server/deviceDescriptorsSource.json +1669 -0
- patchright/driver/package/lib/server/dialog.js +71 -0
- patchright/driver/package/lib/server/dispatchers/androidDispatcher.js +193 -0
- patchright/driver/package/lib/server/dispatchers/artifactDispatcher.js +118 -0
- patchright/driver/package/lib/server/dispatchers/browserContextDispatcher.js +368 -0
- patchright/driver/package/lib/server/dispatchers/browserDispatcher.js +170 -0
- patchright/driver/package/lib/server/dispatchers/browserTypeDispatcher.js +55 -0
- patchright/driver/package/lib/server/dispatchers/cdpSessionDispatcher.js +48 -0
- patchright/driver/package/lib/server/dispatchers/debugControllerDispatcher.js +103 -0
- patchright/driver/package/lib/server/dispatchers/dialogDispatcher.js +44 -0
- patchright/driver/package/lib/server/dispatchers/dispatcher.js +395 -0
- patchright/driver/package/lib/server/dispatchers/electronDispatcher.js +93 -0
- patchright/driver/package/lib/server/dispatchers/elementHandlerDispatcher.js +228 -0
- patchright/driver/package/lib/server/dispatchers/frameDispatcher.js +286 -0
- patchright/driver/package/lib/server/dispatchers/jsHandleDispatcher.js +97 -0
- patchright/driver/package/lib/server/dispatchers/jsonPipeDispatcher.js +59 -0
- patchright/driver/package/lib/server/dispatchers/localUtilsDispatcher.js +413 -0
- patchright/driver/package/lib/server/dispatchers/networkDispatchers.js +221 -0
- patchright/driver/package/lib/server/dispatchers/pageDispatcher.js +367 -0
- patchright/driver/package/lib/server/dispatchers/playwrightDispatcher.js +107 -0
- patchright/driver/package/lib/server/dispatchers/selectorsDispatcher.js +36 -0
- patchright/driver/package/lib/server/dispatchers/streamDispatcher.js +62 -0
- patchright/driver/package/lib/server/dispatchers/tracingDispatcher.js +54 -0
- patchright/driver/package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
- patchright/driver/package/lib/server/dispatchers/writableStreamDispatcher.js +58 -0
- patchright/driver/package/lib/server/dom.js +845 -0
- patchright/driver/package/lib/server/download.js +60 -0
- patchright/driver/package/lib/server/electron/electron.js +296 -0
- patchright/driver/package/lib/server/electron/loader.js +57 -0
- patchright/driver/package/lib/server/errors.js +68 -0
- patchright/driver/package/lib/server/fetch.js +656 -0
- patchright/driver/package/lib/server/fileChooser.js +42 -0
- patchright/driver/package/lib/server/fileUploadUtils.js +75 -0
- patchright/driver/package/lib/server/firefox/ffAccessibility.js +216 -0
- patchright/driver/package/lib/server/firefox/ffBrowser.js +460 -0
- patchright/driver/package/lib/server/firefox/ffConnection.js +168 -0
- patchright/driver/package/lib/server/firefox/ffExecutionContext.js +135 -0
- patchright/driver/package/lib/server/firefox/ffInput.js +150 -0
- patchright/driver/package/lib/server/firefox/ffNetworkManager.js +233 -0
- patchright/driver/package/lib/server/firefox/ffPage.js +559 -0
- patchright/driver/package/lib/server/firefox/firefox.js +99 -0
- patchright/driver/package/lib/server/formData.js +75 -0
- patchright/driver/package/lib/server/frameSelectors.js +171 -0
- patchright/driver/package/lib/server/frames.js +1808 -0
- patchright/driver/package/lib/server/har/harRecorder.js +139 -0
- patchright/driver/package/lib/server/har/harTracer.js +542 -0
- patchright/driver/package/lib/server/helper.js +103 -0
- patchright/driver/package/lib/server/index.js +114 -0
- patchright/driver/package/lib/server/input.js +310 -0
- patchright/driver/package/lib/server/instrumentation.js +70 -0
- patchright/driver/package/lib/server/isomorphic/utilityScriptSerializers.js +226 -0
- patchright/driver/package/lib/server/javascript.js +299 -0
- patchright/driver/package/lib/server/launchApp.js +91 -0
- patchright/driver/package/lib/server/macEditingCommands.js +139 -0
- patchright/driver/package/lib/server/network.js +617 -0
- patchright/driver/package/lib/server/page.js +819 -0
- patchright/driver/package/lib/server/pipeTransport.js +85 -0
- patchright/driver/package/lib/server/playwright.js +88 -0
- patchright/driver/package/lib/server/progress.js +102 -0
- patchright/driver/package/lib/server/protocolError.js +49 -0
- patchright/driver/package/lib/server/recorder/contextRecorder.js +299 -0
- patchright/driver/package/lib/server/recorder/recorderApp.js +196 -0
- patchright/driver/package/lib/server/recorder/recorderCollection.js +116 -0
- patchright/driver/package/lib/server/recorder/recorderFrontend.js +5 -0
- patchright/driver/package/lib/server/recorder/recorderInTraceViewer.js +144 -0
- patchright/driver/package/lib/server/recorder/recorderRunner.js +155 -0
- patchright/driver/package/lib/server/recorder/recorderUtils.js +112 -0
- patchright/driver/package/lib/server/recorder/throttledFile.js +46 -0
- patchright/driver/package/lib/server/recorder.js +327 -0
- patchright/driver/package/lib/server/registry/browserFetcher.js +168 -0
- patchright/driver/package/lib/server/registry/dependencies.js +322 -0
- patchright/driver/package/lib/server/registry/index.js +1005 -0
- patchright/driver/package/lib/server/registry/nativeDeps.js +490 -0
- patchright/driver/package/lib/server/registry/oopDownloadBrowserMain.js +138 -0
- patchright/driver/package/lib/server/screenshotter.js +348 -0
- patchright/driver/package/lib/server/selectors.js +73 -0
- patchright/driver/package/lib/server/socksClientCertificatesInterceptor.js +340 -0
- patchright/driver/package/lib/server/socksInterceptor.js +100 -0
- patchright/driver/package/lib/server/trace/recorder/snapshotter.js +172 -0
- patchright/driver/package/lib/server/trace/recorder/snapshotterInjected.js +493 -0
- patchright/driver/package/lib/server/trace/recorder/tracing.js +542 -0
- patchright/driver/package/lib/server/trace/test/inMemorySnapshotter.js +93 -0
- patchright/driver/package/lib/server/trace/viewer/traceViewer.js +213 -0
- patchright/driver/package/lib/server/transport.js +191 -0
- patchright/driver/package/lib/server/types.js +24 -0
- patchright/driver/package/lib/server/usKeyboardLayout.js +555 -0
- patchright/driver/package/lib/server/webkit/webkit.js +87 -0
- patchright/driver/package/lib/server/webkit/wkAccessibility.js +194 -0
- patchright/driver/package/lib/server/webkit/wkBrowser.js +329 -0
- patchright/driver/package/lib/server/webkit/wkConnection.js +173 -0
- patchright/driver/package/lib/server/webkit/wkExecutionContext.js +143 -0
- patchright/driver/package/lib/server/webkit/wkInput.js +169 -0
- patchright/driver/package/lib/server/webkit/wkInterceptableRequest.js +162 -0
- patchright/driver/package/lib/server/webkit/wkPage.js +1219 -0
- patchright/driver/package/lib/server/webkit/wkProvisionalPage.js +94 -0
- patchright/driver/package/lib/server/webkit/wkWorkers.js +104 -0
- patchright/driver/package/lib/third_party/diff_match_patch.js +2222 -0
- patchright/driver/package/lib/third_party/pixelmatch.js +255 -0
- patchright/driver/package/lib/utils/ascii.js +31 -0
- patchright/driver/package/lib/utils/comparators.js +171 -0
- patchright/driver/package/lib/utils/crypto.js +174 -0
- patchright/driver/package/lib/utils/debug.js +46 -0
- patchright/driver/package/lib/utils/debugLogger.js +91 -0
- patchright/driver/package/lib/utils/env.js +49 -0
- patchright/driver/package/lib/utils/eventsHelper.js +38 -0
- patchright/driver/package/lib/utils/expectUtils.js +33 -0
- patchright/driver/package/lib/utils/fileUtils.js +205 -0
- patchright/driver/package/lib/utils/happy-eyeballs.js +194 -0
- patchright/driver/package/lib/utils/headers.js +52 -0
- patchright/driver/package/lib/utils/hostPlatform.js +133 -0
- patchright/driver/package/lib/utils/httpServer.js +237 -0
- patchright/driver/package/lib/utils/index.js +368 -0
- patchright/driver/package/lib/utils/isomorphic/cssParser.js +250 -0
- patchright/driver/package/lib/utils/isomorphic/cssTokenizer.js +979 -0
- patchright/driver/package/lib/utils/isomorphic/locatorGenerators.js +642 -0
- patchright/driver/package/lib/utils/isomorphic/locatorParser.js +179 -0
- patchright/driver/package/lib/utils/isomorphic/locatorUtils.js +62 -0
- patchright/driver/package/lib/utils/isomorphic/mimeType.js +29 -0
- patchright/driver/package/lib/utils/isomorphic/recorderUtils.js +195 -0
- patchright/driver/package/lib/utils/isomorphic/selectorParser.js +397 -0
- patchright/driver/package/lib/utils/isomorphic/stringUtils.js +139 -0
- patchright/driver/package/lib/utils/isomorphic/traceUtils.js +39 -0
- patchright/driver/package/lib/utils/isomorphic/urlMatch.js +120 -0
- patchright/driver/package/lib/utils/linuxUtils.js +78 -0
- patchright/driver/package/lib/utils/manualPromise.js +109 -0
- patchright/driver/package/lib/utils/multimap.js +75 -0
- patchright/driver/package/lib/utils/network.js +160 -0
- patchright/driver/package/lib/utils/processLauncher.js +248 -0
- patchright/driver/package/lib/utils/profiler.js +53 -0
- patchright/driver/package/lib/utils/rtti.js +44 -0
- patchright/driver/package/lib/utils/semaphore.js +51 -0
- patchright/driver/package/lib/utils/spawnAsync.js +45 -0
- patchright/driver/package/lib/utils/stackTrace.js +121 -0
- patchright/driver/package/lib/utils/task.js +58 -0
- patchright/driver/package/lib/utils/time.js +37 -0
- patchright/driver/package/lib/utils/timeoutRunner.js +66 -0
- patchright/driver/package/lib/utils/traceUtils.js +44 -0
- patchright/driver/package/lib/utils/userAgent.js +105 -0
- patchright/driver/package/lib/utils/wsServer.js +127 -0
- patchright/driver/package/lib/utils/zipFile.js +75 -0
- patchright/driver/package/lib/utils/zones.js +62 -0
- patchright/driver/package/lib/utilsBundle.js +82 -0
- patchright/driver/package/lib/utilsBundleImpl/index.js +53 -0
- patchright/driver/package/lib/utilsBundleImpl/xdg-open +1066 -0
- patchright/driver/package/lib/vite/htmlReport/index.html +66 -0
- patchright/driver/package/lib/vite/recorder/assets/codeMirrorModule-d0KhC1qL.js +24 -0
- patchright/driver/package/lib/vite/recorder/assets/codeMirrorModule-ez37Vkbh.css +1 -0
- patchright/driver/package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
- patchright/driver/package/lib/vite/recorder/assets/index-BW-aOBcL.css +1 -0
- patchright/driver/package/lib/vite/recorder/assets/index-Bxxcmxlu.js +42 -0
- patchright/driver/package/lib/vite/recorder/index.html +29 -0
- patchright/driver/package/lib/vite/recorder/playwright-logo.svg +9 -0
- patchright/driver/package/lib/vite/traceViewer/assets/codeMirrorModule-CZTtn9l8.js +24 -0
- patchright/driver/package/lib/vite/traceViewer/assets/inspectorTab-DTusvprx.js +64 -0
- patchright/driver/package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
- patchright/driver/package/lib/vite/traceViewer/assets/workbench-DIEjrm3Z.js +9 -0
- patchright/driver/package/lib/vite/traceViewer/assets/xtermModule-BeNbaIVa.js +9 -0
- patchright/driver/package/lib/vite/traceViewer/codeMirrorModule.ez37Vkbh.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- patchright/driver/package/lib/vite/traceViewer/embedded.Do_J5Hgs.js +2 -0
- patchright/driver/package/lib/vite/traceViewer/embedded.html +18 -0
- patchright/driver/package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/index.B21BXreT.js +2 -0
- patchright/driver/package/lib/vite/traceViewer/index.CrbWWHbf.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/index.html +29 -0
- patchright/driver/package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/playwright-logo.svg +9 -0
- patchright/driver/package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
- patchright/driver/package/lib/vite/traceViewer/recorder.Bfh_9UGt.js +2 -0
- patchright/driver/package/lib/vite/traceViewer/recorder.html +17 -0
- patchright/driver/package/lib/vite/traceViewer/snapshot.html +21 -0
- patchright/driver/package/lib/vite/traceViewer/sw.bundle.js +3 -0
- patchright/driver/package/lib/vite/traceViewer/uiMode.CAYqod-m.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/uiMode.DloKQa-h.js +5 -0
- patchright/driver/package/lib/vite/traceViewer/uiMode.html +20 -0
- patchright/driver/package/lib/vite/traceViewer/workbench.D3JVcA9K.css +1 -0
- patchright/driver/package/lib/vite/traceViewer/xtermModule.DSXBckUd.css +32 -0
- patchright/driver/package/lib/zipBundle.js +25 -0
- patchright/driver/package/lib/zipBundleImpl.js +5 -0
- patchright/driver/package/package.json +44 -0
- patchright/driver/package/protocol.yml +3720 -0
- patchright/driver/package/types/protocol.d.ts +21571 -0
- patchright/driver/package/types/structs.d.ts +45 -0
- patchright/driver/package/types/types.d.ts +22519 -0
- patchright/py.typed +0 -0
- patchright/sync_api/__init__.py +177 -0
- patchright/sync_api/_context_manager.py +74 -0
- patchright/sync_api/_generated.py +20155 -0
- patchright-1.48.0.dist-info/LICENSE +202 -0
- patchright-1.48.0.dist-info/METADATA +83 -0
- patchright-1.48.0.dist-info/RECORD +406 -0
- patchright-1.48.0.dist-info/WHEEL +5 -0
- patchright-1.48.0.dist-info/entry_points.txt +5 -0
- patchright-1.48.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,934 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
import inspect
|
|
4
|
+
import json
|
|
5
|
+
import json as json_utils
|
|
6
|
+
import mimetypes
|
|
7
|
+
import re
|
|
8
|
+
from collections import defaultdict
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from types import SimpleNamespace
|
|
11
|
+
from typing import (
|
|
12
|
+
TYPE_CHECKING,
|
|
13
|
+
Any,
|
|
14
|
+
Callable,
|
|
15
|
+
Coroutine,
|
|
16
|
+
Dict,
|
|
17
|
+
List,
|
|
18
|
+
Optional,
|
|
19
|
+
TypedDict,
|
|
20
|
+
Union,
|
|
21
|
+
cast,
|
|
22
|
+
)
|
|
23
|
+
from urllib import parse
|
|
24
|
+
from patchright._impl._api_structures import (
|
|
25
|
+
ClientCertificate,
|
|
26
|
+
Headers,
|
|
27
|
+
HeadersArray,
|
|
28
|
+
RemoteAddr,
|
|
29
|
+
RequestSizes,
|
|
30
|
+
ResourceTiming,
|
|
31
|
+
SecurityDetails,
|
|
32
|
+
)
|
|
33
|
+
from patchright._impl._connection import (
|
|
34
|
+
ChannelOwner,
|
|
35
|
+
from_channel,
|
|
36
|
+
from_nullable_channel,
|
|
37
|
+
)
|
|
38
|
+
from patchright._impl._errors import Error
|
|
39
|
+
from patchright._impl._event_context_manager import EventContextManagerImpl
|
|
40
|
+
from patchright._impl._helper import (
|
|
41
|
+
URLMatcher,
|
|
42
|
+
WebSocketRouteHandlerCallback,
|
|
43
|
+
async_readfile,
|
|
44
|
+
locals_to_params,
|
|
45
|
+
)
|
|
46
|
+
from patchright._impl._str_utils import escape_regex_flags
|
|
47
|
+
from patchright._impl._waiter import Waiter
|
|
48
|
+
|
|
49
|
+
if TYPE_CHECKING:
|
|
50
|
+
from patchright._impl._browser_context import BrowserContext
|
|
51
|
+
from patchright._impl._fetch import APIResponse
|
|
52
|
+
from patchright._impl._frame import Frame
|
|
53
|
+
from patchright._impl._page import Page
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class FallbackOverrideParameters(TypedDict, total=False):
|
|
57
|
+
url: Optional[str]
|
|
58
|
+
method: Optional[str]
|
|
59
|
+
headers: Optional[Dict[str, str]]
|
|
60
|
+
postData: Optional[Union[str, bytes]]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class SerializedFallbackOverrides:
|
|
64
|
+
|
|
65
|
+
def __init__(self) -> None:
|
|
66
|
+
self.url: Optional[str] = None
|
|
67
|
+
self.method: Optional[str] = None
|
|
68
|
+
self.headers: Optional[Dict[str, str]] = None
|
|
69
|
+
self.post_data_buffer: Optional[bytes] = None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def serialize_headers(headers: Dict[str, str]) -> HeadersArray:
|
|
73
|
+
return [
|
|
74
|
+
{"name": name, "value": value}
|
|
75
|
+
for name, value in headers.items()
|
|
76
|
+
if value is not None
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
async def to_client_certificates_protocol(
|
|
81
|
+
clientCertificates: Optional[List[ClientCertificate]],
|
|
82
|
+
) -> Optional[List[Dict[str, str]]]:
|
|
83
|
+
if not clientCertificates:
|
|
84
|
+
return None
|
|
85
|
+
out = []
|
|
86
|
+
for clientCertificate in clientCertificates:
|
|
87
|
+
out_record = {"origin": clientCertificate["origin"]}
|
|
88
|
+
if passphrase := clientCertificate.get("passphrase"):
|
|
89
|
+
out_record["passphrase"] = passphrase
|
|
90
|
+
if pfx := clientCertificate.get("pfx"):
|
|
91
|
+
out_record["pfx"] = base64.b64encode(pfx).decode()
|
|
92
|
+
if pfx_path := clientCertificate.get("pfxPath"):
|
|
93
|
+
out_record["pfx"] = base64.b64encode(
|
|
94
|
+
await async_readfile(pfx_path)
|
|
95
|
+
).decode()
|
|
96
|
+
if cert := clientCertificate.get("cert"):
|
|
97
|
+
out_record["cert"] = base64.b64encode(cert).decode()
|
|
98
|
+
if cert_path := clientCertificate.get("certPath"):
|
|
99
|
+
out_record["cert"] = base64.b64encode(
|
|
100
|
+
await async_readfile(cert_path)
|
|
101
|
+
).decode()
|
|
102
|
+
if key := clientCertificate.get("key"):
|
|
103
|
+
out_record["key"] = base64.b64encode(key).decode()
|
|
104
|
+
if key_path := clientCertificate.get("keyPath"):
|
|
105
|
+
out_record["key"] = base64.b64encode(
|
|
106
|
+
await async_readfile(key_path)
|
|
107
|
+
).decode()
|
|
108
|
+
out.append(out_record)
|
|
109
|
+
return out
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Request(ChannelOwner):
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
116
|
+
) -> None:
|
|
117
|
+
super().__init__(parent, type, guid, initializer)
|
|
118
|
+
self._redirected_from: Optional["Request"] = from_nullable_channel(
|
|
119
|
+
initializer.get("redirectedFrom")
|
|
120
|
+
)
|
|
121
|
+
self._redirected_to: Optional["Request"] = None
|
|
122
|
+
if self._redirected_from:
|
|
123
|
+
self._redirected_from._redirected_to = self
|
|
124
|
+
self._failure_text: Optional[str] = None
|
|
125
|
+
self._timing: ResourceTiming = {
|
|
126
|
+
"startTime": 0,
|
|
127
|
+
"domainLookupStart": -1,
|
|
128
|
+
"domainLookupEnd": -1,
|
|
129
|
+
"connectStart": -1,
|
|
130
|
+
"secureConnectionStart": -1,
|
|
131
|
+
"connectEnd": -1,
|
|
132
|
+
"requestStart": -1,
|
|
133
|
+
"responseStart": -1,
|
|
134
|
+
"responseEnd": -1,
|
|
135
|
+
}
|
|
136
|
+
self._provisional_headers = RawHeaders(self._initializer["headers"])
|
|
137
|
+
self._all_headers_future: Optional[asyncio.Future[RawHeaders]] = None
|
|
138
|
+
self._fallback_overrides: SerializedFallbackOverrides = (
|
|
139
|
+
SerializedFallbackOverrides()
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def __repr__(self) -> str:
|
|
143
|
+
return f"<Request url={self.url!r} method={self.method!r}>"
|
|
144
|
+
|
|
145
|
+
def _apply_fallback_overrides(self, overrides: FallbackOverrideParameters) -> None:
|
|
146
|
+
self._fallback_overrides.url = overrides.get(
|
|
147
|
+
"url", self._fallback_overrides.url
|
|
148
|
+
)
|
|
149
|
+
self._fallback_overrides.method = overrides.get(
|
|
150
|
+
"method", self._fallback_overrides.method
|
|
151
|
+
)
|
|
152
|
+
self._fallback_overrides.headers = overrides.get(
|
|
153
|
+
"headers", self._fallback_overrides.headers
|
|
154
|
+
)
|
|
155
|
+
post_data = overrides.get("postData")
|
|
156
|
+
if isinstance(post_data, str):
|
|
157
|
+
self._fallback_overrides.post_data_buffer = post_data.encode()
|
|
158
|
+
elif isinstance(post_data, bytes):
|
|
159
|
+
self._fallback_overrides.post_data_buffer = post_data
|
|
160
|
+
elif post_data is not None:
|
|
161
|
+
self._fallback_overrides.post_data_buffer = json.dumps(post_data).encode()
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def url(self) -> str:
|
|
165
|
+
return cast(str, self._fallback_overrides.url or self._initializer["url"])
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def resource_type(self) -> str:
|
|
169
|
+
return self._initializer["resourceType"]
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def method(self) -> str:
|
|
173
|
+
return cast(str, self._fallback_overrides.method or self._initializer["method"])
|
|
174
|
+
|
|
175
|
+
async def sizes(self) -> RequestSizes:
|
|
176
|
+
response = await self.response()
|
|
177
|
+
if not response:
|
|
178
|
+
raise Error("Unable to fetch sizes for failed request")
|
|
179
|
+
return await response._channel.send("sizes")
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def post_data(self) -> Optional[str]:
|
|
183
|
+
data = self._fallback_overrides.post_data_buffer
|
|
184
|
+
if data:
|
|
185
|
+
return data.decode()
|
|
186
|
+
base64_post_data = self._initializer.get("postData")
|
|
187
|
+
if base64_post_data is not None:
|
|
188
|
+
return base64.b64decode(base64_post_data).decode()
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def post_data_json(self) -> Optional[Any]:
|
|
193
|
+
post_data = self.post_data
|
|
194
|
+
if not post_data:
|
|
195
|
+
return None
|
|
196
|
+
content_type = self.headers["content-type"]
|
|
197
|
+
if "application/x-www-form-urlencoded" in content_type:
|
|
198
|
+
return dict(parse.parse_qsl(post_data))
|
|
199
|
+
try:
|
|
200
|
+
return json.loads(post_data)
|
|
201
|
+
except Exception:
|
|
202
|
+
raise Error(f"POST data is not a valid JSON object: {post_data}")
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def post_data_buffer(self) -> Optional[bytes]:
|
|
206
|
+
if self._fallback_overrides.post_data_buffer:
|
|
207
|
+
return self._fallback_overrides.post_data_buffer
|
|
208
|
+
if self._initializer.get("postData"):
|
|
209
|
+
return base64.b64decode(self._initializer["postData"])
|
|
210
|
+
return None
|
|
211
|
+
|
|
212
|
+
async def response(self) -> Optional["Response"]:
|
|
213
|
+
return from_nullable_channel(await self._channel.send("response"))
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def frame(self) -> "Frame":
|
|
217
|
+
if not self._initializer.get("frame"):
|
|
218
|
+
raise Error("Service Worker requests do not have an associated frame.")
|
|
219
|
+
frame = cast("Frame", from_channel(self._initializer["frame"]))
|
|
220
|
+
if not frame._page:
|
|
221
|
+
raise Error(
|
|
222
|
+
"\n".join(
|
|
223
|
+
[
|
|
224
|
+
"Frame for this navigation request is not available, because the request",
|
|
225
|
+
"was issued before the frame is created. You can check whether the request",
|
|
226
|
+
"is a navigation request by calling isNavigationRequest() method.",
|
|
227
|
+
]
|
|
228
|
+
)
|
|
229
|
+
)
|
|
230
|
+
return frame
|
|
231
|
+
|
|
232
|
+
def is_navigation_request(self) -> bool:
|
|
233
|
+
return self._initializer["isNavigationRequest"]
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def redirected_from(self) -> Optional["Request"]:
|
|
237
|
+
return self._redirected_from
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def redirected_to(self) -> Optional["Request"]:
|
|
241
|
+
return self._redirected_to
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def failure(self) -> Optional[str]:
|
|
245
|
+
return self._failure_text
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def timing(self) -> ResourceTiming:
|
|
249
|
+
return self._timing
|
|
250
|
+
|
|
251
|
+
def _set_response_end_timing(self, response_end_timing: float) -> None:
|
|
252
|
+
self._timing["responseEnd"] = response_end_timing
|
|
253
|
+
if self._timing["responseStart"] == -1:
|
|
254
|
+
self._timing["responseStart"] = response_end_timing
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def headers(self) -> Headers:
|
|
258
|
+
override = self._fallback_overrides.headers
|
|
259
|
+
if override:
|
|
260
|
+
return RawHeaders._from_headers_dict_lossy(override).headers()
|
|
261
|
+
return self._provisional_headers.headers()
|
|
262
|
+
|
|
263
|
+
async def all_headers(self) -> Headers:
|
|
264
|
+
return (await self._actual_headers()).headers()
|
|
265
|
+
|
|
266
|
+
async def headers_array(self) -> HeadersArray:
|
|
267
|
+
return (await self._actual_headers()).headers_array()
|
|
268
|
+
|
|
269
|
+
async def header_value(self, name: str) -> Optional[str]:
|
|
270
|
+
return (await self._actual_headers()).get(name)
|
|
271
|
+
|
|
272
|
+
async def _actual_headers(self) -> "RawHeaders":
|
|
273
|
+
override = self._fallback_overrides.headers
|
|
274
|
+
if override:
|
|
275
|
+
return RawHeaders(serialize_headers(override))
|
|
276
|
+
if not self._all_headers_future:
|
|
277
|
+
self._all_headers_future = asyncio.Future()
|
|
278
|
+
headers = await self._channel.send("rawRequestHeaders")
|
|
279
|
+
self._all_headers_future.set_result(RawHeaders(headers))
|
|
280
|
+
return await self._all_headers_future
|
|
281
|
+
|
|
282
|
+
def _target_closed_future(self) -> asyncio.Future:
|
|
283
|
+
frame = cast(
|
|
284
|
+
Optional["Frame"], from_nullable_channel(self._initializer.get("frame"))
|
|
285
|
+
)
|
|
286
|
+
if not frame:
|
|
287
|
+
return asyncio.Future()
|
|
288
|
+
page = frame._page
|
|
289
|
+
if not page:
|
|
290
|
+
return asyncio.Future()
|
|
291
|
+
return page._closed_or_crashed_future
|
|
292
|
+
|
|
293
|
+
def _safe_page(self) -> "Optional[Page]":
|
|
294
|
+
frame = from_nullable_channel(self._initializer.get("frame"))
|
|
295
|
+
if not frame:
|
|
296
|
+
return None
|
|
297
|
+
return cast("Frame", frame)._page
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class Route(ChannelOwner):
|
|
301
|
+
|
|
302
|
+
def __init__(
|
|
303
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
304
|
+
) -> None:
|
|
305
|
+
super().__init__(parent, type, guid, initializer)
|
|
306
|
+
self.mark_as_internal_type()
|
|
307
|
+
self._handling_future: Optional[asyncio.Future["bool"]] = None
|
|
308
|
+
self._context: "BrowserContext" = cast("BrowserContext", None)
|
|
309
|
+
self._did_throw = False
|
|
310
|
+
|
|
311
|
+
def _start_handling(self) -> "asyncio.Future[bool]":
|
|
312
|
+
self._handling_future = asyncio.Future()
|
|
313
|
+
return self._handling_future
|
|
314
|
+
|
|
315
|
+
def _report_handled(self, done: bool) -> None:
|
|
316
|
+
chain = self._handling_future
|
|
317
|
+
assert chain
|
|
318
|
+
self._handling_future = None
|
|
319
|
+
chain.set_result(done)
|
|
320
|
+
|
|
321
|
+
def _check_not_handled(self) -> None:
|
|
322
|
+
if not self._handling_future:
|
|
323
|
+
raise Error("Route is already handled!")
|
|
324
|
+
|
|
325
|
+
def __repr__(self) -> str:
|
|
326
|
+
return f"<Route request={self.request}>"
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def request(self) -> Request:
|
|
330
|
+
return from_channel(self._initializer["request"])
|
|
331
|
+
|
|
332
|
+
async def abort(self, errorCode: str = None) -> None:
|
|
333
|
+
await self._handle_route(
|
|
334
|
+
lambda: self._race_with_page_close(
|
|
335
|
+
self._channel.send("abort", {"errorCode": errorCode})
|
|
336
|
+
)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
async def fulfill(
|
|
340
|
+
self,
|
|
341
|
+
status: int = None,
|
|
342
|
+
headers: Dict[str, str] = None,
|
|
343
|
+
body: Union[str, bytes] = None,
|
|
344
|
+
json: Any = None,
|
|
345
|
+
path: Union[str, Path] = None,
|
|
346
|
+
contentType: str = None,
|
|
347
|
+
response: "APIResponse" = None,
|
|
348
|
+
) -> None:
|
|
349
|
+
await self._handle_route(
|
|
350
|
+
lambda: self._inner_fulfill(
|
|
351
|
+
status, headers, body, json, path, contentType, response
|
|
352
|
+
)
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
async def _inner_fulfill(
|
|
356
|
+
self,
|
|
357
|
+
status: int = None,
|
|
358
|
+
headers: Dict[str, str] = None,
|
|
359
|
+
body: Union[str, bytes] = None,
|
|
360
|
+
json: Any = None,
|
|
361
|
+
path: Union[str, Path] = None,
|
|
362
|
+
contentType: str = None,
|
|
363
|
+
response: "APIResponse" = None,
|
|
364
|
+
) -> None:
|
|
365
|
+
params = locals_to_params(locals())
|
|
366
|
+
if json is not None:
|
|
367
|
+
if body is not None:
|
|
368
|
+
raise Error("Can specify either body or json parameters")
|
|
369
|
+
body = json_utils.dumps(json)
|
|
370
|
+
if response:
|
|
371
|
+
del params["response"]
|
|
372
|
+
params["status"] = (
|
|
373
|
+
params["status"] if params.get("status") else response.status
|
|
374
|
+
)
|
|
375
|
+
params["headers"] = (
|
|
376
|
+
params["headers"] if params.get("headers") else response.headers
|
|
377
|
+
)
|
|
378
|
+
from patchright._impl._fetch import APIResponse
|
|
379
|
+
|
|
380
|
+
if body is None and path is None and isinstance(response, APIResponse):
|
|
381
|
+
if response._request._connection is self._connection:
|
|
382
|
+
params["fetchResponseUid"] = response._fetch_uid
|
|
383
|
+
else:
|
|
384
|
+
body = await response.body()
|
|
385
|
+
length = 0
|
|
386
|
+
if isinstance(body, str):
|
|
387
|
+
params["body"] = body
|
|
388
|
+
params["isBase64"] = False
|
|
389
|
+
length = len(body.encode())
|
|
390
|
+
elif isinstance(body, bytes):
|
|
391
|
+
params["body"] = base64.b64encode(body).decode()
|
|
392
|
+
params["isBase64"] = True
|
|
393
|
+
length = len(body)
|
|
394
|
+
elif path:
|
|
395
|
+
del params["path"]
|
|
396
|
+
file_content = Path(path).read_bytes()
|
|
397
|
+
params["body"] = base64.b64encode(file_content).decode()
|
|
398
|
+
params["isBase64"] = True
|
|
399
|
+
length = len(file_content)
|
|
400
|
+
headers = {k.lower(): str(v) for k, v in params.get("headers", {}).items()}
|
|
401
|
+
if params.get("contentType"):
|
|
402
|
+
headers["content-type"] = params["contentType"]
|
|
403
|
+
elif json:
|
|
404
|
+
headers["content-type"] = "application/json"
|
|
405
|
+
elif path:
|
|
406
|
+
headers["content-type"] = (
|
|
407
|
+
mimetypes.guess_type(str(Path(path)))[0] or "application/octet-stream"
|
|
408
|
+
)
|
|
409
|
+
if length and "content-length" not in headers:
|
|
410
|
+
headers["content-length"] = str(length)
|
|
411
|
+
params["headers"] = serialize_headers(headers)
|
|
412
|
+
await self._race_with_page_close(self._channel.send("fulfill", params))
|
|
413
|
+
|
|
414
|
+
async def _handle_route(self, callback: Callable) -> None:
|
|
415
|
+
self._check_not_handled()
|
|
416
|
+
try:
|
|
417
|
+
await callback()
|
|
418
|
+
self._report_handled(True)
|
|
419
|
+
except Exception as e:
|
|
420
|
+
self._did_throw = True
|
|
421
|
+
raise e
|
|
422
|
+
|
|
423
|
+
async def fetch(
|
|
424
|
+
self,
|
|
425
|
+
url: str = None,
|
|
426
|
+
method: str = None,
|
|
427
|
+
headers: Dict[str, str] = None,
|
|
428
|
+
postData: Union[Any, str, bytes] = None,
|
|
429
|
+
maxRedirects: int = None,
|
|
430
|
+
maxRetries: int = None,
|
|
431
|
+
timeout: float = None,
|
|
432
|
+
) -> "APIResponse":
|
|
433
|
+
return await self._connection.wrap_api_call(
|
|
434
|
+
lambda: self._context.request._inner_fetch(
|
|
435
|
+
self.request,
|
|
436
|
+
url,
|
|
437
|
+
method,
|
|
438
|
+
headers,
|
|
439
|
+
postData,
|
|
440
|
+
maxRedirects=maxRedirects,
|
|
441
|
+
maxRetries=maxRetries,
|
|
442
|
+
timeout=timeout,
|
|
443
|
+
)
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
async def fallback(
|
|
447
|
+
self,
|
|
448
|
+
url: str = None,
|
|
449
|
+
method: str = None,
|
|
450
|
+
headers: Dict[str, str] = None,
|
|
451
|
+
postData: Union[Any, str, bytes] = None,
|
|
452
|
+
) -> None:
|
|
453
|
+
overrides = cast(FallbackOverrideParameters, locals_to_params(locals()))
|
|
454
|
+
self._check_not_handled()
|
|
455
|
+
self.request._apply_fallback_overrides(overrides)
|
|
456
|
+
self._report_handled(False)
|
|
457
|
+
|
|
458
|
+
async def continue_(
|
|
459
|
+
self,
|
|
460
|
+
url: str = None,
|
|
461
|
+
method: str = None,
|
|
462
|
+
headers: Dict[str, str] = None,
|
|
463
|
+
postData: Union[Any, str, bytes] = None,
|
|
464
|
+
) -> None:
|
|
465
|
+
overrides = cast(FallbackOverrideParameters, locals_to_params(locals()))
|
|
466
|
+
|
|
467
|
+
async def _inner() -> None:
|
|
468
|
+
self.request._apply_fallback_overrides(overrides)
|
|
469
|
+
await self._inner_continue(False)
|
|
470
|
+
|
|
471
|
+
return await self._handle_route(_inner)
|
|
472
|
+
|
|
473
|
+
async def _inner_continue(self, is_fallback: bool = False) -> None:
|
|
474
|
+
options = self.request._fallback_overrides
|
|
475
|
+
await self._race_with_page_close(
|
|
476
|
+
self._channel.send(
|
|
477
|
+
"continue",
|
|
478
|
+
{
|
|
479
|
+
"url": options.url,
|
|
480
|
+
"method": options.method,
|
|
481
|
+
"headers": (
|
|
482
|
+
serialize_headers(options.headers) if options.headers else None
|
|
483
|
+
),
|
|
484
|
+
"postData": (
|
|
485
|
+
base64.b64encode(options.post_data_buffer).decode()
|
|
486
|
+
if options.post_data_buffer is not None
|
|
487
|
+
else None
|
|
488
|
+
),
|
|
489
|
+
"isFallback": is_fallback,
|
|
490
|
+
},
|
|
491
|
+
)
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
async def _redirected_navigation_request(self, url: str) -> None:
|
|
495
|
+
await self._handle_route(
|
|
496
|
+
lambda: self._race_with_page_close(
|
|
497
|
+
self._channel.send("redirectNavigationRequest", {"url": url})
|
|
498
|
+
)
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
async def _race_with_page_close(self, future: Coroutine) -> None:
|
|
502
|
+
fut = asyncio.create_task(future)
|
|
503
|
+
setattr(
|
|
504
|
+
fut,
|
|
505
|
+
"__pw_stack__",
|
|
506
|
+
getattr(asyncio.current_task(self._loop), "__pw_stack__", inspect.stack()),
|
|
507
|
+
)
|
|
508
|
+
target_closed_future = self.request._target_closed_future()
|
|
509
|
+
await asyncio.wait(
|
|
510
|
+
[fut, target_closed_future], return_when=asyncio.FIRST_COMPLETED
|
|
511
|
+
)
|
|
512
|
+
if fut.done() and fut.exception():
|
|
513
|
+
raise cast(BaseException, fut.exception())
|
|
514
|
+
if target_closed_future.done():
|
|
515
|
+
await asyncio.gather(fut, return_exceptions=True)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _create_task_and_ignore_exception(coro: Coroutine) -> None:
|
|
519
|
+
|
|
520
|
+
async def _ignore_exception() -> None:
|
|
521
|
+
try:
|
|
522
|
+
await coro
|
|
523
|
+
except Exception:
|
|
524
|
+
pass
|
|
525
|
+
|
|
526
|
+
asyncio.create_task(_ignore_exception())
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
class ServerWebSocketRoute:
|
|
530
|
+
|
|
531
|
+
def __init__(self, ws: "WebSocketRoute"):
|
|
532
|
+
self._ws = ws
|
|
533
|
+
|
|
534
|
+
def on_message(self, handler: Callable[[Union[str, bytes]], Any]) -> None:
|
|
535
|
+
self._ws._on_server_message = handler
|
|
536
|
+
|
|
537
|
+
def on_close(self, handler: Callable[[Optional[int], Optional[str]], Any]) -> None:
|
|
538
|
+
self._ws._on_server_close = handler
|
|
539
|
+
|
|
540
|
+
def connect_to_server(self) -> None:
|
|
541
|
+
raise NotImplementedError(
|
|
542
|
+
"connectToServer must be called on the page-side WebSocketRoute"
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def url(self) -> str:
|
|
547
|
+
return self._ws._initializer["url"]
|
|
548
|
+
|
|
549
|
+
def close(self, code: int = None, reason: str = None) -> None:
|
|
550
|
+
_create_task_and_ignore_exception(
|
|
551
|
+
self._ws._channel.send(
|
|
552
|
+
"closeServer", {"code": code, "reason": reason, "wasClean": True}
|
|
553
|
+
)
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
def send(self, message: Union[str, bytes]) -> None:
|
|
557
|
+
if isinstance(message, str):
|
|
558
|
+
_create_task_and_ignore_exception(
|
|
559
|
+
self._ws._channel.send(
|
|
560
|
+
"sendToServer", {"message": message, "isBase64": False}
|
|
561
|
+
)
|
|
562
|
+
)
|
|
563
|
+
else:
|
|
564
|
+
_create_task_and_ignore_exception(
|
|
565
|
+
self._ws._channel.send(
|
|
566
|
+
"sendToServer",
|
|
567
|
+
{"message": base64.b64encode(message).decode(), "isBase64": True},
|
|
568
|
+
)
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
class WebSocketRoute(ChannelOwner):
|
|
573
|
+
|
|
574
|
+
def __init__(
|
|
575
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
576
|
+
) -> None:
|
|
577
|
+
super().__init__(parent, type, guid, initializer)
|
|
578
|
+
self.mark_as_internal_type()
|
|
579
|
+
self._on_page_message: Optional[Callable[[Union[str, bytes]], Any]] = None
|
|
580
|
+
self._on_page_close: Optional[Callable[[Optional[int], Optional[str]], Any]] = (
|
|
581
|
+
None
|
|
582
|
+
)
|
|
583
|
+
self._on_server_message: Optional[Callable[[Union[str, bytes]], Any]] = None
|
|
584
|
+
self._on_server_close: Optional[
|
|
585
|
+
Callable[[Optional[int], Optional[str]], Any]
|
|
586
|
+
] = None
|
|
587
|
+
self._server = ServerWebSocketRoute(self)
|
|
588
|
+
self._connected = False
|
|
589
|
+
self._channel.on("messageFromPage", self._channel_message_from_page)
|
|
590
|
+
self._channel.on("messageFromServer", self._channel_message_from_server)
|
|
591
|
+
self._channel.on("closePage", self._channel_close_page)
|
|
592
|
+
self._channel.on("closeServer", self._channel_close_server)
|
|
593
|
+
|
|
594
|
+
def _channel_message_from_page(self, event: Dict) -> None:
|
|
595
|
+
if self._on_page_message:
|
|
596
|
+
self._on_page_message(
|
|
597
|
+
base64.b64decode(event["message"])
|
|
598
|
+
if event["isBase64"]
|
|
599
|
+
else event["message"]
|
|
600
|
+
)
|
|
601
|
+
elif self._connected:
|
|
602
|
+
_create_task_and_ignore_exception(self._channel.send("sendToServer", event))
|
|
603
|
+
|
|
604
|
+
def _channel_message_from_server(self, event: Dict) -> None:
|
|
605
|
+
if self._on_server_message:
|
|
606
|
+
self._on_server_message(
|
|
607
|
+
base64.b64decode(event["message"])
|
|
608
|
+
if event["isBase64"]
|
|
609
|
+
else event["message"]
|
|
610
|
+
)
|
|
611
|
+
else:
|
|
612
|
+
_create_task_and_ignore_exception(self._channel.send("sendToPage", event))
|
|
613
|
+
|
|
614
|
+
def _channel_close_page(self, event: Dict) -> None:
|
|
615
|
+
if self._on_page_close:
|
|
616
|
+
self._on_page_close(event["code"], event["reason"])
|
|
617
|
+
else:
|
|
618
|
+
_create_task_and_ignore_exception(self._channel.send("closeServer", event))
|
|
619
|
+
|
|
620
|
+
def _channel_close_server(self, event: Dict) -> None:
|
|
621
|
+
if self._on_server_close:
|
|
622
|
+
self._on_server_close(event["code"], event["reason"])
|
|
623
|
+
else:
|
|
624
|
+
_create_task_and_ignore_exception(self._channel.send("closePage", event))
|
|
625
|
+
|
|
626
|
+
@property
|
|
627
|
+
def url(self) -> str:
|
|
628
|
+
return self._initializer["url"]
|
|
629
|
+
|
|
630
|
+
async def close(self, code: int = None, reason: str = None) -> None:
|
|
631
|
+
try:
|
|
632
|
+
await self._channel.send(
|
|
633
|
+
"closePage", {"code": code, "reason": reason, "wasClean": True}
|
|
634
|
+
)
|
|
635
|
+
except Exception:
|
|
636
|
+
pass
|
|
637
|
+
|
|
638
|
+
def connect_to_server(self) -> "WebSocketRoute":
|
|
639
|
+
if self._connected:
|
|
640
|
+
raise Error("Already connected to the server")
|
|
641
|
+
self._connected = True
|
|
642
|
+
asyncio.create_task(self._channel.send("connect"))
|
|
643
|
+
return cast("WebSocketRoute", self._server)
|
|
644
|
+
|
|
645
|
+
def send(self, message: Union[str, bytes]) -> None:
|
|
646
|
+
if isinstance(message, str):
|
|
647
|
+
_create_task_and_ignore_exception(
|
|
648
|
+
self._channel.send(
|
|
649
|
+
"sendToPage", {"message": message, "isBase64": False}
|
|
650
|
+
)
|
|
651
|
+
)
|
|
652
|
+
else:
|
|
653
|
+
_create_task_and_ignore_exception(
|
|
654
|
+
self._channel.send(
|
|
655
|
+
"sendToPage",
|
|
656
|
+
{"message": base64.b64encode(message).decode(), "isBase64": True},
|
|
657
|
+
)
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
def on_message(self, handler: Callable[[Union[str, bytes]], Any]) -> None:
|
|
661
|
+
self._on_page_message = handler
|
|
662
|
+
|
|
663
|
+
def on_close(self, handler: Callable[[Optional[int], Optional[str]], Any]) -> None:
|
|
664
|
+
self._on_page_close = handler
|
|
665
|
+
|
|
666
|
+
async def _after_handle(self) -> None:
|
|
667
|
+
if self._connected:
|
|
668
|
+
return
|
|
669
|
+
await self._channel.send("ensureOpened")
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
class WebSocketRouteHandler:
|
|
673
|
+
|
|
674
|
+
def __init__(self, matcher: URLMatcher, handler: WebSocketRouteHandlerCallback):
|
|
675
|
+
self.matcher = matcher
|
|
676
|
+
self.handler = handler
|
|
677
|
+
|
|
678
|
+
@staticmethod
|
|
679
|
+
def prepare_interception_patterns(
|
|
680
|
+
handlers: List["WebSocketRouteHandler"],
|
|
681
|
+
) -> List[dict]:
|
|
682
|
+
patterns = []
|
|
683
|
+
all_urls = False
|
|
684
|
+
for handler in handlers:
|
|
685
|
+
if isinstance(handler.matcher.match, str):
|
|
686
|
+
patterns.append({"glob": handler.matcher.match})
|
|
687
|
+
elif isinstance(handler.matcher._regex_obj, re.Pattern):
|
|
688
|
+
patterns.append(
|
|
689
|
+
{
|
|
690
|
+
"regexSource": handler.matcher._regex_obj.pattern,
|
|
691
|
+
"regexFlags": escape_regex_flags(handler.matcher._regex_obj),
|
|
692
|
+
}
|
|
693
|
+
)
|
|
694
|
+
else:
|
|
695
|
+
all_urls = True
|
|
696
|
+
if all_urls:
|
|
697
|
+
return [{"glob": "**/*"}]
|
|
698
|
+
return patterns
|
|
699
|
+
|
|
700
|
+
def matches(self, ws_url: str) -> bool:
|
|
701
|
+
return self.matcher.matches(ws_url)
|
|
702
|
+
|
|
703
|
+
async def handle(self, websocket_route: "WebSocketRoute") -> None:
|
|
704
|
+
coro_or_future = self.handler(websocket_route)
|
|
705
|
+
if asyncio.iscoroutine(coro_or_future):
|
|
706
|
+
await coro_or_future
|
|
707
|
+
await websocket_route._after_handle()
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
class Response(ChannelOwner):
|
|
711
|
+
|
|
712
|
+
def __init__(
|
|
713
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
714
|
+
) -> None:
|
|
715
|
+
super().__init__(parent, type, guid, initializer)
|
|
716
|
+
self._request: Request = from_channel(self._initializer["request"])
|
|
717
|
+
timing = self._initializer["timing"]
|
|
718
|
+
self._request._timing["startTime"] = timing["startTime"]
|
|
719
|
+
self._request._timing["domainLookupStart"] = timing["domainLookupStart"]
|
|
720
|
+
self._request._timing["domainLookupEnd"] = timing["domainLookupEnd"]
|
|
721
|
+
self._request._timing["connectStart"] = timing["connectStart"]
|
|
722
|
+
self._request._timing["secureConnectionStart"] = timing["secureConnectionStart"]
|
|
723
|
+
self._request._timing["connectEnd"] = timing["connectEnd"]
|
|
724
|
+
self._request._timing["requestStart"] = timing["requestStart"]
|
|
725
|
+
self._request._timing["responseStart"] = timing["responseStart"]
|
|
726
|
+
self._provisional_headers = RawHeaders(
|
|
727
|
+
cast(HeadersArray, self._initializer["headers"])
|
|
728
|
+
)
|
|
729
|
+
self._raw_headers_future: Optional[asyncio.Future[RawHeaders]] = None
|
|
730
|
+
self._finished_future: asyncio.Future[bool] = asyncio.Future()
|
|
731
|
+
|
|
732
|
+
def __repr__(self) -> str:
|
|
733
|
+
return f"<Response url={self.url!r} request={self.request}>"
|
|
734
|
+
|
|
735
|
+
@property
|
|
736
|
+
def url(self) -> str:
|
|
737
|
+
return self._initializer["url"]
|
|
738
|
+
|
|
739
|
+
@property
|
|
740
|
+
def ok(self) -> bool:
|
|
741
|
+
return self._initializer["status"] == 0 or (
|
|
742
|
+
self._initializer["status"] >= 200 and self._initializer["status"] <= 299
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
@property
|
|
746
|
+
def status(self) -> int:
|
|
747
|
+
return self._initializer["status"]
|
|
748
|
+
|
|
749
|
+
@property
|
|
750
|
+
def status_text(self) -> str:
|
|
751
|
+
return self._initializer["statusText"]
|
|
752
|
+
|
|
753
|
+
@property
|
|
754
|
+
def headers(self) -> Headers:
|
|
755
|
+
return self._provisional_headers.headers()
|
|
756
|
+
|
|
757
|
+
@property
|
|
758
|
+
def from_service_worker(self) -> bool:
|
|
759
|
+
return self._initializer["fromServiceWorker"]
|
|
760
|
+
|
|
761
|
+
async def all_headers(self) -> Headers:
|
|
762
|
+
return (await self._actual_headers()).headers()
|
|
763
|
+
|
|
764
|
+
async def headers_array(self) -> HeadersArray:
|
|
765
|
+
return (await self._actual_headers()).headers_array()
|
|
766
|
+
|
|
767
|
+
async def header_value(self, name: str) -> Optional[str]:
|
|
768
|
+
return (await self._actual_headers()).get(name)
|
|
769
|
+
|
|
770
|
+
async def header_values(self, name: str) -> List[str]:
|
|
771
|
+
return (await self._actual_headers()).get_all(name)
|
|
772
|
+
|
|
773
|
+
async def _actual_headers(self) -> "RawHeaders":
|
|
774
|
+
if not self._raw_headers_future:
|
|
775
|
+
self._raw_headers_future = asyncio.Future()
|
|
776
|
+
headers = cast(HeadersArray, await self._channel.send("rawResponseHeaders"))
|
|
777
|
+
self._raw_headers_future.set_result(RawHeaders(headers))
|
|
778
|
+
return await self._raw_headers_future
|
|
779
|
+
|
|
780
|
+
async def server_addr(self) -> Optional[RemoteAddr]:
|
|
781
|
+
return await self._channel.send("serverAddr")
|
|
782
|
+
|
|
783
|
+
async def security_details(self) -> Optional[SecurityDetails]:
|
|
784
|
+
return await self._channel.send("securityDetails")
|
|
785
|
+
|
|
786
|
+
async def finished(self) -> None:
|
|
787
|
+
|
|
788
|
+
async def on_finished() -> None:
|
|
789
|
+
await self._request._target_closed_future()
|
|
790
|
+
raise Error("Target closed")
|
|
791
|
+
|
|
792
|
+
on_finished_task = asyncio.create_task(on_finished())
|
|
793
|
+
await asyncio.wait(
|
|
794
|
+
cast(
|
|
795
|
+
List[Union[asyncio.Task, asyncio.Future]],
|
|
796
|
+
[self._finished_future, on_finished_task],
|
|
797
|
+
),
|
|
798
|
+
return_when=asyncio.FIRST_COMPLETED,
|
|
799
|
+
)
|
|
800
|
+
if on_finished_task.done():
|
|
801
|
+
await on_finished_task
|
|
802
|
+
|
|
803
|
+
async def body(self) -> bytes:
|
|
804
|
+
binary = await self._channel.send("body")
|
|
805
|
+
return base64.b64decode(binary)
|
|
806
|
+
|
|
807
|
+
async def text(self) -> str:
|
|
808
|
+
content = await self.body()
|
|
809
|
+
return content.decode()
|
|
810
|
+
|
|
811
|
+
async def json(self) -> Any:
|
|
812
|
+
return json.loads(await self.text())
|
|
813
|
+
|
|
814
|
+
@property
|
|
815
|
+
def request(self) -> Request:
|
|
816
|
+
return self._request
|
|
817
|
+
|
|
818
|
+
@property
|
|
819
|
+
def frame(self) -> "Frame":
|
|
820
|
+
return self._request.frame
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
class WebSocket(ChannelOwner):
|
|
824
|
+
Events = SimpleNamespace(
|
|
825
|
+
Close="close",
|
|
826
|
+
FrameReceived="framereceived",
|
|
827
|
+
FrameSent="framesent",
|
|
828
|
+
Error="socketerror",
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
def __init__(
|
|
832
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
833
|
+
) -> None:
|
|
834
|
+
super().__init__(parent, type, guid, initializer)
|
|
835
|
+
self._is_closed = False
|
|
836
|
+
self._page = cast("Page", parent)
|
|
837
|
+
self._channel.on(
|
|
838
|
+
"frameSent",
|
|
839
|
+
lambda params: self._on_frame_sent(params["opcode"], params["data"]),
|
|
840
|
+
)
|
|
841
|
+
self._channel.on(
|
|
842
|
+
"frameReceived",
|
|
843
|
+
lambda params: self._on_frame_received(params["opcode"], params["data"]),
|
|
844
|
+
)
|
|
845
|
+
self._channel.on(
|
|
846
|
+
"socketError",
|
|
847
|
+
lambda params: self.emit(WebSocket.Events.Error, params["error"]),
|
|
848
|
+
)
|
|
849
|
+
self._channel.on("close", lambda params: self._on_close())
|
|
850
|
+
|
|
851
|
+
def __repr__(self) -> str:
|
|
852
|
+
return f"<WebSocket url={self.url!r}>"
|
|
853
|
+
|
|
854
|
+
@property
|
|
855
|
+
def url(self) -> str:
|
|
856
|
+
return self._initializer["url"]
|
|
857
|
+
|
|
858
|
+
def expect_event(
|
|
859
|
+
self, event: str, predicate: Callable = None, timeout: float = None
|
|
860
|
+
) -> EventContextManagerImpl:
|
|
861
|
+
if timeout is None:
|
|
862
|
+
timeout = cast(Any, self._parent)._timeout_settings.timeout()
|
|
863
|
+
waiter = Waiter(self, f"web_socket.expect_event({event})")
|
|
864
|
+
waiter.reject_on_timeout(
|
|
865
|
+
cast(float, timeout),
|
|
866
|
+
f'Timeout {timeout}ms exceeded while waiting for event "{event}"',
|
|
867
|
+
)
|
|
868
|
+
if event != WebSocket.Events.Close:
|
|
869
|
+
waiter.reject_on_event(self, WebSocket.Events.Close, Error("Socket closed"))
|
|
870
|
+
if event != WebSocket.Events.Error:
|
|
871
|
+
waiter.reject_on_event(self, WebSocket.Events.Error, Error("Socket error"))
|
|
872
|
+
waiter.reject_on_event(
|
|
873
|
+
self._page, "close", lambda: self._page._close_error_with_reason()
|
|
874
|
+
)
|
|
875
|
+
waiter.wait_for_event(self, event, predicate)
|
|
876
|
+
return EventContextManagerImpl(waiter.result())
|
|
877
|
+
|
|
878
|
+
async def wait_for_event(
|
|
879
|
+
self, event: str, predicate: Callable = None, timeout: float = None
|
|
880
|
+
) -> Any:
|
|
881
|
+
async with self.expect_event(event, predicate, timeout) as event_info:
|
|
882
|
+
pass
|
|
883
|
+
return await event_info
|
|
884
|
+
|
|
885
|
+
def _on_frame_sent(self, opcode: int, data: str) -> None:
|
|
886
|
+
if opcode == 2:
|
|
887
|
+
self.emit(WebSocket.Events.FrameSent, base64.b64decode(data))
|
|
888
|
+
elif opcode == 1:
|
|
889
|
+
self.emit(WebSocket.Events.FrameSent, data)
|
|
890
|
+
|
|
891
|
+
def _on_frame_received(self, opcode: int, data: str) -> None:
|
|
892
|
+
if opcode == 2:
|
|
893
|
+
self.emit(WebSocket.Events.FrameReceived, base64.b64decode(data))
|
|
894
|
+
elif opcode == 1:
|
|
895
|
+
self.emit(WebSocket.Events.FrameReceived, data)
|
|
896
|
+
|
|
897
|
+
def is_closed(self) -> bool:
|
|
898
|
+
return self._is_closed
|
|
899
|
+
|
|
900
|
+
def _on_close(self) -> None:
|
|
901
|
+
self._is_closed = True
|
|
902
|
+
self.emit(WebSocket.Events.Close, self)
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
class RawHeaders:
|
|
906
|
+
|
|
907
|
+
def __init__(self, headers: HeadersArray) -> None:
|
|
908
|
+
self._headers_array = headers
|
|
909
|
+
self._headers_map: Dict[str, Dict[str, bool]] = defaultdict(dict)
|
|
910
|
+
for header in headers:
|
|
911
|
+
self._headers_map[header["name"].lower()][header["value"]] = True
|
|
912
|
+
|
|
913
|
+
@staticmethod
|
|
914
|
+
def _from_headers_dict_lossy(headers: Dict[str, str]) -> "RawHeaders":
|
|
915
|
+
return RawHeaders(serialize_headers(headers))
|
|
916
|
+
|
|
917
|
+
def get(self, name: str) -> Optional[str]:
|
|
918
|
+
values = self.get_all(name)
|
|
919
|
+
if not values:
|
|
920
|
+
return None
|
|
921
|
+
separator = "\n" if name.lower() == "set-cookie" else ", "
|
|
922
|
+
return separator.join(values)
|
|
923
|
+
|
|
924
|
+
def get_all(self, name: str) -> List[str]:
|
|
925
|
+
return list(self._headers_map[name.lower()].keys())
|
|
926
|
+
|
|
927
|
+
def headers(self) -> Dict[str, str]:
|
|
928
|
+
result = {}
|
|
929
|
+
for name in self._headers_map.keys():
|
|
930
|
+
result[name] = cast(str, self.get(name))
|
|
931
|
+
return result
|
|
932
|
+
|
|
933
|
+
def headers_array(self) -> HeadersArray:
|
|
934
|
+
return self._headers_array
|