JinghuiLuAstronaut commited on
Commit
25e08f3
·
verified ·
1 Parent(s): af38f3c

Add files using upload-large-folder tool

Browse files
Files changed (20) hide show
  1. LTA_openwebtext_dualt/docs/lta_samples/metrics_20260517/selected_long20k_len256_bs512_ode128_20260517_1830long20k/rollin_p50_s4_old/step_3000/decode_token_acc.tsv +2 -0
  2. LTA_openwebtext_dualt/logs/ctx1024_sampleds_sweep_4gpu/ctx1024_sampledpath_true_20260517_224139.log +331 -0
  3. LTA_openwebtext_dualt/logs/ctx1024_sampleds_sweep_4gpu/ctx1024_tradeoff_dual_20260517_225705.nohup +0 -0
  4. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/anyio/from_thread.py +578 -0
  5. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/anyio/py.typed +0 -0
  6. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/__init__.py +62 -0
  7. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_abnf.py +132 -0
  8. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_connection.py +659 -0
  9. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_events.py +369 -0
  10. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_headers.py +282 -0
  11. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_readers.py +250 -0
  12. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_receivebuffer.py +153 -0
  13. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_state.py +365 -0
  14. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_util.py +135 -0
  15. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_version.py +16 -0
  16. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_writers.py +145 -0
  17. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/py.typed +1 -0
  18. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/__init__.py +27 -0
  19. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/configuration_rwkv.py +76 -0
  20. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/modeling_rwkv.py +758 -0
LTA_openwebtext_dualt/docs/lta_samples/metrics_20260517/selected_long20k_len256_bs512_ode128_20260517_1830long20k/rollin_p50_s4_old/step_3000/decode_token_acc.tsv ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ run ckpt_step endpoint_softening token_acc_mean token_acc_min token_acc_max exact_acc exact_count exact_ref_coverage exact_ref_count
2
+ train8_rollin_len256_rollin_p50_s4_i32_20260517_171654 3000 none 0.9420166015625 0.12109375 1.0 0.140625 9 0.125 1
LTA_openwebtext_dualt/logs/ctx1024_sampleds_sweep_4gpu/ctx1024_sampledpath_true_20260517_224139.log ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [ctx1024-sampleds] start stamp=ctx1024_sampledpath_true_20260517_224139 len=1024 vocab=2664 out=docs/lta_samples/metrics_20260517/ctx1024_sampleds_sweep_bs512_ode128_ctx1024_sampledpath_true_20260517_224139
2
+ [ctx1024-sampleds] config=p50_path4_unif0_0p125_outwdm1 run=train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139 p=0.50 mode=sampled_path steps=4 s_dist=uniform s_frac=0.0->0.125 beta=2.0,6.0 outwd=-1 sync_t=1
3
+ [ctx1024-sampleds] train config=p50_path4_unif0_0p125_outwdm1 from=0 to=1000
4
+ [ctx1024-sampleds] eval config=p50_path4_unif0_0p125_outwdm1 step=1000
5
+ [eval-decode-acc] train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139 step=1000 soft=none
6
+ [decode] max_len=1024 generated=64/64
7
+ {
8
+ "num_rows": 1,
9
+ "best_by_run": {
10
+ "train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139::none": {
11
+ "run": "train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139",
12
+ "checkpoint": "runs/train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139/step_0001000.pt",
13
+ "ckpt_step": 1000,
14
+ "endpoint_softening": "none",
15
+ "decode_rule": "flowmap",
16
+ "steps": 128,
17
+ "time_schedule": "logit_normal",
18
+ "model_t_mode": "post",
19
+ "final_from": "state",
20
+ "n_gen": 64,
21
+ "n_refs": 8,
22
+ "token_acc_mean": 0.0288543701171875,
23
+ "token_acc_min": 0.01953125,
24
+ "token_acc_max": 0.0478515625,
25
+ "exact_acc": 0.0,
26
+ "exact_count": 0,
27
+ "exact_ref_coverage": 0.0,
28
+ "exact_ref_count": 0,
29
+ "exact_ref_hits": [],
30
+ "best_ref_idx": [
31
+ 7,
32
+ 2,
33
+ 5,
34
+ 7,
35
+ 7,
36
+ 7,
37
+ 2,
38
+ 0,
39
+ 7,
40
+ 3,
41
+ 7,
42
+ 4,
43
+ 2,
44
+ 7,
45
+ 7,
46
+ 5,
47
+ 7,
48
+ 2,
49
+ 1,
50
+ 0,
51
+ 7,
52
+ 2,
53
+ 7,
54
+ 5,
55
+ 7,
56
+ 0,
57
+ 5,
58
+ 5,
59
+ 7,
60
+ 7,
61
+ 5,
62
+ 7,
63
+ 4,
64
+ 7,
65
+ 7,
66
+ 5,
67
+ 5,
68
+ 4,
69
+ 7,
70
+ 5,
71
+ 2,
72
+ 7,
73
+ 5,
74
+ 7,
75
+ 7,
76
+ 7,
77
+ 7,
78
+ 4,
79
+ 4,
80
+ 5,
81
+ 7,
82
+ 2,
83
+ 4,
84
+ 7,
85
+ 0,
86
+ 7,
87
+ 7,
88
+ 5,
89
+ 0,
90
+ 4,
91
+ 0,
92
+ 7,
93
+ 4,
94
+ 5
95
+ ],
96
+ "best_token_acc": [
97
+ 0.0263671875,
98
+ 0.021484375,
99
+ 0.029296875,
100
+ 0.01953125,
101
+ 0.029296875,
102
+ 0.0283203125,
103
+ 0.0234375,
104
+ 0.021484375,
105
+ 0.0263671875,
106
+ 0.0283203125,
107
+ 0.0234375,
108
+ 0.025390625,
109
+ 0.0302734375,
110
+ 0.0263671875,
111
+ 0.0263671875,
112
+ 0.0263671875,
113
+ 0.0263671875,
114
+ 0.0234375,
115
+ 0.0283203125,
116
+ 0.0302734375,
117
+ 0.033203125,
118
+ 0.0380859375,
119
+ 0.0263671875,
120
+ 0.0283203125,
121
+ 0.02734375,
122
+ 0.03515625,
123
+ 0.044921875,
124
+ 0.0419921875,
125
+ 0.03125,
126
+ 0.0283203125,
127
+ 0.0478515625,
128
+ 0.0224609375,
129
+ 0.0263671875,
130
+ 0.0283203125,
131
+ 0.033203125,
132
+ 0.041015625,
133
+ 0.03125,
134
+ 0.0224609375,
135
+ 0.03125,
136
+ 0.03515625,
137
+ 0.0244140625,
138
+ 0.0263671875,
139
+ 0.0302734375,
140
+ 0.0234375,
141
+ 0.01953125,
142
+ 0.021484375,
143
+ 0.0224609375,
144
+ 0.0322265625,
145
+ 0.025390625,
146
+ 0.0322265625,
147
+ 0.029296875,
148
+ 0.033203125,
149
+ 0.0244140625,
150
+ 0.033203125,
151
+ 0.02734375,
152
+ 0.041015625,
153
+ 0.025390625,
154
+ 0.0302734375,
155
+ 0.0234375,
156
+ 0.02734375,
157
+ 0.0244140625,
158
+ 0.025390625,
159
+ 0.025390625,
160
+ 0.0439453125
161
+ ]
162
+ }
163
+ },
164
+ "first_exact_by_run": {}
165
+ }
166
+ RESULT config=p50_path4_unif0_0p125_outwdm1 run=train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139 ckpt_step=1000 views=512000 token_acc=0.0289 exact=0/64 exact_refs=0 hits=[]
167
+ [ctx1024-sampleds] train config=p50_path4_unif0_0p125_outwdm1 from=1000 to=2000
168
+ [ctx1024-sampleds] eval config=p50_path4_unif0_0p125_outwdm1 step=2000
169
+ [eval-decode-acc] train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139 step=2000 soft=none
170
+ [decode] max_len=1024 generated=64/64
171
+ {
172
+ "num_rows": 1,
173
+ "best_by_run": {
174
+ "train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139::none": {
175
+ "run": "train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139",
176
+ "checkpoint": "runs/train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139/step_0002000.pt",
177
+ "ckpt_step": 2000,
178
+ "endpoint_softening": "none",
179
+ "decode_rule": "flowmap",
180
+ "steps": 128,
181
+ "time_schedule": "logit_normal",
182
+ "model_t_mode": "post",
183
+ "final_from": "state",
184
+ "n_gen": 64,
185
+ "n_refs": 8,
186
+ "token_acc_mean": 0.86529541015625,
187
+ "token_acc_min": 0.2119140625,
188
+ "token_acc_max": 0.9921875,
189
+ "exact_acc": 0.0,
190
+ "exact_count": 0,
191
+ "exact_ref_coverage": 0.0,
192
+ "exact_ref_count": 0,
193
+ "exact_ref_hits": [],
194
+ "best_ref_idx": [
195
+ 4,
196
+ 4,
197
+ 5,
198
+ 4,
199
+ 1,
200
+ 7,
201
+ 4,
202
+ 4,
203
+ 5,
204
+ 1,
205
+ 5,
206
+ 1,
207
+ 4,
208
+ 1,
209
+ 4,
210
+ 4,
211
+ 1,
212
+ 5,
213
+ 4,
214
+ 1,
215
+ 4,
216
+ 4,
217
+ 4,
218
+ 4,
219
+ 4,
220
+ 4,
221
+ 7,
222
+ 4,
223
+ 4,
224
+ 1,
225
+ 4,
226
+ 4,
227
+ 4,
228
+ 1,
229
+ 4,
230
+ 4,
231
+ 4,
232
+ 4,
233
+ 5,
234
+ 4,
235
+ 1,
236
+ 4,
237
+ 4,
238
+ 3,
239
+ 4,
240
+ 5,
241
+ 7,
242
+ 7,
243
+ 5,
244
+ 4,
245
+ 4,
246
+ 4,
247
+ 5,
248
+ 4,
249
+ 4,
250
+ 4,
251
+ 5,
252
+ 4,
253
+ 7,
254
+ 4,
255
+ 5,
256
+ 4,
257
+ 1,
258
+ 4
259
+ ],
260
+ "best_token_acc": [
261
+ 0.962890625,
262
+ 0.966796875,
263
+ 0.9912109375,
264
+ 0.3701171875,
265
+ 0.78125,
266
+ 0.7607421875,
267
+ 0.9658203125,
268
+ 0.9560546875,
269
+ 0.9873046875,
270
+ 0.376953125,
271
+ 0.9921875,
272
+ 0.970703125,
273
+ 0.95703125,
274
+ 0.72265625,
275
+ 0.71484375,
276
+ 0.7314453125,
277
+ 0.9765625,
278
+ 0.9892578125,
279
+ 0.73828125,
280
+ 0.861328125,
281
+ 0.9521484375,
282
+ 0.9716796875,
283
+ 0.8662109375,
284
+ 0.8330078125,
285
+ 0.96875,
286
+ 0.9482421875,
287
+ 0.9853515625,
288
+ 0.689453125,
289
+ 0.962890625,
290
+ 0.9775390625,
291
+ 0.9580078125,
292
+ 0.2119140625,
293
+ 0.9345703125,
294
+ 0.2138671875,
295
+ 0.90625,
296
+ 0.5400390625,
297
+ 0.9736328125,
298
+ 0.685546875,
299
+ 0.9716796875,
300
+ 0.8994140625,
301
+ 0.974609375,
302
+ 0.9736328125,
303
+ 0.9248046875,
304
+ 0.984375,
305
+ 0.9677734375,
306
+ 0.7060546875,
307
+ 0.9345703125,
308
+ 0.9228515625,
309
+ 0.9912109375,
310
+ 0.8466796875,
311
+ 0.9599609375,
312
+ 0.9638671875,
313
+ 0.4013671875,
314
+ 0.9033203125,
315
+ 0.9736328125,
316
+ 0.943359375,
317
+ 0.9912109375,
318
+ 0.9716796875,
319
+ 0.98828125,
320
+ 0.9716796875,
321
+ 0.97265625,
322
+ 0.94921875,
323
+ 0.97265625,
324
+ 0.9658203125
325
+ ]
326
+ }
327
+ },
328
+ "first_exact_by_run": {}
329
+ }
330
+ RESULT config=p50_path4_unif0_0p125_outwdm1 run=train8_ctx1024_p50_path4_unif0_0p125_outwdm1_ctx1024_sampledpath_true_20260517_224139 ckpt_step=2000 views=1024000 token_acc=0.8653 exact=0/64 exact_refs=0 hits=[]
331
+ [ctx1024-sampleds] train config=p50_path4_unif0_0p125_outwdm1 from=2000 to=3000
LTA_openwebtext_dualt/logs/ctx1024_sampleds_sweep_4gpu/ctx1024_tradeoff_dual_20260517_225705.nohup ADDED
The diff for this file is too large to render. See raw diff
 
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/anyio/from_thread.py ADDED
@@ -0,0 +1,578 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "BlockingPortal",
5
+ "BlockingPortalProvider",
6
+ "check_cancelled",
7
+ "run",
8
+ "run_sync",
9
+ "start_blocking_portal",
10
+ )
11
+
12
+ import sys
13
+ from collections.abc import Awaitable, Callable, Generator
14
+ from concurrent.futures import Future
15
+ from contextlib import (
16
+ AbstractAsyncContextManager,
17
+ AbstractContextManager,
18
+ contextmanager,
19
+ )
20
+ from dataclasses import dataclass, field
21
+ from functools import partial
22
+ from inspect import isawaitable
23
+ from threading import Lock, Thread, current_thread, get_ident
24
+ from types import TracebackType
25
+ from typing import (
26
+ Any,
27
+ Generic,
28
+ TypeVar,
29
+ cast,
30
+ overload,
31
+ )
32
+
33
+ from ._core._eventloop import (
34
+ get_cancelled_exc_class,
35
+ threadlocals,
36
+ )
37
+ from ._core._eventloop import run as run_eventloop
38
+ from ._core._exceptions import NoEventLoopError
39
+ from ._core._synchronization import Event
40
+ from ._core._tasks import CancelScope, create_task_group
41
+ from .abc._tasks import TaskStatus
42
+ from .lowlevel import EventLoopToken, current_token
43
+
44
+ if sys.version_info >= (3, 11):
45
+ from typing import TypeVarTuple, Unpack
46
+ else:
47
+ from typing_extensions import TypeVarTuple, Unpack
48
+
49
+ T_Retval = TypeVar("T_Retval")
50
+ T_co = TypeVar("T_co", covariant=True)
51
+ PosArgsT = TypeVarTuple("PosArgsT")
52
+
53
+
54
+ def _token_or_error(token: EventLoopToken | None) -> EventLoopToken:
55
+ if token is not None:
56
+ return token
57
+
58
+ try:
59
+ return threadlocals.current_token
60
+ except AttributeError:
61
+ raise NoEventLoopError(
62
+ "Not running inside an AnyIO worker thread, and no event loop token was "
63
+ "provided"
64
+ ) from None
65
+
66
+
67
+ def run(
68
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
69
+ *args: Unpack[PosArgsT],
70
+ token: EventLoopToken | None = None,
71
+ ) -> T_Retval:
72
+ """
73
+ Call a coroutine function from a worker thread.
74
+
75
+ :param func: a coroutine function
76
+ :param args: positional arguments for the callable
77
+ :param token: an event loop token to use to get back to the event loop thread
78
+ (required if calling this function from outside an AnyIO worker thread)
79
+ :return: the return value of the coroutine function
80
+ :raises MissingTokenError: if no token was provided and called from outside an
81
+ AnyIO worker thread
82
+ :raises RunFinishedError: if the event loop tied to ``token`` is no longer running
83
+
84
+ .. versionchanged:: 4.11.0
85
+ Added the ``token`` parameter.
86
+
87
+ """
88
+ explicit_token = token is not None
89
+ token = _token_or_error(token)
90
+ return token.backend_class.run_async_from_thread(
91
+ func, args, token=token.native_token if explicit_token else None
92
+ )
93
+
94
+
95
+ def run_sync(
96
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
97
+ *args: Unpack[PosArgsT],
98
+ token: EventLoopToken | None = None,
99
+ ) -> T_Retval:
100
+ """
101
+ Call a function in the event loop thread from a worker thread.
102
+
103
+ :param func: a callable
104
+ :param args: positional arguments for the callable
105
+ :param token: an event loop token to use to get back to the event loop thread
106
+ (required if calling this function from outside an AnyIO worker thread)
107
+ :return: the return value of the callable
108
+ :raises MissingTokenError: if no token was provided and called from outside an
109
+ AnyIO worker thread
110
+ :raises RunFinishedError: if the event loop tied to ``token`` is no longer running
111
+
112
+ .. versionchanged:: 4.11.0
113
+ Added the ``token`` parameter.
114
+
115
+ """
116
+ explicit_token = token is not None
117
+ token = _token_or_error(token)
118
+ return token.backend_class.run_sync_from_thread(
119
+ func, args, token=token.native_token if explicit_token else None
120
+ )
121
+
122
+
123
+ class _BlockingAsyncContextManager(Generic[T_co], AbstractContextManager):
124
+ _enter_future: Future[T_co]
125
+ _exit_future: Future[bool | None]
126
+ _exit_event: Event
127
+ _exit_exc_info: tuple[
128
+ type[BaseException] | None, BaseException | None, TracebackType | None
129
+ ] = (None, None, None)
130
+
131
+ def __init__(
132
+ self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal
133
+ ):
134
+ self._async_cm = async_cm
135
+ self._portal = portal
136
+
137
+ async def run_async_cm(self) -> bool | None:
138
+ try:
139
+ self._exit_event = Event()
140
+ value = await self._async_cm.__aenter__()
141
+ except BaseException as exc:
142
+ self._enter_future.set_exception(exc)
143
+ raise
144
+ else:
145
+ self._enter_future.set_result(value)
146
+
147
+ try:
148
+ # Wait for the sync context manager to exit.
149
+ # This next statement can raise `get_cancelled_exc_class()` if
150
+ # something went wrong in a task group in this async context
151
+ # manager.
152
+ await self._exit_event.wait()
153
+ finally:
154
+ # In case of cancellation, it could be that we end up here before
155
+ # `_BlockingAsyncContextManager.__exit__` is called, and an
156
+ # `_exit_exc_info` has been set.
157
+ result = await self._async_cm.__aexit__(*self._exit_exc_info)
158
+
159
+ return result
160
+
161
+ def __enter__(self) -> T_co:
162
+ self._enter_future = Future()
163
+ self._exit_future = self._portal.start_task_soon(self.run_async_cm)
164
+ return self._enter_future.result()
165
+
166
+ def __exit__(
167
+ self,
168
+ __exc_type: type[BaseException] | None,
169
+ __exc_value: BaseException | None,
170
+ __traceback: TracebackType | None,
171
+ ) -> bool | None:
172
+ self._exit_exc_info = __exc_type, __exc_value, __traceback
173
+ self._portal.call(self._exit_event.set)
174
+ return self._exit_future.result()
175
+
176
+
177
+ class _BlockingPortalTaskStatus(TaskStatus):
178
+ def __init__(self, future: Future):
179
+ self._future = future
180
+
181
+ def started(self, value: object = None) -> None:
182
+ self._future.set_result(value)
183
+
184
+
185
+ class BlockingPortal:
186
+ """
187
+ An object that lets external threads run code in an asynchronous event loop.
188
+
189
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
190
+ current thread
191
+ """
192
+
193
+ def __init__(self) -> None:
194
+ self._token = current_token()
195
+ self._event_loop_thread_id: int | None = get_ident()
196
+ self._stop_event = Event()
197
+ self._task_group = create_task_group()
198
+
199
+ async def __aenter__(self) -> BlockingPortal:
200
+ await self._task_group.__aenter__()
201
+ return self
202
+
203
+ async def __aexit__(
204
+ self,
205
+ exc_type: type[BaseException] | None,
206
+ exc_val: BaseException | None,
207
+ exc_tb: TracebackType | None,
208
+ ) -> bool:
209
+ await self.stop()
210
+ return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
211
+
212
+ def _check_running(self) -> None:
213
+ if self._event_loop_thread_id is None:
214
+ raise RuntimeError("This portal is not running")
215
+ if self._event_loop_thread_id == get_ident():
216
+ raise RuntimeError(
217
+ "This method cannot be called from the event loop thread"
218
+ )
219
+
220
+ async def sleep_until_stopped(self) -> None:
221
+ """Sleep until :meth:`stop` is called."""
222
+ await self._stop_event.wait()
223
+
224
+ async def stop(self, cancel_remaining: bool = False) -> None:
225
+ """
226
+ Signal the portal to shut down.
227
+
228
+ This marks the portal as no longer accepting new calls and exits from
229
+ :meth:`sleep_until_stopped`.
230
+
231
+ :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False``
232
+ to let them finish before returning
233
+
234
+ """
235
+ self._event_loop_thread_id = None
236
+ self._stop_event.set()
237
+ if cancel_remaining:
238
+ self._task_group.cancel_scope.cancel("the blocking portal is shutting down")
239
+
240
+ async def _call_func(
241
+ self,
242
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
243
+ args: tuple[Unpack[PosArgsT]],
244
+ kwargs: dict[str, Any],
245
+ future: Future[T_Retval],
246
+ ) -> None:
247
+ def callback(f: Future[T_Retval]) -> None:
248
+ if f.cancelled():
249
+ if self._event_loop_thread_id == get_ident():
250
+ scope.cancel("the future was cancelled")
251
+ elif self._event_loop_thread_id is not None:
252
+ self.call(scope.cancel, "the future was cancelled")
253
+
254
+ try:
255
+ retval_or_awaitable = func(*args, **kwargs)
256
+ if isawaitable(retval_or_awaitable):
257
+ with CancelScope() as scope:
258
+ future.add_done_callback(callback)
259
+ retval = await retval_or_awaitable
260
+ else:
261
+ retval = retval_or_awaitable
262
+ except get_cancelled_exc_class():
263
+ future.cancel()
264
+ future.set_running_or_notify_cancel()
265
+ except BaseException as exc:
266
+ if not future.cancelled():
267
+ future.set_exception(exc)
268
+
269
+ # Let base exceptions fall through
270
+ if not isinstance(exc, Exception):
271
+ raise
272
+ else:
273
+ if not future.cancelled():
274
+ future.set_result(retval)
275
+ finally:
276
+ scope = None # type: ignore[assignment]
277
+
278
+ def _spawn_task_from_thread(
279
+ self,
280
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
281
+ args: tuple[Unpack[PosArgsT]],
282
+ kwargs: dict[str, Any],
283
+ name: object,
284
+ future: Future[T_Retval],
285
+ ) -> None:
286
+ """
287
+ Spawn a new task using the given callable.
288
+
289
+ :param func: a callable
290
+ :param args: positional arguments to be passed to the callable
291
+ :param kwargs: keyword arguments to be passed to the callable
292
+ :param name: name of the task (will be coerced to a string if not ``None``)
293
+ :param future: a future that will resolve to the return value of the callable,
294
+ or the exception raised during its execution
295
+
296
+ """
297
+ run_sync(
298
+ partial(self._task_group.start_soon, name=name),
299
+ self._call_func,
300
+ func,
301
+ args,
302
+ kwargs,
303
+ future,
304
+ token=self._token,
305
+ )
306
+
307
+ @overload
308
+ def call(
309
+ self,
310
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
311
+ *args: Unpack[PosArgsT],
312
+ ) -> T_Retval: ...
313
+
314
+ @overload
315
+ def call(
316
+ self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT]
317
+ ) -> T_Retval: ...
318
+
319
+ def call(
320
+ self,
321
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
322
+ *args: Unpack[PosArgsT],
323
+ ) -> T_Retval:
324
+ """
325
+ Call the given function in the event loop thread.
326
+
327
+ If the callable returns a coroutine object, it is awaited on.
328
+
329
+ :param func: any callable
330
+ :raises RuntimeError: if the portal is not running or if this method is called
331
+ from within the event loop thread
332
+
333
+ """
334
+ return cast(T_Retval, self.start_task_soon(func, *args).result())
335
+
336
+ @overload
337
+ def start_task_soon(
338
+ self,
339
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
340
+ *args: Unpack[PosArgsT],
341
+ name: object = None,
342
+ ) -> Future[T_Retval]: ...
343
+
344
+ @overload
345
+ def start_task_soon(
346
+ self,
347
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
348
+ *args: Unpack[PosArgsT],
349
+ name: object = None,
350
+ ) -> Future[T_Retval]: ...
351
+
352
+ def start_task_soon(
353
+ self,
354
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
355
+ *args: Unpack[PosArgsT],
356
+ name: object = None,
357
+ ) -> Future[T_Retval]:
358
+ """
359
+ Start a task in the portal's task group.
360
+
361
+ The task will be run inside a cancel scope which can be cancelled by cancelling
362
+ the returned future.
363
+
364
+ :param func: the target function
365
+ :param args: positional arguments passed to ``func``
366
+ :param name: name of the task (will be coerced to a string if not ``None``)
367
+ :return: a future that resolves with the return value of the callable if the
368
+ task completes successfully, or with the exception raised in the task
369
+ :raises RuntimeError: if the portal is not running or if this method is called
370
+ from within the event loop thread
371
+ :rtype: concurrent.futures.Future[T_Retval]
372
+
373
+ .. versionadded:: 3.0
374
+
375
+ """
376
+ self._check_running()
377
+ f: Future[T_Retval] = Future()
378
+ self._spawn_task_from_thread(func, args, {}, name, f)
379
+ return f
380
+
381
+ def start_task(
382
+ self,
383
+ func: Callable[..., Awaitable[T_Retval]],
384
+ *args: object,
385
+ name: object = None,
386
+ ) -> tuple[Future[T_Retval], Any]:
387
+ """
388
+ Start a task in the portal's task group and wait until it signals for readiness.
389
+
390
+ This method works the same way as :meth:`.abc.TaskGroup.start`.
391
+
392
+ :param func: the target function
393
+ :param args: positional arguments passed to ``func``
394
+ :param name: name of the task (will be coerced to a string if not ``None``)
395
+ :return: a tuple of (future, task_status_value) where the ``task_status_value``
396
+ is the value passed to ``task_status.started()`` from within the target
397
+ function
398
+ :rtype: tuple[concurrent.futures.Future[T_Retval], Any]
399
+
400
+ .. versionadded:: 3.0
401
+
402
+ """
403
+
404
+ def task_done(future: Future[T_Retval]) -> None:
405
+ if not task_status_future.done():
406
+ if future.cancelled():
407
+ task_status_future.cancel()
408
+ elif future.exception():
409
+ task_status_future.set_exception(future.exception())
410
+ else:
411
+ exc = RuntimeError(
412
+ "Task exited without calling task_status.started()"
413
+ )
414
+ task_status_future.set_exception(exc)
415
+
416
+ self._check_running()
417
+ task_status_future: Future = Future()
418
+ task_status = _BlockingPortalTaskStatus(task_status_future)
419
+ f: Future = Future()
420
+ f.add_done_callback(task_done)
421
+ self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f)
422
+ return f, task_status_future.result()
423
+
424
+ def wrap_async_context_manager(
425
+ self, cm: AbstractAsyncContextManager[T_co]
426
+ ) -> AbstractContextManager[T_co]:
427
+ """
428
+ Wrap an async context manager as a synchronous context manager via this portal.
429
+
430
+ Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping
431
+ in the middle until the synchronous context manager exits.
432
+
433
+ :param cm: an asynchronous context manager
434
+ :return: a synchronous context manager
435
+
436
+ .. versionadded:: 2.1
437
+
438
+ """
439
+ return _BlockingAsyncContextManager(cm, self)
440
+
441
+
442
+ @dataclass
443
+ class BlockingPortalProvider:
444
+ """
445
+ A manager for a blocking portal. Used as a context manager. The first thread to
446
+ enter this context manager causes a blocking portal to be started with the specific
447
+ parameters, and the last thread to exit causes the portal to be shut down. Thus,
448
+ there will be exactly one blocking portal running in this context as long as at
449
+ least one thread has entered this context manager.
450
+
451
+ The parameters are the same as for :func:`~anyio.run`.
452
+
453
+ :param backend: name of the backend
454
+ :param backend_options: backend options
455
+
456
+ .. versionadded:: 4.4
457
+ """
458
+
459
+ backend: str = "asyncio"
460
+ backend_options: dict[str, Any] | None = None
461
+ _lock: Lock = field(init=False, default_factory=Lock)
462
+ _leases: int = field(init=False, default=0)
463
+ _portal: BlockingPortal = field(init=False)
464
+ _portal_cm: AbstractContextManager[BlockingPortal] | None = field(
465
+ init=False, default=None
466
+ )
467
+
468
+ def __enter__(self) -> BlockingPortal:
469
+ with self._lock:
470
+ if self._portal_cm is None:
471
+ self._portal_cm = start_blocking_portal(
472
+ self.backend, self.backend_options
473
+ )
474
+ self._portal = self._portal_cm.__enter__()
475
+
476
+ self._leases += 1
477
+ return self._portal
478
+
479
+ def __exit__(
480
+ self,
481
+ exc_type: type[BaseException] | None,
482
+ exc_val: BaseException | None,
483
+ exc_tb: TracebackType | None,
484
+ ) -> None:
485
+ portal_cm: AbstractContextManager[BlockingPortal] | None = None
486
+ with self._lock:
487
+ assert self._portal_cm
488
+ assert self._leases > 0
489
+ self._leases -= 1
490
+ if not self._leases:
491
+ portal_cm = self._portal_cm
492
+ self._portal_cm = None
493
+ del self._portal
494
+
495
+ if portal_cm:
496
+ portal_cm.__exit__(None, None, None)
497
+
498
+
499
+ @contextmanager
500
+ def start_blocking_portal(
501
+ backend: str = "asyncio",
502
+ backend_options: dict[str, Any] | None = None,
503
+ *,
504
+ name: str | None = None,
505
+ ) -> Generator[BlockingPortal, Any, None]:
506
+ """
507
+ Start a new event loop in a new thread and run a blocking portal in its main task.
508
+
509
+ The parameters are the same as for :func:`~anyio.run`.
510
+
511
+ :param backend: name of the backend
512
+ :param backend_options: backend options
513
+ :param name: name of the thread
514
+ :return: a context manager that yields a blocking portal
515
+
516
+ .. versionchanged:: 3.0
517
+ Usage as a context manager is now required.
518
+
519
+ """
520
+
521
+ async def run_portal() -> None:
522
+ async with BlockingPortal() as portal_:
523
+ if name is None:
524
+ current_thread().name = f"{backend}-portal-{id(portal_):x}"
525
+
526
+ future.set_result(portal_)
527
+ await portal_.sleep_until_stopped()
528
+
529
+ def run_blocking_portal() -> None:
530
+ if future.set_running_or_notify_cancel():
531
+ try:
532
+ run_eventloop(
533
+ run_portal, backend=backend, backend_options=backend_options
534
+ )
535
+ except BaseException as exc:
536
+ if not future.done():
537
+ future.set_exception(exc)
538
+
539
+ future: Future[BlockingPortal] = Future()
540
+ thread = Thread(target=run_blocking_portal, daemon=True, name=name)
541
+ thread.start()
542
+ try:
543
+ cancel_remaining_tasks = False
544
+ portal = future.result()
545
+ try:
546
+ yield portal
547
+ except BaseException:
548
+ cancel_remaining_tasks = True
549
+ raise
550
+ finally:
551
+ try:
552
+ portal.call(portal.stop, cancel_remaining_tasks)
553
+ except RuntimeError:
554
+ pass
555
+ finally:
556
+ thread.join()
557
+
558
+
559
+ def check_cancelled() -> None:
560
+ """
561
+ Check if the cancel scope of the host task's running the current worker thread has
562
+ been cancelled.
563
+
564
+ If the host task's current cancel scope has indeed been cancelled, the
565
+ backend-specific cancellation exception will be raised.
566
+
567
+ :raises RuntimeError: if the current thread was not spawned by
568
+ :func:`.to_thread.run_sync`
569
+
570
+ """
571
+ try:
572
+ token: EventLoopToken = threadlocals.current_token
573
+ except AttributeError:
574
+ raise NoEventLoopError(
575
+ "This function can only be called inside an AnyIO worker thread"
576
+ ) from None
577
+
578
+ token.backend_class.check_cancelled()
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/anyio/py.typed ADDED
File without changes
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/__init__.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230),
2
+ # containing no networking code at all, loosely modelled on hyper-h2's generic
3
+ # implementation of HTTP/2 (and in particular the h2.connection.H2Connection
4
+ # class). There's still a bunch of subtle details you need to get right if you
5
+ # want to make this actually useful, because it doesn't implement all the
6
+ # semantics to check that what you're asking to write to the wire is sensible,
7
+ # but at least it gets you out of dealing with the wire itself.
8
+
9
+ from h11._connection import Connection, NEED_DATA, PAUSED
10
+ from h11._events import (
11
+ ConnectionClosed,
12
+ Data,
13
+ EndOfMessage,
14
+ Event,
15
+ InformationalResponse,
16
+ Request,
17
+ Response,
18
+ )
19
+ from h11._state import (
20
+ CLIENT,
21
+ CLOSED,
22
+ DONE,
23
+ ERROR,
24
+ IDLE,
25
+ MIGHT_SWITCH_PROTOCOL,
26
+ MUST_CLOSE,
27
+ SEND_BODY,
28
+ SEND_RESPONSE,
29
+ SERVER,
30
+ SWITCHED_PROTOCOL,
31
+ )
32
+ from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError
33
+ from h11._version import __version__
34
+
35
+ PRODUCT_ID = "python-h11/" + __version__
36
+
37
+
38
+ __all__ = (
39
+ "Connection",
40
+ "NEED_DATA",
41
+ "PAUSED",
42
+ "ConnectionClosed",
43
+ "Data",
44
+ "EndOfMessage",
45
+ "Event",
46
+ "InformationalResponse",
47
+ "Request",
48
+ "Response",
49
+ "CLIENT",
50
+ "CLOSED",
51
+ "DONE",
52
+ "ERROR",
53
+ "IDLE",
54
+ "MUST_CLOSE",
55
+ "SEND_BODY",
56
+ "SEND_RESPONSE",
57
+ "SERVER",
58
+ "SWITCHED_PROTOCOL",
59
+ "ProtocolError",
60
+ "LocalProtocolError",
61
+ "RemoteProtocolError",
62
+ )
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_abnf.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # We use native strings for all the re patterns, to take advantage of string
2
+ # formatting, and then convert to bytestrings when compiling the final re
3
+ # objects.
4
+
5
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#whitespace
6
+ # OWS = *( SP / HTAB )
7
+ # ; optional whitespace
8
+ OWS = r"[ \t]*"
9
+
10
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.token.separators
11
+ # token = 1*tchar
12
+ #
13
+ # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
14
+ # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
15
+ # / DIGIT / ALPHA
16
+ # ; any VCHAR, except delimiters
17
+ token = r"[-!#$%&'*+.^_`|~0-9a-zA-Z]+"
18
+
19
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#header.fields
20
+ # field-name = token
21
+ field_name = token
22
+
23
+ # The standard says:
24
+ #
25
+ # field-value = *( field-content / obs-fold )
26
+ # field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
27
+ # field-vchar = VCHAR / obs-text
28
+ # obs-fold = CRLF 1*( SP / HTAB )
29
+ # ; obsolete line folding
30
+ # ; see Section 3.2.4
31
+ #
32
+ # https://tools.ietf.org/html/rfc5234#appendix-B.1
33
+ #
34
+ # VCHAR = %x21-7E
35
+ # ; visible (printing) characters
36
+ #
37
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.quoted-string
38
+ # obs-text = %x80-FF
39
+ #
40
+ # However, the standard definition of field-content is WRONG! It disallows
41
+ # fields containing a single visible character surrounded by whitespace,
42
+ # e.g. "foo a bar".
43
+ #
44
+ # See: https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189
45
+ #
46
+ # So our definition of field_content attempts to fix it up...
47
+ #
48
+ # Also, we allow lots of control characters, because apparently people assume
49
+ # that they're legal in practice (e.g., google analytics makes cookies with
50
+ # \x01 in them!):
51
+ # https://github.com/python-hyper/h11/issues/57
52
+ # We still don't allow NUL or whitespace, because those are often treated as
53
+ # meta-characters and letting them through can lead to nasty issues like SSRF.
54
+ vchar = r"[\x21-\x7e]"
55
+ vchar_or_obs_text = r"[^\x00\s]"
56
+ field_vchar = vchar_or_obs_text
57
+ field_content = r"{field_vchar}+(?:[ \t]+{field_vchar}+)*".format(**globals())
58
+
59
+ # We handle obs-fold at a different level, and our fixed-up field_content
60
+ # already grows to swallow the whole value, so ? instead of *
61
+ field_value = r"({field_content})?".format(**globals())
62
+
63
+ # header-field = field-name ":" OWS field-value OWS
64
+ header_field = (
65
+ r"(?P<field_name>{field_name})"
66
+ r":"
67
+ r"{OWS}"
68
+ r"(?P<field_value>{field_value})"
69
+ r"{OWS}".format(**globals())
70
+ )
71
+
72
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#request.line
73
+ #
74
+ # request-line = method SP request-target SP HTTP-version CRLF
75
+ # method = token
76
+ # HTTP-version = HTTP-name "/" DIGIT "." DIGIT
77
+ # HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive
78
+ #
79
+ # request-target is complicated (see RFC 7230 sec 5.3) -- could be path, full
80
+ # URL, host+port (for connect), or even "*", but in any case we are guaranteed
81
+ # that it contists of the visible printing characters.
82
+ method = token
83
+ request_target = r"{vchar}+".format(**globals())
84
+ http_version = r"HTTP/(?P<http_version>[0-9]\.[0-9])"
85
+ request_line = (
86
+ r"(?P<method>{method})"
87
+ r" "
88
+ r"(?P<target>{request_target})"
89
+ r" "
90
+ r"{http_version}".format(**globals())
91
+ )
92
+
93
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#status.line
94
+ #
95
+ # status-line = HTTP-version SP status-code SP reason-phrase CRLF
96
+ # status-code = 3DIGIT
97
+ # reason-phrase = *( HTAB / SP / VCHAR / obs-text )
98
+ status_code = r"[0-9]{3}"
99
+ reason_phrase = r"([ \t]|{vchar_or_obs_text})*".format(**globals())
100
+ status_line = (
101
+ r"{http_version}"
102
+ r" "
103
+ r"(?P<status_code>{status_code})"
104
+ # However, there are apparently a few too many servers out there that just
105
+ # leave out the reason phrase:
106
+ # https://github.com/scrapy/scrapy/issues/345#issuecomment-281756036
107
+ # https://github.com/seanmonstar/httparse/issues/29
108
+ # so make it optional. ?: is a non-capturing group.
109
+ r"(?: (?P<reason>{reason_phrase}))?".format(**globals())
110
+ )
111
+
112
+ HEXDIG = r"[0-9A-Fa-f]"
113
+ # Actually
114
+ #
115
+ # chunk-size = 1*HEXDIG
116
+ #
117
+ # but we impose an upper-limit to avoid ridiculosity. len(str(2**64)) == 20
118
+ chunk_size = r"({HEXDIG}){{1,20}}".format(**globals())
119
+ # Actually
120
+ #
121
+ # chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
122
+ #
123
+ # but we aren't parsing the things so we don't really care.
124
+ chunk_ext = r";.*"
125
+ chunk_header = (
126
+ r"(?P<chunk_size>{chunk_size})"
127
+ r"(?P<chunk_ext>{chunk_ext})?"
128
+ r"{OWS}\r\n".format(
129
+ **globals()
130
+ ) # Even though the specification does not allow for extra whitespaces,
131
+ # we are lenient with trailing whitespaces because some servers on the wild use it.
132
+ )
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_connection.py ADDED
@@ -0,0 +1,659 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This contains the main Connection class. Everything in h11 revolves around
2
+ # this.
3
+ from typing import (
4
+ Any,
5
+ Callable,
6
+ cast,
7
+ Dict,
8
+ List,
9
+ Optional,
10
+ overload,
11
+ Tuple,
12
+ Type,
13
+ Union,
14
+ )
15
+
16
+ from ._events import (
17
+ ConnectionClosed,
18
+ Data,
19
+ EndOfMessage,
20
+ Event,
21
+ InformationalResponse,
22
+ Request,
23
+ Response,
24
+ )
25
+ from ._headers import get_comma_header, has_expect_100_continue, set_comma_header
26
+ from ._readers import READERS, ReadersType
27
+ from ._receivebuffer import ReceiveBuffer
28
+ from ._state import (
29
+ _SWITCH_CONNECT,
30
+ _SWITCH_UPGRADE,
31
+ CLIENT,
32
+ ConnectionState,
33
+ DONE,
34
+ ERROR,
35
+ MIGHT_SWITCH_PROTOCOL,
36
+ SEND_BODY,
37
+ SERVER,
38
+ SWITCHED_PROTOCOL,
39
+ )
40
+ from ._util import ( # Import the internal things we need
41
+ LocalProtocolError,
42
+ RemoteProtocolError,
43
+ Sentinel,
44
+ )
45
+ from ._writers import WRITERS, WritersType
46
+
47
+ # Everything in __all__ gets re-exported as part of the h11 public API.
48
+ __all__ = ["Connection", "NEED_DATA", "PAUSED"]
49
+
50
+
51
+ class NEED_DATA(Sentinel, metaclass=Sentinel):
52
+ pass
53
+
54
+
55
+ class PAUSED(Sentinel, metaclass=Sentinel):
56
+ pass
57
+
58
+
59
+ # If we ever have this much buffered without it making a complete parseable
60
+ # event, we error out. The only time we really buffer is when reading the
61
+ # request/response line + headers together, so this is effectively the limit on
62
+ # the size of that.
63
+ #
64
+ # Some precedents for defaults:
65
+ # - node.js: 80 * 1024
66
+ # - tomcat: 8 * 1024
67
+ # - IIS: 16 * 1024
68
+ # - Apache: <8 KiB per line>
69
+ DEFAULT_MAX_INCOMPLETE_EVENT_SIZE = 16 * 1024
70
+
71
+
72
+ # RFC 7230's rules for connection lifecycles:
73
+ # - If either side says they want to close the connection, then the connection
74
+ # must close.
75
+ # - HTTP/1.1 defaults to keep-alive unless someone says Connection: close
76
+ # - HTTP/1.0 defaults to close unless both sides say Connection: keep-alive
77
+ # (and even this is a mess -- e.g. if you're implementing a proxy then
78
+ # sending Connection: keep-alive is forbidden).
79
+ #
80
+ # We simplify life by simply not supporting keep-alive with HTTP/1.0 peers. So
81
+ # our rule is:
82
+ # - If someone says Connection: close, we will close
83
+ # - If someone uses HTTP/1.0, we will close.
84
+ def _keep_alive(event: Union[Request, Response]) -> bool:
85
+ connection = get_comma_header(event.headers, b"connection")
86
+ if b"close" in connection:
87
+ return False
88
+ if getattr(event, "http_version", b"1.1") < b"1.1":
89
+ return False
90
+ return True
91
+
92
+
93
+ def _body_framing(
94
+ request_method: bytes, event: Union[Request, Response]
95
+ ) -> Tuple[str, Union[Tuple[()], Tuple[int]]]:
96
+ # Called when we enter SEND_BODY to figure out framing information for
97
+ # this body.
98
+ #
99
+ # These are the only two events that can trigger a SEND_BODY state:
100
+ assert type(event) in (Request, Response)
101
+ # Returns one of:
102
+ #
103
+ # ("content-length", count)
104
+ # ("chunked", ())
105
+ # ("http/1.0", ())
106
+ #
107
+ # which are (lookup key, *args) for constructing body reader/writer
108
+ # objects.
109
+ #
110
+ # Reference: https://tools.ietf.org/html/rfc7230#section-3.3.3
111
+ #
112
+ # Step 1: some responses always have an empty body, regardless of what the
113
+ # headers say.
114
+ if type(event) is Response:
115
+ if (
116
+ event.status_code in (204, 304)
117
+ or request_method == b"HEAD"
118
+ or (request_method == b"CONNECT" and 200 <= event.status_code < 300)
119
+ ):
120
+ return ("content-length", (0,))
121
+ # Section 3.3.3 also lists another case -- responses with status_code
122
+ # < 200. For us these are InformationalResponses, not Responses, so
123
+ # they can't get into this function in the first place.
124
+ assert event.status_code >= 200
125
+
126
+ # Step 2: check for Transfer-Encoding (T-E beats C-L):
127
+ transfer_encodings = get_comma_header(event.headers, b"transfer-encoding")
128
+ if transfer_encodings:
129
+ assert transfer_encodings == [b"chunked"]
130
+ return ("chunked", ())
131
+
132
+ # Step 3: check for Content-Length
133
+ content_lengths = get_comma_header(event.headers, b"content-length")
134
+ if content_lengths:
135
+ return ("content-length", (int(content_lengths[0]),))
136
+
137
+ # Step 4: no applicable headers; fallback/default depends on type
138
+ if type(event) is Request:
139
+ return ("content-length", (0,))
140
+ else:
141
+ return ("http/1.0", ())
142
+
143
+
144
+ ################################################################
145
+ #
146
+ # The main Connection class
147
+ #
148
+ ################################################################
149
+
150
+
151
+ class Connection:
152
+ """An object encapsulating the state of an HTTP connection.
153
+
154
+ Args:
155
+ our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If
156
+ you're implementing a server, pass :data:`h11.SERVER`.
157
+
158
+ max_incomplete_event_size (int):
159
+ The maximum number of bytes we're willing to buffer of an
160
+ incomplete event. In practice this mostly sets a limit on the
161
+ maximum size of the request/response line + headers. If this is
162
+ exceeded, then :meth:`next_event` will raise
163
+ :exc:`RemoteProtocolError`.
164
+
165
+ """
166
+
167
+ def __init__(
168
+ self,
169
+ our_role: Type[Sentinel],
170
+ max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE,
171
+ ) -> None:
172
+ self._max_incomplete_event_size = max_incomplete_event_size
173
+ # State and role tracking
174
+ if our_role not in (CLIENT, SERVER):
175
+ raise ValueError(f"expected CLIENT or SERVER, not {our_role!r}")
176
+ self.our_role = our_role
177
+ self.their_role: Type[Sentinel]
178
+ if our_role is CLIENT:
179
+ self.their_role = SERVER
180
+ else:
181
+ self.their_role = CLIENT
182
+ self._cstate = ConnectionState()
183
+
184
+ # Callables for converting data->events or vice-versa given the
185
+ # current state
186
+ self._writer = self._get_io_object(self.our_role, None, WRITERS)
187
+ self._reader = self._get_io_object(self.their_role, None, READERS)
188
+
189
+ # Holds any unprocessed received data
190
+ self._receive_buffer = ReceiveBuffer()
191
+ # If this is true, then it indicates that the incoming connection was
192
+ # closed *after* the end of whatever's in self._receive_buffer:
193
+ self._receive_buffer_closed = False
194
+
195
+ # Extra bits of state that don't fit into the state machine.
196
+ #
197
+ # These two are only used to interpret framing headers for figuring
198
+ # out how to read/write response bodies. their_http_version is also
199
+ # made available as a convenient public API.
200
+ self.their_http_version: Optional[bytes] = None
201
+ self._request_method: Optional[bytes] = None
202
+ # This is pure flow-control and doesn't at all affect the set of legal
203
+ # transitions, so no need to bother ConnectionState with it:
204
+ self.client_is_waiting_for_100_continue = False
205
+
206
+ @property
207
+ def states(self) -> Dict[Type[Sentinel], Type[Sentinel]]:
208
+ """A dictionary like::
209
+
210
+ {CLIENT: <client state>, SERVER: <server state>}
211
+
212
+ See :ref:`state-machine` for details.
213
+
214
+ """
215
+ return dict(self._cstate.states)
216
+
217
+ @property
218
+ def our_state(self) -> Type[Sentinel]:
219
+ """The current state of whichever role we are playing. See
220
+ :ref:`state-machine` for details.
221
+ """
222
+ return self._cstate.states[self.our_role]
223
+
224
+ @property
225
+ def their_state(self) -> Type[Sentinel]:
226
+ """The current state of whichever role we are NOT playing. See
227
+ :ref:`state-machine` for details.
228
+ """
229
+ return self._cstate.states[self.their_role]
230
+
231
+ @property
232
+ def they_are_waiting_for_100_continue(self) -> bool:
233
+ return self.their_role is CLIENT and self.client_is_waiting_for_100_continue
234
+
235
+ def start_next_cycle(self) -> None:
236
+ """Attempt to reset our connection state for a new request/response
237
+ cycle.
238
+
239
+ If both client and server are in :data:`DONE` state, then resets them
240
+ both to :data:`IDLE` state in preparation for a new request/response
241
+ cycle on this same connection. Otherwise, raises a
242
+ :exc:`LocalProtocolError`.
243
+
244
+ See :ref:`keepalive-and-pipelining`.
245
+
246
+ """
247
+ old_states = dict(self._cstate.states)
248
+ self._cstate.start_next_cycle()
249
+ self._request_method = None
250
+ # self.their_http_version gets left alone, since it presumably lasts
251
+ # beyond a single request/response cycle
252
+ assert not self.client_is_waiting_for_100_continue
253
+ self._respond_to_state_changes(old_states)
254
+
255
+ def _process_error(self, role: Type[Sentinel]) -> None:
256
+ old_states = dict(self._cstate.states)
257
+ self._cstate.process_error(role)
258
+ self._respond_to_state_changes(old_states)
259
+
260
+ def _server_switch_event(self, event: Event) -> Optional[Type[Sentinel]]:
261
+ if type(event) is InformationalResponse and event.status_code == 101:
262
+ return _SWITCH_UPGRADE
263
+ if type(event) is Response:
264
+ if (
265
+ _SWITCH_CONNECT in self._cstate.pending_switch_proposals
266
+ and 200 <= event.status_code < 300
267
+ ):
268
+ return _SWITCH_CONNECT
269
+ return None
270
+
271
+ # All events go through here
272
+ def _process_event(self, role: Type[Sentinel], event: Event) -> None:
273
+ # First, pass the event through the state machine to make sure it
274
+ # succeeds.
275
+ old_states = dict(self._cstate.states)
276
+ if role is CLIENT and type(event) is Request:
277
+ if event.method == b"CONNECT":
278
+ self._cstate.process_client_switch_proposal(_SWITCH_CONNECT)
279
+ if get_comma_header(event.headers, b"upgrade"):
280
+ self._cstate.process_client_switch_proposal(_SWITCH_UPGRADE)
281
+ server_switch_event = None
282
+ if role is SERVER:
283
+ server_switch_event = self._server_switch_event(event)
284
+ self._cstate.process_event(role, type(event), server_switch_event)
285
+
286
+ # Then perform the updates triggered by it.
287
+
288
+ if type(event) is Request:
289
+ self._request_method = event.method
290
+
291
+ if role is self.their_role and type(event) in (
292
+ Request,
293
+ Response,
294
+ InformationalResponse,
295
+ ):
296
+ event = cast(Union[Request, Response, InformationalResponse], event)
297
+ self.their_http_version = event.http_version
298
+
299
+ # Keep alive handling
300
+ #
301
+ # RFC 7230 doesn't really say what one should do if Connection: close
302
+ # shows up on a 1xx InformationalResponse. I think the idea is that
303
+ # this is not supposed to happen. In any case, if it does happen, we
304
+ # ignore it.
305
+ if type(event) in (Request, Response) and not _keep_alive(
306
+ cast(Union[Request, Response], event)
307
+ ):
308
+ self._cstate.process_keep_alive_disabled()
309
+
310
+ # 100-continue
311
+ if type(event) is Request and has_expect_100_continue(event):
312
+ self.client_is_waiting_for_100_continue = True
313
+ if type(event) in (InformationalResponse, Response):
314
+ self.client_is_waiting_for_100_continue = False
315
+ if role is CLIENT and type(event) in (Data, EndOfMessage):
316
+ self.client_is_waiting_for_100_continue = False
317
+
318
+ self._respond_to_state_changes(old_states, event)
319
+
320
+ def _get_io_object(
321
+ self,
322
+ role: Type[Sentinel],
323
+ event: Optional[Event],
324
+ io_dict: Union[ReadersType, WritersType],
325
+ ) -> Optional[Callable[..., Any]]:
326
+ # event may be None; it's only used when entering SEND_BODY
327
+ state = self._cstate.states[role]
328
+ if state is SEND_BODY:
329
+ # Special case: the io_dict has a dict of reader/writer factories
330
+ # that depend on the request/response framing.
331
+ framing_type, args = _body_framing(
332
+ cast(bytes, self._request_method), cast(Union[Request, Response], event)
333
+ )
334
+ return io_dict[SEND_BODY][framing_type](*args) # type: ignore[index]
335
+ else:
336
+ # General case: the io_dict just has the appropriate reader/writer
337
+ # for this state
338
+ return io_dict.get((role, state)) # type: ignore[return-value]
339
+
340
+ # This must be called after any action that might have caused
341
+ # self._cstate.states to change.
342
+ def _respond_to_state_changes(
343
+ self,
344
+ old_states: Dict[Type[Sentinel], Type[Sentinel]],
345
+ event: Optional[Event] = None,
346
+ ) -> None:
347
+ # Update reader/writer
348
+ if self.our_state != old_states[self.our_role]:
349
+ self._writer = self._get_io_object(self.our_role, event, WRITERS)
350
+ if self.their_state != old_states[self.their_role]:
351
+ self._reader = self._get_io_object(self.their_role, event, READERS)
352
+
353
+ @property
354
+ def trailing_data(self) -> Tuple[bytes, bool]:
355
+ """Data that has been received, but not yet processed, represented as
356
+ a tuple with two elements, where the first is a byte-string containing
357
+ the unprocessed data itself, and the second is a bool that is True if
358
+ the receive connection was closed.
359
+
360
+ See :ref:`switching-protocols` for discussion of why you'd want this.
361
+ """
362
+ return (bytes(self._receive_buffer), self._receive_buffer_closed)
363
+
364
+ def receive_data(self, data: bytes) -> None:
365
+ """Add data to our internal receive buffer.
366
+
367
+ This does not actually do any processing on the data, just stores
368
+ it. To trigger processing, you have to call :meth:`next_event`.
369
+
370
+ Args:
371
+ data (:term:`bytes-like object`):
372
+ The new data that was just received.
373
+
374
+ Special case: If *data* is an empty byte-string like ``b""``,
375
+ then this indicates that the remote side has closed the
376
+ connection (end of file). Normally this is convenient, because
377
+ standard Python APIs like :meth:`file.read` or
378
+ :meth:`socket.recv` use ``b""`` to indicate end-of-file, while
379
+ other failures to read are indicated using other mechanisms
380
+ like raising :exc:`TimeoutError`. When using such an API you
381
+ can just blindly pass through whatever you get from ``read``
382
+ to :meth:`receive_data`, and everything will work.
383
+
384
+ But, if you have an API where reading an empty string is a
385
+ valid non-EOF condition, then you need to be aware of this and
386
+ make sure to check for such strings and avoid passing them to
387
+ :meth:`receive_data`.
388
+
389
+ Returns:
390
+ Nothing, but after calling this you should call :meth:`next_event`
391
+ to parse the newly received data.
392
+
393
+ Raises:
394
+ RuntimeError:
395
+ Raised if you pass an empty *data*, indicating EOF, and then
396
+ pass a non-empty *data*, indicating more data that somehow
397
+ arrived after the EOF.
398
+
399
+ (Calling ``receive_data(b"")`` multiple times is fine,
400
+ and equivalent to calling it once.)
401
+
402
+ """
403
+ if data:
404
+ if self._receive_buffer_closed:
405
+ raise RuntimeError("received close, then received more data?")
406
+ self._receive_buffer += data
407
+ else:
408
+ self._receive_buffer_closed = True
409
+
410
+ def _extract_next_receive_event(
411
+ self,
412
+ ) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]:
413
+ state = self.their_state
414
+ # We don't pause immediately when they enter DONE, because even in
415
+ # DONE state we can still process a ConnectionClosed() event. But
416
+ # if we have data in our buffer, then we definitely aren't getting
417
+ # a ConnectionClosed() immediately and we need to pause.
418
+ if state is DONE and self._receive_buffer:
419
+ return PAUSED
420
+ if state is MIGHT_SWITCH_PROTOCOL or state is SWITCHED_PROTOCOL:
421
+ return PAUSED
422
+ assert self._reader is not None
423
+ event = self._reader(self._receive_buffer)
424
+ if event is None:
425
+ if not self._receive_buffer and self._receive_buffer_closed:
426
+ # In some unusual cases (basically just HTTP/1.0 bodies), EOF
427
+ # triggers an actual protocol event; in that case, we want to
428
+ # return that event, and then the state will change and we'll
429
+ # get called again to generate the actual ConnectionClosed().
430
+ if hasattr(self._reader, "read_eof"):
431
+ event = self._reader.read_eof()
432
+ else:
433
+ event = ConnectionClosed()
434
+ if event is None:
435
+ event = NEED_DATA
436
+ return event # type: ignore[no-any-return]
437
+
438
+ def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]:
439
+ """Parse the next event out of our receive buffer, update our internal
440
+ state, and return it.
441
+
442
+ This is a mutating operation -- think of it like calling :func:`next`
443
+ on an iterator.
444
+
445
+ Returns:
446
+ : One of three things:
447
+
448
+ 1) An event object -- see :ref:`events`.
449
+
450
+ 2) The special constant :data:`NEED_DATA`, which indicates that
451
+ you need to read more data from your socket and pass it to
452
+ :meth:`receive_data` before this method will be able to return
453
+ any more events.
454
+
455
+ 3) The special constant :data:`PAUSED`, which indicates that we
456
+ are not in a state where we can process incoming data (usually
457
+ because the peer has finished their part of the current
458
+ request/response cycle, and you have not yet called
459
+ :meth:`start_next_cycle`). See :ref:`flow-control` for details.
460
+
461
+ Raises:
462
+ RemoteProtocolError:
463
+ The peer has misbehaved. You should close the connection
464
+ (possibly after sending some kind of 4xx response).
465
+
466
+ Once this method returns :class:`ConnectionClosed` once, then all
467
+ subsequent calls will also return :class:`ConnectionClosed`.
468
+
469
+ If this method raises any exception besides :exc:`RemoteProtocolError`
470
+ then that's a bug -- if it happens please file a bug report!
471
+
472
+ If this method raises any exception then it also sets
473
+ :attr:`Connection.their_state` to :data:`ERROR` -- see
474
+ :ref:`error-handling` for discussion.
475
+
476
+ """
477
+
478
+ if self.their_state is ERROR:
479
+ raise RemoteProtocolError("Can't receive data when peer state is ERROR")
480
+ try:
481
+ event = self._extract_next_receive_event()
482
+ if event not in [NEED_DATA, PAUSED]:
483
+ self._process_event(self.their_role, cast(Event, event))
484
+ if event is NEED_DATA:
485
+ if len(self._receive_buffer) > self._max_incomplete_event_size:
486
+ # 431 is "Request header fields too large" which is pretty
487
+ # much the only situation where we can get here
488
+ raise RemoteProtocolError(
489
+ "Receive buffer too long", error_status_hint=431
490
+ )
491
+ if self._receive_buffer_closed:
492
+ # We're still trying to complete some event, but that's
493
+ # never going to happen because no more data is coming
494
+ raise RemoteProtocolError("peer unexpectedly closed connection")
495
+ return event
496
+ except BaseException as exc:
497
+ self._process_error(self.their_role)
498
+ if isinstance(exc, LocalProtocolError):
499
+ exc._reraise_as_remote_protocol_error()
500
+ else:
501
+ raise
502
+
503
+ @overload
504
+ def send(self, event: ConnectionClosed) -> None:
505
+ ...
506
+
507
+ @overload
508
+ def send(
509
+ self, event: Union[Request, InformationalResponse, Response, Data, EndOfMessage]
510
+ ) -> bytes:
511
+ ...
512
+
513
+ @overload
514
+ def send(self, event: Event) -> Optional[bytes]:
515
+ ...
516
+
517
+ def send(self, event: Event) -> Optional[bytes]:
518
+ """Convert a high-level event into bytes that can be sent to the peer,
519
+ while updating our internal state machine.
520
+
521
+ Args:
522
+ event: The :ref:`event <events>` to send.
523
+
524
+ Returns:
525
+ If ``type(event) is ConnectionClosed``, then returns
526
+ ``None``. Otherwise, returns a :term:`bytes-like object`.
527
+
528
+ Raises:
529
+ LocalProtocolError:
530
+ Sending this event at this time would violate our
531
+ understanding of the HTTP/1.1 protocol.
532
+
533
+ If this method raises any exception then it also sets
534
+ :attr:`Connection.our_state` to :data:`ERROR` -- see
535
+ :ref:`error-handling` for discussion.
536
+
537
+ """
538
+ data_list = self.send_with_data_passthrough(event)
539
+ if data_list is None:
540
+ return None
541
+ else:
542
+ return b"".join(data_list)
543
+
544
+ def send_with_data_passthrough(self, event: Event) -> Optional[List[bytes]]:
545
+ """Identical to :meth:`send`, except that in situations where
546
+ :meth:`send` returns a single :term:`bytes-like object`, this instead
547
+ returns a list of them -- and when sending a :class:`Data` event, this
548
+ list is guaranteed to contain the exact object you passed in as
549
+ :attr:`Data.data`. See :ref:`sendfile` for discussion.
550
+
551
+ """
552
+ if self.our_state is ERROR:
553
+ raise LocalProtocolError("Can't send data when our state is ERROR")
554
+ try:
555
+ if type(event) is Response:
556
+ event = self._clean_up_response_headers_for_sending(event)
557
+ # We want to call _process_event before calling the writer,
558
+ # because if someone tries to do something invalid then this will
559
+ # give a sensible error message, while our writers all just assume
560
+ # they will only receive valid events. But, _process_event might
561
+ # change self._writer. So we have to do a little dance:
562
+ writer = self._writer
563
+ self._process_event(self.our_role, event)
564
+ if type(event) is ConnectionClosed:
565
+ return None
566
+ else:
567
+ # In any situation where writer is None, process_event should
568
+ # have raised ProtocolError
569
+ assert writer is not None
570
+ data_list: List[bytes] = []
571
+ writer(event, data_list.append)
572
+ return data_list
573
+ except:
574
+ self._process_error(self.our_role)
575
+ raise
576
+
577
+ def send_failed(self) -> None:
578
+ """Notify the state machine that we failed to send the data it gave
579
+ us.
580
+
581
+ This causes :attr:`Connection.our_state` to immediately become
582
+ :data:`ERROR` -- see :ref:`error-handling` for discussion.
583
+
584
+ """
585
+ self._process_error(self.our_role)
586
+
587
+ # When sending a Response, we take responsibility for a few things:
588
+ #
589
+ # - Sometimes you MUST set Connection: close. We take care of those
590
+ # times. (You can also set it yourself if you want, and if you do then
591
+ # we'll respect that and close the connection at the right time. But you
592
+ # don't have to worry about that unless you want to.)
593
+ #
594
+ # - The user has to set Content-Length if they want it. Otherwise, for
595
+ # responses that have bodies (e.g. not HEAD), then we will automatically
596
+ # select the right mechanism for streaming a body of unknown length,
597
+ # which depends on depending on the peer's HTTP version.
598
+ #
599
+ # This function's *only* responsibility is making sure headers are set up
600
+ # right -- everything downstream just looks at the headers. There are no
601
+ # side channels.
602
+ def _clean_up_response_headers_for_sending(self, response: Response) -> Response:
603
+ assert type(response) is Response
604
+
605
+ headers = response.headers
606
+ need_close = False
607
+
608
+ # HEAD requests need some special handling: they always act like they
609
+ # have Content-Length: 0, and that's how _body_framing treats
610
+ # them. But their headers are supposed to match what we would send if
611
+ # the request was a GET. (Technically there is one deviation allowed:
612
+ # we're allowed to leave out the framing headers -- see
613
+ # https://tools.ietf.org/html/rfc7231#section-4.3.2 . But it's just as
614
+ # easy to get them right.)
615
+ method_for_choosing_headers = cast(bytes, self._request_method)
616
+ if method_for_choosing_headers == b"HEAD":
617
+ method_for_choosing_headers = b"GET"
618
+ framing_type, _ = _body_framing(method_for_choosing_headers, response)
619
+ if framing_type in ("chunked", "http/1.0"):
620
+ # This response has a body of unknown length.
621
+ # If our peer is HTTP/1.1, we use Transfer-Encoding: chunked
622
+ # If our peer is HTTP/1.0, we use no framing headers, and close the
623
+ # connection afterwards.
624
+ #
625
+ # Make sure to clear Content-Length (in principle user could have
626
+ # set both and then we ignored Content-Length b/c
627
+ # Transfer-Encoding overwrote it -- this would be naughty of them,
628
+ # but the HTTP spec says that if our peer does this then we have
629
+ # to fix it instead of erroring out, so we'll accord the user the
630
+ # same respect).
631
+ headers = set_comma_header(headers, b"content-length", [])
632
+ if self.their_http_version is None or self.their_http_version < b"1.1":
633
+ # Either we never got a valid request and are sending back an
634
+ # error (their_http_version is None), so we assume the worst;
635
+ # or else we did get a valid HTTP/1.0 request, so we know that
636
+ # they don't understand chunked encoding.
637
+ headers = set_comma_header(headers, b"transfer-encoding", [])
638
+ # This is actually redundant ATM, since currently we
639
+ # unconditionally disable keep-alive when talking to HTTP/1.0
640
+ # peers. But let's be defensive just in case we add
641
+ # Connection: keep-alive support later:
642
+ if self._request_method != b"HEAD":
643
+ need_close = True
644
+ else:
645
+ headers = set_comma_header(headers, b"transfer-encoding", [b"chunked"])
646
+
647
+ if not self._cstate.keep_alive or need_close:
648
+ # Make sure Connection: close is set
649
+ connection = set(get_comma_header(headers, b"connection"))
650
+ connection.discard(b"keep-alive")
651
+ connection.add(b"close")
652
+ headers = set_comma_header(headers, b"connection", sorted(connection))
653
+
654
+ return Response(
655
+ headers=headers,
656
+ status_code=response.status_code,
657
+ http_version=response.http_version,
658
+ reason=response.reason,
659
+ )
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_events.py ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # High level events that make up HTTP/1.1 conversations. Loosely inspired by
2
+ # the corresponding events in hyper-h2:
3
+ #
4
+ # http://python-hyper.org/h2/en/stable/api.html#events
5
+ #
6
+ # Don't subclass these. Stuff will break.
7
+
8
+ import re
9
+ from abc import ABC
10
+ from dataclasses import dataclass
11
+ from typing import List, Tuple, Union
12
+
13
+ from ._abnf import method, request_target
14
+ from ._headers import Headers, normalize_and_validate
15
+ from ._util import bytesify, LocalProtocolError, validate
16
+
17
+ # Everything in __all__ gets re-exported as part of the h11 public API.
18
+ __all__ = [
19
+ "Event",
20
+ "Request",
21
+ "InformationalResponse",
22
+ "Response",
23
+ "Data",
24
+ "EndOfMessage",
25
+ "ConnectionClosed",
26
+ ]
27
+
28
+ method_re = re.compile(method.encode("ascii"))
29
+ request_target_re = re.compile(request_target.encode("ascii"))
30
+
31
+
32
+ class Event(ABC):
33
+ """
34
+ Base class for h11 events.
35
+ """
36
+
37
+ __slots__ = ()
38
+
39
+
40
+ @dataclass(init=False, frozen=True)
41
+ class Request(Event):
42
+ """The beginning of an HTTP request.
43
+
44
+ Fields:
45
+
46
+ .. attribute:: method
47
+
48
+ An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte
49
+ string. :term:`Bytes-like objects <bytes-like object>` and native
50
+ strings containing only ascii characters will be automatically
51
+ converted to byte strings.
52
+
53
+ .. attribute:: target
54
+
55
+ The target of an HTTP request, e.g. ``b"/index.html"``, or one of the
56
+ more exotic formats described in `RFC 7320, section 5.3
57
+ <https://tools.ietf.org/html/rfc7230#section-5.3>`_. Always a byte
58
+ string. :term:`Bytes-like objects <bytes-like object>` and native
59
+ strings containing only ascii characters will be automatically
60
+ converted to byte strings.
61
+
62
+ .. attribute:: headers
63
+
64
+ Request headers, represented as a list of (name, value) pairs. See
65
+ :ref:`the header normalization rules <headers-format>` for details.
66
+
67
+ .. attribute:: http_version
68
+
69
+ The HTTP protocol version, represented as a byte string like
70
+ ``b"1.1"``. See :ref:`the HTTP version normalization rules
71
+ <http_version-format>` for details.
72
+
73
+ """
74
+
75
+ __slots__ = ("method", "headers", "target", "http_version")
76
+
77
+ method: bytes
78
+ headers: Headers
79
+ target: bytes
80
+ http_version: bytes
81
+
82
+ def __init__(
83
+ self,
84
+ *,
85
+ method: Union[bytes, str],
86
+ headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]],
87
+ target: Union[bytes, str],
88
+ http_version: Union[bytes, str] = b"1.1",
89
+ _parsed: bool = False,
90
+ ) -> None:
91
+ super().__init__()
92
+ if isinstance(headers, Headers):
93
+ object.__setattr__(self, "headers", headers)
94
+ else:
95
+ object.__setattr__(
96
+ self, "headers", normalize_and_validate(headers, _parsed=_parsed)
97
+ )
98
+ if not _parsed:
99
+ object.__setattr__(self, "method", bytesify(method))
100
+ object.__setattr__(self, "target", bytesify(target))
101
+ object.__setattr__(self, "http_version", bytesify(http_version))
102
+ else:
103
+ object.__setattr__(self, "method", method)
104
+ object.__setattr__(self, "target", target)
105
+ object.__setattr__(self, "http_version", http_version)
106
+
107
+ # "A server MUST respond with a 400 (Bad Request) status code to any
108
+ # HTTP/1.1 request message that lacks a Host header field and to any
109
+ # request message that contains more than one Host header field or a
110
+ # Host header field with an invalid field-value."
111
+ # -- https://tools.ietf.org/html/rfc7230#section-5.4
112
+ host_count = 0
113
+ for name, value in self.headers:
114
+ if name == b"host":
115
+ host_count += 1
116
+ if self.http_version == b"1.1" and host_count == 0:
117
+ raise LocalProtocolError("Missing mandatory Host: header")
118
+ if host_count > 1:
119
+ raise LocalProtocolError("Found multiple Host: headers")
120
+
121
+ validate(method_re, self.method, "Illegal method characters")
122
+ validate(request_target_re, self.target, "Illegal target characters")
123
+
124
+ # This is an unhashable type.
125
+ __hash__ = None # type: ignore
126
+
127
+
128
+ @dataclass(init=False, frozen=True)
129
+ class _ResponseBase(Event):
130
+ __slots__ = ("headers", "http_version", "reason", "status_code")
131
+
132
+ headers: Headers
133
+ http_version: bytes
134
+ reason: bytes
135
+ status_code: int
136
+
137
+ def __init__(
138
+ self,
139
+ *,
140
+ headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]],
141
+ status_code: int,
142
+ http_version: Union[bytes, str] = b"1.1",
143
+ reason: Union[bytes, str] = b"",
144
+ _parsed: bool = False,
145
+ ) -> None:
146
+ super().__init__()
147
+ if isinstance(headers, Headers):
148
+ object.__setattr__(self, "headers", headers)
149
+ else:
150
+ object.__setattr__(
151
+ self, "headers", normalize_and_validate(headers, _parsed=_parsed)
152
+ )
153
+ if not _parsed:
154
+ object.__setattr__(self, "reason", bytesify(reason))
155
+ object.__setattr__(self, "http_version", bytesify(http_version))
156
+ if not isinstance(status_code, int):
157
+ raise LocalProtocolError("status code must be integer")
158
+ # Because IntEnum objects are instances of int, but aren't
159
+ # duck-compatible (sigh), see gh-72.
160
+ object.__setattr__(self, "status_code", int(status_code))
161
+ else:
162
+ object.__setattr__(self, "reason", reason)
163
+ object.__setattr__(self, "http_version", http_version)
164
+ object.__setattr__(self, "status_code", status_code)
165
+
166
+ self.__post_init__()
167
+
168
+ def __post_init__(self) -> None:
169
+ pass
170
+
171
+ # This is an unhashable type.
172
+ __hash__ = None # type: ignore
173
+
174
+
175
+ @dataclass(init=False, frozen=True)
176
+ class InformationalResponse(_ResponseBase):
177
+ """An HTTP informational response.
178
+
179
+ Fields:
180
+
181
+ .. attribute:: status_code
182
+
183
+ The status code of this response, as an integer. For an
184
+ :class:`InformationalResponse`, this is always in the range [100,
185
+ 200).
186
+
187
+ .. attribute:: headers
188
+
189
+ Request headers, represented as a list of (name, value) pairs. See
190
+ :ref:`the header normalization rules <headers-format>` for
191
+ details.
192
+
193
+ .. attribute:: http_version
194
+
195
+ The HTTP protocol version, represented as a byte string like
196
+ ``b"1.1"``. See :ref:`the HTTP version normalization rules
197
+ <http_version-format>` for details.
198
+
199
+ .. attribute:: reason
200
+
201
+ The reason phrase of this response, as a byte string. For example:
202
+ ``b"OK"``, or ``b"Not Found"``.
203
+
204
+ """
205
+
206
+ def __post_init__(self) -> None:
207
+ if not (100 <= self.status_code < 200):
208
+ raise LocalProtocolError(
209
+ "InformationalResponse status_code should be in range "
210
+ "[100, 200), not {}".format(self.status_code)
211
+ )
212
+
213
+ # This is an unhashable type.
214
+ __hash__ = None # type: ignore
215
+
216
+
217
+ @dataclass(init=False, frozen=True)
218
+ class Response(_ResponseBase):
219
+ """The beginning of an HTTP response.
220
+
221
+ Fields:
222
+
223
+ .. attribute:: status_code
224
+
225
+ The status code of this response, as an integer. For an
226
+ :class:`Response`, this is always in the range [200,
227
+ 1000).
228
+
229
+ .. attribute:: headers
230
+
231
+ Request headers, represented as a list of (name, value) pairs. See
232
+ :ref:`the header normalization rules <headers-format>` for details.
233
+
234
+ .. attribute:: http_version
235
+
236
+ The HTTP protocol version, represented as a byte string like
237
+ ``b"1.1"``. See :ref:`the HTTP version normalization rules
238
+ <http_version-format>` for details.
239
+
240
+ .. attribute:: reason
241
+
242
+ The reason phrase of this response, as a byte string. For example:
243
+ ``b"OK"``, or ``b"Not Found"``.
244
+
245
+ """
246
+
247
+ def __post_init__(self) -> None:
248
+ if not (200 <= self.status_code < 1000):
249
+ raise LocalProtocolError(
250
+ "Response status_code should be in range [200, 1000), not {}".format(
251
+ self.status_code
252
+ )
253
+ )
254
+
255
+ # This is an unhashable type.
256
+ __hash__ = None # type: ignore
257
+
258
+
259
+ @dataclass(init=False, frozen=True)
260
+ class Data(Event):
261
+ """Part of an HTTP message body.
262
+
263
+ Fields:
264
+
265
+ .. attribute:: data
266
+
267
+ A :term:`bytes-like object` containing part of a message body. Or, if
268
+ using the ``combine=False`` argument to :meth:`Connection.send`, then
269
+ any object that your socket writing code knows what to do with, and for
270
+ which calling :func:`len` returns the number of bytes that will be
271
+ written -- see :ref:`sendfile` for details.
272
+
273
+ .. attribute:: chunk_start
274
+
275
+ A marker that indicates whether this data object is from the start of a
276
+ chunked transfer encoding chunk. This field is ignored when when a Data
277
+ event is provided to :meth:`Connection.send`: it is only valid on
278
+ events emitted from :meth:`Connection.next_event`. You probably
279
+ shouldn't use this attribute at all; see
280
+ :ref:`chunk-delimiters-are-bad` for details.
281
+
282
+ .. attribute:: chunk_end
283
+
284
+ A marker that indicates whether this data object is the last for a
285
+ given chunked transfer encoding chunk. This field is ignored when when
286
+ a Data event is provided to :meth:`Connection.send`: it is only valid
287
+ on events emitted from :meth:`Connection.next_event`. You probably
288
+ shouldn't use this attribute at all; see
289
+ :ref:`chunk-delimiters-are-bad` for details.
290
+
291
+ """
292
+
293
+ __slots__ = ("data", "chunk_start", "chunk_end")
294
+
295
+ data: bytes
296
+ chunk_start: bool
297
+ chunk_end: bool
298
+
299
+ def __init__(
300
+ self, data: bytes, chunk_start: bool = False, chunk_end: bool = False
301
+ ) -> None:
302
+ object.__setattr__(self, "data", data)
303
+ object.__setattr__(self, "chunk_start", chunk_start)
304
+ object.__setattr__(self, "chunk_end", chunk_end)
305
+
306
+ # This is an unhashable type.
307
+ __hash__ = None # type: ignore
308
+
309
+
310
+ # XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that
311
+ # are forbidden to be sent in a trailer, since processing them as if they were
312
+ # present in the header section might bypass external security filters."
313
+ # https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part
314
+ # Unfortunately, the list of forbidden fields is long and vague :-/
315
+ @dataclass(init=False, frozen=True)
316
+ class EndOfMessage(Event):
317
+ """The end of an HTTP message.
318
+
319
+ Fields:
320
+
321
+ .. attribute:: headers
322
+
323
+ Default value: ``[]``
324
+
325
+ Any trailing headers attached to this message, represented as a list of
326
+ (name, value) pairs. See :ref:`the header normalization rules
327
+ <headers-format>` for details.
328
+
329
+ Must be empty unless ``Transfer-Encoding: chunked`` is in use.
330
+
331
+ """
332
+
333
+ __slots__ = ("headers",)
334
+
335
+ headers: Headers
336
+
337
+ def __init__(
338
+ self,
339
+ *,
340
+ headers: Union[
341
+ Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]], None
342
+ ] = None,
343
+ _parsed: bool = False,
344
+ ) -> None:
345
+ super().__init__()
346
+ if headers is None:
347
+ headers = Headers([])
348
+ elif not isinstance(headers, Headers):
349
+ headers = normalize_and_validate(headers, _parsed=_parsed)
350
+
351
+ object.__setattr__(self, "headers", headers)
352
+
353
+ # This is an unhashable type.
354
+ __hash__ = None # type: ignore
355
+
356
+
357
+ @dataclass(frozen=True)
358
+ class ConnectionClosed(Event):
359
+ """This event indicates that the sender has closed their outgoing
360
+ connection.
361
+
362
+ Note that this does not necessarily mean that they can't *receive* further
363
+ data, because TCP connections are composed to two one-way channels which
364
+ can be closed independently. See :ref:`closing` for details.
365
+
366
+ No fields.
367
+ """
368
+
369
+ pass
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_headers.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union
3
+
4
+ from ._abnf import field_name, field_value
5
+ from ._util import bytesify, LocalProtocolError, validate
6
+
7
+ if TYPE_CHECKING:
8
+ from ._events import Request
9
+
10
+ try:
11
+ from typing import Literal
12
+ except ImportError:
13
+ from typing_extensions import Literal # type: ignore
14
+
15
+ CONTENT_LENGTH_MAX_DIGITS = 20 # allow up to 1 billion TB - 1
16
+
17
+
18
+ # Facts
19
+ # -----
20
+ #
21
+ # Headers are:
22
+ # keys: case-insensitive ascii
23
+ # values: mixture of ascii and raw bytes
24
+ #
25
+ # "Historically, HTTP has allowed field content with text in the ISO-8859-1
26
+ # charset [ISO-8859-1], supporting other charsets only through use of
27
+ # [RFC2047] encoding. In practice, most HTTP header field values use only a
28
+ # subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD
29
+ # limit their field values to US-ASCII octets. A recipient SHOULD treat other
30
+ # octets in field content (obs-text) as opaque data."
31
+ # And it deprecates all non-ascii values
32
+ #
33
+ # Leading/trailing whitespace in header names is forbidden
34
+ #
35
+ # Values get leading/trailing whitespace stripped
36
+ #
37
+ # Content-Disposition actually needs to contain unicode semantically; to
38
+ # accomplish this it has a terrifically weird way of encoding the filename
39
+ # itself as ascii (and even this still has lots of cross-browser
40
+ # incompatibilities)
41
+ #
42
+ # Order is important:
43
+ # "a proxy MUST NOT change the order of these field values when forwarding a
44
+ # message"
45
+ # (and there are several headers where the order indicates a preference)
46
+ #
47
+ # Multiple occurences of the same header:
48
+ # "A sender MUST NOT generate multiple header fields with the same field name
49
+ # in a message unless either the entire field value for that header field is
50
+ # defined as a comma-separated list [or the header is Set-Cookie which gets a
51
+ # special exception]" - RFC 7230. (cookies are in RFC 6265)
52
+ #
53
+ # So every header aside from Set-Cookie can be merged by b", ".join if it
54
+ # occurs repeatedly. But, of course, they can't necessarily be split by
55
+ # .split(b","), because quoting.
56
+ #
57
+ # Given all this mess (case insensitive, duplicates allowed, order is
58
+ # important, ...), there doesn't appear to be any standard way to handle
59
+ # headers in Python -- they're almost like dicts, but... actually just
60
+ # aren't. For now we punt and just use a super simple representation: headers
61
+ # are a list of pairs
62
+ #
63
+ # [(name1, value1), (name2, value2), ...]
64
+ #
65
+ # where all entries are bytestrings, names are lowercase and have no
66
+ # leading/trailing whitespace, and values are bytestrings with no
67
+ # leading/trailing whitespace. Searching and updating are done via naive O(n)
68
+ # methods.
69
+ #
70
+ # Maybe a dict-of-lists would be better?
71
+
72
+ _content_length_re = re.compile(rb"[0-9]+")
73
+ _field_name_re = re.compile(field_name.encode("ascii"))
74
+ _field_value_re = re.compile(field_value.encode("ascii"))
75
+
76
+
77
+ class Headers(Sequence[Tuple[bytes, bytes]]):
78
+ """
79
+ A list-like interface that allows iterating over headers as byte-pairs
80
+ of (lowercased-name, value).
81
+
82
+ Internally we actually store the representation as three-tuples,
83
+ including both the raw original casing, in order to preserve casing
84
+ over-the-wire, and the lowercased name, for case-insensitive comparisions.
85
+
86
+ r = Request(
87
+ method="GET",
88
+ target="/",
89
+ headers=[("Host", "example.org"), ("Connection", "keep-alive")],
90
+ http_version="1.1",
91
+ )
92
+ assert r.headers == [
93
+ (b"host", b"example.org"),
94
+ (b"connection", b"keep-alive")
95
+ ]
96
+ assert r.headers.raw_items() == [
97
+ (b"Host", b"example.org"),
98
+ (b"Connection", b"keep-alive")
99
+ ]
100
+ """
101
+
102
+ __slots__ = "_full_items"
103
+
104
+ def __init__(self, full_items: List[Tuple[bytes, bytes, bytes]]) -> None:
105
+ self._full_items = full_items
106
+
107
+ def __bool__(self) -> bool:
108
+ return bool(self._full_items)
109
+
110
+ def __eq__(self, other: object) -> bool:
111
+ return list(self) == list(other) # type: ignore
112
+
113
+ def __len__(self) -> int:
114
+ return len(self._full_items)
115
+
116
+ def __repr__(self) -> str:
117
+ return "<Headers(%s)>" % repr(list(self))
118
+
119
+ def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: # type: ignore[override]
120
+ _, name, value = self._full_items[idx]
121
+ return (name, value)
122
+
123
+ def raw_items(self) -> List[Tuple[bytes, bytes]]:
124
+ return [(raw_name, value) for raw_name, _, value in self._full_items]
125
+
126
+
127
+ HeaderTypes = Union[
128
+ List[Tuple[bytes, bytes]],
129
+ List[Tuple[bytes, str]],
130
+ List[Tuple[str, bytes]],
131
+ List[Tuple[str, str]],
132
+ ]
133
+
134
+
135
+ @overload
136
+ def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers:
137
+ ...
138
+
139
+
140
+ @overload
141
+ def normalize_and_validate(headers: HeaderTypes, _parsed: Literal[False]) -> Headers:
142
+ ...
143
+
144
+
145
+ @overload
146
+ def normalize_and_validate(
147
+ headers: Union[Headers, HeaderTypes], _parsed: bool = False
148
+ ) -> Headers:
149
+ ...
150
+
151
+
152
+ def normalize_and_validate(
153
+ headers: Union[Headers, HeaderTypes], _parsed: bool = False
154
+ ) -> Headers:
155
+ new_headers = []
156
+ seen_content_length = None
157
+ saw_transfer_encoding = False
158
+ for name, value in headers:
159
+ # For headers coming out of the parser, we can safely skip some steps,
160
+ # because it always returns bytes and has already run these regexes
161
+ # over the data:
162
+ if not _parsed:
163
+ name = bytesify(name)
164
+ value = bytesify(value)
165
+ validate(_field_name_re, name, "Illegal header name {!r}", name)
166
+ validate(_field_value_re, value, "Illegal header value {!r}", value)
167
+ assert isinstance(name, bytes)
168
+ assert isinstance(value, bytes)
169
+
170
+ raw_name = name
171
+ name = name.lower()
172
+ if name == b"content-length":
173
+ lengths = {length.strip() for length in value.split(b",")}
174
+ if len(lengths) != 1:
175
+ raise LocalProtocolError("conflicting Content-Length headers")
176
+ value = lengths.pop()
177
+ validate(_content_length_re, value, "bad Content-Length")
178
+ if len(value) > CONTENT_LENGTH_MAX_DIGITS:
179
+ raise LocalProtocolError("bad Content-Length")
180
+ if seen_content_length is None:
181
+ seen_content_length = value
182
+ new_headers.append((raw_name, name, value))
183
+ elif seen_content_length != value:
184
+ raise LocalProtocolError("conflicting Content-Length headers")
185
+ elif name == b"transfer-encoding":
186
+ # "A server that receives a request message with a transfer coding
187
+ # it does not understand SHOULD respond with 501 (Not
188
+ # Implemented)."
189
+ # https://tools.ietf.org/html/rfc7230#section-3.3.1
190
+ if saw_transfer_encoding:
191
+ raise LocalProtocolError(
192
+ "multiple Transfer-Encoding headers", error_status_hint=501
193
+ )
194
+ # "All transfer-coding names are case-insensitive"
195
+ # -- https://tools.ietf.org/html/rfc7230#section-4
196
+ value = value.lower()
197
+ if value != b"chunked":
198
+ raise LocalProtocolError(
199
+ "Only Transfer-Encoding: chunked is supported",
200
+ error_status_hint=501,
201
+ )
202
+ saw_transfer_encoding = True
203
+ new_headers.append((raw_name, name, value))
204
+ else:
205
+ new_headers.append((raw_name, name, value))
206
+ return Headers(new_headers)
207
+
208
+
209
+ def get_comma_header(headers: Headers, name: bytes) -> List[bytes]:
210
+ # Should only be used for headers whose value is a list of
211
+ # comma-separated, case-insensitive values.
212
+ #
213
+ # The header name `name` is expected to be lower-case bytes.
214
+ #
215
+ # Connection: meets these criteria (including cast insensitivity).
216
+ #
217
+ # Content-Length: technically is just a single value (1*DIGIT), but the
218
+ # standard makes reference to implementations that do multiple values, and
219
+ # using this doesn't hurt. Ditto, case insensitivity doesn't things either
220
+ # way.
221
+ #
222
+ # Transfer-Encoding: is more complex (allows for quoted strings), so
223
+ # splitting on , is actually wrong. For example, this is legal:
224
+ #
225
+ # Transfer-Encoding: foo; options="1,2", chunked
226
+ #
227
+ # and should be parsed as
228
+ #
229
+ # foo; options="1,2"
230
+ # chunked
231
+ #
232
+ # but this naive function will parse it as
233
+ #
234
+ # foo; options="1
235
+ # 2"
236
+ # chunked
237
+ #
238
+ # However, this is okay because the only thing we are going to do with
239
+ # any Transfer-Encoding is reject ones that aren't just "chunked", so
240
+ # both of these will be treated the same anyway.
241
+ #
242
+ # Expect: the only legal value is the literal string
243
+ # "100-continue". Splitting on commas is harmless. Case insensitive.
244
+ #
245
+ out: List[bytes] = []
246
+ for _, found_name, found_raw_value in headers._full_items:
247
+ if found_name == name:
248
+ found_raw_value = found_raw_value.lower()
249
+ for found_split_value in found_raw_value.split(b","):
250
+ found_split_value = found_split_value.strip()
251
+ if found_split_value:
252
+ out.append(found_split_value)
253
+ return out
254
+
255
+
256
+ def set_comma_header(headers: Headers, name: bytes, new_values: List[bytes]) -> Headers:
257
+ # The header name `name` is expected to be lower-case bytes.
258
+ #
259
+ # Note that when we store the header we use title casing for the header
260
+ # names, in order to match the conventional HTTP header style.
261
+ #
262
+ # Simply calling `.title()` is a blunt approach, but it's correct
263
+ # here given the cases where we're using `set_comma_header`...
264
+ #
265
+ # Connection, Content-Length, Transfer-Encoding.
266
+ new_headers: List[Tuple[bytes, bytes]] = []
267
+ for found_raw_name, found_name, found_raw_value in headers._full_items:
268
+ if found_name != name:
269
+ new_headers.append((found_raw_name, found_raw_value))
270
+ for new_value in new_values:
271
+ new_headers.append((name.title(), new_value))
272
+ return normalize_and_validate(new_headers)
273
+
274
+
275
+ def has_expect_100_continue(request: "Request") -> bool:
276
+ # https://tools.ietf.org/html/rfc7231#section-5.1.1
277
+ # "A server that receives a 100-continue expectation in an HTTP/1.0 request
278
+ # MUST ignore that expectation."
279
+ if request.http_version < b"1.1":
280
+ return False
281
+ expect = get_comma_header(request.headers, b"expect")
282
+ return b"100-continue" in expect
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_readers.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code to read HTTP data
2
+ #
3
+ # Strategy: each reader is a callable which takes a ReceiveBuffer object, and
4
+ # either:
5
+ # 1) consumes some of it and returns an Event
6
+ # 2) raises a LocalProtocolError (for consistency -- e.g. we call validate()
7
+ # and it might raise a LocalProtocolError, so simpler just to always use
8
+ # this)
9
+ # 3) returns None, meaning "I need more data"
10
+ #
11
+ # If they have a .read_eof attribute, then this will be called if an EOF is
12
+ # received -- but this is optional. Either way, the actual ConnectionClosed
13
+ # event will be generated afterwards.
14
+ #
15
+ # READERS is a dict describing how to pick a reader. It maps states to either:
16
+ # - a reader
17
+ # - or, for body readers, a dict of per-framing reader factories
18
+
19
+ import re
20
+ from typing import Any, Callable, Dict, Iterable, NoReturn, Optional, Tuple, Type, Union
21
+
22
+ from ._abnf import chunk_header, header_field, request_line, status_line
23
+ from ._events import Data, EndOfMessage, InformationalResponse, Request, Response
24
+ from ._receivebuffer import ReceiveBuffer
25
+ from ._state import (
26
+ CLIENT,
27
+ CLOSED,
28
+ DONE,
29
+ IDLE,
30
+ MUST_CLOSE,
31
+ SEND_BODY,
32
+ SEND_RESPONSE,
33
+ SERVER,
34
+ )
35
+ from ._util import LocalProtocolError, RemoteProtocolError, Sentinel, validate
36
+
37
+ __all__ = ["READERS"]
38
+
39
+ header_field_re = re.compile(header_field.encode("ascii"))
40
+ obs_fold_re = re.compile(rb"[ \t]+")
41
+
42
+
43
+ def _obsolete_line_fold(lines: Iterable[bytes]) -> Iterable[bytes]:
44
+ it = iter(lines)
45
+ last: Optional[bytes] = None
46
+ for line in it:
47
+ match = obs_fold_re.match(line)
48
+ if match:
49
+ if last is None:
50
+ raise LocalProtocolError("continuation line at start of headers")
51
+ if not isinstance(last, bytearray):
52
+ # Cast to a mutable type, avoiding copy on append to ensure O(n) time
53
+ last = bytearray(last)
54
+ last += b" "
55
+ last += line[match.end() :]
56
+ else:
57
+ if last is not None:
58
+ yield last
59
+ last = line
60
+ if last is not None:
61
+ yield last
62
+
63
+
64
+ def _decode_header_lines(
65
+ lines: Iterable[bytes],
66
+ ) -> Iterable[Tuple[bytes, bytes]]:
67
+ for line in _obsolete_line_fold(lines):
68
+ matches = validate(header_field_re, line, "illegal header line: {!r}", line)
69
+ yield (matches["field_name"], matches["field_value"])
70
+
71
+
72
+ request_line_re = re.compile(request_line.encode("ascii"))
73
+
74
+
75
+ def maybe_read_from_IDLE_client(buf: ReceiveBuffer) -> Optional[Request]:
76
+ lines = buf.maybe_extract_lines()
77
+ if lines is None:
78
+ if buf.is_next_line_obviously_invalid_request_line():
79
+ raise LocalProtocolError("illegal request line")
80
+ return None
81
+ if not lines:
82
+ raise LocalProtocolError("no request line received")
83
+ matches = validate(
84
+ request_line_re, lines[0], "illegal request line: {!r}", lines[0]
85
+ )
86
+ return Request(
87
+ headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches
88
+ )
89
+
90
+
91
+ status_line_re = re.compile(status_line.encode("ascii"))
92
+
93
+
94
+ def maybe_read_from_SEND_RESPONSE_server(
95
+ buf: ReceiveBuffer,
96
+ ) -> Union[InformationalResponse, Response, None]:
97
+ lines = buf.maybe_extract_lines()
98
+ if lines is None:
99
+ if buf.is_next_line_obviously_invalid_request_line():
100
+ raise LocalProtocolError("illegal request line")
101
+ return None
102
+ if not lines:
103
+ raise LocalProtocolError("no response line received")
104
+ matches = validate(status_line_re, lines[0], "illegal status line: {!r}", lines[0])
105
+ http_version = (
106
+ b"1.1" if matches["http_version"] is None else matches["http_version"]
107
+ )
108
+ reason = b"" if matches["reason"] is None else matches["reason"]
109
+ status_code = int(matches["status_code"])
110
+ class_: Union[Type[InformationalResponse], Type[Response]] = (
111
+ InformationalResponse if status_code < 200 else Response
112
+ )
113
+ return class_(
114
+ headers=list(_decode_header_lines(lines[1:])),
115
+ _parsed=True,
116
+ status_code=status_code,
117
+ reason=reason,
118
+ http_version=http_version,
119
+ )
120
+
121
+
122
+ class ContentLengthReader:
123
+ def __init__(self, length: int) -> None:
124
+ self._length = length
125
+ self._remaining = length
126
+
127
+ def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]:
128
+ if self._remaining == 0:
129
+ return EndOfMessage()
130
+ data = buf.maybe_extract_at_most(self._remaining)
131
+ if data is None:
132
+ return None
133
+ self._remaining -= len(data)
134
+ return Data(data=data)
135
+
136
+ def read_eof(self) -> NoReturn:
137
+ raise RemoteProtocolError(
138
+ "peer closed connection without sending complete message body "
139
+ "(received {} bytes, expected {})".format(
140
+ self._length - self._remaining, self._length
141
+ )
142
+ )
143
+
144
+
145
+ chunk_header_re = re.compile(chunk_header.encode("ascii"))
146
+
147
+
148
+ class ChunkedReader:
149
+ def __init__(self) -> None:
150
+ self._bytes_in_chunk = 0
151
+ # After reading a chunk, we have to throw away the trailing \r\n.
152
+ # This tracks the bytes that we need to match and throw away.
153
+ self._bytes_to_discard = b""
154
+ self._reading_trailer = False
155
+
156
+ def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]:
157
+ if self._reading_trailer:
158
+ lines = buf.maybe_extract_lines()
159
+ if lines is None:
160
+ return None
161
+ return EndOfMessage(headers=list(_decode_header_lines(lines)))
162
+ if self._bytes_to_discard:
163
+ data = buf.maybe_extract_at_most(len(self._bytes_to_discard))
164
+ if data is None:
165
+ return None
166
+ if data != self._bytes_to_discard[: len(data)]:
167
+ raise LocalProtocolError(
168
+ f"malformed chunk footer: {data!r} (expected {self._bytes_to_discard!r})"
169
+ )
170
+ self._bytes_to_discard = self._bytes_to_discard[len(data) :]
171
+ if self._bytes_to_discard:
172
+ return None
173
+ # else, fall through and read some more
174
+ assert self._bytes_to_discard == b""
175
+ if self._bytes_in_chunk == 0:
176
+ # We need to refill our chunk count
177
+ chunk_header = buf.maybe_extract_next_line()
178
+ if chunk_header is None:
179
+ return None
180
+ matches = validate(
181
+ chunk_header_re,
182
+ chunk_header,
183
+ "illegal chunk header: {!r}",
184
+ chunk_header,
185
+ )
186
+ # XX FIXME: we discard chunk extensions. Does anyone care?
187
+ self._bytes_in_chunk = int(matches["chunk_size"], base=16)
188
+ if self._bytes_in_chunk == 0:
189
+ self._reading_trailer = True
190
+ return self(buf)
191
+ chunk_start = True
192
+ else:
193
+ chunk_start = False
194
+ assert self._bytes_in_chunk > 0
195
+ data = buf.maybe_extract_at_most(self._bytes_in_chunk)
196
+ if data is None:
197
+ return None
198
+ self._bytes_in_chunk -= len(data)
199
+ if self._bytes_in_chunk == 0:
200
+ self._bytes_to_discard = b"\r\n"
201
+ chunk_end = True
202
+ else:
203
+ chunk_end = False
204
+ return Data(data=data, chunk_start=chunk_start, chunk_end=chunk_end)
205
+
206
+ def read_eof(self) -> NoReturn:
207
+ raise RemoteProtocolError(
208
+ "peer closed connection without sending complete message body "
209
+ "(incomplete chunked read)"
210
+ )
211
+
212
+
213
+ class Http10Reader:
214
+ def __call__(self, buf: ReceiveBuffer) -> Optional[Data]:
215
+ data = buf.maybe_extract_at_most(999999999)
216
+ if data is None:
217
+ return None
218
+ return Data(data=data)
219
+
220
+ def read_eof(self) -> EndOfMessage:
221
+ return EndOfMessage()
222
+
223
+
224
+ def expect_nothing(buf: ReceiveBuffer) -> None:
225
+ if buf:
226
+ raise LocalProtocolError("Got data when expecting EOF")
227
+ return None
228
+
229
+
230
+ ReadersType = Dict[
231
+ Union[Type[Sentinel], Tuple[Type[Sentinel], Type[Sentinel]]],
232
+ Union[Callable[..., Any], Dict[str, Callable[..., Any]]],
233
+ ]
234
+
235
+ READERS: ReadersType = {
236
+ (CLIENT, IDLE): maybe_read_from_IDLE_client,
237
+ (SERVER, IDLE): maybe_read_from_SEND_RESPONSE_server,
238
+ (SERVER, SEND_RESPONSE): maybe_read_from_SEND_RESPONSE_server,
239
+ (CLIENT, DONE): expect_nothing,
240
+ (CLIENT, MUST_CLOSE): expect_nothing,
241
+ (CLIENT, CLOSED): expect_nothing,
242
+ (SERVER, DONE): expect_nothing,
243
+ (SERVER, MUST_CLOSE): expect_nothing,
244
+ (SERVER, CLOSED): expect_nothing,
245
+ SEND_BODY: {
246
+ "chunked": ChunkedReader,
247
+ "content-length": ContentLengthReader,
248
+ "http/1.0": Http10Reader,
249
+ },
250
+ }
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_receivebuffer.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import sys
3
+ from typing import List, Optional, Union
4
+
5
+ __all__ = ["ReceiveBuffer"]
6
+
7
+
8
+ # Operations we want to support:
9
+ # - find next \r\n or \r\n\r\n (\n or \n\n are also acceptable),
10
+ # or wait until there is one
11
+ # - read at-most-N bytes
12
+ # Goals:
13
+ # - on average, do this fast
14
+ # - worst case, do this in O(n) where n is the number of bytes processed
15
+ # Plan:
16
+ # - store bytearray, offset, how far we've searched for a separator token
17
+ # - use the how-far-we've-searched data to avoid rescanning
18
+ # - while doing a stream of uninterrupted processing, advance offset instead
19
+ # of constantly copying
20
+ # WARNING:
21
+ # - I haven't benchmarked or profiled any of this yet.
22
+ #
23
+ # Note that starting in Python 3.4, deleting the initial n bytes from a
24
+ # bytearray is amortized O(n), thanks to some excellent work by Antoine
25
+ # Martin:
26
+ #
27
+ # https://bugs.python.org/issue19087
28
+ #
29
+ # This means that if we only supported 3.4+, we could get rid of the code here
30
+ # involving self._start and self.compress, because it's doing exactly the same
31
+ # thing that bytearray now does internally.
32
+ #
33
+ # BUT unfortunately, we still support 2.7, and reading short segments out of a
34
+ # long buffer MUST be O(bytes read) to avoid DoS issues, so we can't actually
35
+ # delete this code. Yet:
36
+ #
37
+ # https://pythonclock.org/
38
+ #
39
+ # (Two things to double-check first though: make sure PyPy also has the
40
+ # optimization, and benchmark to make sure it's a win, since we do have a
41
+ # slightly clever thing where we delay calling compress() until we've
42
+ # processed a whole event, which could in theory be slightly more efficient
43
+ # than the internal bytearray support.)
44
+ blank_line_regex = re.compile(b"\n\r?\n", re.MULTILINE)
45
+
46
+
47
+ class ReceiveBuffer:
48
+ def __init__(self) -> None:
49
+ self._data = bytearray()
50
+ self._next_line_search = 0
51
+ self._multiple_lines_search = 0
52
+
53
+ def __iadd__(self, byteslike: Union[bytes, bytearray]) -> "ReceiveBuffer":
54
+ self._data += byteslike
55
+ return self
56
+
57
+ def __bool__(self) -> bool:
58
+ return bool(len(self))
59
+
60
+ def __len__(self) -> int:
61
+ return len(self._data)
62
+
63
+ # for @property unprocessed_data
64
+ def __bytes__(self) -> bytes:
65
+ return bytes(self._data)
66
+
67
+ def _extract(self, count: int) -> bytearray:
68
+ # extracting an initial slice of the data buffer and return it
69
+ out = self._data[:count]
70
+ del self._data[:count]
71
+
72
+ self._next_line_search = 0
73
+ self._multiple_lines_search = 0
74
+
75
+ return out
76
+
77
+ def maybe_extract_at_most(self, count: int) -> Optional[bytearray]:
78
+ """
79
+ Extract a fixed number of bytes from the buffer.
80
+ """
81
+ out = self._data[:count]
82
+ if not out:
83
+ return None
84
+
85
+ return self._extract(count)
86
+
87
+ def maybe_extract_next_line(self) -> Optional[bytearray]:
88
+ """
89
+ Extract the first line, if it is completed in the buffer.
90
+ """
91
+ # Only search in buffer space that we've not already looked at.
92
+ search_start_index = max(0, self._next_line_search - 1)
93
+ partial_idx = self._data.find(b"\r\n", search_start_index)
94
+
95
+ if partial_idx == -1:
96
+ self._next_line_search = len(self._data)
97
+ return None
98
+
99
+ # + 2 is to compensate len(b"\r\n")
100
+ idx = partial_idx + 2
101
+
102
+ return self._extract(idx)
103
+
104
+ def maybe_extract_lines(self) -> Optional[List[bytearray]]:
105
+ """
106
+ Extract everything up to the first blank line, and return a list of lines.
107
+ """
108
+ # Handle the case where we have an immediate empty line.
109
+ if self._data[:1] == b"\n":
110
+ self._extract(1)
111
+ return []
112
+
113
+ if self._data[:2] == b"\r\n":
114
+ self._extract(2)
115
+ return []
116
+
117
+ # Only search in buffer space that we've not already looked at.
118
+ match = blank_line_regex.search(self._data, self._multiple_lines_search)
119
+ if match is None:
120
+ self._multiple_lines_search = max(0, len(self._data) - 2)
121
+ return None
122
+
123
+ # Truncate the buffer and return it.
124
+ idx = match.span(0)[-1]
125
+ out = self._extract(idx)
126
+ lines = out.split(b"\n")
127
+
128
+ for line in lines:
129
+ if line.endswith(b"\r"):
130
+ del line[-1]
131
+
132
+ assert lines[-2] == lines[-1] == b""
133
+
134
+ del lines[-2:]
135
+
136
+ return lines
137
+
138
+ # In theory we should wait until `\r\n` before starting to validate
139
+ # incoming data. However it's interesting to detect (very) invalid data
140
+ # early given they might not even contain `\r\n` at all (hence only
141
+ # timeout will get rid of them).
142
+ # This is not a 100% effective detection but more of a cheap sanity check
143
+ # allowing for early abort in some useful cases.
144
+ # This is especially interesting when peer is messing up with HTTPS and
145
+ # sent us a TLS stream where we were expecting plain HTTP given all
146
+ # versions of TLS so far start handshake with a 0x16 message type code.
147
+ def is_next_line_obviously_invalid_request_line(self) -> bool:
148
+ try:
149
+ # HTTP header line must not contain non-printable characters
150
+ # and should not start with a space
151
+ return self._data[0] < 0x21
152
+ except IndexError:
153
+ return False
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_state.py ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ################################################################
2
+ # The core state machine
3
+ ################################################################
4
+ #
5
+ # Rule 1: everything that affects the state machine and state transitions must
6
+ # live here in this file. As much as possible goes into the table-based
7
+ # representation, but for the bits that don't quite fit, the actual code and
8
+ # state must nonetheless live here.
9
+ #
10
+ # Rule 2: this file does not know about what role we're playing; it only knows
11
+ # about HTTP request/response cycles in the abstract. This ensures that we
12
+ # don't cheat and apply different rules to local and remote parties.
13
+ #
14
+ #
15
+ # Theory of operation
16
+ # ===================
17
+ #
18
+ # Possibly the simplest way to think about this is that we actually have 5
19
+ # different state machines here. Yes, 5. These are:
20
+ #
21
+ # 1) The client state, with its complicated automaton (see the docs)
22
+ # 2) The server state, with its complicated automaton (see the docs)
23
+ # 3) The keep-alive state, with possible states {True, False}
24
+ # 4) The SWITCH_CONNECT state, with possible states {False, True}
25
+ # 5) The SWITCH_UPGRADE state, with possible states {False, True}
26
+ #
27
+ # For (3)-(5), the first state listed is the initial state.
28
+ #
29
+ # (1)-(3) are stored explicitly in member variables. The last
30
+ # two are stored implicitly in the pending_switch_proposals set as:
31
+ # (state of 4) == (_SWITCH_CONNECT in pending_switch_proposals)
32
+ # (state of 5) == (_SWITCH_UPGRADE in pending_switch_proposals)
33
+ #
34
+ # And each of these machines has two different kinds of transitions:
35
+ #
36
+ # a) Event-triggered
37
+ # b) State-triggered
38
+ #
39
+ # Event triggered is the obvious thing that you'd think it is: some event
40
+ # happens, and if it's the right event at the right time then a transition
41
+ # happens. But there are somewhat complicated rules for which machines can
42
+ # "see" which events. (As a rule of thumb, if a machine "sees" an event, this
43
+ # means two things: the event can affect the machine, and if the machine is
44
+ # not in a state where it expects that event then it's an error.) These rules
45
+ # are:
46
+ #
47
+ # 1) The client machine sees all h11.events objects emitted by the client.
48
+ #
49
+ # 2) The server machine sees all h11.events objects emitted by the server.
50
+ #
51
+ # It also sees the client's Request event.
52
+ #
53
+ # And sometimes, server events are annotated with a _SWITCH_* event. For
54
+ # example, we can have a (Response, _SWITCH_CONNECT) event, which is
55
+ # different from a regular Response event.
56
+ #
57
+ # 3) The keep-alive machine sees the process_keep_alive_disabled() event
58
+ # (which is derived from Request/Response events), and this event
59
+ # transitions it from True -> False, or from False -> False. There's no way
60
+ # to transition back.
61
+ #
62
+ # 4&5) The _SWITCH_* machines transition from False->True when we get a
63
+ # Request that proposes the relevant type of switch (via
64
+ # process_client_switch_proposals), and they go from True->False when we
65
+ # get a Response that has no _SWITCH_* annotation.
66
+ #
67
+ # So that's event-triggered transitions.
68
+ #
69
+ # State-triggered transitions are less standard. What they do here is couple
70
+ # the machines together. The way this works is, when certain *joint*
71
+ # configurations of states are achieved, then we automatically transition to a
72
+ # new *joint* state. So, for example, if we're ever in a joint state with
73
+ #
74
+ # client: DONE
75
+ # keep-alive: False
76
+ #
77
+ # then the client state immediately transitions to:
78
+ #
79
+ # client: MUST_CLOSE
80
+ #
81
+ # This is fundamentally different from an event-based transition, because it
82
+ # doesn't matter how we arrived at the {client: DONE, keep-alive: False} state
83
+ # -- maybe the client transitioned SEND_BODY -> DONE, or keep-alive
84
+ # transitioned True -> False. Either way, once this precondition is satisfied,
85
+ # this transition is immediately triggered.
86
+ #
87
+ # What if two conflicting state-based transitions get enabled at the same
88
+ # time? In practice there's only one case where this arises (client DONE ->
89
+ # MIGHT_SWITCH_PROTOCOL versus DONE -> MUST_CLOSE), and we resolve it by
90
+ # explicitly prioritizing the DONE -> MIGHT_SWITCH_PROTOCOL transition.
91
+ #
92
+ # Implementation
93
+ # --------------
94
+ #
95
+ # The event-triggered transitions for the server and client machines are all
96
+ # stored explicitly in a table. Ditto for the state-triggered transitions that
97
+ # involve just the server and client state.
98
+ #
99
+ # The transitions for the other machines, and the state-triggered transitions
100
+ # that involve the other machines, are written out as explicit Python code.
101
+ #
102
+ # It'd be nice if there were some cleaner way to do all this. This isn't
103
+ # *too* terrible, but I feel like it could probably be better.
104
+ #
105
+ # WARNING
106
+ # -------
107
+ #
108
+ # The script that generates the state machine diagrams for the docs knows how
109
+ # to read out the EVENT_TRIGGERED_TRANSITIONS and STATE_TRIGGERED_TRANSITIONS
110
+ # tables. But it can't automatically read the transitions that are written
111
+ # directly in Python code. So if you touch those, you need to also update the
112
+ # script to keep it in sync!
113
+ from typing import cast, Dict, Optional, Set, Tuple, Type, Union
114
+
115
+ from ._events import *
116
+ from ._util import LocalProtocolError, Sentinel
117
+
118
+ # Everything in __all__ gets re-exported as part of the h11 public API.
119
+ __all__ = [
120
+ "CLIENT",
121
+ "SERVER",
122
+ "IDLE",
123
+ "SEND_RESPONSE",
124
+ "SEND_BODY",
125
+ "DONE",
126
+ "MUST_CLOSE",
127
+ "CLOSED",
128
+ "MIGHT_SWITCH_PROTOCOL",
129
+ "SWITCHED_PROTOCOL",
130
+ "ERROR",
131
+ ]
132
+
133
+
134
+ class CLIENT(Sentinel, metaclass=Sentinel):
135
+ pass
136
+
137
+
138
+ class SERVER(Sentinel, metaclass=Sentinel):
139
+ pass
140
+
141
+
142
+ # States
143
+ class IDLE(Sentinel, metaclass=Sentinel):
144
+ pass
145
+
146
+
147
+ class SEND_RESPONSE(Sentinel, metaclass=Sentinel):
148
+ pass
149
+
150
+
151
+ class SEND_BODY(Sentinel, metaclass=Sentinel):
152
+ pass
153
+
154
+
155
+ class DONE(Sentinel, metaclass=Sentinel):
156
+ pass
157
+
158
+
159
+ class MUST_CLOSE(Sentinel, metaclass=Sentinel):
160
+ pass
161
+
162
+
163
+ class CLOSED(Sentinel, metaclass=Sentinel):
164
+ pass
165
+
166
+
167
+ class ERROR(Sentinel, metaclass=Sentinel):
168
+ pass
169
+
170
+
171
+ # Switch types
172
+ class MIGHT_SWITCH_PROTOCOL(Sentinel, metaclass=Sentinel):
173
+ pass
174
+
175
+
176
+ class SWITCHED_PROTOCOL(Sentinel, metaclass=Sentinel):
177
+ pass
178
+
179
+
180
+ class _SWITCH_UPGRADE(Sentinel, metaclass=Sentinel):
181
+ pass
182
+
183
+
184
+ class _SWITCH_CONNECT(Sentinel, metaclass=Sentinel):
185
+ pass
186
+
187
+
188
+ EventTransitionType = Dict[
189
+ Type[Sentinel],
190
+ Dict[
191
+ Type[Sentinel],
192
+ Dict[Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], Type[Sentinel]],
193
+ ],
194
+ ]
195
+
196
+ EVENT_TRIGGERED_TRANSITIONS: EventTransitionType = {
197
+ CLIENT: {
198
+ IDLE: {Request: SEND_BODY, ConnectionClosed: CLOSED},
199
+ SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE},
200
+ DONE: {ConnectionClosed: CLOSED},
201
+ MUST_CLOSE: {ConnectionClosed: CLOSED},
202
+ CLOSED: {ConnectionClosed: CLOSED},
203
+ MIGHT_SWITCH_PROTOCOL: {},
204
+ SWITCHED_PROTOCOL: {},
205
+ ERROR: {},
206
+ },
207
+ SERVER: {
208
+ IDLE: {
209
+ ConnectionClosed: CLOSED,
210
+ Response: SEND_BODY,
211
+ # Special case: server sees client Request events, in this form
212
+ (Request, CLIENT): SEND_RESPONSE,
213
+ },
214
+ SEND_RESPONSE: {
215
+ InformationalResponse: SEND_RESPONSE,
216
+ Response: SEND_BODY,
217
+ (InformationalResponse, _SWITCH_UPGRADE): SWITCHED_PROTOCOL,
218
+ (Response, _SWITCH_CONNECT): SWITCHED_PROTOCOL,
219
+ },
220
+ SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE},
221
+ DONE: {ConnectionClosed: CLOSED},
222
+ MUST_CLOSE: {ConnectionClosed: CLOSED},
223
+ CLOSED: {ConnectionClosed: CLOSED},
224
+ SWITCHED_PROTOCOL: {},
225
+ ERROR: {},
226
+ },
227
+ }
228
+
229
+ StateTransitionType = Dict[
230
+ Tuple[Type[Sentinel], Type[Sentinel]], Dict[Type[Sentinel], Type[Sentinel]]
231
+ ]
232
+
233
+ # NB: there are also some special-case state-triggered transitions hard-coded
234
+ # into _fire_state_triggered_transitions below.
235
+ STATE_TRIGGERED_TRANSITIONS: StateTransitionType = {
236
+ # (Client state, Server state) -> new states
237
+ # Protocol negotiation
238
+ (MIGHT_SWITCH_PROTOCOL, SWITCHED_PROTOCOL): {CLIENT: SWITCHED_PROTOCOL},
239
+ # Socket shutdown
240
+ (CLOSED, DONE): {SERVER: MUST_CLOSE},
241
+ (CLOSED, IDLE): {SERVER: MUST_CLOSE},
242
+ (ERROR, DONE): {SERVER: MUST_CLOSE},
243
+ (DONE, CLOSED): {CLIENT: MUST_CLOSE},
244
+ (IDLE, CLOSED): {CLIENT: MUST_CLOSE},
245
+ (DONE, ERROR): {CLIENT: MUST_CLOSE},
246
+ }
247
+
248
+
249
+ class ConnectionState:
250
+ def __init__(self) -> None:
251
+ # Extra bits of state that don't quite fit into the state model.
252
+
253
+ # If this is False then it enables the automatic DONE -> MUST_CLOSE
254
+ # transition. Don't set this directly; call .keep_alive_disabled()
255
+ self.keep_alive = True
256
+
257
+ # This is a subset of {UPGRADE, CONNECT}, containing the proposals
258
+ # made by the client for switching protocols.
259
+ self.pending_switch_proposals: Set[Type[Sentinel]] = set()
260
+
261
+ self.states: Dict[Type[Sentinel], Type[Sentinel]] = {CLIENT: IDLE, SERVER: IDLE}
262
+
263
+ def process_error(self, role: Type[Sentinel]) -> None:
264
+ self.states[role] = ERROR
265
+ self._fire_state_triggered_transitions()
266
+
267
+ def process_keep_alive_disabled(self) -> None:
268
+ self.keep_alive = False
269
+ self._fire_state_triggered_transitions()
270
+
271
+ def process_client_switch_proposal(self, switch_event: Type[Sentinel]) -> None:
272
+ self.pending_switch_proposals.add(switch_event)
273
+ self._fire_state_triggered_transitions()
274
+
275
+ def process_event(
276
+ self,
277
+ role: Type[Sentinel],
278
+ event_type: Type[Event],
279
+ server_switch_event: Optional[Type[Sentinel]] = None,
280
+ ) -> None:
281
+ _event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]] = event_type
282
+ if server_switch_event is not None:
283
+ assert role is SERVER
284
+ if server_switch_event not in self.pending_switch_proposals:
285
+ raise LocalProtocolError(
286
+ "Received server _SWITCH_UPGRADE event without a pending proposal"
287
+ )
288
+ _event_type = (event_type, server_switch_event)
289
+ if server_switch_event is None and _event_type is Response:
290
+ self.pending_switch_proposals = set()
291
+ self._fire_event_triggered_transitions(role, _event_type)
292
+ # Special case: the server state does get to see Request
293
+ # events.
294
+ if _event_type is Request:
295
+ assert role is CLIENT
296
+ self._fire_event_triggered_transitions(SERVER, (Request, CLIENT))
297
+ self._fire_state_triggered_transitions()
298
+
299
+ def _fire_event_triggered_transitions(
300
+ self,
301
+ role: Type[Sentinel],
302
+ event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]],
303
+ ) -> None:
304
+ state = self.states[role]
305
+ try:
306
+ new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type]
307
+ except KeyError:
308
+ event_type = cast(Type[Event], event_type)
309
+ raise LocalProtocolError(
310
+ "can't handle event type {} when role={} and state={}".format(
311
+ event_type.__name__, role, self.states[role]
312
+ )
313
+ ) from None
314
+ self.states[role] = new_state
315
+
316
+ def _fire_state_triggered_transitions(self) -> None:
317
+ # We apply these rules repeatedly until converging on a fixed point
318
+ while True:
319
+ start_states = dict(self.states)
320
+
321
+ # It could happen that both these special-case transitions are
322
+ # enabled at the same time:
323
+ #
324
+ # DONE -> MIGHT_SWITCH_PROTOCOL
325
+ # DONE -> MUST_CLOSE
326
+ #
327
+ # For example, this will always be true of a HTTP/1.0 client
328
+ # requesting CONNECT. If this happens, the protocol switch takes
329
+ # priority. From there the client will either go to
330
+ # SWITCHED_PROTOCOL, in which case it's none of our business when
331
+ # they close the connection, or else the server will deny the
332
+ # request, in which case the client will go back to DONE and then
333
+ # from there to MUST_CLOSE.
334
+ if self.pending_switch_proposals:
335
+ if self.states[CLIENT] is DONE:
336
+ self.states[CLIENT] = MIGHT_SWITCH_PROTOCOL
337
+
338
+ if not self.pending_switch_proposals:
339
+ if self.states[CLIENT] is MIGHT_SWITCH_PROTOCOL:
340
+ self.states[CLIENT] = DONE
341
+
342
+ if not self.keep_alive:
343
+ for role in (CLIENT, SERVER):
344
+ if self.states[role] is DONE:
345
+ self.states[role] = MUST_CLOSE
346
+
347
+ # Tabular state-triggered transitions
348
+ joint_state = (self.states[CLIENT], self.states[SERVER])
349
+ changes = STATE_TRIGGERED_TRANSITIONS.get(joint_state, {})
350
+ self.states.update(changes)
351
+
352
+ if self.states == start_states:
353
+ # Fixed point reached
354
+ return
355
+
356
+ def start_next_cycle(self) -> None:
357
+ if self.states != {CLIENT: DONE, SERVER: DONE}:
358
+ raise LocalProtocolError(
359
+ f"not in a reusable state. self.states={self.states}"
360
+ )
361
+ # Can't reach DONE/DONE with any of these active, but still, let's be
362
+ # sure.
363
+ assert self.keep_alive
364
+ assert not self.pending_switch_proposals
365
+ self.states = {CLIENT: IDLE, SERVER: IDLE}
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_util.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any, Dict, NoReturn, Pattern, Tuple, Type, TypeVar, Union
2
+
3
+ __all__ = [
4
+ "ProtocolError",
5
+ "LocalProtocolError",
6
+ "RemoteProtocolError",
7
+ "validate",
8
+ "bytesify",
9
+ ]
10
+
11
+
12
+ class ProtocolError(Exception):
13
+ """Exception indicating a violation of the HTTP/1.1 protocol.
14
+
15
+ This as an abstract base class, with two concrete base classes:
16
+ :exc:`LocalProtocolError`, which indicates that you tried to do something
17
+ that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which
18
+ indicates that the remote peer tried to do something that HTTP/1.1 says is
19
+ illegal. See :ref:`error-handling` for details.
20
+
21
+ In addition to the normal :exc:`Exception` features, it has one attribute:
22
+
23
+ .. attribute:: error_status_hint
24
+
25
+ This gives a suggestion as to what status code a server might use if
26
+ this error occurred as part of a request.
27
+
28
+ For a :exc:`RemoteProtocolError`, this is useful as a suggestion for
29
+ how you might want to respond to a misbehaving peer, if you're
30
+ implementing a server.
31
+
32
+ For a :exc:`LocalProtocolError`, this can be taken as a suggestion for
33
+ how your peer might have responded to *you* if h11 had allowed you to
34
+ continue.
35
+
36
+ The default is 400 Bad Request, a generic catch-all for protocol
37
+ violations.
38
+
39
+ """
40
+
41
+ def __init__(self, msg: str, error_status_hint: int = 400) -> None:
42
+ if type(self) is ProtocolError:
43
+ raise TypeError("tried to directly instantiate ProtocolError")
44
+ Exception.__init__(self, msg)
45
+ self.error_status_hint = error_status_hint
46
+
47
+
48
+ # Strategy: there are a number of public APIs where a LocalProtocolError can
49
+ # be raised (send(), all the different event constructors, ...), and only one
50
+ # public API where RemoteProtocolError can be raised
51
+ # (receive_data()). Therefore we always raise LocalProtocolError internally,
52
+ # and then receive_data will translate this into a RemoteProtocolError.
53
+ #
54
+ # Internally:
55
+ # LocalProtocolError is the generic "ProtocolError".
56
+ # Externally:
57
+ # LocalProtocolError is for local errors and RemoteProtocolError is for
58
+ # remote errors.
59
+ class LocalProtocolError(ProtocolError):
60
+ def _reraise_as_remote_protocol_error(self) -> NoReturn:
61
+ # After catching a LocalProtocolError, use this method to re-raise it
62
+ # as a RemoteProtocolError. This method must be called from inside an
63
+ # except: block.
64
+ #
65
+ # An easy way to get an equivalent RemoteProtocolError is just to
66
+ # modify 'self' in place.
67
+ self.__class__ = RemoteProtocolError # type: ignore
68
+ # But the re-raising is somewhat non-trivial -- you might think that
69
+ # now that we've modified the in-flight exception object, that just
70
+ # doing 'raise' to re-raise it would be enough. But it turns out that
71
+ # this doesn't work, because Python tracks the exception type
72
+ # (exc_info[0]) separately from the exception object (exc_info[1]),
73
+ # and we only modified the latter. So we really do need to re-raise
74
+ # the new type explicitly.
75
+ # On py3, the traceback is part of the exception object, so our
76
+ # in-place modification preserved it and we can just re-raise:
77
+ raise self
78
+
79
+
80
+ class RemoteProtocolError(ProtocolError):
81
+ pass
82
+
83
+
84
+ def validate(
85
+ regex: Pattern[bytes], data: bytes, msg: str = "malformed data", *format_args: Any
86
+ ) -> Dict[str, bytes]:
87
+ match = regex.fullmatch(data)
88
+ if not match:
89
+ if format_args:
90
+ msg = msg.format(*format_args)
91
+ raise LocalProtocolError(msg)
92
+ return match.groupdict()
93
+
94
+
95
+ # Sentinel values
96
+ #
97
+ # - Inherit identity-based comparison and hashing from object
98
+ # - Have a nice repr
99
+ # - Have a *bonus property*: type(sentinel) is sentinel
100
+ #
101
+ # The bonus property is useful if you want to take the return value from
102
+ # next_event() and do some sort of dispatch based on type(event).
103
+
104
+ _T_Sentinel = TypeVar("_T_Sentinel", bound="Sentinel")
105
+
106
+
107
+ class Sentinel(type):
108
+ def __new__(
109
+ cls: Type[_T_Sentinel],
110
+ name: str,
111
+ bases: Tuple[type, ...],
112
+ namespace: Dict[str, Any],
113
+ **kwds: Any
114
+ ) -> _T_Sentinel:
115
+ assert bases == (Sentinel,)
116
+ v = super().__new__(cls, name, bases, namespace, **kwds)
117
+ v.__class__ = v # type: ignore
118
+ return v
119
+
120
+ def __repr__(self) -> str:
121
+ return self.__name__
122
+
123
+
124
+ # Used for methods, request targets, HTTP versions, header names, and header
125
+ # values. Accepts ascii-strings, or bytes/bytearray/memoryview/..., and always
126
+ # returns bytes.
127
+ def bytesify(s: Union[bytes, bytearray, memoryview, int, str]) -> bytes:
128
+ # Fast-path:
129
+ if type(s) is bytes:
130
+ return s
131
+ if isinstance(s, str):
132
+ s = s.encode("ascii")
133
+ if isinstance(s, int):
134
+ raise TypeError("expected bytes-like object, not int")
135
+ return bytes(s)
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_version.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be kept very simple, because it is consumed from several
2
+ # places -- it is imported by h11/__init__.py, execfile'd by setup.py, etc.
3
+
4
+ # We use a simple scheme:
5
+ # 1.0.0 -> 1.0.0+dev -> 1.1.0 -> 1.1.0+dev
6
+ # where the +dev versions are never released into the wild, they're just what
7
+ # we stick into the VCS in between releases.
8
+ #
9
+ # This is compatible with PEP 440:
10
+ # http://legacy.python.org/dev/peps/pep-0440/
11
+ # via the use of the "local suffix" "+dev", which is disallowed on index
12
+ # servers and causes 1.0.0+dev to sort after plain 1.0.0, which is what we
13
+ # want. (Contrast with the special suffix 1.0.0.dev, which sorts *before*
14
+ # 1.0.0.)
15
+
16
+ __version__ = "0.16.0"
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/_writers.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code to read HTTP data
2
+ #
3
+ # Strategy: each writer takes an event + a write-some-bytes function, which is
4
+ # calls.
5
+ #
6
+ # WRITERS is a dict describing how to pick a reader. It maps states to either:
7
+ # - a writer
8
+ # - or, for body writers, a dict of framin-dependent writer factories
9
+
10
+ from typing import Any, Callable, Dict, List, Tuple, Type, Union
11
+
12
+ from ._events import Data, EndOfMessage, Event, InformationalResponse, Request, Response
13
+ from ._headers import Headers
14
+ from ._state import CLIENT, IDLE, SEND_BODY, SEND_RESPONSE, SERVER
15
+ from ._util import LocalProtocolError, Sentinel
16
+
17
+ __all__ = ["WRITERS"]
18
+
19
+ Writer = Callable[[bytes], Any]
20
+
21
+
22
+ def write_headers(headers: Headers, write: Writer) -> None:
23
+ # "Since the Host field-value is critical information for handling a
24
+ # request, a user agent SHOULD generate Host as the first header field
25
+ # following the request-line." - RFC 7230
26
+ raw_items = headers._full_items
27
+ for raw_name, name, value in raw_items:
28
+ if name == b"host":
29
+ write(b"%s: %s\r\n" % (raw_name, value))
30
+ for raw_name, name, value in raw_items:
31
+ if name != b"host":
32
+ write(b"%s: %s\r\n" % (raw_name, value))
33
+ write(b"\r\n")
34
+
35
+
36
+ def write_request(request: Request, write: Writer) -> None:
37
+ if request.http_version != b"1.1":
38
+ raise LocalProtocolError("I only send HTTP/1.1")
39
+ write(b"%s %s HTTP/1.1\r\n" % (request.method, request.target))
40
+ write_headers(request.headers, write)
41
+
42
+
43
+ # Shared between InformationalResponse and Response
44
+ def write_any_response(
45
+ response: Union[InformationalResponse, Response], write: Writer
46
+ ) -> None:
47
+ if response.http_version != b"1.1":
48
+ raise LocalProtocolError("I only send HTTP/1.1")
49
+ status_bytes = str(response.status_code).encode("ascii")
50
+ # We don't bother sending ascii status messages like "OK"; they're
51
+ # optional and ignored by the protocol. (But the space after the numeric
52
+ # status code is mandatory.)
53
+ #
54
+ # XX FIXME: could at least make an effort to pull out the status message
55
+ # from stdlib's http.HTTPStatus table. Or maybe just steal their enums
56
+ # (either by import or copy/paste). We already accept them as status codes
57
+ # since they're of type IntEnum < int.
58
+ write(b"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason))
59
+ write_headers(response.headers, write)
60
+
61
+
62
+ class BodyWriter:
63
+ def __call__(self, event: Event, write: Writer) -> None:
64
+ if type(event) is Data:
65
+ self.send_data(event.data, write)
66
+ elif type(event) is EndOfMessage:
67
+ self.send_eom(event.headers, write)
68
+ else: # pragma: no cover
69
+ assert False
70
+
71
+ def send_data(self, data: bytes, write: Writer) -> None:
72
+ pass
73
+
74
+ def send_eom(self, headers: Headers, write: Writer) -> None:
75
+ pass
76
+
77
+
78
+ #
79
+ # These are all careful not to do anything to 'data' except call len(data) and
80
+ # write(data). This allows us to transparently pass-through funny objects,
81
+ # like placeholder objects referring to files on disk that will be sent via
82
+ # sendfile(2).
83
+ #
84
+ class ContentLengthWriter(BodyWriter):
85
+ def __init__(self, length: int) -> None:
86
+ self._length = length
87
+
88
+ def send_data(self, data: bytes, write: Writer) -> None:
89
+ self._length -= len(data)
90
+ if self._length < 0:
91
+ raise LocalProtocolError("Too much data for declared Content-Length")
92
+ write(data)
93
+
94
+ def send_eom(self, headers: Headers, write: Writer) -> None:
95
+ if self._length != 0:
96
+ raise LocalProtocolError("Too little data for declared Content-Length")
97
+ if headers:
98
+ raise LocalProtocolError("Content-Length and trailers don't mix")
99
+
100
+
101
+ class ChunkedWriter(BodyWriter):
102
+ def send_data(self, data: bytes, write: Writer) -> None:
103
+ # if we encoded 0-length data in the naive way, it would look like an
104
+ # end-of-message.
105
+ if not data:
106
+ return
107
+ write(b"%x\r\n" % len(data))
108
+ write(data)
109
+ write(b"\r\n")
110
+
111
+ def send_eom(self, headers: Headers, write: Writer) -> None:
112
+ write(b"0\r\n")
113
+ write_headers(headers, write)
114
+
115
+
116
+ class Http10Writer(BodyWriter):
117
+ def send_data(self, data: bytes, write: Writer) -> None:
118
+ write(data)
119
+
120
+ def send_eom(self, headers: Headers, write: Writer) -> None:
121
+ if headers:
122
+ raise LocalProtocolError("can't send trailers to HTTP/1.0 client")
123
+ # no need to close the socket ourselves, that will be taken care of by
124
+ # Connection: close machinery
125
+
126
+
127
+ WritersType = Dict[
128
+ Union[Tuple[Type[Sentinel], Type[Sentinel]], Type[Sentinel]],
129
+ Union[
130
+ Dict[str, Type[BodyWriter]],
131
+ Callable[[Union[InformationalResponse, Response], Writer], None],
132
+ Callable[[Request, Writer], None],
133
+ ],
134
+ ]
135
+
136
+ WRITERS: WritersType = {
137
+ (CLIENT, IDLE): write_request,
138
+ (SERVER, IDLE): write_any_response,
139
+ (SERVER, SEND_RESPONSE): write_any_response,
140
+ SEND_BODY: {
141
+ "chunked": ChunkedWriter,
142
+ "content-length": ContentLengthWriter,
143
+ "http/1.0": Http10Writer,
144
+ },
145
+ }
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/h11/py.typed ADDED
@@ -0,0 +1 @@
 
 
1
+ Marker
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/__init__.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from typing import TYPE_CHECKING
15
+
16
+ from ...utils import _LazyModule
17
+ from ...utils.import_utils import define_import_structure
18
+
19
+
20
+ if TYPE_CHECKING:
21
+ from .configuration_rwkv import *
22
+ from .modeling_rwkv import *
23
+ else:
24
+ import sys
25
+
26
+ _file = globals()["__file__"]
27
+ sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/configuration_rwkv.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 The OpenAI Team Authors and HuggingFace Inc. team.
2
+ # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """RWKV configuration"""
16
+
17
+ from huggingface_hub.dataclasses import strict
18
+
19
+ from ...configuration_utils import PreTrainedConfig
20
+ from ...utils import auto_docstring
21
+
22
+
23
+ @auto_docstring(checkpoint="RWKV/rwkv-4-169m-pile")
24
+ @strict
25
+ class RwkvConfig(PreTrainedConfig):
26
+ r"""
27
+ context_length (`int`, *optional*, defaults to 1024):
28
+ The maximum sequence length that this model can be used with in a single forward (using it in RNN mode
29
+ lets use any sequence length).
30
+ attention_hidden_size (`int`, *optional*):
31
+ Dimensionality of the attention hidden states. Will default to `hidden_size` if unset.
32
+ rescale_every (`int`, *optional*, defaults to 6):
33
+ At inference, the hidden states (and weights of the corresponding output layers) are divided by 2 every
34
+ `rescale_every` layer. If set to 0 or a negative number, no rescale is done.
35
+
36
+ Example:
37
+
38
+ ```python
39
+ >>> from transformers import RwkvConfig, RwkvModel
40
+
41
+ >>> # Initializing a Rwkv configuration
42
+ >>> configuration = RwkvConfig()
43
+
44
+ >>> # Initializing a model (with random weights) from the configuration
45
+ >>> model = RwkvModel(configuration)
46
+
47
+ >>> # Accessing the model configuration
48
+ >>> configuration = model.config
49
+ ```"""
50
+
51
+ model_type = "rwkv"
52
+ attribute_map = {"max_position_embeddings": "context_length"}
53
+
54
+ vocab_size: int = 50277
55
+ context_length: int = 1024
56
+ hidden_size: int = 4096
57
+ num_hidden_layers: int = 32
58
+ attention_hidden_size: int | None = None
59
+ intermediate_size: int | None = None
60
+ layer_norm_epsilon: float = 1e-5
61
+ bos_token_id: int | None = 0
62
+ eos_token_id: int | list[int] | None = 0
63
+ rescale_every: int = 6
64
+ tie_word_embeddings: bool = False
65
+ use_cache: bool = True
66
+
67
+ def __post_init__(self, **kwargs):
68
+ self.attention_hidden_size = (
69
+ self.attention_hidden_size if self.attention_hidden_size is not None else self.hidden_size
70
+ )
71
+ self.intermediate_size = self.intermediate_size if self.intermediate_size is not None else 4 * self.hidden_size
72
+
73
+ super().__post_init__(**kwargs)
74
+
75
+
76
+ __all__ = ["RwkvConfig"]
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/rwkv/modeling_rwkv.py ADDED
@@ -0,0 +1,758 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 Bo Peng and HuggingFace Inc. team.
2
+ # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """PyTorch RWKV model."""
16
+
17
+ import math
18
+ from dataclasses import dataclass
19
+
20
+ import torch
21
+ from torch import nn
22
+
23
+ from ... import initialization as init
24
+ from ...generation import GenerationMixin
25
+ from ...modeling_layers import GradientCheckpointingLayer
26
+ from ...modeling_utils import PreTrainedModel
27
+ from ...utils import (
28
+ ModelOutput,
29
+ auto_docstring,
30
+ is_bitsandbytes_available,
31
+ is_kernels_available,
32
+ is_ninja_available,
33
+ is_torch_cuda_available,
34
+ logging,
35
+ )
36
+ from .configuration_rwkv import RwkvConfig
37
+
38
+
39
+ logger = logging.get_logger(__name__)
40
+
41
+
42
+ rwkv_cuda_kernel = None
43
+
44
+
45
+ def load_wkv_cuda_kernel(context_length):
46
+ global rwkv_cuda_kernel
47
+ if not is_kernels_available():
48
+ raise ImportError("kernels is not installed, please install it with `pip install kernels`")
49
+
50
+ from ...integrations.hub_kernels import get_kernel
51
+
52
+ rwkv_cuda_kernel = get_kernel("kernels-community/rwkv")
53
+ rwkv_cuda_kernel.max_seq_length = context_length
54
+
55
+
56
+ class RwkvLinearAttention(torch.autograd.Function):
57
+ @staticmethod
58
+ def forward(ctx, time_decay, time_first, key, value, state=None, return_state=False):
59
+ batch_size, seq_len, hidden_size = key.size()
60
+ if seq_len > rwkv_cuda_kernel.max_seq_length:
61
+ raise ValueError(
62
+ f"Cannot process a batch with {seq_len} tokens at the same time, use a maximum of "
63
+ f"{rwkv_cuda_kernel.max_seq_length} with this model."
64
+ )
65
+ if batch_size * hidden_size % min(hidden_size, 32) != 0:
66
+ raise ValueError(
67
+ f"The product of batch size ({batch_size}) and hidden size ({hidden_size}) needs to be a round "
68
+ f"multiple of {min(hidden_size, 32)}."
69
+ )
70
+
71
+ ctx.input_dtype = key.dtype
72
+
73
+ if (
74
+ time_decay.device.type != "cuda"
75
+ or time_first.device.type != "cuda"
76
+ or key.device.type != "cuda"
77
+ or value.device.type != "cuda"
78
+ ):
79
+ raise ValueError("Calling the CUDA kernel for wkv attention requires all tensors to be on CUDA devices.")
80
+
81
+ time_decay = -torch.exp(time_decay.float().contiguous())
82
+ if key.dtype == torch.float16:
83
+ time_first = time_first.float()
84
+ key = key.float()
85
+ value = value.float()
86
+ time_first = time_first.contiguous()
87
+ key = key.contiguous()
88
+ value = value.contiguous()
89
+ # The CUDA kernel will fill this tensor.
90
+ output = torch.empty_like(key, memory_format=torch.contiguous_format)
91
+ if return_state or state is not None:
92
+ if state is None:
93
+ state = torch.zeros(
94
+ batch_size,
95
+ hidden_size,
96
+ 3,
97
+ dtype=torch.float32,
98
+ device=key.device,
99
+ memory_format=torch.contiguous_format,
100
+ )
101
+ state[:, :, 2] -= 1e38
102
+ else:
103
+ state = torch.cat([s.unsqueeze(2) for s in state], dim=2).contiguous()
104
+ if key.dtype == torch.bfloat16:
105
+ forward_func = rwkv_cuda_kernel.forward_with_state_bf16
106
+ else:
107
+ forward_func = rwkv_cuda_kernel.forward_with_state
108
+ forward_func(time_decay, time_first, key, value, output, state)
109
+ else:
110
+ forward_func = rwkv_cuda_kernel.forward_bf16 if key.dtype == torch.bfloat16 else rwkv_cuda_kernel.forward
111
+ forward_func(time_decay, time_first, key, value, output)
112
+
113
+ ctx.save_for_backward(time_decay, time_first, key, value, output)
114
+
115
+ if state is not None:
116
+ state = [s.squeeze(2) for s in torch.chunk(state, 3, dim=2)]
117
+
118
+ return output.to(ctx.input_dtype), state
119
+
120
+ @staticmethod
121
+ # g stands for grad
122
+ def backward(ctx, g_output, g_state=None):
123
+ input_dtype = ctx.input_dtype
124
+
125
+ time_decay, time_first, key, value, output = ctx.saved_tensors
126
+ # The CUDA kernel will fill those tensors.
127
+ g_time_decay = torch.empty_like(
128
+ time_decay,
129
+ memory_format=torch.contiguous_format,
130
+ dtype=torch.bfloat16 if input_dtype == torch.bfloat16 else torch.float32,
131
+ )
132
+ g_time_first = torch.empty_like(time_first, memory_format=torch.contiguous_format)
133
+ g_key = torch.empty_like(key, memory_format=torch.contiguous_format)
134
+ g_value = torch.empty_like(value, memory_format=torch.contiguous_format)
135
+
136
+ if input_dtype == torch.float16:
137
+ g_output = g_output.float()
138
+ backward_func = rwkv_cuda_kernel.backward_bf16 if input_dtype == torch.bfloat16 else rwkv_cuda_kernel.backward
139
+ backward_func(
140
+ time_decay,
141
+ time_first,
142
+ key,
143
+ value,
144
+ output,
145
+ g_output.contiguous(),
146
+ g_time_decay,
147
+ g_time_first,
148
+ g_key,
149
+ g_value,
150
+ )
151
+
152
+ return (
153
+ g_time_decay.to(input_dtype),
154
+ g_time_first.to(input_dtype),
155
+ g_key.to(input_dtype),
156
+ g_value.to(input_dtype),
157
+ None,
158
+ None,
159
+ )
160
+
161
+
162
+ def rwkv_linear_attention_cpu(time_decay, time_first, key, value, state=None, return_state=False):
163
+ # For CPU fallback. Will be slower and probably take more memory than the custom CUDA kernel if not executed
164
+ # within a torch.no_grad.
165
+ _, seq_length, _ = key.size()
166
+ output = torch.zeros_like(key)
167
+
168
+ if state is None:
169
+ num_state = torch.zeros_like(key[:, 0], dtype=torch.float32)
170
+ den_state = torch.zeros_like(key[:, 0], dtype=torch.float32)
171
+ max_state = torch.zeros_like(key[:, 0], dtype=torch.float32) - 1e38
172
+ else:
173
+ num_state, den_state, max_state = state
174
+ # For numerical stability
175
+ # real_numerator_state = num_state * torch.exp(max_state)
176
+ # real_denominator_state = den_state * torch.exp(max_state)
177
+
178
+ time_decay = -torch.exp(time_decay)
179
+
180
+ for current_index in range(seq_length):
181
+ current_key = key[:, current_index].float()
182
+ current_value = value[:, current_index]
183
+
184
+ # wkv computation at time t
185
+ max_for_output = torch.maximum(max_state, current_key + time_first)
186
+ e1 = torch.exp(max_state - max_for_output)
187
+ e2 = torch.exp(current_key + time_first - max_for_output)
188
+ numerator = e1 * num_state + e2 * current_value
189
+ denominator = e1 * den_state + e2
190
+ output[:, current_index] = (numerator / denominator).to(output.dtype)
191
+
192
+ # Update state for next iteration
193
+ max_for_state = torch.maximum(max_state + time_decay, current_key)
194
+ e1 = torch.exp(max_state + time_decay - max_for_state)
195
+ e2 = torch.exp(current_key - max_for_state)
196
+ num_state = e1 * num_state + e2 * current_value
197
+ den_state = e1 * den_state + e2
198
+ max_state = max_for_state
199
+
200
+ if return_state or state is not None:
201
+ state = [num_state, den_state, max_state]
202
+
203
+ return output, state
204
+
205
+
206
+ def rwkv_linear_attention(time_decay, time_first, key, value, state=None, return_state=False):
207
+ no_cuda = any(t.device.type != "cuda" for t in [time_decay, time_first, key, value])
208
+ # Launching the CUDA kernel for just one token will actually be slower (there is no for loop in the CPU version
209
+ # in this case).
210
+ one_token = key.size(1) == 1
211
+ if rwkv_cuda_kernel is None or no_cuda or one_token:
212
+ return rwkv_linear_attention_cpu(time_decay, time_first, key, value, state=state, return_state=return_state)
213
+ else:
214
+ return RwkvLinearAttention.apply(time_decay, time_first, key, value, state, return_state)
215
+
216
+
217
+ class RwkvSelfAttention(nn.Module):
218
+ def __init__(self, config, layer_id=0):
219
+ super().__init__()
220
+ self.config = config
221
+ kernel_loaded = rwkv_cuda_kernel is not None and rwkv_cuda_kernel.max_seq_length == config.context_length
222
+ if is_ninja_available() and is_torch_cuda_available() and not kernel_loaded:
223
+ try:
224
+ load_wkv_cuda_kernel(config.context_length)
225
+ except Exception:
226
+ logger.info("Could not load the custom CUDA kernel for RWKV attention.")
227
+ self.layer_id = layer_id
228
+ hidden_size = config.hidden_size
229
+ attention_hidden_size = (
230
+ config.attention_hidden_size if config.attention_hidden_size is not None else hidden_size
231
+ )
232
+ self.attention_hidden_size = attention_hidden_size
233
+
234
+ self.time_decay = nn.Parameter(torch.empty(attention_hidden_size))
235
+ self.time_first = nn.Parameter(torch.empty(attention_hidden_size))
236
+
237
+ self.time_mix_key = nn.Parameter(torch.empty(1, 1, hidden_size))
238
+ self.time_mix_value = nn.Parameter(torch.empty(1, 1, hidden_size))
239
+ self.time_mix_receptance = nn.Parameter(torch.empty(1, 1, hidden_size))
240
+
241
+ self.time_shift = nn.ZeroPad2d((0, 0, 1, -1))
242
+ self.key = nn.Linear(hidden_size, attention_hidden_size, bias=False)
243
+ self.value = nn.Linear(hidden_size, attention_hidden_size, bias=False)
244
+ self.receptance = nn.Linear(hidden_size, attention_hidden_size, bias=False)
245
+ self.output = nn.Linear(attention_hidden_size, hidden_size, bias=False)
246
+
247
+ # TODO: maybe jit, otherwise move inside forward
248
+ def extract_key_value(self, hidden, state=None):
249
+ # Mix hidden with the previous timestep to produce key, value, receptance
250
+ if hidden.size(1) == 1 and state is not None:
251
+ shifted = state[1][:, :, self.layer_id]
252
+ else:
253
+ shifted = self.time_shift(hidden)
254
+ if state is not None:
255
+ shifted[:, 0] = state[1][:, :, self.layer_id]
256
+ key = hidden * self.time_mix_key + shifted * (1 - self.time_mix_key)
257
+ value = hidden * self.time_mix_value + shifted * (1 - self.time_mix_value)
258
+ receptance = hidden * self.time_mix_receptance + shifted * (1 - self.time_mix_receptance)
259
+
260
+ key = self.key(key)
261
+ value = self.value(value)
262
+ receptance = torch.sigmoid(self.receptance(receptance))
263
+ if state is not None:
264
+ state[1][:, :, self.layer_id] = hidden[:, -1]
265
+ return receptance, key, value, state
266
+
267
+ def forward(self, hidden, state=None, use_cache=False):
268
+ receptance, key, value, state = self.extract_key_value(hidden, state=state)
269
+ layer_state = tuple(s[:, :, self.layer_id] for s in state[2:]) if state is not None else None
270
+ rwkv, layer_state = rwkv_linear_attention(
271
+ self.time_decay,
272
+ self.time_first,
273
+ key,
274
+ value,
275
+ state=layer_state,
276
+ return_state=use_cache,
277
+ )
278
+
279
+ if layer_state is not None:
280
+ state[2][:, :, self.layer_id] = layer_state[0]
281
+ state[3][:, :, self.layer_id] = layer_state[1]
282
+ state[4][:, :, self.layer_id] = layer_state[2]
283
+
284
+ return self.output(receptance * rwkv), state
285
+
286
+
287
+ class RwkvFeedForward(nn.Module):
288
+ def __init__(self, config, layer_id=0):
289
+ super().__init__()
290
+ self.config = config
291
+ self.layer_id = layer_id
292
+ hidden_size = config.hidden_size
293
+ intermediate_size = (
294
+ config.intermediate_size if config.intermediate_size is not None else 4 * config.hidden_size
295
+ )
296
+
297
+ self.time_shift = nn.ZeroPad2d((0, 0, 1, -1))
298
+ self.time_mix_key = nn.Parameter(torch.empty(1, 1, hidden_size))
299
+ self.time_mix_receptance = nn.Parameter(torch.empty(1, 1, hidden_size))
300
+
301
+ self.key = nn.Linear(hidden_size, intermediate_size, bias=False)
302
+ self.receptance = nn.Linear(hidden_size, hidden_size, bias=False)
303
+ self.value = nn.Linear(intermediate_size, hidden_size, bias=False)
304
+
305
+ def forward(self, hidden, state=None):
306
+ if hidden.size(1) == 1 and state is not None:
307
+ shifted = state[0][:, :, self.layer_id]
308
+ else:
309
+ shifted = self.time_shift(hidden)
310
+ if state is not None:
311
+ shifted[:, 0] = state[0][:, :, self.layer_id]
312
+ key = hidden * self.time_mix_key + shifted * (1 - self.time_mix_key)
313
+ receptance = hidden * self.time_mix_receptance + shifted * (1 - self.time_mix_receptance)
314
+
315
+ key = torch.square(torch.relu(self.key(key)))
316
+ value = self.value(key)
317
+ receptance = torch.sigmoid(self.receptance(receptance))
318
+
319
+ if state is not None:
320
+ state[0][:, :, self.layer_id] = hidden[:, -1]
321
+
322
+ return receptance * value, state
323
+
324
+
325
+ class RwkvBlock(GradientCheckpointingLayer):
326
+ def __init__(self, config, layer_id):
327
+ super().__init__()
328
+ self.config = config
329
+ self.layer_id = layer_id
330
+
331
+ if layer_id == 0:
332
+ self.pre_ln = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_epsilon)
333
+
334
+ self.ln1 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_epsilon)
335
+ self.ln2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_epsilon)
336
+
337
+ self.attention = RwkvSelfAttention(config, layer_id)
338
+ self.feed_forward = RwkvFeedForward(config, layer_id)
339
+
340
+ def forward(self, hidden, state=None, use_cache=False, output_attentions=False):
341
+ if self.layer_id == 0:
342
+ hidden = self.pre_ln(hidden)
343
+
344
+ attention, state = self.attention(self.ln1(hidden), state=state, use_cache=use_cache)
345
+ hidden = hidden + attention
346
+
347
+ feed_forward, state = self.feed_forward(self.ln2(hidden), state=state)
348
+ hidden = hidden + feed_forward
349
+
350
+ outputs = (hidden, state)
351
+ if output_attentions:
352
+ outputs += (attention,)
353
+ else:
354
+ outputs += (None,)
355
+
356
+ return outputs
357
+
358
+
359
+ @auto_docstring
360
+ class RwkvPreTrainedModel(PreTrainedModel):
361
+ config: RwkvConfig
362
+ base_model_prefix = "rwkv"
363
+ _no_split_modules = ["RwkvBlock"]
364
+ _keep_in_fp32_modules = ["time_decay", "time_first"]
365
+ supports_gradient_checkpointing = True
366
+ _is_stateful = True
367
+
368
+ @torch.no_grad()
369
+ def _init_weights(self, module: nn.Module):
370
+ """Initialize the weights."""
371
+ if isinstance(module, RwkvSelfAttention):
372
+ layer_id = module.layer_id
373
+ num_hidden_layers = module.config.num_hidden_layers
374
+ hidden_size = module.config.hidden_size
375
+ attention_hidden_size = module.attention_hidden_size
376
+
377
+ ratio_0_to_1 = layer_id / (num_hidden_layers - 1) # 0 to 1
378
+ ratio_1_to_almost0 = 1.0 - (layer_id / num_hidden_layers) # 1 to ~0
379
+
380
+ time_weight = torch.tensor(
381
+ [i / hidden_size for i in range(hidden_size)],
382
+ dtype=module.time_mix_key.dtype,
383
+ device=module.time_mix_key.device,
384
+ )
385
+ time_weight = time_weight[None, None, :]
386
+
387
+ decay_speed = [
388
+ -5 + 8 * (h / (attention_hidden_size - 1)) ** (0.7 + 1.3 * ratio_0_to_1)
389
+ for h in range(attention_hidden_size)
390
+ ]
391
+ decay_speed = torch.tensor(decay_speed, dtype=module.time_decay.dtype, device=module.time_decay.device)
392
+ zigzag = (
393
+ torch.tensor(
394
+ [(i + 1) % 3 - 1 for i in range(attention_hidden_size)],
395
+ dtype=module.time_first.dtype,
396
+ device=module.time_first.device,
397
+ )
398
+ * 0.5
399
+ )
400
+
401
+ init.copy_(module.time_decay, decay_speed)
402
+ init.copy_(module.time_first, torch.ones_like(module.time_first * math.log(0.3) + zigzag))
403
+
404
+ init.copy_(module.time_mix_key, torch.pow(time_weight, ratio_1_to_almost0))
405
+ init.copy_(module.time_mix_value, torch.pow(time_weight, ratio_1_to_almost0) + 0.3 * ratio_0_to_1)
406
+ init.copy_(module.time_mix_receptance, torch.pow(time_weight, 0.5 * ratio_1_to_almost0))
407
+ elif isinstance(module, RwkvFeedForward):
408
+ layer_id = module.layer_id
409
+ num_hidden_layers = module.config.num_hidden_layers
410
+ hidden_size = module.config.hidden_size
411
+
412
+ ratio_1_to_almost0 = 1.0 - (layer_id / num_hidden_layers) # 1 to ~0
413
+
414
+ time_weight = torch.tensor(
415
+ [i / hidden_size for i in range(hidden_size)],
416
+ dtype=module.time_mix_key.dtype,
417
+ device=module.time_mix_key.device,
418
+ )
419
+ time_weight = time_weight[None, None, :]
420
+
421
+ init.copy_(module.time_mix_key, torch.pow(time_weight, ratio_1_to_almost0))
422
+ init.copy_(module.time_mix_receptance, torch.pow(time_weight, ratio_1_to_almost0))
423
+ elif isinstance(module, nn.Linear):
424
+ shape = module.weight.shape
425
+ gain = 1.0
426
+ scale = 1.0 # extra scale for gain
427
+ if module.bias is not None:
428
+ init.zeros_(module.bias)
429
+ if shape[0] > shape[1]:
430
+ gain = math.sqrt(shape[0] / shape[1])
431
+ if shape[0] == self.config.vocab_size and shape[1] == self.config.hidden_size: # final projection?
432
+ scale = 0.5
433
+
434
+ gain *= scale
435
+ init.orthogonal_(module.weight, gain=gain)
436
+ elif isinstance(module, nn.Embedding):
437
+ shape = module.weight.shape
438
+ gain = 1e-4 * math.sqrt(max(shape[0], shape[1]))
439
+ init.orthogonal_(module.weight, gain=gain)
440
+ elif isinstance(module, nn.LayerNorm):
441
+ init.ones_(module.weight)
442
+ init.zeros_(module.bias)
443
+
444
+
445
+ @auto_docstring(
446
+ custom_intro="""
447
+ Class for the RWKV model outputs.
448
+ """
449
+ )
450
+ @dataclass
451
+ class RwkvOutput(ModelOutput):
452
+ r"""
453
+ state (list of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`):
454
+ The state of the model at the last time step. Can be used in a forward method with the next `input_ids` to
455
+ avoid providing the old `input_ids`.
456
+ """
457
+
458
+ last_hidden_state: torch.FloatTensor | None = None
459
+ state: list[torch.FloatTensor] | None = None
460
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
461
+ attentions: tuple[torch.FloatTensor, ...] | None = None
462
+
463
+
464
+ @auto_docstring(
465
+ custom_intro="""
466
+ Base class for causal language model (or autoregressive) outputs.
467
+ """
468
+ )
469
+ @dataclass
470
+ class RwkvCausalLMOutput(ModelOutput):
471
+ r"""
472
+ loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
473
+ Language modeling loss (for next-token prediction).
474
+ logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
475
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
476
+ state (list of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`):
477
+ The state of the model at the last time step. Can be used in a forward method with the next `input_ids` to
478
+ avoid providing the old `input_ids`.
479
+ """
480
+
481
+ loss: torch.FloatTensor | None = None
482
+ logits: torch.FloatTensor | None = None
483
+ state: list[torch.FloatTensor] | None = None
484
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
485
+ attentions: tuple[torch.FloatTensor, ...] | None = None
486
+
487
+
488
+ @auto_docstring
489
+ class RwkvModel(RwkvPreTrainedModel):
490
+ def __init__(self, config):
491
+ super().__init__(config)
492
+
493
+ self.embeddings = nn.Embedding(config.vocab_size, config.hidden_size)
494
+ self.blocks = nn.ModuleList([RwkvBlock(config, layer_id=idx) for idx in range(config.num_hidden_layers)])
495
+ self.ln_out = nn.LayerNorm(config.hidden_size)
496
+
497
+ self.layers_are_rescaled = False
498
+
499
+ self.gradient_checkpointing = False
500
+
501
+ # Initialize weights and apply final processing
502
+ self.post_init()
503
+
504
+ def get_input_embeddings(self):
505
+ return self.embeddings
506
+
507
+ def set_input_embeddings(self, new_embeddings):
508
+ self.embeddings = new_embeddings
509
+
510
+ @auto_docstring
511
+ def forward(
512
+ self,
513
+ input_ids: torch.LongTensor | None = None,
514
+ attention_mask: torch.LongTensor | None = None,
515
+ inputs_embeds: torch.FloatTensor | None = None,
516
+ state: list[torch.FloatTensor] | None = None,
517
+ use_cache: bool | None = None,
518
+ output_attentions: bool | None = None,
519
+ output_hidden_states: bool | None = None,
520
+ return_dict: bool | None = None,
521
+ **kwargs,
522
+ ) -> tuple | RwkvOutput:
523
+ r"""
524
+ input_ids (`torch.LongTensor` of shape `(batch_size, input_ids_length)`):
525
+ `input_ids_length` = `sequence_length` if `past_key_values` is `None` else
526
+ `past_key_values.get_seq_length()` (`sequence_length` of input past key value states). Indices of input
527
+ sequence tokens in the vocabulary.
528
+
529
+ If `past_key_values` is used, only `input_ids` that do not have their past calculated should be passed as
530
+ `input_ids`.
531
+
532
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
533
+ [`PreTrainedTokenizer.__call__`] for details.
534
+
535
+ [What are input IDs?](../glossary#input-ids)
536
+ state (tuple of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`, *optional*):
537
+ If passed along, the model uses the previous state in all the blocks (which will give the output for the
538
+ `input_ids` provided as if the model add `state_input_ids + input_ids` as context).
539
+ use_cache (`bool`, *optional*):
540
+ If set to `True`, the last state is returned and can be used to quickly generate the next logits.
541
+ """
542
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
543
+ output_hidden_states = (
544
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
545
+ )
546
+ use_cache = use_cache if use_cache is not None else (self.config.use_cache if not self.training else False)
547
+ return_dict = return_dict if return_dict is not None else self.config.return_dict
548
+
549
+ if attention_mask is not None:
550
+ logger.warning_once("`attention_mask` was passed, but it is unused in this model.")
551
+
552
+ if self.training == self.layers_are_rescaled:
553
+ self._rescale_layers()
554
+
555
+ if input_ids is not None and inputs_embeds is not None:
556
+ raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
557
+ elif input_ids is None and inputs_embeds is None:
558
+ raise ValueError("You have to specify either input_ids or inputs_embeds")
559
+
560
+ if inputs_embeds is None:
561
+ inputs_embeds = self.embeddings(input_ids)
562
+
563
+ if use_cache and state is None:
564
+ shape = (inputs_embeds.size(0), self.config.hidden_size, self.config.num_hidden_layers)
565
+ state = [
566
+ torch.zeros(
567
+ *shape, dtype=inputs_embeds.dtype if i <= 1 else torch.float32, device=inputs_embeds.device
568
+ )
569
+ for i in range(5)
570
+ ]
571
+ state[4] -= 1e30
572
+
573
+ if self.gradient_checkpointing and self.training:
574
+ if use_cache:
575
+ logger.warning_once(
576
+ "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..."
577
+ )
578
+ use_cache = False
579
+
580
+ hidden_states = inputs_embeds
581
+
582
+ all_self_attentions = () if output_attentions else None
583
+ all_hidden_states = () if output_hidden_states else None
584
+ for idx, block in enumerate(self.blocks):
585
+ hidden_states, state, attentions = block(
586
+ hidden_states, state=state, use_cache=use_cache, output_attentions=output_attentions
587
+ )
588
+
589
+ if (
590
+ self.layers_are_rescaled
591
+ and self.config.rescale_every > 0
592
+ and (idx + 1) % self.config.rescale_every == 0
593
+ ):
594
+ hidden_states = hidden_states / 2
595
+
596
+ if output_hidden_states:
597
+ all_hidden_states = all_hidden_states + (hidden_states,)
598
+
599
+ if output_attentions:
600
+ all_self_attentions = all_self_attentions + (attentions,)
601
+
602
+ hidden_states = self.ln_out(hidden_states)
603
+
604
+ if output_hidden_states:
605
+ all_hidden_states = all_hidden_states + (hidden_states,)
606
+
607
+ if not return_dict:
608
+ return tuple(x for x in [hidden_states, state, all_hidden_states, all_self_attentions] if x is not None)
609
+
610
+ return RwkvOutput(
611
+ last_hidden_state=hidden_states,
612
+ state=state,
613
+ hidden_states=all_hidden_states,
614
+ attentions=all_self_attentions,
615
+ )
616
+
617
+ def _rescale_layers(self):
618
+ # Layers should be rescaled for inference only.
619
+ if self.layers_are_rescaled == (not self.training):
620
+ return
621
+ if self.config.rescale_every > 0:
622
+ with torch.no_grad():
623
+ for block_id, block in enumerate(self.blocks):
624
+ if self.training:
625
+ block.attention.output.weight.mul_(2 ** int(block_id // self.config.rescale_every))
626
+ block.feed_forward.value.weight.mul_(2 ** int(block_id // self.config.rescale_every))
627
+ else:
628
+ # Deal with quantization statistics
629
+ if hasattr(block.attention.output.weight, "SCB"):
630
+ block.attention.output.weight.SCB.div_(2 ** int(block_id // self.config.rescale_every))
631
+ block.feed_forward.value.weight.SCB.div_(2 ** int(block_id // self.config.rescale_every))
632
+ elif hasattr(block.attention.output.weight, "quant_state"):
633
+ self._bnb_4bit_dequantize_and_rescale(block.attention.output, block_id)
634
+ self._bnb_4bit_dequantize_and_rescale(block.feed_forward.value, block_id)
635
+ else:
636
+ block.attention.output.weight.div_(2 ** int(block_id // self.config.rescale_every))
637
+ block.feed_forward.value.weight.div_(2 ** int(block_id // self.config.rescale_every))
638
+
639
+ self.layers_are_rescaled = not self.training
640
+
641
+ def _bnb_4bit_dequantize_and_rescale(self, target_layer, block_id):
642
+ r"""
643
+ Perform the dequantization and rescaling of the weights of a given layer. After that operation the layer will
644
+ be quantized again.
645
+ """
646
+ if not is_bitsandbytes_available():
647
+ raise ImportError("Please install bitsandbytes to use this method.")
648
+ import bitsandbytes as bnb
649
+
650
+ dequant_weights = bnb.functional.dequantize_4bit(target_layer.weight.data, target_layer.weight.quant_state)
651
+
652
+ dequant_weights.div_(2 ** int(block_id // self.config.rescale_every))
653
+
654
+ # re-quantize the model:
655
+ # we need to put it first on CPU then back to the device
656
+ # this will create an overhead :/
657
+ # We set requires_grad=False as we cannot compute gradients on top of 4bit parameters anyway and to avoid
658
+ # bugs with bnb
659
+ quant_weight = bnb.nn.Params4bit(dequant_weights.to("cpu"), requires_grad=False).to(dequant_weights.device)
660
+ setattr(target_layer, "weight", quant_weight)
661
+
662
+
663
+ @auto_docstring(
664
+ custom_intro="""
665
+ The RWKV Model transformer with a language modeling head on top (linear layer with weights tied to the input
666
+ embeddings).
667
+ """
668
+ )
669
+ class RwkvForCausalLM(RwkvPreTrainedModel, GenerationMixin):
670
+ _tied_weights_keys = {"head.weight": "rwkv.embeddings.weight"}
671
+
672
+ def __init__(self, config):
673
+ super().__init__(config)
674
+ self.rwkv = RwkvModel(config)
675
+ self.head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
676
+
677
+ # Initialize weights and apply final processing
678
+ self.post_init()
679
+
680
+ def get_output_embeddings(self):
681
+ return self.head
682
+
683
+ def set_output_embeddings(self, new_embeddings):
684
+ self.head = new_embeddings
685
+
686
+ @auto_docstring
687
+ def forward(
688
+ self,
689
+ input_ids: torch.LongTensor | None = None,
690
+ attention_mask: torch.LongTensor | None = None,
691
+ inputs_embeds: torch.FloatTensor | None = None,
692
+ state: list[torch.FloatTensor] | None = None,
693
+ labels: torch.LongTensor | None = None,
694
+ use_cache: bool | None = None,
695
+ output_attentions: bool | None = None,
696
+ output_hidden_states: bool | None = None,
697
+ return_dict: bool | None = None,
698
+ logits_to_keep: int | torch.Tensor = 0,
699
+ **kwargs,
700
+ ) -> tuple | RwkvCausalLMOutput:
701
+ r"""
702
+ input_ids (`torch.LongTensor` of shape `(batch_size, input_ids_length)`):
703
+ `input_ids_length` = `sequence_length` if `past_key_values` is `None` else
704
+ `past_key_values.get_seq_length()` (`sequence_length` of input past key value states). Indices of input
705
+ sequence tokens in the vocabulary.
706
+
707
+ If `past_key_values` is used, only `input_ids` that do not have their past calculated should be passed as
708
+ `input_ids`.
709
+
710
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
711
+ [`PreTrainedTokenizer.__call__`] for details.
712
+
713
+ [What are input IDs?](../glossary#input-ids)
714
+ state (tuple of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`, *optional*):
715
+ If passed along, the model uses the previous state in all the blocks (which will give the output for the
716
+ `input_ids` provided as if the model add `state_input_ids + input_ids` as context).
717
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
718
+ Labels for language modeling. Note that the labels **are shifted** inside the model, i.e. you can set
719
+ `labels = input_ids` Indices are selected in `[-100, 0, ..., config.vocab_size]` All labels set to `-100`
720
+ are ignored (masked), the loss is only computed for labels in `[0, ..., config.vocab_size]`
721
+ use_cache (`bool`, *optional*):
722
+ If set to `True`, the last state is returned and can be used to quickly generate the next logits.
723
+ """
724
+ return_dict = return_dict if return_dict is not None else self.config.return_dict
725
+
726
+ rwkv_outputs = self.rwkv(
727
+ input_ids,
728
+ inputs_embeds=inputs_embeds,
729
+ state=state,
730
+ use_cache=use_cache,
731
+ output_attentions=output_attentions,
732
+ output_hidden_states=output_hidden_states,
733
+ return_dict=return_dict,
734
+ )
735
+
736
+ hidden_states = rwkv_outputs[0]
737
+ # Only compute necessary logits, and do not upcast them to float if we are not computing the loss
738
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
739
+ logits = self.head(hidden_states[:, slice_indices, :])
740
+
741
+ loss = None
742
+ if labels is not None:
743
+ loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
744
+
745
+ if not return_dict:
746
+ output = (logits,) + rwkv_outputs[1:]
747
+ return ((loss,) + output) if loss is not None else output
748
+
749
+ return RwkvCausalLMOutput(
750
+ loss=loss,
751
+ logits=logits,
752
+ state=rwkv_outputs.state,
753
+ hidden_states=rwkv_outputs.hidden_states,
754
+ attentions=rwkv_outputs.attentions,
755
+ )
756
+
757
+
758
+ __all__ = ["RwkvForCausalLM", "RwkvModel", "RwkvPreTrainedModel"]