Compare commits

...

320 Commits

Author SHA1 Message Date
05b98392d1 Update
[ghstack-poisoned]
2025-10-29 21:23:29 +08:00
de47db1cfb Update (base update)
[ghstack-poisoned]
2025-10-29 21:23:29 +08:00
5eb5a20f97 Update
[ghstack-poisoned]
2025-10-29 21:02:53 +08:00
31489d30bd Update (base update)
[ghstack-poisoned]
2025-10-29 21:02:53 +08:00
be1e65f502 Update
[ghstack-poisoned]
2025-10-11 21:35:30 +08:00
5aa2b2289a Update (base update)
[ghstack-poisoned]
2025-10-11 21:35:30 +08:00
79a2dbe9ec Update
[ghstack-poisoned]
2025-10-08 22:52:12 +08:00
942125a6b4 Update (base update)
[ghstack-poisoned]
2025-10-08 22:52:12 +08:00
ba819dc881 Update
[ghstack-poisoned]
2025-10-08 22:39:23 +08:00
700b6d22e8 Update (base update)
[ghstack-poisoned]
2025-10-08 22:39:23 +08:00
fa21c89451 Update
[ghstack-poisoned]
2025-09-19 18:03:45 +08:00
7ad880e219 Update (base update)
[ghstack-poisoned]
2025-09-19 18:03:45 +08:00
1be59e9fde Update
[ghstack-poisoned]
2025-09-06 11:34:33 +08:00
f30affbef0 Update (base update)
[ghstack-poisoned]
2025-09-06 11:34:33 +08:00
f42a2f1441 Update
[ghstack-poisoned]
2025-08-17 16:23:37 +08:00
e154a852fd Update (base update)
[ghstack-poisoned]
2025-08-17 16:23:37 +08:00
1d0555100e Update
[ghstack-poisoned]
2025-08-09 02:53:28 +08:00
3e2800dc1c Update (base update)
[ghstack-poisoned]
2025-08-09 02:53:28 +08:00
ad0a47d92b Update
[ghstack-poisoned]
2025-08-09 02:51:18 +08:00
73997578c7 Update (base update)
[ghstack-poisoned]
2025-08-09 02:51:18 +08:00
43fffb8595 Update
[ghstack-poisoned]
2025-07-31 15:19:07 +08:00
2e8442fac4 Update (base update)
[ghstack-poisoned]
2025-07-31 15:19:07 +08:00
bb1ff5a369 Update
[ghstack-poisoned]
2025-07-25 20:00:30 +08:00
77cbd4e043 Update (base update)
[ghstack-poisoned]
2025-07-25 20:00:30 +08:00
a83ce9d5fe Update
[ghstack-poisoned]
2025-07-17 15:02:02 +08:00
c95331cd83 Update (base update)
[ghstack-poisoned]
2025-07-17 15:02:02 +08:00
1efebd5638 Update
[ghstack-poisoned]
2025-07-09 19:01:33 +08:00
a0dbea65e6 Update (base update)
[ghstack-poisoned]
2025-07-09 19:01:33 +08:00
13c9ef51d9 Update
[ghstack-poisoned]
2025-07-03 16:24:22 +08:00
6833d2f254 Update (base update)
[ghstack-poisoned]
2025-07-03 16:24:22 +08:00
94d89dbf93 Update
[ghstack-poisoned]
2025-06-28 20:59:45 +08:00
3f148162d3 Update (base update)
[ghstack-poisoned]
2025-06-28 20:59:45 +08:00
b0caf4fdb6 Update
[ghstack-poisoned]
2025-06-27 21:27:43 +08:00
45f4d0dda5 Update (base update)
[ghstack-poisoned]
2025-06-27 21:27:43 +08:00
54b5c6e74f Update
[ghstack-poisoned]
2025-06-23 22:51:20 +08:00
951ea096b8 Update (base update)
[ghstack-poisoned]
2025-06-23 22:51:20 +08:00
b982c1a717 Update
[ghstack-poisoned]
2025-06-18 23:17:47 +08:00
0afa77db11 Update (base update)
[ghstack-poisoned]
2025-06-18 23:17:47 +08:00
f577b631f8 Update
[ghstack-poisoned]
2025-06-06 19:50:49 +08:00
33e67d1dd1 Update (base update)
[ghstack-poisoned]
2025-06-06 19:50:49 +08:00
029d95db8e Update
[ghstack-poisoned]
2025-05-31 21:59:58 +08:00
6f26bc7b67 Update (base update)
[ghstack-poisoned]
2025-05-31 21:59:58 +08:00
e34d064b52 Update
[ghstack-poisoned]
2025-05-28 20:43:31 +08:00
d88137444d Update (base update)
[ghstack-poisoned]
2025-05-28 20:43:31 +08:00
087c7b2f5f Update
[ghstack-poisoned]
2025-05-16 11:37:31 +08:00
e263e3aa79 Update (base update)
[ghstack-poisoned]
2025-05-16 11:37:31 +08:00
a2bb393c35 Update
[ghstack-poisoned]
2025-05-14 20:35:00 +08:00
f750ebdb21 Update (base update)
[ghstack-poisoned]
2025-05-14 20:35:00 +08:00
4b154faad1 Update
[ghstack-poisoned]
2025-05-08 21:19:06 +08:00
8ef111eb54 Update (base update)
[ghstack-poisoned]
2025-05-08 21:19:06 +08:00
d665e57c3b Update
[ghstack-poisoned]
2025-05-04 02:10:43 +08:00
99b18ec71a Update (base update)
[ghstack-poisoned]
2025-05-03 02:34:22 +08:00
81e6b015d7 Update
[ghstack-poisoned]
2025-05-03 02:34:22 +08:00
e44bdcbd75 Update (base update)
[ghstack-poisoned]
2025-05-03 01:14:43 +08:00
9efa19ccee Update
[ghstack-poisoned]
2025-05-03 01:14:43 +08:00
8ddb577253 Update (base update)
[ghstack-poisoned]
2025-05-03 00:44:59 +08:00
e635263dcd Update
[ghstack-poisoned]
2025-05-03 00:44:59 +08:00
576feb523b Update (base update)
[ghstack-poisoned]
2025-05-03 00:40:33 +08:00
2fc047bd9f Update
[ghstack-poisoned]
2025-05-03 00:40:33 +08:00
745a9d962b Update (base update)
[ghstack-poisoned]
2025-05-02 02:30:02 +08:00
abae549796 Update
[ghstack-poisoned]
2025-05-02 02:30:02 +08:00
141a10e1c7 Update (base update)
[ghstack-poisoned]
2025-05-02 02:25:06 +08:00
7e0f5462b3 Update
[ghstack-poisoned]
2025-05-02 02:25:06 +08:00
c91f575aed Update
[ghstack-poisoned]
2025-05-02 01:44:36 +08:00
f72b55e91a Update
[ghstack-poisoned]
2025-05-02 01:39:05 +08:00
1115e0fc50 Update (base update)
[ghstack-poisoned]
2025-04-26 11:34:38 +08:00
5515da310e Update
[ghstack-poisoned]
2025-04-26 11:34:38 +08:00
643f208d77 Update (base update)
[ghstack-poisoned]
2025-04-23 21:35:45 +08:00
22947d7c07 Update
[ghstack-poisoned]
2025-04-23 21:35:45 +08:00
45a3e195ef Update (base update)
[ghstack-poisoned]
2025-04-15 22:19:47 +08:00
f61beebf00 Update
[ghstack-poisoned]
2025-04-15 22:19:47 +08:00
cf716c9688 Update (base update)
[ghstack-poisoned]
2025-04-15 22:12:30 +08:00
69f80f4784 Update
[ghstack-poisoned]
2025-04-15 22:12:30 +08:00
416b3ace72 Update (base update)
[ghstack-poisoned]
2025-04-15 22:10:40 +08:00
e5b6f6349b Update
[ghstack-poisoned]
2025-04-15 22:10:40 +08:00
7d7c5ae8e6 Update (base update)
[ghstack-poisoned]
2025-04-15 22:03:22 +08:00
183358a9f1 Update
[ghstack-poisoned]
2025-04-15 22:03:22 +08:00
4cdc74b9f7 Update (base update)
[ghstack-poisoned]
2025-04-11 19:04:55 +08:00
a5c5404553 Update
[ghstack-poisoned]
2025-04-11 19:04:55 +08:00
59dca2d82f Update (base update)
[ghstack-poisoned]
2025-04-11 18:35:19 +08:00
2e3b261908 Update
[ghstack-poisoned]
2025-04-11 18:35:19 +08:00
8077299bd2 Update (base update)
[ghstack-poisoned]
2025-04-11 18:27:38 +08:00
197d5b4329 Update
[ghstack-poisoned]
2025-04-11 18:27:38 +08:00
391ac27a26 Update
[ghstack-poisoned]
2025-04-11 18:16:45 +08:00
67c9aea71d Update (base update)
[ghstack-poisoned]
2025-04-11 18:16:44 +08:00
ee326e80e5 Update
[ghstack-poisoned]
2025-04-10 17:25:13 +08:00
690337abef Update (base update)
[ghstack-poisoned]
2025-04-10 17:25:13 +08:00
e9d6c69d39 Update
[ghstack-poisoned]
2025-04-07 22:41:37 +08:00
22427995f6 Update (base update)
[ghstack-poisoned]
2025-04-07 22:41:37 +08:00
c0a2be67c4 Update
[ghstack-poisoned]
2025-04-05 23:26:57 +08:00
afa0b4695f Update (base update)
[ghstack-poisoned]
2025-04-05 23:26:57 +08:00
40df9f673f Update
[ghstack-poisoned]
2025-04-03 23:11:58 +08:00
8673d9897b Update
[ghstack-poisoned]
2025-04-03 22:22:51 +08:00
7b58f15e10 Update (base update)
[ghstack-poisoned]
2025-04-03 21:58:27 +08:00
1d1a757bfe Update
[ghstack-poisoned]
2025-04-03 21:58:27 +08:00
40876a33cd Update (base update)
[ghstack-poisoned]
2025-04-02 00:14:57 +08:00
760acdc5e1 Update
[ghstack-poisoned]
2025-04-02 00:14:57 +08:00
8d98e7acd6 Update (base update)
[ghstack-poisoned]
2025-03-21 00:08:14 +08:00
70a0491b41 Update
[ghstack-poisoned]
2025-03-21 00:08:14 +08:00
df9eb561f4 Update (base update)
[ghstack-poisoned]
2025-03-14 12:47:27 +08:00
dae2fd762e Update
[ghstack-poisoned]
2025-03-14 12:47:27 +08:00
dec95a75ad Update (base update)
[ghstack-poisoned]
2025-03-13 04:41:39 +08:00
b797ea9517 Update
[ghstack-poisoned]
2025-03-13 04:41:39 +08:00
e5d2c8f12f Update (base update)
[ghstack-poisoned]
2025-03-07 18:09:19 +08:00
a9d4c2d592 Update
[ghstack-poisoned]
2025-03-07 18:09:19 +08:00
e2fd435d78 Update (base update)
[ghstack-poisoned]
2025-03-07 03:57:19 +08:00
0fc2587fd0 Update
[ghstack-poisoned]
2025-03-07 03:57:19 +08:00
ca6372ceec Update (base update)
[ghstack-poisoned]
2025-03-07 03:19:27 +08:00
bbe07eb5fc Update
[ghstack-poisoned]
2025-03-07 03:19:27 +08:00
89964801b6 Update (base update)
[ghstack-poisoned]
2025-03-06 21:45:26 +08:00
2c22765284 Update
[ghstack-poisoned]
2025-03-06 21:45:26 +08:00
501add1e2c Update
[ghstack-poisoned]
2025-03-05 20:36:41 +08:00
4b5925ba69 Update
[ghstack-poisoned]
2025-03-05 20:19:46 +08:00
019f8ed4bd Update
[ghstack-poisoned]
2025-03-05 20:14:47 +08:00
17ec427a57 Update
[ghstack-poisoned]
2025-03-05 00:41:45 +08:00
9e093f979b Update
[ghstack-poisoned]
2025-03-04 22:37:23 +08:00
7ebca96122 Update
[ghstack-poisoned]
2025-03-04 19:05:37 +08:00
14a46ede88 Update
[ghstack-poisoned]
2025-03-04 17:15:29 +08:00
ab23e9b30c Update (base update)
[ghstack-poisoned]
2025-03-04 11:43:01 +08:00
311a537282 Update
[ghstack-poisoned]
2025-03-04 11:43:01 +08:00
5a6aec8adb Update
[ghstack-poisoned]
2025-03-04 04:46:16 +08:00
ce179d1444 Update
[ghstack-poisoned]
2025-03-04 03:31:32 +08:00
3ea6e9451f Update
[ghstack-poisoned]
2025-03-04 03:09:36 +08:00
5962bd90c4 Update (base update)
[ghstack-poisoned]
2025-03-04 02:44:31 +08:00
e0fe4fe5bb Update
[ghstack-poisoned]
2025-03-04 02:44:31 +08:00
4d0c4e6896 Update
[ghstack-poisoned]
2025-03-01 21:29:31 +08:00
d517304a1b Update (base update)
[ghstack-poisoned]
2025-03-01 19:17:03 +08:00
fadd417340 Update
[ghstack-poisoned]
2025-03-01 19:17:03 +08:00
1609c4d5f0 Update
[ghstack-poisoned]
2025-03-01 00:37:36 +08:00
21dfc971e5 Update
[ghstack-poisoned]
2025-03-01 00:36:37 +08:00
b71fafd7ee Update
[ghstack-poisoned]
2025-03-01 00:24:07 +08:00
0a505caad6 Update
[ghstack-poisoned]
2025-03-01 00:03:42 +08:00
13d10c6079 Update
[ghstack-poisoned]
2025-02-28 23:53:48 +08:00
5ca27b33d9 Update (base update)
[ghstack-poisoned]
2025-02-28 23:45:39 +08:00
ffc158cb09 Update
[ghstack-poisoned]
2025-02-28 23:45:39 +08:00
c85a982eb6 Update (base update)
[ghstack-poisoned]
2025-02-28 22:39:23 +08:00
76de3696e2 Update
[ghstack-poisoned]
2025-02-28 22:39:23 +08:00
884b510df1 Update
[ghstack-poisoned]
2025-02-28 20:16:11 +08:00
6295224fb9 Update (base update)
[ghstack-poisoned]
2025-02-28 17:02:58 +08:00
a380b160f3 Update
[ghstack-poisoned]
2025-02-28 17:02:58 +08:00
36cc0a6f00 Update (base update)
[ghstack-poisoned]
2025-02-17 16:21:38 +08:00
d686ab3647 Update
[ghstack-poisoned]
2025-02-17 16:21:38 +08:00
b72851c401 Update (base update)
[ghstack-poisoned]
2025-02-17 04:37:46 +08:00
267d766992 Update
[ghstack-poisoned]
2025-02-17 04:37:46 +08:00
f3e9391814 Update
[ghstack-poisoned]
2025-02-09 22:38:01 +08:00
2e1a2bd3c6 Update (base update)
[ghstack-poisoned]
2025-02-09 21:42:43 +08:00
b061f4e769 Update
[ghstack-poisoned]
2025-02-09 21:42:43 +08:00
5bebdf42c7 Update (base update)
[ghstack-poisoned]
2025-02-05 01:33:14 +08:00
f9c861584f Update
[ghstack-poisoned]
2025-02-05 01:33:14 +08:00
ec19497b20 Update (base update)
[ghstack-poisoned]
2025-01-10 20:38:40 +08:00
97e64709fc Update
[ghstack-poisoned]
2025-01-10 20:38:40 +08:00
c2f1967480 Update (base update)
[ghstack-poisoned]
2025-01-10 20:34:19 +08:00
f4b033fdf4 Update
[ghstack-poisoned]
2025-01-10 20:34:19 +08:00
2c25cc7084 Update
[ghstack-poisoned]
2025-01-10 01:12:12 +08:00
2f231de458 Update
[ghstack-poisoned]
2025-01-09 21:11:55 +08:00
fecce12d46 Update (base update)
[ghstack-poisoned]
2025-01-09 20:27:15 +08:00
40ad21a93b Update
[ghstack-poisoned]
2025-01-09 20:27:15 +08:00
928ebf50bc Update
[ghstack-poisoned]
2025-01-09 01:52:52 +08:00
23256b321b Update
[ghstack-poisoned]
2025-01-09 00:33:36 +08:00
ca51b0eec9 Update (base update)
[ghstack-poisoned]
2025-01-08 23:20:58 +08:00
2f912e0c32 Update
[ghstack-poisoned]
2025-01-08 23:20:58 +08:00
788c7b6f8f Update (base update)
[ghstack-poisoned]
2025-01-08 00:32:21 +08:00
7ece048762 Update
[ghstack-poisoned]
2025-01-08 00:32:21 +08:00
3f353cafad Update
[ghstack-poisoned]
2024-12-25 17:35:17 +08:00
5f5c7b48d2 Update
[ghstack-poisoned]
2024-12-25 16:39:12 +08:00
880d3ddfdc Update (base update)
[ghstack-poisoned]
2024-12-25 16:29:49 +08:00
29fba0504d Update
[ghstack-poisoned]
2024-12-25 16:29:49 +08:00
766339d76b Update
[ghstack-poisoned]
2024-12-14 01:17:25 +08:00
40be6bcd1a Update (base update)
[ghstack-poisoned]
2024-12-13 22:34:45 +08:00
601fd57c21 Update
[ghstack-poisoned]
2024-12-13 22:34:45 +08:00
4391105988 Update (base update)
[ghstack-poisoned]
2024-12-09 18:24:42 +08:00
f1ad58bb26 Update
[ghstack-poisoned]
2024-12-09 18:24:42 +08:00
9da99a0dbc Update (base update)
[ghstack-poisoned]
2024-12-07 22:41:07 +08:00
9daa07c7ed Update
[ghstack-poisoned]
2024-12-07 22:41:07 +08:00
fe04454c81 Update (base update)
[ghstack-poisoned]
2024-12-03 02:26:52 +08:00
da1133250a Update
[ghstack-poisoned]
2024-12-03 02:26:52 +08:00
484bd9bf68 Update (base update)
[ghstack-poisoned]
2024-12-03 02:02:27 +08:00
dbe2b61267 Update
[ghstack-poisoned]
2024-12-03 02:02:27 +08:00
e549c572b6 Update (base update)
[ghstack-poisoned]
2024-11-27 20:46:45 +08:00
75956318cb Update
[ghstack-poisoned]
2024-11-27 20:46:45 +08:00
d4cf41755a Update (base update)
[ghstack-poisoned]
2024-11-27 02:54:55 +08:00
b51f674452 Update
[ghstack-poisoned]
2024-11-27 02:54:55 +08:00
770723e55e Update (base update)
[ghstack-poisoned]
2024-11-27 02:43:57 +08:00
a95d0d04b4 Update
[ghstack-poisoned]
2024-11-27 02:43:57 +08:00
506d63fabd Update (base update)
[ghstack-poisoned]
2024-11-23 06:14:15 +08:00
0efaf64271 Update
[ghstack-poisoned]
2024-11-23 06:14:15 +08:00
fa01b64af4 Update (base update)
[ghstack-poisoned]
2024-11-23 02:43:59 +08:00
7a8cdb843a Update
[ghstack-poisoned]
2024-11-23 02:43:59 +08:00
d0b5e8526e Update (base update)
[ghstack-poisoned]
2024-11-21 19:39:15 +08:00
f4e853470f Update
[ghstack-poisoned]
2024-11-21 19:39:15 +08:00
e749f2d8cc Update (base update)
[ghstack-poisoned]
2024-11-21 18:10:06 +08:00
7c8e8466cb Update
[ghstack-poisoned]
2024-11-21 18:10:06 +08:00
d13cbe3fb1 Update (base update)
[ghstack-poisoned]
2024-11-21 17:51:26 +08:00
7ffad9b32c Update
[ghstack-poisoned]
2024-11-21 17:51:26 +08:00
c1f4d4265f Update (base update)
[ghstack-poisoned]
2024-11-21 17:17:41 +08:00
da88b3555e Update
[ghstack-poisoned]
2024-11-21 17:17:41 +08:00
2d0e47b93e Update (base update)
[ghstack-poisoned]
2024-11-21 01:54:53 +08:00
7f99a04424 Update
[ghstack-poisoned]
2024-11-21 01:54:53 +08:00
f6c74aa4e4 Update (base update)
[ghstack-poisoned]
2024-11-21 01:26:43 +08:00
8f83ebec0e Update
[ghstack-poisoned]
2024-11-21 01:26:43 +08:00
bc4a38bd50 Update (base update)
[ghstack-poisoned]
2024-11-20 20:44:53 +08:00
1e5c70d83c Update
[ghstack-poisoned]
2024-11-20 20:44:53 +08:00
3a60712378 Update (base update)
[ghstack-poisoned]
2024-11-20 20:10:49 +08:00
59c9eb5a53 Update
[ghstack-poisoned]
2024-11-20 20:10:49 +08:00
9bf086b49c Update (base update)
[ghstack-poisoned]
2024-11-20 19:33:14 +08:00
40407802c4 Update
[ghstack-poisoned]
2024-11-20 19:33:14 +08:00
3ae028b157 Update (base update)
[ghstack-poisoned]
2024-11-20 18:41:57 +08:00
7df9f45c29 Update
[ghstack-poisoned]
2024-11-20 18:41:57 +08:00
2466732048 Update (base update)
[ghstack-poisoned]
2024-11-20 16:39:23 +08:00
04490d5ba5 Update
[ghstack-poisoned]
2024-11-20 16:39:23 +08:00
b5d8df8fdd Update (base update)
[ghstack-poisoned]
2024-11-18 00:57:01 +08:00
0e0d1712ed Update
[ghstack-poisoned]
2024-11-18 00:57:01 +08:00
eab4e875f5 Update (base update)
[ghstack-poisoned]
2024-11-12 02:26:18 +08:00
abbfd648d7 Update
[ghstack-poisoned]
2024-11-12 02:26:18 +08:00
b4327590cb Update (base update)
[ghstack-poisoned]
2024-11-05 17:55:33 +08:00
e1077e3c67 Update
[ghstack-poisoned]
2024-11-05 17:55:33 +08:00
45a5317dfe Update (base update)
[ghstack-poisoned]
2024-10-30 18:30:34 +08:00
0783f49e36 Update
[ghstack-poisoned]
2024-10-30 18:30:34 +08:00
4fa7d72228 Update (base update)
[ghstack-poisoned]
2024-10-30 13:55:10 +08:00
697256880d Update
[ghstack-poisoned]
2024-10-30 13:55:10 +08:00
4709438fbd Update (base update)
[ghstack-poisoned]
2024-10-30 01:22:36 +08:00
41f79bff88 Update
[ghstack-poisoned]
2024-10-30 01:22:36 +08:00
166b988122 Update (base update)
[ghstack-poisoned]
2024-10-29 23:43:05 +08:00
a7ba175dfd Update
[ghstack-poisoned]
2024-10-29 23:43:05 +08:00
b55011fd0d Update (base update)
[ghstack-poisoned]
2024-10-29 20:26:49 +08:00
75fcd3128d Update
[ghstack-poisoned]
2024-10-29 20:26:49 +08:00
d90e20f550 Update (base update)
[ghstack-poisoned]
2024-10-29 19:39:58 +08:00
a976bb7f42 Update
[ghstack-poisoned]
2024-10-29 19:39:58 +08:00
74e3e51a41 Update (base update)
[ghstack-poisoned]
2024-10-29 19:23:07 +08:00
16e7ce5c87 Update
[ghstack-poisoned]
2024-10-29 19:23:07 +08:00
447d8a8eae Update (base update)
[ghstack-poisoned]
2024-10-29 19:10:45 +08:00
3ee9bf7496 Update
[ghstack-poisoned]
2024-10-29 19:10:45 +08:00
2f4fc7db81 Update (base update)
[ghstack-poisoned]
2024-10-29 18:51:46 +08:00
29f0d14320 Update
[ghstack-poisoned]
2024-10-29 18:51:46 +08:00
6ca5b803c0 Update (base update)
[ghstack-poisoned]
2024-10-26 17:03:25 +08:00
a67ffdf668 Update
[ghstack-poisoned]
2024-10-26 17:03:25 +08:00
fd68bc6638 Update (base update)
[ghstack-poisoned]
2024-10-25 21:18:27 +08:00
0bf16a54e8 Update
[ghstack-poisoned]
2024-10-25 21:18:27 +08:00
67aed45904 Update (base update)
[ghstack-poisoned]
2024-10-17 18:36:20 +08:00
051141b58b Update
[ghstack-poisoned]
2024-10-17 18:36:20 +08:00
14a4b6a5db Update (base update)
[ghstack-poisoned]
2024-10-17 18:13:38 +08:00
1ad1ae6b69 Update
[ghstack-poisoned]
2024-10-17 18:13:38 +08:00
90d56d25fb Update (base update)
[ghstack-poisoned]
2024-10-17 17:32:58 +08:00
b97ff03aeb Update
[ghstack-poisoned]
2024-10-17 17:32:58 +08:00
fdcf208f65 Update (base update)
[ghstack-poisoned]
2024-10-16 23:43:32 +08:00
263a0ac4b5 Update
[ghstack-poisoned]
2024-10-16 23:43:32 +08:00
594bc23aa6 Update (base update)
[ghstack-poisoned]
2024-10-16 22:06:22 +08:00
aea9c80348 Update
[ghstack-poisoned]
2024-10-16 22:06:22 +08:00
4ddd5eb041 Update (base update)
[ghstack-poisoned]
2024-10-16 21:57:51 +08:00
5caefe39b6 Update
[ghstack-poisoned]
2024-10-16 21:57:51 +08:00
abaf3329fc Update (base update)
[ghstack-poisoned]
2024-10-16 21:02:28 +08:00
5f3730ff6d Update
[ghstack-poisoned]
2024-10-16 21:02:28 +08:00
e57d66c6a9 Update (base update)
[ghstack-poisoned]
2024-10-16 20:59:18 +08:00
fcdaf197ee Update
[ghstack-poisoned]
2024-10-16 20:59:18 +08:00
066c7fb037 Update (base update)
[ghstack-poisoned]
2024-10-16 17:12:33 +08:00
2ddea8a158 Update
[ghstack-poisoned]
2024-10-16 17:12:33 +08:00
2645ccb198 Update (base update)
[ghstack-poisoned]
2024-10-16 17:02:20 +08:00
81b174c826 Update
[ghstack-poisoned]
2024-10-16 17:02:20 +08:00
a1a75d3c22 Update (base update)
[ghstack-poisoned]
2024-10-16 16:34:57 +08:00
134d27cf9d Update
[ghstack-poisoned]
2024-10-16 16:34:57 +08:00
cdd86ca04e Update (base update)
[ghstack-poisoned]
2024-10-16 15:46:47 +08:00
c19ca5328a Update
[ghstack-poisoned]
2024-10-16 15:46:47 +08:00
d9b1b717f5 Update (base update)
[ghstack-poisoned]
2024-10-16 14:51:41 +08:00
cecb2f8ded Update
[ghstack-poisoned]
2024-10-16 14:51:41 +08:00
8b12a94edc Update
[ghstack-poisoned]
2024-10-16 14:28:55 +08:00
9e41c11203 Update (base update)
[ghstack-poisoned]
2024-10-16 14:28:54 +08:00
71d3b3b6bd Update
[ghstack-poisoned]
2024-10-16 13:55:15 +08:00
ef2b1d3361 Update (base update)
[ghstack-poisoned]
2024-10-16 13:55:15 +08:00
9920717cb4 Update
[ghstack-poisoned]
2024-10-15 04:30:03 +08:00
99ecfb01c5 Update
[ghstack-poisoned]
2024-10-14 23:00:48 +08:00
2c4092e876 Update
[ghstack-poisoned]
2024-10-14 20:36:27 +08:00
e5ee365a96 Update
[ghstack-poisoned]
2024-10-14 19:01:41 +08:00
3260ab7390 Update
[ghstack-poisoned]
2024-10-14 00:54:05 +08:00
09e0f52037 Update
[ghstack-poisoned]
2024-10-14 00:49:34 +08:00
817f3e7682 Update
[ghstack-poisoned]
2024-10-13 20:16:19 +08:00
442d540fe8 Update
[ghstack-poisoned]
2024-10-13 20:13:55 +08:00
f2c379768f Update (base update)
[ghstack-poisoned]
2024-10-13 19:51:06 +08:00
2009f30b50 Update
[ghstack-poisoned]
2024-10-13 19:51:06 +08:00
f1a2d26341 Update (base update)
[ghstack-poisoned]
2024-10-13 15:01:49 +08:00
6262031ab6 Update
[ghstack-poisoned]
2024-10-13 15:01:49 +08:00
adf0570d87 Update (base update)
[ghstack-poisoned]
2024-10-07 17:57:19 +08:00
368e7275fd Update
[ghstack-poisoned]
2024-10-07 17:57:19 +08:00
e973096b0b Update (base update)
[ghstack-poisoned]
2024-10-07 17:55:11 +08:00
0ee2c92c73 Update
[ghstack-poisoned]
2024-10-07 17:55:11 +08:00
4965702964 Update (base update)
[ghstack-poisoned]
2024-10-07 00:13:30 +08:00
19dc9443e5 Update
[ghstack-poisoned]
2024-10-07 00:13:30 +08:00
5263c1cb1e Update (base update)
[ghstack-poisoned]
2024-10-06 23:10:11 +08:00
ab67952e0f Update
[ghstack-poisoned]
2024-10-06 23:10:11 +08:00
e5099a0afd Update (base update)
[ghstack-poisoned]
2024-10-06 21:26:07 +08:00
f9603a17ed Update
[ghstack-poisoned]
2024-10-06 21:26:07 +08:00
27597f8ae4 Update (base update)
[ghstack-poisoned]
2024-10-06 21:13:47 +08:00
973f82393d Update
[ghstack-poisoned]
2024-10-06 21:13:47 +08:00
5a3b21fd46 Update (base update)
[ghstack-poisoned]
2024-10-06 18:05:08 +08:00
3301607cac Update
[ghstack-poisoned]
2024-10-06 18:05:08 +08:00
33b4f01298 Update (base update)
[ghstack-poisoned]
2024-10-06 16:53:22 +08:00
456e43f4e1 Update
[ghstack-poisoned]
2024-10-06 16:53:22 +08:00
b4f7e43b22 Update (base update)
[ghstack-poisoned]
2024-10-06 15:52:28 +08:00
4e889a372c Update
[ghstack-poisoned]
2024-10-06 15:52:28 +08:00
5e5e6a8d32 Update (base update)
[ghstack-poisoned]
2024-10-06 15:47:09 +08:00
1c55add027 Update
[ghstack-poisoned]
2024-10-06 15:47:09 +08:00
f98bd3af1a Update (base update)
[ghstack-poisoned]
2024-10-06 14:19:55 +08:00
75cf1693aa Update
[ghstack-poisoned]
2024-10-06 14:19:55 +08:00
62bd418e76 Update
[ghstack-poisoned]
2024-10-06 14:00:49 +08:00
58dba16e99 Update (base update)
[ghstack-poisoned]
2024-10-06 13:40:26 +08:00
8faa309c62 Update
[ghstack-poisoned]
2024-10-06 13:40:26 +08:00
ad4ff1b88f Update (base update)
[ghstack-poisoned]
2024-10-06 02:24:41 +08:00
afe4cbcbd5 Update
[ghstack-poisoned]
2024-10-06 02:24:41 +08:00
355d748bd1 Update (base update)
[ghstack-poisoned]
2024-10-06 02:21:58 +08:00
4ae51d3c42 Update
[ghstack-poisoned]
2024-10-06 02:21:58 +08:00
77f3d2d0ae Update (base update)
[ghstack-poisoned]
2024-10-06 02:19:48 +08:00
d98b7610e6 Update
[ghstack-poisoned]
2024-10-06 02:19:48 +08:00
411b2f1d24 Update (base update)
[ghstack-poisoned]
2024-10-06 02:14:42 +08:00
f1f9fe1152 Update
[ghstack-poisoned]
2024-10-06 02:14:42 +08:00
eb4f8e9486 Update (base update)
[ghstack-poisoned]
2024-10-06 01:55:51 +08:00
9b21fd9ef1 Update
[ghstack-poisoned]
2024-10-06 01:55:51 +08:00
93cf5a2f80 Update (base update)
[ghstack-poisoned]
2024-10-05 22:37:53 +08:00
bdb27239fe Update
[ghstack-poisoned]
2024-10-05 22:37:53 +08:00
b8642958d0 Update
[ghstack-poisoned]
2024-10-05 22:31:30 +08:00
3a47c15917 Update (base update)
[ghstack-poisoned]
2024-10-05 22:16:48 +08:00
b69d677726 Update
[ghstack-poisoned]
2024-10-05 22:16:48 +08:00
19 changed files with 438 additions and 124 deletions

View File

@ -183,6 +183,7 @@ include_patterns = [
'benchmarks/instruction_counts/**/*.py',
'tools/**/*.py',
'torchgen/**/*.py',
'torch/utils/pytree/__init__.py',
'torch/utils/_pytree.py',
'torch/utils/_cxx_pytree.py',
'torch/utils/benchmark/utils/common.py',

View File

@ -76,6 +76,7 @@ sparse
storage
torch.testing <testing>
torch.utils <utils>
torch.utils.pytree
torch.utils.benchmark <benchmark_utils>
torch.utils.checkpoint <checkpoint>
torch.utils.cpp_extension <cpp_extension>

View File

@ -0,0 +1,7 @@
torch.utils.pytree
==================
.. currentmodule:: torch.utils.pytree
.. automodule:: torch.utils.pytree
:members:

View File

@ -29,6 +29,7 @@ files =
benchmarks/instruction_counts,
tools,
torch/profiler/_memory_profiler.py,
torch/utils/pytree/__init__.py,
torch/utils/_pytree.py,
torch/utils/_cxx_pytree.py,
torch/utils/benchmark/utils/common.py,

View File

@ -147,8 +147,8 @@ class GraphModule(torch.nn.Module):
t: "f32[10]" = l_x_ + l_y_
trace_point_tensor_spec : torch.utils._pytree.TreeSpec = self.trace_point_tensor_spec
trace_point_tensor_input_spec : torch.utils._pytree.TreeSpec = self.trace_point_tensor_input_spec
trace_point_tensor_spec : torch.utils.pytree.PyTreeSpec = self.trace_point_tensor_spec
trace_point_tensor_input_spec : torch.utils.pytree.PyTreeSpec = self.trace_point_tensor_input_spec
res: "f32[10]" = torch.ops.higher_order.flat_apply(trace_point_tensor_spec, trace_point_tensor_input_spec, l_x_, l_y_, t); trace_point_tensor_spec = trace_point_tensor_input_spec = l_x_ = l_y_ = t = None
return (res,)
""", # NOQA: B950

View File

@ -40,6 +40,7 @@ import torch._inductor.test_case
import torch.onnx.operators
import torch.utils._pytree as python_pytree
import torch.utils.cpp_extension
import torch.utils.pytree as generic_pytree
from torch import Tensor
from torch._C import FileCheck
from torch._dynamo import allow_in_graph
@ -104,6 +105,7 @@ from torch.testing._internal.logging_utils import logs_to_string
pytree_modules = {
"generic": generic_pytree,
"python": python_pytree,
}
if python_pytree._cxx_pytree_dynamo_traceable:

View File

@ -8245,7 +8245,7 @@ graph():
%to : [num_users=1] = call_function[target=operator.getitem](args = (%tree_flatten_spec, 0), kwargs = {})
%sum_1 : [num_users=1] = call_function[target=torch.ops.aten.sum.default](args = (%to,), kwargs = {})
%_spec_1 : [num_users=1] = get_attr[target=_spec_1]
%tree_unflatten : [num_users=1] = call_function[target=torch.utils._pytree.tree_unflatten](args = ((%sum_1,), %_spec_1), kwargs = {})
%tree_unflatten : [num_users=1] = call_function[target=torch.utils.pytree.tree_unflatten](args = ((%sum_1,), %_spec_1), kwargs = {})
return tree_unflatten""",
)

View File

@ -249,11 +249,11 @@ def forward(self, x, y):
_spec_0 = self._spec_0
_spec_1 = self._spec_1
_spec_4 = self._spec_4
tree_flatten = torch.utils._pytree.tree_flatten((x_1, y_1)); x_1 = y_1 = None
tree_flatten = torch.utils.pytree.tree_flatten((x_1, y_1)); x_1 = y_1 = None
getitem = tree_flatten[0]; tree_flatten = None
x = getitem[0]
y = getitem[1]; getitem = None
tree_unflatten_1 = torch.utils._pytree.tree_unflatten([x, y], _spec_1); x = y = _spec_1 = None
tree_unflatten_1 = torch.utils.pytree.tree_unflatten([x, y], _spec_1); x = y = _spec_1 = None
getitem_1 = tree_unflatten_1[0]; tree_unflatten_1 = None
getitem_2 = getitem_1[0]
getitem_3 = getitem_1[1]; getitem_1 = None
@ -261,7 +261,7 @@ def forward(self, x, y):
bar = self.bar(foo); foo = None
tree_flatten_spec_1 = torch.fx._pytree.tree_flatten_spec(bar, _spec_4); bar = _spec_4 = None
getitem_10 = tree_flatten_spec_1[0]; tree_flatten_spec_1 = None
tree_unflatten = torch.utils._pytree.tree_unflatten((getitem_10,), _spec_0); getitem_10 = _spec_0 = None
tree_unflatten = torch.utils.pytree.tree_unflatten((getitem_10,), _spec_0); getitem_10 = _spec_0 = None
return tree_unflatten""",
)

View File

@ -820,12 +820,13 @@ class TestPythonPytree(TestCase):
script = """
import sys
import torch
import torch.utils._pytree
assert "torch.utils.pytree" in sys.modules
assert "torch.utils._pytree" in sys.modules
if "torch.utils._cxx_pytree" in sys.modules:
raise RuntimeError("importing torch.utils._pytree should not import torch.utils._cxx_pytree")
if "optree" in sys.modules:
raise RuntimeError("importing torch.utils._pytree should not import optree")
if not torch.utils.pytree.PYTORCH_USE_CXX_PYTREE:
if "torch.utils._cxx_pytree" in sys.modules:
raise RuntimeError("importing torch.utils._pytree should not import torch.utils._cxx_pytree")
if "optree" in sys.modules:
raise RuntimeError("importing torch.utils._pytree should not import optree")
"""
try:
subprocess.check_output(

View File

@ -1,3 +1,5 @@
# Owner(s): ["module: pytree"]
"""
Python polyfills for torch.utils.pytree
"""
@ -7,7 +9,6 @@ from __future__ import annotations
from collections import deque
from dataclasses import dataclass, field
from typing import Any, TYPE_CHECKING
from typing_extensions import TypeIs
import torch.utils._pytree as python_pytree
from torch.utils._pytree import BUILTIN_TYPES, STANDARD_DICT_TYPES
@ -18,7 +19,7 @@ from ..decorators import substitute_in_graph
if TYPE_CHECKING:
import builtins
from collections.abc import Callable, Iterable, Mapping
from typing_extensions import Self
from typing_extensions import Self, TypeIs
__all__: list[str] = []
@ -346,8 +347,10 @@ if python_pytree._cxx_pytree_dynamo_traceable:
assert callable(self._unflatten_func)
return self._unflatten_func(self._metadata, subtrees)
def _is_pytreespec_instance(obj: Any, /) -> TypeIs[PyTreeSpec]:
return isinstance(obj, PyTreeSpec)
def _is_pytreespec_instance(
obj: Any, /
) -> TypeIs[PyTreeSpec | python_pytree.TreeSpec]:
return isinstance(obj, (PyTreeSpec, python_pytree.TreeSpec))
@substitute_in_graph( # type: ignore[arg-type]
optree.treespec_leaf,
@ -550,7 +553,7 @@ if python_pytree._cxx_pytree_dynamo_traceable:
def tree_unflatten(treespec: PyTreeSpec, leaves: Iterable[Any]) -> PyTree:
if not _is_pytreespec_instance(treespec):
raise TypeError(
f"tree_unflatten(leaves, treespec): Expected `treespec` to be instance of "
f"Expected `treespec` to be an instance of "
f"PyTreeSpec but got item of type {type(treespec)}."
)
return treespec.unflatten(leaves)

View File

@ -3450,6 +3450,7 @@ MOD_INLINELIST = [
"torch.utils._python_dispatch",
"torch.utils._pytree",
"torch.utils.hooks",
"torch.utils.pytree",
]
assert sorted(set(MOD_INLINELIST)) == MOD_INLINELIST
MOD_INLINELIST = set(MOD_INLINELIST)

View File

@ -39,13 +39,13 @@ from torch.utils._pytree import (
_register_pytree_node,
Context,
FlattenFunc,
FromDumpableContextFn,
FromDumpableContextFunc,
GetAttrKey,
KeyPath,
keystr,
MappingKey,
SequenceKey,
ToDumpableContextFn,
ToDumpableContextFunc,
tree_flatten_with_path,
UnflattenFunc,
)
@ -485,8 +485,8 @@ def register_dataclass_as_pytree_node(
unflatten_fn: Optional[UnflattenFunc] = None,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
return_none_fields: bool = False,
) -> None:
assert dataclasses.is_dataclass(cls), (

View File

@ -42,7 +42,7 @@ def _try_remove_connecting_pytrees(curr_module_node: torch.fx.Node) -> None:
%foo : [num_users=1] = call_module[target=foo](args = (%getitem_1, %getitem_2), kwargs = {})
%tree_flatten_spec : [num_users=1] = call_function[target=torch.fx._pytree.tree_flatten_spec](args = (%foo, %_spec_1), kwargs = {})
%getitem_4 : [num_users=1] = call_function[target=operator.getitem](args = (%tree_flatten_spec, 0), kwargs = {})
%tree_unflatten_1 : [num_users=2] = call_function[target=torch.utils._pytree.tree_unflatten](args = ([%getitem_4], %_spec_2), kwargs = {})
%tree_unflatten_1 : [num_users=2] = call_function[target=torch.utils.pytree.tree_unflatten](args = ([%getitem_4], %_spec_2), kwargs = {})
%getitem_5 : [num_users=1] = call_function[target=operator.getitem](args = (%tree_unflatten_1, 0), kwargs = {})
%getitem_7 : [num_users=0] = call_function[target=operator.getitem](args = (%tree_unflatten_1, 1), kwargs = {})
%getitem_6 : [num_users=1] = call_function[target=operator.getitem](args = (%getitem_5, 0), kwargs = {})
@ -293,7 +293,7 @@ def _swap_module_helper(
%y : [num_users=1] = placeholder[target=y]
%_spec_0 : [num_users=1] = get_attr[target=_spec_0]
%tree_unflatten : [num_users=2] = call_function[target=torch.utils._pytree.tree_unflatten](args = ([%x, %y], %_spec_0), kwargs = {})
%tree_unflatten : [num_users=2] = call_function[target=torch.utils.pytree.tree_unflatten](args = ([%x, %y], %_spec_0), kwargs = {})
%getitem : [num_users=2] = call_function[target=operator.getitem](args = (%tree_unflatten, 0), kwargs = {})
%getitem_1 : [num_users=1] = call_function[target=operator.getitem](args = (%getitem, 0), kwargs = {})
%getitem_2 : [num_users=1] = call_function[target=operator.getitem](args = (%getitem, 1), kwargs = {})

View File

@ -11,6 +11,7 @@ from torch.utils import (
data as data,
deterministic as deterministic,
hooks as hooks,
pytree as pytree,
)
from torch.utils.backend_registration import (
generate_methods_for_privateuse1_backend,

View File

@ -1,3 +1,5 @@
# Owner(s): ["module: pytree"]
"""
Contains utility functions for working with nested python data structures.
@ -21,13 +23,21 @@ from typing_extensions import deprecated, Self, TypeAlias, TypeIs
import torch.utils._pytree as python_pytree
from torch.torch_version import TorchVersion as _TorchVersion
from torch.utils._pytree import (
Context,
DumpableContext,
FlattenFunc,
FlattenWithKeysFunc,
FromDumpableContextFunc,
is_namedtuple,
is_namedtuple_class,
is_namedtuple_instance,
is_structseq,
is_structseq_class,
is_structseq_instance,
KeyEntry,
KeyPath,
PyTree,
ToDumpableContextFunc,
UnflattenFunc,
)
@ -51,8 +61,9 @@ __all__ = [
"FlattenFunc",
"UnflattenFunc",
"DumpableContext",
"ToDumpableContextFn",
"FromDumpableContextFn",
"ToDumpableContextFunc",
"FromDumpableContextFunc",
"PyTreeSpec",
"TreeSpec",
"LeafSpec",
"keystr",
@ -99,19 +110,8 @@ S = TypeVar("S")
U = TypeVar("U")
R = TypeVar("R")
TreeSpec: TypeAlias = PyTreeSpec
Context = Any
PyTree = Any
FlattenFunc = Callable[[PyTree], tuple[list[Any], Context]]
UnflattenFunc = Callable[[Iterable[Any], Context], PyTree]
OpTreeUnflattenFunc = Callable[[Context, Iterable[Any]], PyTree]
DumpableContext = Any # Any json dumpable text
ToDumpableContextFn = Callable[[Context], DumpableContext]
FromDumpableContextFn = Callable[[DumpableContext], Context]
KeyPath = tuple[KeyEntry, ...]
FlattenWithKeysFunc = Callable[[PyTree], tuple[list[tuple[KeyEntry, Any]], Any]]
OpTreeUnflattenFunc: TypeAlias = Callable[[Context, Iterable[Any]], PyTree]
def _reverse_args(func: UnflattenFunc) -> OpTreeUnflattenFunc:
@ -128,8 +128,8 @@ def register_pytree_node(
unflatten_fn: UnflattenFunc,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
flatten_with_keys_fn: Optional[FlattenWithKeysFunc] = None,
) -> None:
"""Register a container-like type as pytree node.
@ -196,8 +196,8 @@ def _register_pytree_node(
unflatten_fn: UnflattenFunc,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
) -> None:
"""Register a container-like type as pytree node for the C++ pytree only.
@ -247,8 +247,8 @@ def _private_register_pytree_node(
unflatten_fn: UnflattenFunc,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
) -> None:
"""This is an internal function that is used to register a pytree node type
for the C++ pytree only. End-users should use :func:`register_pytree_node`
@ -265,8 +265,10 @@ def _private_register_pytree_node(
)
def _is_pytreespec_instance(obj: Any, /) -> TypeIs[TreeSpec]:
return isinstance(obj, TreeSpec)
def _is_pytreespec_instance(
obj: Any, /
) -> TypeIs[Union[TreeSpec, python_pytree.TreeSpec]]:
return isinstance(obj, (TreeSpec, python_pytree.TreeSpec))
def treespec_leaf() -> TreeSpec:
@ -972,7 +974,7 @@ def treespec_dumps(treespec: TreeSpec, protocol: Optional[int] = None) -> str:
"""Serialize a treespec to a JSON string."""
if not _is_pytreespec_instance(treespec):
raise TypeError(
f"treespec_dumps(treespec): Expected `treespec` to be instance of "
f"Expected `treespec` to be instance of "
f"PyTreeSpec but got item of type {type(treespec)}."
)
@ -993,16 +995,22 @@ def treespec_loads(serialized: str) -> TreeSpec:
return treespec
class _DummyLeaf:
class _Asterisk(str):
__slots__ = ()
def __new__(cls) -> Self:
return super().__new__(cls, "*")
def __repr__(self) -> str:
return "*"
return "*" # no quotes
_asterisk = _Asterisk()
del _Asterisk
def treespec_pprint(treespec: TreeSpec) -> str:
dummy_tree = tree_unflatten(
[_DummyLeaf() for _ in range(treespec.num_leaves)],
treespec,
)
dummy_tree = tree_unflatten([_asterisk] * treespec.num_leaves, treespec)
return repr(dummy_tree)

View File

@ -1,3 +1,5 @@
# Owner(s): ["module: pytree"]
"""
Contains utility functions for working with nested python data structures.
@ -20,6 +22,7 @@ import functools
import importlib
import importlib.metadata
import json
import sys
import threading
import types
import warnings
@ -36,10 +39,11 @@ from typing import (
Optional,
overload,
Protocol,
TYPE_CHECKING,
TypeVar,
Union,
)
from typing_extensions import deprecated, NamedTuple, Self
from typing_extensions import deprecated, NamedTuple, Self, TypeAlias, TypeIs
from torch.torch_version import TorchVersion as _TorchVersion
@ -50,8 +54,9 @@ __all__ = [
"FlattenFunc",
"UnflattenFunc",
"DumpableContext",
"ToDumpableContextFn",
"FromDumpableContextFn",
"ToDumpableContextFunc",
"FromDumpableContextFunc",
"PyTreeSpec",
"TreeSpec",
"LeafSpec",
"keystr",
@ -117,17 +122,21 @@ class EnumEncoder(json.JSONEncoder):
return cast(str, super().default(obj))
Context = Any
PyTree = Any
FlattenFunc = Callable[[PyTree], tuple[list[Any], Context]]
UnflattenFunc = Callable[[Iterable[Any], Context], PyTree]
DumpableContext = Any # Any json dumpable text
ToDumpableContextFn = Callable[[Context], DumpableContext]
FromDumpableContextFn = Callable[[DumpableContext], Context]
ToStrFunc = Callable[["TreeSpec", list[str]], str]
MaybeFromStrFunc = Callable[[str], Optional[tuple[Any, Context, str]]]
KeyPath = tuple[KeyEntry, ...]
FlattenWithKeysFunc = Callable[[PyTree], tuple[list[tuple[KeyEntry, Any]], Any]]
Context: TypeAlias = Any
PyTree: TypeAlias = Any
FlattenFunc: TypeAlias = Callable[[PyTree], tuple[list[Any], Context]]
UnflattenFunc: TypeAlias = Callable[[Iterable[Any], Context], PyTree]
DumpableContext: TypeAlias = Any # Any json dumpable text
ToDumpableContextFunc: TypeAlias = Callable[[Context], DumpableContext]
FromDumpableContextFunc: TypeAlias = Callable[[DumpableContext], Context]
ToDumpableContextFn: TypeAlias = ToDumpableContextFunc
FromDumpableContextFn: TypeAlias = FromDumpableContextFunc
ToStrFunc: TypeAlias = Callable[["TreeSpec", list[str]], str]
MaybeFromStrFunc: TypeAlias = Callable[[str], Optional[tuple[Any, Context, str]]]
KeyPath: TypeAlias = tuple[KeyEntry, ...]
FlattenWithKeysFunc: TypeAlias = Callable[
[PyTree], tuple[list[tuple[KeyEntry, Any]], Any]
]
# A NodeDef holds two callables:
@ -160,8 +169,8 @@ SUPPORTED_NODES: dict[type[Any], NodeDef] = {}
class _SerializeNodeDef(NamedTuple):
typ: type[Any]
serialized_type_name: str
to_dumpable_context: Optional[ToDumpableContextFn]
from_dumpable_context: Optional[FromDumpableContextFn]
to_dumpable_context: Optional[ToDumpableContextFunc]
from_dumpable_context: Optional[FromDumpableContextFunc]
SUPPORTED_SERIALIZED_TYPES: dict[type[Any], _SerializeNodeDef] = {}
@ -198,8 +207,8 @@ def register_pytree_node(
unflatten_fn: UnflattenFunc,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
flatten_with_keys_fn: Optional[FlattenWithKeysFunc] = None,
) -> None:
"""Register a container-like type as pytree node.
@ -522,8 +531,8 @@ def _register_pytree_node(
maybe_from_str_fn: Optional[MaybeFromStrFunc] = None, # deprecated
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
flatten_with_keys_fn: Optional[FlattenWithKeysFunc] = None,
) -> None:
"""Register a container-like type as pytree node for the Python pytree only.
@ -589,8 +598,8 @@ def _private_register_pytree_node(
unflatten_fn: UnflattenFunc,
*,
serialized_type_name: Optional[str] = None,
to_dumpable_context: Optional[ToDumpableContextFn] = None,
from_dumpable_context: Optional[FromDumpableContextFn] = None,
to_dumpable_context: Optional[ToDumpableContextFunc] = None,
from_dumpable_context: Optional[FromDumpableContextFunc] = None,
flatten_with_keys_fn: Optional[FlattenWithKeysFunc] = None,
) -> None:
"""This is an internal function that is used to register a pytree node type
@ -1072,7 +1081,9 @@ def _is_leaf(tree: PyTree, is_leaf: Optional[Callable[[PyTree], bool]] = None) -
# children_specs: specs for each child of the root Node
# num_leaves: the number of leaves
@dataclasses.dataclass(init=True, frozen=True, eq=True, repr=False)
class TreeSpec:
class PyTreeSpec:
"""Representing the structure of the pytree."""
type: Any
_context: Context
_children: list[Self]
@ -1140,6 +1151,7 @@ class TreeSpec:
return self._children
def is_leaf(self) -> bool:
"""Test whether the treespec represents a leaf."""
return self.num_nodes == 1 and self.num_leaves == 1
def children(self) -> list[Self]:
@ -1149,12 +1161,14 @@ class TreeSpec:
return self._children[index]
def flatten_up_to(self, tree: PyTree) -> list[PyTree]:
def helper(treespec: TreeSpec, tree: PyTree, subtrees: list[PyTree]) -> None:
"""Flatten the subtrees in ``tree`` up to the structure of this treespec and return a list of subtrees."""
def helper(treespec: TreeSpec, node: PyTree, subtrees: list[PyTree]) -> None:
if treespec.is_leaf():
subtrees.append(tree)
subtrees.append(node)
return
node_type = _get_node_type(tree)
node_type = _get_node_type(node)
if treespec.type not in BUILTIN_TYPES:
# Always require custom node types to match exactly
if node_type != treespec.type:
@ -1163,7 +1177,7 @@ class TreeSpec:
f"expected {treespec.type!r}, but got {node_type!r}.",
)
flatten_fn = SUPPORTED_NODES[node_type].flatten_fn
children, context = flatten_fn(tree)
children, context = flatten_fn(node)
if len(children) != treespec.num_children:
raise ValueError(
f"Node arity mismatch; "
@ -1185,10 +1199,10 @@ class TreeSpec:
f"Node type mismatch; "
f"expected {treespec.type!r}, but got {node_type!r}.",
)
if len(tree) != treespec.num_children:
if len(node) != treespec.num_children:
raise ValueError(
f"Node arity mismatch; "
f"expected {treespec.num_children}, but got {len(tree)}.",
f"expected {treespec.num_children}, but got {len(node)}.",
)
if both_standard_dict:
@ -1200,7 +1214,7 @@ class TreeSpec:
else treespec._context[1]
)
expected_keys = dict_context
got_key_set = set(tree)
got_key_set = set(node)
expected_key_set = set(expected_keys)
if got_key_set != expected_key_set:
missing_keys = expected_key_set.difference(got_key_set)
@ -1211,11 +1225,11 @@ class TreeSpec:
if extra_keys:
message += f"; extra key(s): {extra_keys}"
raise ValueError(f"Node keys mismatch{message}.")
children = [tree[key] for key in expected_keys]
children = [node[key] for key in expected_keys]
else:
# node_type is treespec.type
flatten_fn = SUPPORTED_NODES[node_type].flatten_fn
children, context = flatten_fn(tree)
children, context = flatten_fn(node)
if (
node_type is not deque # ignore mismatch of `maxlen` for deque
) and context != treespec._context:
@ -1232,6 +1246,7 @@ class TreeSpec:
return subtrees
def unflatten(self, leaves: Iterable[Any]) -> PyTree:
"""Reconstruct a pytree from the leaves."""
if not isinstance(leaves, (list, tuple)):
leaves = list(leaves)
if len(leaves) != self.num_leaves:
@ -1277,6 +1292,9 @@ class TreeSpec:
return hash((node_type, hashable_context, tuple(self._children)))
TreeSpec: TypeAlias = PyTreeSpec
# NOTE: subclassing a dataclass is subtle. In order to enable reasoning about
# this class with `dataclasses.fields`, etc., while having a simplified
# constructor that takes no argument, we wrap with `dataclass(init=True, ...)`
@ -1336,6 +1354,39 @@ def treespec_dict(
return TreeSpec(dict, list(dct.keys()), list(dct.values()))
if TYPE_CHECKING:
import torch.utils._cxx_pytree as cxx
def _is_pytreespec_instance(obj: Any) -> TypeIs[Union[TreeSpec, "cxx.TreeSpec"]]:
if isinstance(obj, TreeSpec):
return True
if "torch.utils._cxx_pytree" in sys.modules:
# The C++ pytree module is not always available, so we check if it is loaded.
# If the C++ pytree module is loaded, we can check if the treespec
# is an instance of the C++ TreeSpec class.
from torch.utils._cxx_pytree import TreeSpec as CxxTreeSpec
if isinstance(obj, CxxTreeSpec):
return True
return False
def _ensure_python_treespec_instance(
treespec: Union[TreeSpec, "cxx.TreeSpec"],
) -> TreeSpec:
if isinstance(treespec, TreeSpec):
return treespec
if not _is_pytreespec_instance(treespec):
raise TypeError(
f"Expected `treespec` to be an instance of "
f"PyTreeSpec but got item of type {type(treespec)}."
)
dummy_tree = treespec.unflatten([0] * treespec.num_leaves)
return tree_structure(dummy_tree)
def tree_flatten(
tree: PyTree,
is_leaf: Optional[Callable[[PyTree], bool]] = None,
@ -1366,10 +1417,10 @@ def tree_unflatten(leaves: Iterable[Any], treespec: TreeSpec) -> PyTree:
"""Given a list of values and a TreeSpec, builds a pytree.
This is the inverse operation of `tree_flatten`.
"""
if not isinstance(treespec, TreeSpec):
if not _is_pytreespec_instance(treespec):
raise TypeError(
f"tree_unflatten(leaves, treespec): Expected `treespec` to be "
f"instance of TreeSpec but got item of type {type(treespec)}.",
f"Expected `treespec` to be an instance of "
f"PyTreeSpec but got item of type {type(treespec)}."
)
return treespec.unflatten(leaves)
@ -1800,34 +1851,30 @@ def _broadcast_to_and_flatten(
treespec: TreeSpec,
is_leaf: Optional[Callable[[PyTree], bool]] = None,
) -> Optional[list[Any]]:
if not isinstance(treespec, TreeSpec):
raise AssertionError("treespec must be a TreeSpec")
def broadcast_prefix(
prefix_tree: PyTree,
full_tree: PyTree,
is_leaf: Optional[Callable[[PyTree], bool]] = None,
) -> list[Any]:
result: list[Any] = []
if tree_is_leaf(tree, is_leaf=is_leaf):
return [tree] * treespec.num_leaves
if treespec.is_leaf():
def add_leaves(x: Any, subtree: PyTree) -> None:
subtreespec = tree_structure(subtree, is_leaf=is_leaf)
result.extend([x] * subtreespec.num_leaves)
tree_map_(
add_leaves,
prefix_tree,
full_tree,
is_leaf=is_leaf,
)
return result
full_tree = tree_unflatten([0] * treespec.num_leaves, treespec)
try:
return broadcast_prefix(tree, full_tree, is_leaf=is_leaf)
except ValueError:
return None
node_type = _get_node_type(tree)
if node_type != treespec.type:
return None
flatten_fn = SUPPORTED_NODES[node_type].flatten_fn
child_pytrees, context = flatten_fn(tree)
# Check if the Node is different from the spec
if len(child_pytrees) != treespec.num_children or context != treespec._context:
return None
# Recursively flatten the children
result: list[Any] = []
for child, child_spec in zip(child_pytrees, treespec._children):
flat = _broadcast_to_and_flatten(child, child_spec, is_leaf=is_leaf)
if flat is not None:
result += flat
else:
return None
return result
@dataclasses.dataclass
@ -1941,11 +1988,7 @@ _SUPPORTED_PROTOCOLS[1] = _ProtocolFn(_treespec_to_json, _json_to_treespec)
def treespec_dumps(treespec: TreeSpec, protocol: Optional[int] = None) -> str:
if not isinstance(treespec, TreeSpec):
raise TypeError(
f"treespec_dumps(treespec, protocol): Expected `treespec` to be instance of "
f"TreeSpec but got item of type {type(treespec)}.",
)
treespec = _ensure_python_treespec_instance(treespec)
if protocol is None:
protocol = DEFAULT_TREESPEC_SERIALIZATION_PROTOCOL
@ -1974,16 +2017,22 @@ def treespec_loads(serialized: str) -> TreeSpec:
)
class _DummyLeaf:
class _Asterisk(str):
__slots__ = ()
def __new__(cls) -> Self:
return super().__new__(cls, "*")
def __repr__(self) -> str:
return "*"
return "*" # no quotes
_asterisk = _Asterisk()
del _Asterisk
def treespec_pprint(treespec: TreeSpec) -> str:
dummy_tree = tree_unflatten(
[_DummyLeaf() for _ in range(treespec.num_leaves)],
treespec,
)
dummy_tree = tree_unflatten([_asterisk] * treespec.num_leaves, treespec)
return repr(dummy_tree)

View File

@ -0,0 +1,216 @@
# Owner(s): ["module: pytree"]
"""
Contains utility functions for working with nested python data structures.
A *pytree* is Python nested data structure. It is a tree in the sense that
nodes are Python collections (e.g., list, tuple, dict) and the leaves are
Python values. Furthermore, a pytree should not contain reference cycles.
pytrees are useful for working with nested collections of Tensors. For example,
one can use `tree_map` to map a function over all Tensors inside some nested
collection of Tensors and `tree_leaves` to get a flat list of all Tensors
inside some nested collection. pytrees are helpful for implementing nested
collection support for PyTorch APIs.
"""
import os as _os
import sys as _sys
from typing import Any as _Any, Optional as _Optional
import torch.utils._pytree as python
from torch.utils._exposed_in import exposed_in as _exposed_in
from torch.utils._pytree import ( # these type aliases are identical in both implementations
FlattenFunc,
FlattenWithKeysFunc,
FromDumpableContextFunc,
PyTree,
ToDumpableContextFunc,
UnflattenFunc,
)
__all__ = [
"PyTreeSpec",
"register_pytree_node",
"tree_flatten",
"tree_unflatten",
"tree_iter",
"tree_leaves",
"tree_structure",
"tree_map",
"tree_map_",
"tree_map_only",
"tree_map_only_",
"tree_all",
"tree_any",
"tree_all_only",
"tree_any_only",
"treespec_pprint",
"is_namedtuple",
"is_namedtuple_class",
"is_namedtuple_instance",
"is_structseq",
"is_structseq_class",
"is_structseq_instance",
]
# NB: Once this variable is read from the environment, the underlying pytree
# implementation is frozen. It cannot be swapped to another at runtime.
PYTORCH_USE_CXX_PYTREE: bool = _os.getenv("PYTORCH_USE_CXX_PYTREE", "0") not in {
"0",
"",
}
if PYTORCH_USE_CXX_PYTREE:
import torch.utils._cxx_pytree as cxx # noqa: F401
if not python._cxx_pytree_dynamo_traceable:
raise ImportError(
"Cannot import package `optree`. "
"Please install `optree` via `python -m pip install --upgrade optree`. "
"Or set the environment variable `PYTORCH_USE_CXX_PYTREE=0`."
)
_sys.modules[f"{__name__}.cxx"] = _sys.modules.get("torch.utils._cxx_pytree") # type: ignore[assignment]
if not PYTORCH_USE_CXX_PYTREE:
from torch.utils._pytree import (
is_namedtuple,
is_namedtuple_class,
is_namedtuple_instance,
is_structseq,
is_structseq_class,
is_structseq_instance,
PyTreeSpec,
register_pytree_node as _register_pytree_node,
tree_all,
tree_all_only,
tree_any,
tree_any_only,
tree_flatten,
tree_iter,
tree_leaves,
tree_map,
tree_map_,
tree_map_only,
tree_map_only_,
tree_structure,
tree_unflatten,
treespec_pprint,
)
PyTreeSpec = _exposed_in(__name__)(PyTreeSpec) # type: ignore[misc]
else:
from torch.utils._cxx_pytree import ( # type: ignore[assignment,no-redef]
is_namedtuple,
is_namedtuple_class,
is_namedtuple_instance,
is_structseq,
is_structseq_class,
is_structseq_instance,
PyTreeSpec,
register_pytree_node as _register_pytree_node,
tree_all,
tree_all_only,
tree_any,
tree_any_only,
tree_flatten,
tree_iter,
tree_leaves,
tree_map,
tree_map_,
tree_map_only,
tree_map_only_,
tree_structure,
tree_unflatten,
treespec_pprint,
)
# Change `__module__` of reexported public APIs to 'torch.utils.pytree'
__func_names = frozenset(
{
"tree_all",
"tree_all_only",
"tree_any",
"tree_any_only",
"tree_flatten",
"tree_iter",
"tree_leaves",
"tree_map",
"tree_map_",
"tree_map_only",
"tree_map_only_",
"tree_structure",
"tree_unflatten",
"treespec_pprint",
"is_namedtuple",
"is_namedtuple_class",
"is_namedtuple_instance",
"is_structseq",
"is_structseq_class",
"is_structseq_instance",
}
)
globals().update(
{
name: _exposed_in(__name__)(member)
for name, member in globals().items()
if name in __func_names
}
)
del __func_names, _exposed_in
def register_pytree_node(
cls: type[_Any],
/,
# intentionally use `*_func` over `*_fn` to match annotations
flatten_func: FlattenFunc,
unflatten_func: UnflattenFunc,
) -> None:
"""Register a container-like type as pytree node.
Args:
cls (type): A Python type to treat as an internal pytree node.
flatten_func (callable): A function to be used during flattening, taking an instance of
``cls`` and returning a pair, with (1) an iterable for the children to be flattened
recursively, and (2) some hashable auxiliary data to be stored in the treespec and to be
passed to the ``unflatten_func``.
unflatten_func (callable): A function taking two arguments: the unflattened children, and
the auxiliary data that was returned by ``flatten_func`` and stored in the treespec.
The function should return an instance of ``cls``.
Example::
>>> # xdoctest: +SKIP
>>> from collections import UserList
... class MyList(UserList): pass
>>> # Registry a Python type with lambda functions
... register_pytree_node(
... MyList,
... lambda lst: (list(lst), None),
... lambda children, _: MyList(children),
... )
"""
_register_pytree_node(
cls,
flatten_func,
unflatten_func,
)
def __getattr__(name: str) -> _Any:
if name == "cxx":
# Lazy import
import torch.utils._cxx_pytree as cxx # noqa: F811
_sys.modules[f"{__name__}.cxx"] = globals()["cxx"] = cxx
return cxx
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

View File

@ -0,0 +1,8 @@
# Owner(s): ["module: pytree"]
from .._cxx_pytree import * # noqa: F403
from .._cxx_pytree import (
__all__ as __all__,
_broadcast_to_and_flatten as _broadcast_to_and_flatten,
KeyPath as KeyPath,
)

View File

@ -0,0 +1,15 @@
# Owner(s): ["module: pytree"]
from .._pytree import * # noqa: F403
from .._pytree import (
__all__ as __all__,
_broadcast_to_and_flatten as _broadcast_to_and_flatten,
arg_tree_leaves as arg_tree_leaves,
BUILTIN_TYPES as BUILTIN_TYPES,
GetAttrKey as GetAttrKey,
KeyEntry as KeyEntry,
KeyPath as KeyPath,
MappingKey as MappingKey,
SequenceKey as SequenceKey,
SUPPORTED_NODES as SUPPORTED_NODES,
)