inspect-ai 0.3.70__py3-none-any.whl → 0.3.72__py3-none-any.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.
- inspect_ai/_cli/eval.py +14 -8
- inspect_ai/_display/core/display.py +2 -0
- inspect_ai/_display/core/footer.py +13 -3
- inspect_ai/_display/plain/display.py +6 -2
- inspect_ai/_display/rich/display.py +19 -6
- inspect_ai/_display/textual/app.py +6 -1
- inspect_ai/_display/textual/display.py +4 -0
- inspect_ai/_display/textual/widgets/transcript.py +10 -6
- inspect_ai/_eval/task/run.py +5 -8
- inspect_ai/_util/content.py +20 -1
- inspect_ai/_util/transcript.py +10 -4
- inspect_ai/_util/working.py +4 -0
- inspect_ai/_view/www/App.css +6 -0
- inspect_ai/_view/www/dist/assets/index.css +115 -87
- inspect_ai/_view/www/dist/assets/index.js +5324 -2276
- inspect_ai/_view/www/eslint.config.mjs +24 -1
- inspect_ai/_view/www/log-schema.json +283 -20
- inspect_ai/_view/www/package.json +8 -3
- inspect_ai/_view/www/src/App.tsx +2 -2
- inspect_ai/_view/www/src/components/AnsiDisplay.tsx +4 -3
- inspect_ai/_view/www/src/components/Card.tsx +9 -8
- inspect_ai/_view/www/src/components/DownloadButton.tsx +2 -1
- inspect_ai/_view/www/src/components/EmptyPanel.tsx +2 -2
- inspect_ai/_view/www/src/components/ErrorPanel.tsx +4 -3
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +13 -5
- inspect_ai/_view/www/src/components/FindBand.tsx +3 -3
- inspect_ai/_view/www/src/components/HumanBaselineView.tsx +3 -3
- inspect_ai/_view/www/src/components/LabeledValue.tsx +5 -4
- inspect_ai/_view/www/src/components/LargeModal.tsx +18 -13
- inspect_ai/_view/www/src/components/{LightboxCarousel.css → LightboxCarousel.module.css} +22 -18
- inspect_ai/_view/www/src/components/LightboxCarousel.tsx +36 -27
- inspect_ai/_view/www/src/components/MessageBand.tsx +2 -1
- inspect_ai/_view/www/src/components/NavPills.tsx +9 -8
- inspect_ai/_view/www/src/components/ProgressBar.tsx +2 -1
- inspect_ai/_view/www/src/components/TabSet.tsx +21 -15
- inspect_ai/_view/www/src/index.tsx +2 -2
- inspect_ai/_view/www/src/metadata/MetaDataGrid.tsx +11 -9
- inspect_ai/_view/www/src/metadata/MetaDataView.tsx +3 -2
- inspect_ai/_view/www/src/metadata/MetadataGrid.module.css +1 -0
- inspect_ai/_view/www/src/metadata/RenderedContent.tsx +16 -0
- inspect_ai/_view/www/src/plan/DatasetDetailView.tsx +3 -2
- inspect_ai/_view/www/src/plan/DetailStep.tsx +2 -1
- inspect_ai/_view/www/src/plan/PlanCard.tsx +2 -5
- inspect_ai/_view/www/src/plan/PlanDetailView.tsx +6 -9
- inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +2 -1
- inspect_ai/_view/www/src/plan/SolverDetailView.tsx +3 -3
- inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +2 -2
- inspect_ai/_view/www/src/samples/SampleDialog.tsx +3 -3
- inspect_ai/_view/www/src/samples/SampleDisplay.tsx +2 -2
- inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +2 -2
- inspect_ai/_view/www/src/samples/SamplesTools.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +3 -19
- inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessageRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatView.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +22 -7
- inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +35 -6
- inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +2 -2
- inspect_ai/_view/www/src/samples/chat/messages.ts +15 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +13 -4
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.module.css +2 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +18 -19
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.module.css +1 -1
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.tsx +4 -3
- inspect_ai/_view/www/src/samples/chat/tools/ToolTitle.tsx +2 -2
- inspect_ai/_view/www/src/samples/error/FlatSampleErrorView.tsx +2 -3
- inspect_ai/_view/www/src/samples/error/SampleErrorView.tsx +3 -2
- inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleHeader.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleList.tsx +57 -45
- inspect_ai/_view/www/src/samples/list/SampleRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleSeparator.tsx +2 -1
- inspect_ai/_view/www/src/samples/sample-tools/EpochFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +4 -3
- inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +2 -5
- inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +2 -1
- inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/ApprovalEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.module.css +4 -0
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.tsx +12 -2
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +1 -1
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +25 -28
- inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +5 -4
- inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +8 -7
- inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +3 -3
- inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +18 -14
- inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +5 -5
- inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +34 -15
- inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventNavs.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventRow.tsx +3 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventSection.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.module.css +28 -0
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.tsx +115 -0
- inspect_ai/_view/www/src/samples/transcript/event/utils.ts +29 -0
- inspect_ai/_view/www/src/samples/transcript/state/StateDiffView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +3 -3
- inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +11 -8
- inspect_ai/_view/www/src/types/log.d.ts +129 -34
- inspect_ai/_view/www/src/usage/ModelTokenTable.tsx +6 -10
- inspect_ai/_view/www/src/usage/ModelUsagePanel.module.css +4 -0
- inspect_ai/_view/www/src/usage/ModelUsagePanel.tsx +32 -9
- inspect_ai/_view/www/src/usage/TokenTable.tsx +4 -6
- inspect_ai/_view/www/src/usage/UsageCard.tsx +2 -1
- inspect_ai/_view/www/src/utils/format.ts +1 -1
- inspect_ai/_view/www/src/utils/json.ts +24 -0
- inspect_ai/_view/www/src/workspace/WorkSpace.tsx +6 -5
- inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +9 -2
- inspect_ai/_view/www/src/workspace/error/TaskErrorPanel.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +3 -3
- inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +4 -3
- inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +5 -4
- inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +5 -8
- inspect_ai/_view/www/src/workspace/sidebar/EvalStatus.tsx +5 -4
- inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarLogEntry.tsx +2 -2
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoreView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoresView.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +2 -5
- inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +12 -11
- inspect_ai/_view/www/yarn.lock +241 -5
- inspect_ai/log/_condense.py +3 -0
- inspect_ai/log/_recorders/eval.py +6 -1
- inspect_ai/log/_transcript.py +58 -1
- inspect_ai/model/__init__.py +2 -0
- inspect_ai/model/_call_tools.py +7 -0
- inspect_ai/model/_chat_message.py +22 -7
- inspect_ai/model/_conversation.py +10 -8
- inspect_ai/model/_generate_config.py +25 -4
- inspect_ai/model/_model.py +133 -57
- inspect_ai/model/_model_output.py +3 -0
- inspect_ai/model/_openai.py +106 -40
- inspect_ai/model/_providers/anthropic.py +281 -153
- inspect_ai/model/_providers/google.py +27 -8
- inspect_ai/model/_providers/groq.py +9 -4
- inspect_ai/model/_providers/openai.py +57 -4
- inspect_ai/model/_providers/openai_o1.py +10 -0
- inspect_ai/model/_providers/providers.py +1 -1
- inspect_ai/model/_reasoning.py +15 -2
- inspect_ai/scorer/_model.py +23 -19
- inspect_ai/solver/_human_agent/agent.py +14 -10
- inspect_ai/solver/_human_agent/commands/__init__.py +7 -3
- inspect_ai/solver/_human_agent/commands/submit.py +76 -30
- inspect_ai/tool/__init__.py +2 -0
- inspect_ai/tool/_tool.py +3 -1
- inspect_ai/tool/_tools/_computer/_common.py +117 -58
- inspect_ai/tool/_tools/_computer/_computer.py +80 -57
- inspect_ai/tool/_tools/_computer/_resources/image_home_dir/.config/Code/User/settings.json +7 -1
- inspect_ai/tool/_tools/_computer/_resources/image_home_dir/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml +91 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/.pylintrc +8 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/.vscode/settings.json +12 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_args.py +78 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_constants.py +20 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_run.py +1 -1
- inspect_ai/tool/_tools/_computer/_resources/tool/_x11_client.py +175 -113
- inspect_ai/tool/_tools/_computer/_resources/tool/computer_tool.py +76 -20
- inspect_ai/tool/_tools/_computer/_resources/tool/pyproject.toml +65 -0
- inspect_ai/tool/_tools/_computer/test_args.py +151 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.pylintrc +8 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/launch.json +24 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/settings.json +25 -0
- inspect_ai/tool/_tools/_web_browser/_resources/Dockerfile +5 -6
- inspect_ai/tool/_tools/_web_browser/_resources/README.md +10 -11
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree.py +71 -0
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree_node.py +323 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/__init__.py +5 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/a11y.py +279 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom.py +9 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom_snapshot.py +293 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/page.py +94 -0
- inspect_ai/tool/_tools/_web_browser/_resources/constants.py +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.svg +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_browser.py +50 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_crawler.py +31 -359
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_page_crawler.py +280 -0
- inspect_ai/tool/_tools/_web_browser/_resources/pyproject.toml +65 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rectangle.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rpc_client_helpers.py +146 -0
- inspect_ai/tool/_tools/_web_browser/_resources/scale_factor.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_tree_node.py +180 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_playwright_crawler.py +15 -9
- inspect_ai/tool/_tools/_web_browser/_resources/test_rectangle.py +15 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_client.py +44 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_browser_rpc_types.py +39 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_client.py +198 -48
- inspect_ai/tool/_tools/_web_browser/_resources/web_client_new_session.py +26 -25
- inspect_ai/tool/_tools/_web_browser/_resources/web_server.py +178 -39
- inspect_ai/tool/_tools/_web_browser/_web_browser.py +38 -19
- inspect_ai/util/__init__.py +2 -1
- inspect_ai/util/_display.py +12 -0
- inspect_ai/util/_sandbox/events.py +55 -21
- inspect_ai/util/_sandbox/self_check.py +131 -43
- inspect_ai/util/_subtask.py +11 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/METADATA +1 -1
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/RECORD +209 -186
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/WHEEL +1 -1
- inspect_ai/_view/www/src/components/VirtualList.module.css +0 -19
- inspect_ai/_view/www/src/components/VirtualList.tsx +0 -292
- inspect_ai/tool/_tools/_computer/_computer_split.py +0 -198
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_node.py +0 -312
- inspect_ai/tool/_tools/_web_browser/_resources/dm_env_servicer.py +0 -275
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.png +0 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_node.py +0 -176
- inspect_ai/tool/_tools/_web_browser/_resources/test_dm_env_servicer.py +0 -135
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_environment.py +0 -71
- inspect_ai/tool/_tools/_web_browser/_resources/web_environment.py +0 -184
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/LICENSE +0 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,279 @@
|
|
1
|
+
"""
|
2
|
+
Types and pure functional helpers associated with Chrome DevTools Protocol's 'Accessibility' Domain
|
3
|
+
|
4
|
+
https://chromedevtools.github.io/devtools-protocol/tot/Accessibility/
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Literal, NewType, Optional
|
8
|
+
|
9
|
+
from pydantic import BaseModel
|
10
|
+
|
11
|
+
from cdp.dom import DOMBackendNodeId
|
12
|
+
|
13
|
+
# brand these str's so that we don't confuse them with other str's
|
14
|
+
PageFrameId = NewType("PageFrameId", str)
|
15
|
+
AXNodeId = NewType("AXNodeId", str)
|
16
|
+
|
17
|
+
|
18
|
+
AXPropertyName = Literal[
|
19
|
+
"actions",
|
20
|
+
"busy",
|
21
|
+
"disabled",
|
22
|
+
"editable",
|
23
|
+
"focusable",
|
24
|
+
"focused",
|
25
|
+
"hidden",
|
26
|
+
"hiddenRoot",
|
27
|
+
"invalid",
|
28
|
+
"keyshortcuts",
|
29
|
+
"settable",
|
30
|
+
"roledescription",
|
31
|
+
"live",
|
32
|
+
"atomic",
|
33
|
+
"relevant",
|
34
|
+
"root",
|
35
|
+
"autocomplete",
|
36
|
+
"hasPopup",
|
37
|
+
"level",
|
38
|
+
"multiselectable",
|
39
|
+
"orientation",
|
40
|
+
"multiline",
|
41
|
+
"readonly",
|
42
|
+
"required",
|
43
|
+
"valuemin",
|
44
|
+
"valuemax",
|
45
|
+
"valuetext",
|
46
|
+
"checked",
|
47
|
+
"expanded",
|
48
|
+
"modal",
|
49
|
+
"pressed",
|
50
|
+
"selected",
|
51
|
+
"activedescendant",
|
52
|
+
"controls",
|
53
|
+
"describedby",
|
54
|
+
"details",
|
55
|
+
"errormessage",
|
56
|
+
"flowto",
|
57
|
+
"labelledby",
|
58
|
+
"owns",
|
59
|
+
"url",
|
60
|
+
]
|
61
|
+
|
62
|
+
|
63
|
+
AXValueType = Literal[
|
64
|
+
"boolean",
|
65
|
+
"tristate",
|
66
|
+
"booleanOrUndefined",
|
67
|
+
"idref",
|
68
|
+
"idrefList",
|
69
|
+
"integer",
|
70
|
+
"node",
|
71
|
+
"nodeList",
|
72
|
+
"number",
|
73
|
+
"string",
|
74
|
+
"computedString",
|
75
|
+
"token",
|
76
|
+
"tokenList",
|
77
|
+
"domRelation",
|
78
|
+
"role",
|
79
|
+
"internalRole",
|
80
|
+
"valueUndefined",
|
81
|
+
]
|
82
|
+
|
83
|
+
|
84
|
+
class AXRelatedNode(BaseModel, frozen=True):
|
85
|
+
backendDOMNodeId: DOMBackendNodeId
|
86
|
+
"""The BackendNodeId of the related DOM node."""
|
87
|
+
idref: str | None = None
|
88
|
+
"""The IDRef value provided, if any."""
|
89
|
+
text: str | None = None
|
90
|
+
"""The text alternative of this node in the current context."""
|
91
|
+
|
92
|
+
|
93
|
+
AXValueSourceType = Literal[
|
94
|
+
"attribute", "implicit", "stylet", "contents", "placeholder", "relatedElement"
|
95
|
+
]
|
96
|
+
|
97
|
+
AXValueNativeSourceType = Literal[
|
98
|
+
"description",
|
99
|
+
"figcaption",
|
100
|
+
"label",
|
101
|
+
"labelfor",
|
102
|
+
"labelwrapped",
|
103
|
+
"legend",
|
104
|
+
"rubyannotation",
|
105
|
+
"tablecaption",
|
106
|
+
"title",
|
107
|
+
"other",
|
108
|
+
]
|
109
|
+
|
110
|
+
|
111
|
+
class AXValueSource(BaseModel, frozen=True):
|
112
|
+
"""A single source for a computed AX property."""
|
113
|
+
|
114
|
+
type: AXValueSourceType
|
115
|
+
"""What type of source this is."""
|
116
|
+
value: Optional["AXValue"] = None
|
117
|
+
"""The value of this property source."""
|
118
|
+
attribute: str | None = None
|
119
|
+
"""The name of the relevant attribute, if any."""
|
120
|
+
attributeValue: Optional["AXValue"] = None
|
121
|
+
"""The value of the relevant attribute, if any."""
|
122
|
+
superseded: bool | None = None
|
123
|
+
"""Whether this source is superseded by a higher priority source."""
|
124
|
+
nativeSource: AXValueNativeSourceType | None = None
|
125
|
+
"""The native markup source for this value, e.g. a `<label>` element."""
|
126
|
+
nativeSourceValue: Optional["AXValue"] = None
|
127
|
+
"""The value, such as a node or node list, of the native source."""
|
128
|
+
invalid: bool | None = None
|
129
|
+
"""Whether the value for this property is invalid."""
|
130
|
+
invalidReason: str | None = None
|
131
|
+
"""Reason for the value being invalid, if it is."""
|
132
|
+
|
133
|
+
|
134
|
+
class AXValue(BaseModel, frozen=True):
|
135
|
+
"""A single computed AX property."""
|
136
|
+
|
137
|
+
type: AXValueType
|
138
|
+
"""The type of this value."""
|
139
|
+
value: object | None = None
|
140
|
+
"""The computed value of this property."""
|
141
|
+
relatedNodes: tuple[AXRelatedNode, ...] | None = None
|
142
|
+
"""One or more related nodes, if applicable."""
|
143
|
+
sources: tuple[AXValueSource, ...] | None = None
|
144
|
+
"""The sources which contributed to the computation of this property."""
|
145
|
+
|
146
|
+
|
147
|
+
class AXProperty(BaseModel, frozen=True):
|
148
|
+
name: AXPropertyName
|
149
|
+
"""The name of this property."""
|
150
|
+
value: AXValue
|
151
|
+
"""The value of this property."""
|
152
|
+
|
153
|
+
|
154
|
+
# AXNode's ignoredReasons is documented to be a list[AXProperty]. However, that seems to
|
155
|
+
# be erroneous since the namespace for ignored reason names is completely separate from property names.
|
156
|
+
class AXIgnoredReason(BaseModel, frozen=True):
|
157
|
+
# name: Literal[
|
158
|
+
# "uninteresting",
|
159
|
+
# "ariaHiddenSubtree",
|
160
|
+
# "ariaHiddenElement",
|
161
|
+
# "notRendered",
|
162
|
+
# "notVisible",
|
163
|
+
# "emptyAlt",
|
164
|
+
# ]
|
165
|
+
name: str # since this is all undocumented, it's best to be loose
|
166
|
+
"""The name of this ignored reason."""
|
167
|
+
value: AXValue
|
168
|
+
"""The value of this ignored reason."""
|
169
|
+
|
170
|
+
|
171
|
+
class AXNode(BaseModel, frozen=True):
|
172
|
+
"""A node in the accessibility tree."""
|
173
|
+
|
174
|
+
nodeId: AXNodeId
|
175
|
+
"""Unique identifier for this node."""
|
176
|
+
ignored: bool
|
177
|
+
"""Wether this node is ignore3d for accessibility"""
|
178
|
+
ignoredReasons: tuple[AXIgnoredReason, ...] | None = None
|
179
|
+
"""Collection of reasons why this node is hidden."""
|
180
|
+
role: AXValue | None = None
|
181
|
+
"""This `Node`'s role, wether explicit or implicit."""
|
182
|
+
chromeRole: AXValue | None = None
|
183
|
+
"""This `Node`'s Chrome raw role."""
|
184
|
+
name: AXValue | None = None
|
185
|
+
"""The accessible name for this `Node`."""
|
186
|
+
description: AXValue | None = None
|
187
|
+
"""The accessible description for this `Node`."""
|
188
|
+
value: AXValue | None = None
|
189
|
+
"""The value for this `Node`."""
|
190
|
+
properties: tuple[AXProperty, ...] | None = None
|
191
|
+
"""All other properties"""
|
192
|
+
parentId: AXNodeId | None = None
|
193
|
+
"""ID for this node's parent."""
|
194
|
+
childIds: tuple[AXNodeId, ...] | None = None
|
195
|
+
"""IDs for each of this node's child nodes."""
|
196
|
+
backendDOMNodeId: DOMBackendNodeId | None = None
|
197
|
+
"""The backend ID for the associated DOM node, if any."""
|
198
|
+
frameId: PageFrameId | None = None
|
199
|
+
"""The frame ID for the frame associated with this nodes document."""
|
200
|
+
|
201
|
+
|
202
|
+
class AXTree(BaseModel, frozen=True):
|
203
|
+
nodes: tuple[AXNode, ...]
|
204
|
+
|
205
|
+
|
206
|
+
# CDP defines `AXValue.value` as `Any`, so this is a coercion function
|
207
|
+
def string_from_ax_value(value: AXValue | None) -> str:
|
208
|
+
"""
|
209
|
+
Coerces an AXValue to a string.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
value (AXValue | None): The AXValue to be coerced.
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
str: The string representation of the AXValue, or an empty string if the value is None or not a string.
|
216
|
+
"""
|
217
|
+
return value.value if value and isinstance(value.value, str) else ""
|
218
|
+
|
219
|
+
|
220
|
+
def node_has_property(node: AXNode, property_name: AXPropertyName) -> bool:
|
221
|
+
"""
|
222
|
+
Checks if an AXNode has a specific property.
|
223
|
+
|
224
|
+
Args:
|
225
|
+
node (AXNode): The AXNode to check.
|
226
|
+
property_name (AXPropertyName): The name of the property to look for.
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
bool: True if the node has the property, False otherwise.
|
230
|
+
"""
|
231
|
+
return node_property(node, property_name) is not None
|
232
|
+
|
233
|
+
|
234
|
+
def node_property(node: AXNode, property_name: AXPropertyName) -> AXProperty | None:
|
235
|
+
"""
|
236
|
+
Retrieves a specific property from an AXNode.
|
237
|
+
|
238
|
+
Args:
|
239
|
+
node (AXNode): The AXNode to retrieve the property from.
|
240
|
+
property_name (AXPropertyName): The name of the property to retrieve.
|
241
|
+
|
242
|
+
Returns:
|
243
|
+
AXProperty | None: The property if found, otherwise None.
|
244
|
+
"""
|
245
|
+
return next(
|
246
|
+
(prop for prop in node.properties or () if prop.name == property_name), None
|
247
|
+
)
|
248
|
+
|
249
|
+
|
250
|
+
def node_bool_property(node: AXNode, property_name: AXPropertyName) -> bool:
|
251
|
+
"""
|
252
|
+
Retrieves a boolean property from an AXNode.
|
253
|
+
|
254
|
+
Args:
|
255
|
+
node (AXNode): The AXNode to retrieve the property from.
|
256
|
+
property_name (AXPropertyName): The name of the property to retrieve.
|
257
|
+
|
258
|
+
Returns:
|
259
|
+
bool: The boolean value of the property, or False if the property is not found or not a boolean.
|
260
|
+
"""
|
261
|
+
return bool(prop.value) if (prop := node_property(node, property_name)) else False
|
262
|
+
|
263
|
+
|
264
|
+
def node_str_property(node: AXNode, property_name: AXPropertyName) -> str | None:
|
265
|
+
"""
|
266
|
+
Retrieves a str property from an AXNode.
|
267
|
+
|
268
|
+
Args:
|
269
|
+
node (AXNode): The AXNode to retrieve the property from.
|
270
|
+
property_name (AXPropertyName): The name of the property to retrieve.
|
271
|
+
|
272
|
+
Returns:
|
273
|
+
str: The str value of the property, or None if the property is not found or not a str.
|
274
|
+
"""
|
275
|
+
prop = node_property(node, property_name)
|
276
|
+
if prop is None:
|
277
|
+
return None
|
278
|
+
v = prop.value
|
279
|
+
return v.value if isinstance(v.value, str) else None
|
@@ -0,0 +1,293 @@
|
|
1
|
+
"""
|
2
|
+
Types and pure functional helpers associated with Chrome DevTools Protocol's 'DOMSnapshot' Domain
|
3
|
+
|
4
|
+
https://chromedevtools.github.io/devtools-protocol/tot/DOMSnapshot/
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Literal, NewType, TypedDict
|
8
|
+
|
9
|
+
from pydantic import BaseModel
|
10
|
+
|
11
|
+
from cdp.dom import DOMBackendNodeId
|
12
|
+
|
13
|
+
StringIndex = NewType("StringIndex", int)
|
14
|
+
Rectangle = tuple[float, ...]
|
15
|
+
ArrayOfStrings = tuple[StringIndex, ...]
|
16
|
+
|
17
|
+
|
18
|
+
class RareStringData(BaseModel, frozen=True):
|
19
|
+
"""Data that is only present on rare nodes."""
|
20
|
+
|
21
|
+
index: tuple[int, ...]
|
22
|
+
value: tuple[StringIndex, ...]
|
23
|
+
|
24
|
+
|
25
|
+
class RareIntegerData(BaseModel, frozen=True):
|
26
|
+
index: tuple[int, ...]
|
27
|
+
value: tuple[int, ...]
|
28
|
+
|
29
|
+
|
30
|
+
class RareBooleanData(BaseModel, frozen=True):
|
31
|
+
index: tuple[int, ...]
|
32
|
+
|
33
|
+
|
34
|
+
class NodeTreeSnapshot(BaseModel, frozen=True):
|
35
|
+
"""Table containing nodes."""
|
36
|
+
|
37
|
+
parentIndex: tuple[int, ...] | None = None
|
38
|
+
"""Parent node index."""
|
39
|
+
nodeType: tuple[int, ...] | None = None
|
40
|
+
"""`Node`'s nodeType"""
|
41
|
+
shadowRootType: RareStringData | None = None
|
42
|
+
"""Type of the shadow root the `Node` is in. String values are equal to the `ShadowRootType` enum."""
|
43
|
+
nodeName: tuple[StringIndex, ...] | None = None
|
44
|
+
"""`Node`'s nodeName."""
|
45
|
+
nodeValue: tuple[StringIndex, ...] | None = None
|
46
|
+
"""`Node`'s nodeValue."""
|
47
|
+
backendNodeId: tuple[DOMBackendNodeId, ...] | None = None
|
48
|
+
"""`Node`'s id, corresponds to DOM.Node.backendNodeId."""
|
49
|
+
attributes: tuple[ArrayOfStrings, ...] | None = None
|
50
|
+
# attributes: list[int] | None = None
|
51
|
+
"""Attributes of an `Element` node. Flatten name, value pairs."""
|
52
|
+
textValue: RareStringData | None = None
|
53
|
+
"""Only set for textarea elements, contains the text value."""
|
54
|
+
inputValue: RareStringData | None = None
|
55
|
+
"""Only set for input elements, contains the input's associated text value."""
|
56
|
+
inputChecked: RareBooleanData | None = None
|
57
|
+
"""Only set for radio and checkbox input elements, indicates if the element has been checked"""
|
58
|
+
optionSelected: RareBooleanData | None = None
|
59
|
+
"""Only set for option elements, indicates if the element has been selected"""
|
60
|
+
contentDocumentIndex: RareIntegerData | None = None
|
61
|
+
"""The index of the document in the list of the snapshot documents."""
|
62
|
+
pseudoType: RareStringData | None = None
|
63
|
+
"""Type of a pseudo element node."""
|
64
|
+
pseudoIdentifier: RareStringData | None = None
|
65
|
+
"""Pseudo element identifier for this node. Only present if there is a valid pseudoType."""
|
66
|
+
isClickable: RareBooleanData | None = None
|
67
|
+
"""Whether this DOM node responds to mouse clicks. This includes nodes that have had click event listeners attached via JavaScript as well as anchor tags that naturally navigate when clicked."""
|
68
|
+
currentSourceURL: RareStringData | None = None
|
69
|
+
"""The selected url for nodes with a srcset attribute."""
|
70
|
+
originURL: RareStringData | None = None
|
71
|
+
"""The url of the script (if any) that generates this node."""
|
72
|
+
|
73
|
+
|
74
|
+
class LayoutTreeSnapshot(BaseModel, frozen=True):
|
75
|
+
"""Table of details of an element in the DOM tree with a `LayoutObject`."""
|
76
|
+
|
77
|
+
nodeIndex: tuple[int, ...]
|
78
|
+
"""Index of the corresponding node in the `NodeTreeSnapshot` array returned by `captureSnapshot`."""
|
79
|
+
styles: tuple[ArrayOfStrings, ...]
|
80
|
+
"""Array of indexes specifying computed style strings, filtered according to the computedStyles parameter passed to captureSnapshot."""
|
81
|
+
bounds: tuple[Rectangle, ...]
|
82
|
+
"""The absolute position bounding box."""
|
83
|
+
text: tuple[StringIndex, ...]
|
84
|
+
"""Contents of the `LayoutText`, if any."""
|
85
|
+
stackingContexts: RareBooleanData
|
86
|
+
"""Stacking context information."""
|
87
|
+
paintOrders: tuple[int, ...] | None = None
|
88
|
+
"""Global paint order index, which is determined by the stacking order of the nodes. Nodes that are painted together will have the same index. Only provided if `includePaintOrder` in `captureSnapshot` was true."""
|
89
|
+
offsetRects: tuple[Rectangle, ...] | None = None
|
90
|
+
"""The offset rect of nodes. Only available when `includeDOMRects` is set to true"""
|
91
|
+
scrollRects: tuple[Rectangle, ...] | None = None
|
92
|
+
"""The scroll rect of nodes. Only available when `includeDOMRects` is set to true"""
|
93
|
+
clientRects: tuple[Rectangle, ...] | None = None
|
94
|
+
"""The client rect of nodes. Only available when `includeDOMRects` is set to true"""
|
95
|
+
blendedBackgroundColors: tuple[StringIndex, ...] | None = None
|
96
|
+
"""The list of background colors that are blended with colors of overlapping elements. Experimental"""
|
97
|
+
textColorOpacities: tuple[float, ...] | None = None
|
98
|
+
"""The list of computed text opacities. Experimental"""
|
99
|
+
|
100
|
+
|
101
|
+
class TextBoxSnapshot(BaseModel, frozen=True):
|
102
|
+
"""Table of details of the post layout rendered text positions. The exact layout should not be regarded as stable and may change between versions."""
|
103
|
+
|
104
|
+
layoutIndex: tuple[int, ...]
|
105
|
+
"""Index of the layout tree node that owns this box collection."""
|
106
|
+
bounds: tuple[Rectangle, ...]
|
107
|
+
"""The absolute position bounding box."""
|
108
|
+
start: tuple[int, ...]
|
109
|
+
"""The starting index in characters, for this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2."""
|
110
|
+
length: tuple[int, ...]
|
111
|
+
"""The number of characters in this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2."""
|
112
|
+
|
113
|
+
|
114
|
+
class DocumentSnapshot(BaseModel, frozen=True):
|
115
|
+
documentURL: StringIndex
|
116
|
+
"""Document URL that `Document` or `FrameOwner` node points to."""
|
117
|
+
title: StringIndex
|
118
|
+
"""Document title."""
|
119
|
+
baseURL: StringIndex
|
120
|
+
"""Base URL that `Document` or `FrameOwner` node uses for URL completion."""
|
121
|
+
contentLanguage: StringIndex
|
122
|
+
"""Contains the document's content language."""
|
123
|
+
encodingName: StringIndex
|
124
|
+
"""Contains the document's character set encoding."""
|
125
|
+
publicId: StringIndex
|
126
|
+
"""`DocumentType` node's publicId."""
|
127
|
+
systemId: StringIndex
|
128
|
+
"""`DocumentType` node's systemId."""
|
129
|
+
frameId: StringIndex
|
130
|
+
"""Frame ID for frame owner elements and also for the document node."""
|
131
|
+
nodes: NodeTreeSnapshot
|
132
|
+
"""A table with dom nodes."""
|
133
|
+
layout: LayoutTreeSnapshot
|
134
|
+
"""The nodes in the layout tree."""
|
135
|
+
textBoxes: TextBoxSnapshot
|
136
|
+
"""The post-layout inline text nodes."""
|
137
|
+
scrollOffsetX: float | None = None
|
138
|
+
"""Horizontal scroll offset."""
|
139
|
+
scrollOffsetY: float | None = None
|
140
|
+
"""Vertical scroll offset."""
|
141
|
+
contentWidth: float | None = None
|
142
|
+
"""Document content width."""
|
143
|
+
contentHeight: float | None = None
|
144
|
+
"""Document content height."""
|
145
|
+
|
146
|
+
|
147
|
+
class DOMSnapshot(BaseModel, frozen=True):
|
148
|
+
documents: tuple[DocumentSnapshot, ...]
|
149
|
+
"""The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document."""
|
150
|
+
strings: tuple[str, ...]
|
151
|
+
"""Shared string table that all string properties refer to with indexes."""
|
152
|
+
|
153
|
+
|
154
|
+
NodeIndex = NewType("NodeIndex", int)
|
155
|
+
LayoutIndex = NewType("LayoutIndex", int)
|
156
|
+
|
157
|
+
|
158
|
+
class DOMSnapshotContext(TypedDict):
|
159
|
+
dom_snapshot: DOMSnapshot
|
160
|
+
node_id_to_node_index: dict[DOMBackendNodeId, NodeIndex]
|
161
|
+
# Below are dicts to help with non-1:1 index mappings like layouts and RareStringData's
|
162
|
+
node_index_to_layout_index: dict[NodeIndex, LayoutIndex]
|
163
|
+
node_index_to_current_src_url_index: dict[NodeIndex, StringIndex]
|
164
|
+
node_index_to_text_value_index: dict[NodeIndex, StringIndex]
|
165
|
+
|
166
|
+
|
167
|
+
def create_snapshot_context(dom_snapshot: DOMSnapshot) -> DOMSnapshotContext:
|
168
|
+
"""
|
169
|
+
Creates a DOMSnapshotContext that can be used to efficiently extract data from a DOMSnapshot.
|
170
|
+
|
171
|
+
Given the fact that a DOMSnapshot uses long flat correlated lists (see below), this context
|
172
|
+
enables efficient lookups that avoid full list scans.
|
173
|
+
|
174
|
+
NOTE: Currently, this context and associated code assumes document[0]
|
175
|
+
|
176
|
+
The DOMSnapshot domain represents the DOM tree as as set of objects each containing
|
177
|
+
parallel flat arrays — NodeTreeSnapshot, LayoutTreeSnapshot, etc.
|
178
|
+
|
179
|
+
Each node in the DOM tree is represented in the NodeTreeSnapshot object by corresponding
|
180
|
+
entries at the same index across multiple arrays (parentIndex, nodeType, backendNodeId, etc.):
|
181
|
+
|
182
|
+
NodeTreeSnapshot:
|
183
|
+
│ 0 │ 1 | 2 | 3 | 4
|
184
|
+
──────────────┼────────┼────────┼────────┼────────┼────────
|
185
|
+
actual tag │ <html> │ <body> │ <div> │ <p> │ <span>
|
186
|
+
parentIndex │ -1 │ 0 │ 1 │ 2 │ 3
|
187
|
+
backendNodeId │ 666 │ 745 │ 103 │ 421 │ 7
|
188
|
+
attributes │ ... │ ... │ ... │ ... │ ...
|
189
|
+
nodeValue │ ... │ ... │ ... │ ... │ ...
|
190
|
+
etc │ ... │ ... │ ... │ ... │ ...
|
191
|
+
|
192
|
+
|
193
|
+
Because layout is independent of node ordering, entries in the LayoutTreeSnapshot object maintain
|
194
|
+
a reference back to their corresponding node through the nodeIndex field along with layout specific
|
195
|
+
properties (bounds, paintOrders, etc).
|
196
|
+
|
197
|
+
LayoutTreeSnapshot:
|
198
|
+
│ 0 │ 1 │ 2 │ 3 │ 4
|
199
|
+
──────────────┼────────┼────────┼────────┼────────┼────────
|
200
|
+
bounds │ ... │ ... │ ... │ ... │ ...
|
201
|
+
etc │ ... │ ... │ ... │ ... │ ...
|
202
|
+
nodeIndex │ 3 │ 0 │ 4 │ 2 │ 1
|
203
|
+
──────────────┼────────┼────────┼────────┼────────┼────────
|
204
|
+
│ ↓ │ ↓ │ ↓ │ ↓ │ ↓
|
205
|
+
backendNodeId │ 421 │ 666 │ 7 │ 103 │ 745
|
206
|
+
actual tag │ <p> │ <html> │ <span> │ <div> │ <body>
|
207
|
+
"""
|
208
|
+
document = dom_snapshot.documents[0]
|
209
|
+
return {
|
210
|
+
"dom_snapshot": dom_snapshot,
|
211
|
+
"node_id_to_node_index": {
|
212
|
+
node_id: index
|
213
|
+
for index, node_id in enumerate(document.nodes.backendNodeId or [])
|
214
|
+
},
|
215
|
+
"node_index_to_layout_index": {
|
216
|
+
node_index: layout_index
|
217
|
+
for layout_index, node_index in enumerate(document.layout.nodeIndex)
|
218
|
+
},
|
219
|
+
"node_index_to_current_src_url_index": _dict_for_rare_string_data(
|
220
|
+
document.nodes.currentSourceURL
|
221
|
+
),
|
222
|
+
"node_index_to_text_value_index": _dict_for_rare_string_data(
|
223
|
+
document.nodes.textValue
|
224
|
+
),
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
def index_for_node_id(
|
229
|
+
node_id: DOMBackendNodeId, context: DOMSnapshotContext
|
230
|
+
) -> NodeIndex | None:
|
231
|
+
return context["node_id_to_node_index"].get(node_id, None)
|
232
|
+
|
233
|
+
|
234
|
+
def bounds_for_node_index(
|
235
|
+
node_index: NodeIndex, context: DOMSnapshotContext
|
236
|
+
) -> Rectangle | None:
|
237
|
+
return (
|
238
|
+
context["dom_snapshot"].documents[0].layout.bounds[layout_index]
|
239
|
+
if (layout_index := _layout_index_for_node_index(node_index, context))
|
240
|
+
is not None
|
241
|
+
else None
|
242
|
+
)
|
243
|
+
|
244
|
+
|
245
|
+
def current_url_src_for_node_index(
|
246
|
+
node_index: NodeIndex, context: DOMSnapshotContext
|
247
|
+
) -> str | None:
|
248
|
+
return _rare_string_for_node_index(
|
249
|
+
node_index, "node_index_to_current_src_url_index", context
|
250
|
+
)
|
251
|
+
|
252
|
+
|
253
|
+
def text_value_for_node_index(
|
254
|
+
node_index: NodeIndex, context: DOMSnapshotContext
|
255
|
+
) -> str | None:
|
256
|
+
return _rare_string_for_node_index(
|
257
|
+
node_index, "node_index_to_text_value_index", context
|
258
|
+
)
|
259
|
+
|
260
|
+
|
261
|
+
def _layout_index_for_node_index(
|
262
|
+
node_index: NodeIndex, context: DOMSnapshotContext
|
263
|
+
) -> LayoutIndex | None:
|
264
|
+
"""Returns the index of the layout entry, if any, corresponding to the given node id."""
|
265
|
+
return context["node_index_to_layout_index"].get(node_index, None)
|
266
|
+
|
267
|
+
|
268
|
+
def _rare_string_for_node_index(
|
269
|
+
node_index: NodeIndex,
|
270
|
+
dict_name: Literal[
|
271
|
+
"node_index_to_text_value_index", "node_index_to_current_src_url_index"
|
272
|
+
],
|
273
|
+
context: DOMSnapshotContext,
|
274
|
+
) -> str | None:
|
275
|
+
return (
|
276
|
+
_string_for_string_index(text_value_index, context)
|
277
|
+
if (text_value_index := context[dict_name].get(node_index, None))
|
278
|
+
else None
|
279
|
+
)
|
280
|
+
|
281
|
+
|
282
|
+
def _string_for_string_index(index: StringIndex, context: DOMSnapshotContext) -> str:
|
283
|
+
return context["dom_snapshot"].strings[index]
|
284
|
+
|
285
|
+
|
286
|
+
def _dict_for_rare_string_data(
|
287
|
+
rare_string_data: RareStringData,
|
288
|
+
) -> dict[NodeIndex, StringIndex]:
|
289
|
+
"""Creates a dictionary from a RareStringData object enabling lookups given a node index."""
|
290
|
+
return {
|
291
|
+
index: value
|
292
|
+
for index, value in zip(rare_string_data.index, rare_string_data.value)
|
293
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
"""
|
2
|
+
Types associated with Chrome DevTools Protocol's 'Page' Domain
|
3
|
+
|
4
|
+
https://chromedevtools.github.io/devtools-protocol/tot/Page/
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Literal, NewType
|
8
|
+
|
9
|
+
from pydantic import BaseModel
|
10
|
+
|
11
|
+
FrameId = NewType("FrameId", str)
|
12
|
+
|
13
|
+
|
14
|
+
class SecurityOriginDetails(BaseModel, frozen=True):
|
15
|
+
"""Additional information about the frame document's security origin."""
|
16
|
+
|
17
|
+
isLocalhost: bool
|
18
|
+
"""Indicates whether the frame document's security origin is one of the local hostnames (e.g. "localhost") or IP addresses (IPv4 127.0.0.0/8 or IPv6 ::1)."""
|
19
|
+
|
20
|
+
|
21
|
+
AdFrameType = Literal["none", "child", "root"]
|
22
|
+
|
23
|
+
AdFrameExplanation = Literal["ParentIsAd", "CreatedByAdScript", "MatchedBlockingRule"]
|
24
|
+
|
25
|
+
|
26
|
+
class AdFrameStatus(BaseModel, frozen=True):
|
27
|
+
"""Indicates whether a frame has been identified as an ad and why."""
|
28
|
+
|
29
|
+
adFrameType: AdFrameType
|
30
|
+
explanations: tuple[AdFrameExplanation, ...] | None = None
|
31
|
+
|
32
|
+
|
33
|
+
SecureContextType = Literal[
|
34
|
+
"Secure", "SecureLocalhost", "InsecureScheme", "InsecureAncestor"
|
35
|
+
]
|
36
|
+
|
37
|
+
|
38
|
+
CrossOriginIsolatedContextType = Literal[
|
39
|
+
"Isolated", "NotIsolated", "NotIsolatedFeatureDisabled"
|
40
|
+
]
|
41
|
+
|
42
|
+
|
43
|
+
GatedAPIFeatures = Literal[
|
44
|
+
"SharedArrayBuffers",
|
45
|
+
"SharedArrayBuffersTransferAllowed",
|
46
|
+
"PerformanceMeasureMemory",
|
47
|
+
"PerformanceProfile",
|
48
|
+
]
|
49
|
+
|
50
|
+
|
51
|
+
class Frame(BaseModel, frozen=True):
|
52
|
+
"""Information about the Frame on the page."""
|
53
|
+
|
54
|
+
id: FrameId
|
55
|
+
"""Frame unique identifier."""
|
56
|
+
parentId: FrameId | None = None
|
57
|
+
"""Parent frame identifier."""
|
58
|
+
loaderId: object # Network.LoaderId
|
59
|
+
"""Identifier of the loader associated with this frame."""
|
60
|
+
name: str | None = None
|
61
|
+
"""Frame's name as specified in the tag."""
|
62
|
+
url: str
|
63
|
+
"""Frame document's URL without fragment."""
|
64
|
+
urlFragment: str | None = None
|
65
|
+
"""Frame document's URL fragment including the '#'."""
|
66
|
+
domainAndRegistry: str
|
67
|
+
"""Frame document's registered domain, taking the public suffixes list into account. Extracted from the Frame's url. Example URLs: http://www.google.com/file.html -> "google.com" http://a.b.co.uk/file.html -> "b.co.uk"""
|
68
|
+
securityOrigin: str
|
69
|
+
"""Frame document's security origin."""
|
70
|
+
securityOriginDetails: SecurityOriginDetails | None = None
|
71
|
+
"""Additional details about the frame document's security origin."""
|
72
|
+
mimeType: str
|
73
|
+
"""Frame document's mimeType as determined by the browser."""
|
74
|
+
unreachableUrl: str | None = None
|
75
|
+
"""If the frame failed to load, this contains the URL that could not be loaded. Note that unlike url above, this URL may contain a fragment."""
|
76
|
+
adFrameStatus: AdFrameStatus | None = None
|
77
|
+
"""Indicates whether this frame was tagged as an ad and why."""
|
78
|
+
secureContextType: SecureContextType
|
79
|
+
"""Indicates whether the main document is a secure context and explains why that is the case."""
|
80
|
+
crossOriginIsolatedContextType: CrossOriginIsolatedContextType
|
81
|
+
"""Indicates whether this is a cross origin isolated context."""
|
82
|
+
gatedAPIFeatures: tuple[GatedAPIFeatures, ...]
|
83
|
+
"""Indicated which gated APIs / features are available."""
|
84
|
+
|
85
|
+
|
86
|
+
class FrameTree(BaseModel, frozen=True):
|
87
|
+
frame: Frame
|
88
|
+
"""Frame information for this tree item."""
|
89
|
+
childFrames: tuple["FrameTree", ...] | None = None
|
90
|
+
"""Child frames."""
|
91
|
+
|
92
|
+
|
93
|
+
class FrameTrees(BaseModel, frozen=True):
|
94
|
+
frameTree: FrameTree
|