polyfile-weave 0.5.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of polyfile-weave might be problematic. Click here for more details.

Files changed (585) hide show
  1. polyfile/__init__.py +15 -0
  2. polyfile/__main__.py +394 -0
  3. polyfile/arithmetic.py +27 -0
  4. polyfile/ast.py +114 -0
  5. polyfile/debugger.py +1039 -0
  6. polyfile/expressions.py +346 -0
  7. polyfile/fileutils.py +343 -0
  8. polyfile/html.py +135 -0
  9. polyfile/http/__init__.py +1 -0
  10. polyfile/http/defacto.py +37 -0
  11. polyfile/http/deprecated.py +51 -0
  12. polyfile/http/experimental.py +67 -0
  13. polyfile/http/http_11.py +548 -0
  14. polyfile/http/matcher.py +37 -0
  15. polyfile/http/structured_headers.py +48 -0
  16. polyfile/iterators.py +72 -0
  17. polyfile/jpeg.py +24 -0
  18. polyfile/kaitai/__init__.py +0 -0
  19. polyfile/kaitai/compiler.py +156 -0
  20. polyfile/kaitai/parser.py +312 -0
  21. polyfile/kaitai/parsers/__init__.py +0 -0
  22. polyfile/kaitai/parsers/aix_utmp.py +116 -0
  23. polyfile/kaitai/parsers/allegro_dat.py +367 -0
  24. polyfile/kaitai/parsers/andes_firmware.py +64 -0
  25. polyfile/kaitai/parsers/android_bootldr_asus.py +105 -0
  26. polyfile/kaitai/parsers/android_bootldr_huawei.py +181 -0
  27. polyfile/kaitai/parsers/android_bootldr_qcom.py +217 -0
  28. polyfile/kaitai/parsers/android_dto.py +138 -0
  29. polyfile/kaitai/parsers/android_img.py +319 -0
  30. polyfile/kaitai/parsers/android_nanoapp_header.py +83 -0
  31. polyfile/kaitai/parsers/android_opengl_shaders_cache.py +151 -0
  32. polyfile/kaitai/parsers/android_sparse.py +237 -0
  33. polyfile/kaitai/parsers/android_super.py +401 -0
  34. polyfile/kaitai/parsers/apm_partition_table.py +196 -0
  35. polyfile/kaitai/parsers/apple_single_double.py +180 -0
  36. polyfile/kaitai/parsers/asn1_der.py +235 -0
  37. polyfile/kaitai/parsers/au.py +138 -0
  38. polyfile/kaitai/parsers/avantes_roh60.py +112 -0
  39. polyfile/kaitai/parsers/avi.py +296 -0
  40. polyfile/kaitai/parsers/bcd.py +111 -0
  41. polyfile/kaitai/parsers/bitcoin_transaction.py +210 -0
  42. polyfile/kaitai/parsers/blender_blend.py +334 -0
  43. polyfile/kaitai/parsers/bmp.py +780 -0
  44. polyfile/kaitai/parsers/bson.py +411 -0
  45. polyfile/kaitai/parsers/btrfs_stream.py +318 -0
  46. polyfile/kaitai/parsers/bytes_with_io.py +27 -0
  47. polyfile/kaitai/parsers/chrome_pak.py +194 -0
  48. polyfile/kaitai/parsers/code_6502.py +456 -0
  49. polyfile/kaitai/parsers/compressed_resource.py +217 -0
  50. polyfile/kaitai/parsers/cpio_old_le.py +154 -0
  51. polyfile/kaitai/parsers/cramfs.py +344 -0
  52. polyfile/kaitai/parsers/creative_voice_file.py +342 -0
  53. polyfile/kaitai/parsers/dbf.py +274 -0
  54. polyfile/kaitai/parsers/dcmp_0.py +664 -0
  55. polyfile/kaitai/parsers/dcmp_1.py +422 -0
  56. polyfile/kaitai/parsers/dcmp_2.py +312 -0
  57. polyfile/kaitai/parsers/dcmp_variable_length_integer.py +66 -0
  58. polyfile/kaitai/parsers/dex.py +1086 -0
  59. polyfile/kaitai/parsers/dicom.py +4370 -0
  60. polyfile/kaitai/parsers/dime_message.py +201 -0
  61. polyfile/kaitai/parsers/dns_packet.py +569 -0
  62. polyfile/kaitai/parsers/doom_wad.py +654 -0
  63. polyfile/kaitai/parsers/dos_datetime.py +191 -0
  64. polyfile/kaitai/parsers/dos_mz.py +172 -0
  65. polyfile/kaitai/parsers/ds_store.py +513 -0
  66. polyfile/kaitai/parsers/dtb.py +310 -0
  67. polyfile/kaitai/parsers/dune_2_pak.py +126 -0
  68. polyfile/kaitai/parsers/edid.py +472 -0
  69. polyfile/kaitai/parsers/efivar_signature_list.py +331 -0
  70. polyfile/kaitai/parsers/elf.py +2482 -0
  71. polyfile/kaitai/parsers/ethernet_frame.py +114 -0
  72. polyfile/kaitai/parsers/exif.py +723 -0
  73. polyfile/kaitai/parsers/ext2.py +537 -0
  74. polyfile/kaitai/parsers/fallout2_dat.py +187 -0
  75. polyfile/kaitai/parsers/fallout_dat.py +156 -0
  76. polyfile/kaitai/parsers/fasttracker_xm_module.py +558 -0
  77. polyfile/kaitai/parsers/ftl_dat.py +90 -0
  78. polyfile/kaitai/parsers/genmidi_op2.py +161 -0
  79. polyfile/kaitai/parsers/gettext_mo.py +541 -0
  80. polyfile/kaitai/parsers/gif.py +492 -0
  81. polyfile/kaitai/parsers/gimp_brush.py +244 -0
  82. polyfile/kaitai/parsers/glibc_utmp.py +114 -0
  83. polyfile/kaitai/parsers/gltf_binary.py +132 -0
  84. polyfile/kaitai/parsers/google_protobuf.py +151 -0
  85. polyfile/kaitai/parsers/gpt_partition_table.py +175 -0
  86. polyfile/kaitai/parsers/gran_turismo_vol.py +140 -0
  87. polyfile/kaitai/parsers/grub2_font.py +337 -0
  88. polyfile/kaitai/parsers/gzip.py +232 -0
  89. polyfile/kaitai/parsers/hashcat_restore.py +60 -0
  90. polyfile/kaitai/parsers/hccap.py +111 -0
  91. polyfile/kaitai/parsers/hccapx.py +103 -0
  92. polyfile/kaitai/parsers/heaps_pak.py +177 -0
  93. polyfile/kaitai/parsers/heroes_of_might_and_magic_agg.py +116 -0
  94. polyfile/kaitai/parsers/heroes_of_might_and_magic_bmp.py +34 -0
  95. polyfile/kaitai/parsers/icmp_packet.py +136 -0
  96. polyfile/kaitai/parsers/ico.py +129 -0
  97. polyfile/kaitai/parsers/id3v1_1.py +220 -0
  98. polyfile/kaitai/parsers/id3v2_3.py +324 -0
  99. polyfile/kaitai/parsers/id3v2_4.py +423 -0
  100. polyfile/kaitai/parsers/ines.py +282 -0
  101. polyfile/kaitai/parsers/ipv4_packet.py +158 -0
  102. polyfile/kaitai/parsers/ipv6_packet.py +55 -0
  103. polyfile/kaitai/parsers/iso9660.py +544 -0
  104. polyfile/kaitai/parsers/java_class.py +1113 -0
  105. polyfile/kaitai/parsers/jpeg.py +361 -0
  106. polyfile/kaitai/parsers/luks.py +149 -0
  107. polyfile/kaitai/parsers/lzh.py +165 -0
  108. polyfile/kaitai/parsers/mac_os_resource_snd.py +493 -0
  109. polyfile/kaitai/parsers/mach_o.py +3033 -0
  110. polyfile/kaitai/parsers/mach_o_fat.py +92 -0
  111. polyfile/kaitai/parsers/magicavoxel_vox.py +391 -0
  112. polyfile/kaitai/parsers/manifest.json +1 -0
  113. polyfile/kaitai/parsers/mbr_partition_table.py +119 -0
  114. polyfile/kaitai/parsers/mcap.py +1015 -0
  115. polyfile/kaitai/parsers/microsoft_cfb.py +293 -0
  116. polyfile/kaitai/parsers/microsoft_network_monitor_v2.py +309 -0
  117. polyfile/kaitai/parsers/microsoft_pe.py +765 -0
  118. polyfile/kaitai/parsers/mifare_classic.py +706 -0
  119. polyfile/kaitai/parsers/minecraft_nbt.py +449 -0
  120. polyfile/kaitai/parsers/monomakh_sapr_chg.py +69 -0
  121. polyfile/kaitai/parsers/mozilla_mar.py +239 -0
  122. polyfile/kaitai/parsers/mp4.py +333 -0
  123. polyfile/kaitai/parsers/msgpack.py +467 -0
  124. polyfile/kaitai/parsers/nitf.py +1189 -0
  125. polyfile/kaitai/parsers/nt_mdt_pal.py +155 -0
  126. polyfile/kaitai/parsers/ogg.py +118 -0
  127. polyfile/kaitai/parsers/openpgp_message.py +993 -0
  128. polyfile/kaitai/parsers/packet_ppi.py +515 -0
  129. polyfile/kaitai/parsers/pcap.py +344 -0
  130. polyfile/kaitai/parsers/pcf_font.py +506 -0
  131. polyfile/kaitai/parsers/pcx.py +195 -0
  132. polyfile/kaitai/parsers/pcx_dcx.py +79 -0
  133. polyfile/kaitai/parsers/phar_without_stub.py +399 -0
  134. polyfile/kaitai/parsers/php_serialized_value.py +505 -0
  135. polyfile/kaitai/parsers/png.py +721 -0
  136. polyfile/kaitai/parsers/protocol_body.py +260 -0
  137. polyfile/kaitai/parsers/psx_tim.py +104 -0
  138. polyfile/kaitai/parsers/python_pickle.py +718 -0
  139. polyfile/kaitai/parsers/python_pyc_27.py +510 -0
  140. polyfile/kaitai/parsers/quake_mdl.py +441 -0
  141. polyfile/kaitai/parsers/quake_pak.py +112 -0
  142. polyfile/kaitai/parsers/quicktime_mov.py +634 -0
  143. polyfile/kaitai/parsers/rar.py +265 -0
  144. polyfile/kaitai/parsers/regf.py +569 -0
  145. polyfile/kaitai/parsers/renderware_binary_stream.py +877 -0
  146. polyfile/kaitai/parsers/resource_fork.py +611 -0
  147. polyfile/kaitai/parsers/respack.py +57 -0
  148. polyfile/kaitai/parsers/riff.py +409 -0
  149. polyfile/kaitai/parsers/rpm.py +964 -0
  150. polyfile/kaitai/parsers/rtcp_payload.py +579 -0
  151. polyfile/kaitai/parsers/rtp_packet.py +150 -0
  152. polyfile/kaitai/parsers/rtpdump.py +115 -0
  153. polyfile/kaitai/parsers/ruby_marshal.py +423 -0
  154. polyfile/kaitai/parsers/s3m.py +493 -0
  155. polyfile/kaitai/parsers/saints_row_2_vpp_pc.py +254 -0
  156. polyfile/kaitai/parsers/shapefile_index.py +174 -0
  157. polyfile/kaitai/parsers/shapefile_main.py +893 -0
  158. polyfile/kaitai/parsers/some_ip.py +209 -0
  159. polyfile/kaitai/parsers/some_ip_container.py +37 -0
  160. polyfile/kaitai/parsers/some_ip_sd.py +86 -0
  161. polyfile/kaitai/parsers/some_ip_sd_entries.py +160 -0
  162. polyfile/kaitai/parsers/some_ip_sd_options.py +374 -0
  163. polyfile/kaitai/parsers/specpr.py +404 -0
  164. polyfile/kaitai/parsers/sqlite3.py +472 -0
  165. polyfile/kaitai/parsers/ssh_public_key.py +252 -0
  166. polyfile/kaitai/parsers/standard_midi_file.py +390 -0
  167. polyfile/kaitai/parsers/stl.py +111 -0
  168. polyfile/kaitai/parsers/sudoers_ts.py +201 -0
  169. polyfile/kaitai/parsers/swf.py +406 -0
  170. polyfile/kaitai/parsers/systemd_journal.py +361 -0
  171. polyfile/kaitai/parsers/tcp_segment.py +57 -0
  172. polyfile/kaitai/parsers/tga.py +213 -0
  173. polyfile/kaitai/parsers/tls_client_hello.py +293 -0
  174. polyfile/kaitai/parsers/tr_dos_image.py +322 -0
  175. polyfile/kaitai/parsers/tsm.py +198 -0
  176. polyfile/kaitai/parsers/ttf.py +1847 -0
  177. polyfile/kaitai/parsers/udp_datagram.py +42 -0
  178. polyfile/kaitai/parsers/uefi_te.py +236 -0
  179. polyfile/kaitai/parsers/uimage.py +198 -0
  180. polyfile/kaitai/parsers/utf8_string.py +137 -0
  181. polyfile/kaitai/parsers/vfat.py +410 -0
  182. polyfile/kaitai/parsers/vlq_base128_be.py +104 -0
  183. polyfile/kaitai/parsers/vlq_base128_le.py +129 -0
  184. polyfile/kaitai/parsers/vmware_vmdk.py +167 -0
  185. polyfile/kaitai/parsers/vp8_ivf.py +112 -0
  186. polyfile/kaitai/parsers/warcraft_2_pud.py +423 -0
  187. polyfile/kaitai/parsers/wav.py +1014 -0
  188. polyfile/kaitai/parsers/websocket.py +167 -0
  189. polyfile/kaitai/parsers/windows_evt_log.py +304 -0
  190. polyfile/kaitai/parsers/windows_lnk_file.py +467 -0
  191. polyfile/kaitai/parsers/windows_minidump.py +575 -0
  192. polyfile/kaitai/parsers/windows_resource_file.py +243 -0
  193. polyfile/kaitai/parsers/windows_shell_items.py +190 -0
  194. polyfile/kaitai/parsers/windows_systemtime.py +52 -0
  195. polyfile/kaitai/parsers/wmf.py +502 -0
  196. polyfile/kaitai/parsers/xar.py +181 -0
  197. polyfile/kaitai/parsers/xwd.py +189 -0
  198. polyfile/kaitai/parsers/zip.py +685 -0
  199. polyfile/kaitai/parsers/zisofs.py +158 -0
  200. polyfile/kaitai/parsers/zx_spectrum_tap.py +184 -0
  201. polyfile/kaitaimatcher.py +113 -0
  202. polyfile/languagematcher.py +217 -0
  203. polyfile/logger.py +135 -0
  204. polyfile/magic.py +2983 -0
  205. polyfile/magic_defs/COPYING +29 -0
  206. polyfile/magic_defs/__init__.py +0 -0
  207. polyfile/magic_defs/acorn +102 -0
  208. polyfile/magic_defs/adi +13 -0
  209. polyfile/magic_defs/adventure +122 -0
  210. polyfile/magic_defs/aes +29 -0
  211. polyfile/magic_defs/algol68 +35 -0
  212. polyfile/magic_defs/allegro +9 -0
  213. polyfile/magic_defs/alliant +18 -0
  214. polyfile/magic_defs/alpha +32 -0
  215. polyfile/magic_defs/amanda +12 -0
  216. polyfile/magic_defs/amigaos +218 -0
  217. polyfile/magic_defs/android +259 -0
  218. polyfile/magic_defs/animation +1197 -0
  219. polyfile/magic_defs/aout +46 -0
  220. polyfile/magic_defs/apache +28 -0
  221. polyfile/magic_defs/apl +7 -0
  222. polyfile/magic_defs/apple +773 -0
  223. polyfile/magic_defs/application +7 -0
  224. polyfile/magic_defs/applix +13 -0
  225. polyfile/magic_defs/apt +52 -0
  226. polyfile/magic_defs/archive +2586 -0
  227. polyfile/magic_defs/aria +38 -0
  228. polyfile/magic_defs/arm +50 -0
  229. polyfile/magic_defs/asf +132 -0
  230. polyfile/magic_defs/assembler +18 -0
  231. polyfile/magic_defs/asterix +18 -0
  232. polyfile/magic_defs/att3b +41 -0
  233. polyfile/magic_defs/audio +1291 -0
  234. polyfile/magic_defs/avm +33 -0
  235. polyfile/magic_defs/basis +18 -0
  236. polyfile/magic_defs/beetle +7 -0
  237. polyfile/magic_defs/ber +65 -0
  238. polyfile/magic_defs/bflt +14 -0
  239. polyfile/magic_defs/bhl +10 -0
  240. polyfile/magic_defs/bioinformatics +178 -0
  241. polyfile/magic_defs/biosig +154 -0
  242. polyfile/magic_defs/blackberry +8 -0
  243. polyfile/magic_defs/blcr +25 -0
  244. polyfile/magic_defs/blender +50 -0
  245. polyfile/magic_defs/blit +24 -0
  246. polyfile/magic_defs/bm +10 -0
  247. polyfile/magic_defs/bout +11 -0
  248. polyfile/magic_defs/bsdi +33 -0
  249. polyfile/magic_defs/bsi +10 -0
  250. polyfile/magic_defs/btsnoop +13 -0
  251. polyfile/magic_defs/burp +7 -0
  252. polyfile/magic_defs/bytecode +41 -0
  253. polyfile/magic_defs/c-lang +110 -0
  254. polyfile/magic_defs/c64 +531 -0
  255. polyfile/magic_defs/cad +437 -0
  256. polyfile/magic_defs/cafebabe +107 -0
  257. polyfile/magic_defs/cbor +21 -0
  258. polyfile/magic_defs/ccf +14 -0
  259. polyfile/magic_defs/cddb +12 -0
  260. polyfile/magic_defs/chord +15 -0
  261. polyfile/magic_defs/cisco +12 -0
  262. polyfile/magic_defs/citrus +12 -0
  263. polyfile/magic_defs/clarion +27 -0
  264. polyfile/magic_defs/claris +48 -0
  265. polyfile/magic_defs/clipper +65 -0
  266. polyfile/magic_defs/clojure +30 -0
  267. polyfile/magic_defs/coff +98 -0
  268. polyfile/magic_defs/commands +201 -0
  269. polyfile/magic_defs/communications +22 -0
  270. polyfile/magic_defs/compress +461 -0
  271. polyfile/magic_defs/console +1213 -0
  272. polyfile/magic_defs/convex +69 -0
  273. polyfile/magic_defs/coverage +91 -0
  274. polyfile/magic_defs/cracklib +14 -0
  275. polyfile/magic_defs/crypto +31 -0
  276. polyfile/magic_defs/csv +8 -0
  277. polyfile/magic_defs/ctags +6 -0
  278. polyfile/magic_defs/ctf +23 -0
  279. polyfile/magic_defs/cubemap +8 -0
  280. polyfile/magic_defs/cups +56 -0
  281. polyfile/magic_defs/dact +11 -0
  282. polyfile/magic_defs/database +886 -0
  283. polyfile/magic_defs/dataone +47 -0
  284. polyfile/magic_defs/dbpf +15 -0
  285. polyfile/magic_defs/der +146 -0
  286. polyfile/magic_defs/diamond +12 -0
  287. polyfile/magic_defs/dif +33 -0
  288. polyfile/magic_defs/diff +41 -0
  289. polyfile/magic_defs/digital +59 -0
  290. polyfile/magic_defs/dolby +69 -0
  291. polyfile/magic_defs/dsf +25 -0
  292. polyfile/magic_defs/dump +96 -0
  293. polyfile/magic_defs/dwarfs +45 -0
  294. polyfile/magic_defs/dyadic +61 -0
  295. polyfile/magic_defs/ebml +8 -0
  296. polyfile/magic_defs/edid +11 -0
  297. polyfile/magic_defs/editors +43 -0
  298. polyfile/magic_defs/efi +15 -0
  299. polyfile/magic_defs/elf +379 -0
  300. polyfile/magic_defs/encore +22 -0
  301. polyfile/magic_defs/epoc +62 -0
  302. polyfile/magic_defs/erlang +21 -0
  303. polyfile/magic_defs/espressif +57 -0
  304. polyfile/magic_defs/esri +28 -0
  305. polyfile/magic_defs/etf +33 -0
  306. polyfile/magic_defs/fcs +9 -0
  307. polyfile/magic_defs/filesystems +2694 -0
  308. polyfile/magic_defs/finger +16 -0
  309. polyfile/magic_defs/firmware +133 -0
  310. polyfile/magic_defs/flash +62 -0
  311. polyfile/magic_defs/flif +36 -0
  312. polyfile/magic_defs/fonts +449 -0
  313. polyfile/magic_defs/forth +82 -0
  314. polyfile/magic_defs/fortran +9 -0
  315. polyfile/magic_defs/frame +62 -0
  316. polyfile/magic_defs/freebsd +164 -0
  317. polyfile/magic_defs/fsav +128 -0
  318. polyfile/magic_defs/fusecompress +12 -0
  319. polyfile/magic_defs/games +696 -0
  320. polyfile/magic_defs/gcc +17 -0
  321. polyfile/magic_defs/gconv +10 -0
  322. polyfile/magic_defs/gentoo +85 -0
  323. polyfile/magic_defs/geo +166 -0
  324. polyfile/magic_defs/geos +20 -0
  325. polyfile/magic_defs/gimp +77 -0
  326. polyfile/magic_defs/git +13 -0
  327. polyfile/magic_defs/glibc +21 -0
  328. polyfile/magic_defs/gnome +59 -0
  329. polyfile/magic_defs/gnu +173 -0
  330. polyfile/magic_defs/gnumeric +8 -0
  331. polyfile/magic_defs/gpt +240 -0
  332. polyfile/magic_defs/gpu +28 -0
  333. polyfile/magic_defs/grace +21 -0
  334. polyfile/magic_defs/graphviz +12 -0
  335. polyfile/magic_defs/gringotts +48 -0
  336. polyfile/magic_defs/guile +13 -0
  337. polyfile/magic_defs/hardware +12 -0
  338. polyfile/magic_defs/hitachi-sh +30 -0
  339. polyfile/magic_defs/hp +433 -0
  340. polyfile/magic_defs/human68k +26 -0
  341. polyfile/magic_defs/ibm370 +52 -0
  342. polyfile/magic_defs/ibm6000 +35 -0
  343. polyfile/magic_defs/icc +214 -0
  344. polyfile/magic_defs/iff +80 -0
  345. polyfile/magic_defs/images +4210 -0
  346. polyfile/magic_defs/inform +9 -0
  347. polyfile/magic_defs/intel +310 -0
  348. polyfile/magic_defs/interleaf +9 -0
  349. polyfile/magic_defs/island +10 -0
  350. polyfile/magic_defs/ispell +63 -0
  351. polyfile/magic_defs/isz +15 -0
  352. polyfile/magic_defs/java +52 -0
  353. polyfile/magic_defs/javascript +171 -0
  354. polyfile/magic_defs/jpeg +252 -0
  355. polyfile/magic_defs/json +8 -0
  356. polyfile/magic_defs/karma +9 -0
  357. polyfile/magic_defs/kde +11 -0
  358. polyfile/magic_defs/keepass +20 -0
  359. polyfile/magic_defs/kerberos +45 -0
  360. polyfile/magic_defs/kicad +85 -0
  361. polyfile/magic_defs/kml +34 -0
  362. polyfile/magic_defs/lammps +64 -0
  363. polyfile/magic_defs/lecter +6 -0
  364. polyfile/magic_defs/lex +12 -0
  365. polyfile/magic_defs/lif +50 -0
  366. polyfile/magic_defs/linux +557 -0
  367. polyfile/magic_defs/lisp +78 -0
  368. polyfile/magic_defs/llvm +22 -0
  369. polyfile/magic_defs/locoscript +12 -0
  370. polyfile/magic_defs/lua +31 -0
  371. polyfile/magic_defs/luks +126 -0
  372. polyfile/magic_defs/m4 +11 -0
  373. polyfile/magic_defs/mach +303 -0
  374. polyfile/magic_defs/macintosh +505 -0
  375. polyfile/magic_defs/macos +7 -0
  376. polyfile/magic_defs/magic +10 -0
  377. polyfile/magic_defs/magic.mgc +0 -0
  378. polyfile/magic_defs/mail.news +132 -0
  379. polyfile/magic_defs/make +21 -0
  380. polyfile/magic_defs/map +413 -0
  381. polyfile/magic_defs/maple +109 -0
  382. polyfile/magic_defs/marc21 +30 -0
  383. polyfile/magic_defs/mathcad +8 -0
  384. polyfile/magic_defs/mathematica +188 -0
  385. polyfile/magic_defs/matroska +17 -0
  386. polyfile/magic_defs/mcrypt +52 -0
  387. polyfile/magic_defs/measure +44 -0
  388. polyfile/magic_defs/mercurial +13 -0
  389. polyfile/magic_defs/metastore +8 -0
  390. polyfile/magic_defs/meteorological +53 -0
  391. polyfile/magic_defs/microfocus +21 -0
  392. polyfile/magic_defs/mime +9 -0
  393. polyfile/magic_defs/mips +120 -0
  394. polyfile/magic_defs/mirage +8 -0
  395. polyfile/magic_defs/misctools +140 -0
  396. polyfile/magic_defs/mkid +11 -0
  397. polyfile/magic_defs/mlssa +8 -0
  398. polyfile/magic_defs/mmdf +6 -0
  399. polyfile/magic_defs/modem +92 -0
  400. polyfile/magic_defs/modulefile +9 -0
  401. polyfile/magic_defs/motorola +71 -0
  402. polyfile/magic_defs/mozilla +37 -0
  403. polyfile/magic_defs/msdos +2304 -0
  404. polyfile/magic_defs/msooxml +68 -0
  405. polyfile/magic_defs/msvc +222 -0
  406. polyfile/magic_defs/msx +309 -0
  407. polyfile/magic_defs/mup +24 -0
  408. polyfile/magic_defs/music +17 -0
  409. polyfile/magic_defs/nasa +7 -0
  410. polyfile/magic_defs/natinst +24 -0
  411. polyfile/magic_defs/ncr +49 -0
  412. polyfile/magic_defs/neko +12 -0
  413. polyfile/magic_defs/netbsd +251 -0
  414. polyfile/magic_defs/netscape +26 -0
  415. polyfile/magic_defs/netware +11 -0
  416. polyfile/magic_defs/news +13 -0
  417. polyfile/magic_defs/nifty +202 -0
  418. polyfile/magic_defs/nim-lang +29 -0
  419. polyfile/magic_defs/nitpicker +14 -0
  420. polyfile/magic_defs/numpy +9 -0
  421. polyfile/magic_defs/oasis +12 -0
  422. polyfile/magic_defs/ocaml +14 -0
  423. polyfile/magic_defs/octave +6 -0
  424. polyfile/magic_defs/ole2compounddocs +760 -0
  425. polyfile/magic_defs/olf +98 -0
  426. polyfile/magic_defs/openfst +17 -0
  427. polyfile/magic_defs/opentimestamps +16 -0
  428. polyfile/magic_defs/oric +16 -0
  429. polyfile/magic_defs/os2 +186 -0
  430. polyfile/magic_defs/os400 +39 -0
  431. polyfile/magic_defs/os9 +80 -0
  432. polyfile/magic_defs/osf1 +10 -0
  433. polyfile/magic_defs/palm +156 -0
  434. polyfile/magic_defs/parix +13 -0
  435. polyfile/magic_defs/parrot +22 -0
  436. polyfile/magic_defs/pascal +39 -0
  437. polyfile/magic_defs/pbf +11 -0
  438. polyfile/magic_defs/pbm +8 -0
  439. polyfile/magic_defs/pc88 +24 -0
  440. polyfile/magic_defs/pc98 +77 -0
  441. polyfile/magic_defs/pci_ids +116 -0
  442. polyfile/magic_defs/pcjr +8 -0
  443. polyfile/magic_defs/pdf +51 -0
  444. polyfile/magic_defs/pdp +42 -0
  445. polyfile/magic_defs/perl +100 -0
  446. polyfile/magic_defs/pgf +52 -0
  447. polyfile/magic_defs/pgp +581 -0
  448. polyfile/magic_defs/pgp-binary-keys +388 -0
  449. polyfile/magic_defs/pkgadd +7 -0
  450. polyfile/magic_defs/plan9 +25 -0
  451. polyfile/magic_defs/playdate +57 -0
  452. polyfile/magic_defs/plus5 +18 -0
  453. polyfile/magic_defs/pmem +46 -0
  454. polyfile/magic_defs/polyfile_zip +5 -0
  455. polyfile/magic_defs/polyml +23 -0
  456. polyfile/magic_defs/printer +269 -0
  457. polyfile/magic_defs/project +10 -0
  458. polyfile/magic_defs/psdbms +14 -0
  459. polyfile/magic_defs/psl +14 -0
  460. polyfile/magic_defs/pulsar +13 -0
  461. polyfile/magic_defs/puzzle +17 -0
  462. polyfile/magic_defs/pwsafe +14 -0
  463. polyfile/magic_defs/pyramid +12 -0
  464. polyfile/magic_defs/python +305 -0
  465. polyfile/magic_defs/qt +30 -0
  466. polyfile/magic_defs/revision +66 -0
  467. polyfile/magic_defs/riff +840 -0
  468. polyfile/magic_defs/rinex +44 -0
  469. polyfile/magic_defs/ringdove +45 -0
  470. polyfile/magic_defs/rpi +52 -0
  471. polyfile/magic_defs/rpm +45 -0
  472. polyfile/magic_defs/rpmsg +7 -0
  473. polyfile/magic_defs/rst +11 -0
  474. polyfile/magic_defs/rtf +94 -0
  475. polyfile/magic_defs/ruby +55 -0
  476. polyfile/magic_defs/rust +21 -0
  477. polyfile/magic_defs/sc +7 -0
  478. polyfile/magic_defs/sccs +24 -0
  479. polyfile/magic_defs/scientific +144 -0
  480. polyfile/magic_defs/securitycerts +6 -0
  481. polyfile/magic_defs/selinux +24 -0
  482. polyfile/magic_defs/sendmail +37 -0
  483. polyfile/magic_defs/sequent +42 -0
  484. polyfile/magic_defs/sereal +35 -0
  485. polyfile/magic_defs/sgi +144 -0
  486. polyfile/magic_defs/sgml +161 -0
  487. polyfile/magic_defs/sharc +23 -0
  488. polyfile/magic_defs/sinclair +40 -0
  489. polyfile/magic_defs/sisu +18 -0
  490. polyfile/magic_defs/sketch +6 -0
  491. polyfile/magic_defs/smalltalk +25 -0
  492. polyfile/magic_defs/smile +34 -0
  493. polyfile/magic_defs/sniffer +482 -0
  494. polyfile/magic_defs/softquad +40 -0
  495. polyfile/magic_defs/sosi +40 -0
  496. polyfile/magic_defs/spec +21 -0
  497. polyfile/magic_defs/spectrum +184 -0
  498. polyfile/magic_defs/sql +288 -0
  499. polyfile/magic_defs/ssh +39 -0
  500. polyfile/magic_defs/ssl +20 -0
  501. polyfile/magic_defs/statistics +45 -0
  502. polyfile/magic_defs/subtitle +38 -0
  503. polyfile/magic_defs/sun +141 -0
  504. polyfile/magic_defs/svf +5 -0
  505. polyfile/magic_defs/sylk +36 -0
  506. polyfile/magic_defs/symbos +42 -0
  507. polyfile/magic_defs/sysex +429 -0
  508. polyfile/magic_defs/tcl +29 -0
  509. polyfile/magic_defs/teapot +6 -0
  510. polyfile/magic_defs/terminfo +63 -0
  511. polyfile/magic_defs/tex +141 -0
  512. polyfile/magic_defs/tgif +7 -0
  513. polyfile/magic_defs/ti-8x +239 -0
  514. polyfile/magic_defs/timezone +42 -0
  515. polyfile/magic_defs/tplink +95 -0
  516. polyfile/magic_defs/troff +38 -0
  517. polyfile/magic_defs/tuxedo +8 -0
  518. polyfile/magic_defs/typeset +8 -0
  519. polyfile/magic_defs/uf2 +72 -0
  520. polyfile/magic_defs/unicode +15 -0
  521. polyfile/magic_defs/unisig +12 -0
  522. polyfile/magic_defs/unknown +34 -0
  523. polyfile/magic_defs/usd +21 -0
  524. polyfile/magic_defs/uterus +16 -0
  525. polyfile/magic_defs/uuencode +28 -0
  526. polyfile/magic_defs/vacuum-cleaner +54 -0
  527. polyfile/magic_defs/varied.out +46 -0
  528. polyfile/magic_defs/varied.script +21 -0
  529. polyfile/magic_defs/vax +32 -0
  530. polyfile/magic_defs/vicar +17 -0
  531. polyfile/magic_defs/virtual +307 -0
  532. polyfile/magic_defs/virtutech +12 -0
  533. polyfile/magic_defs/visx +32 -0
  534. polyfile/magic_defs/vms +30 -0
  535. polyfile/magic_defs/vmware +6 -0
  536. polyfile/magic_defs/vorbis +155 -0
  537. polyfile/magic_defs/vxl +14 -0
  538. polyfile/magic_defs/warc +16 -0
  539. polyfile/magic_defs/weak +16 -0
  540. polyfile/magic_defs/web +18 -0
  541. polyfile/magic_defs/webassembly +17 -0
  542. polyfile/magic_defs/windows +1811 -0
  543. polyfile/magic_defs/wireless +7 -0
  544. polyfile/magic_defs/wordprocessors +630 -0
  545. polyfile/magic_defs/wsdl +23 -0
  546. polyfile/magic_defs/x68000 +25 -0
  547. polyfile/magic_defs/xdelta +13 -0
  548. polyfile/magic_defs/xenix +106 -0
  549. polyfile/magic_defs/xilinx +58 -0
  550. polyfile/magic_defs/xo65 +37 -0
  551. polyfile/magic_defs/xwindows +43 -0
  552. polyfile/magic_defs/yara +17 -0
  553. polyfile/magic_defs/zfs +96 -0
  554. polyfile/magic_defs/zilog +12 -0
  555. polyfile/magic_defs/zip +126 -0
  556. polyfile/magic_defs/zyxel +17 -0
  557. polyfile/nes.py +144 -0
  558. polyfile/nitf.py +15 -0
  559. polyfile/pdf.py +1264 -0
  560. polyfile/pickles.py +45 -0
  561. polyfile/polyfile.py +409 -0
  562. polyfile/profiling.py +115 -0
  563. polyfile/repl.py +624 -0
  564. polyfile/search.py +310 -0
  565. polyfile/serialization.py +323 -0
  566. polyfile/structmatcher.py +46 -0
  567. polyfile/structs.py +281 -0
  568. polyfile/templates/download.js +162 -0
  569. polyfile/templates/hexdump.css +268 -0
  570. polyfile/templates/hexdump.js +756 -0
  571. polyfile/templates/jquery-3.4.1.min.js +2 -0
  572. polyfile/templates/template.html +119 -0
  573. polyfile/wildcards.py +62 -0
  574. polyfile/zipmatcher.py +183 -0
  575. polyfile_weave-0.5.5.dist-info/METADATA +173 -0
  576. polyfile_weave-0.5.5.dist-info/RECORD +585 -0
  577. polyfile_weave-0.5.5.dist-info/WHEEL +5 -0
  578. polyfile_weave-0.5.5.dist-info/entry_points.txt +2 -0
  579. polyfile_weave-0.5.5.dist-info/licenses/LICENSE +202 -0
  580. polyfile_weave-0.5.5.dist-info/top_level.txt +2 -0
  581. polymerge/__init__.py +1 -0
  582. polymerge/__main__.py +296 -0
  583. polymerge/cfg.py +127 -0
  584. polymerge/polymerge.py +227 -0
  585. polymerge/polytracker.py +190 -0
polyfile/repl.py ADDED
@@ -0,0 +1,624 @@
1
+ import atexit
2
+ from abc import ABC, abstractmethod
3
+ from enum import Enum
4
+ from functools import partial, wraps
5
+ from io import StringIO
6
+ import os
7
+ from pathlib import Path
8
+ import sys
9
+ import traceback
10
+ from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Type, TypeVar, Union
11
+
12
+ from .fileutils import make_stream, Streamable
13
+ from .profiling import Unprofiled
14
+
15
+ if os.name == "posix":
16
+ import readline
17
+ else:
18
+ import pyreadline3 as readline
19
+
20
+ from .logger import getStatusLogger
21
+
22
+ log = getStatusLogger("polyfile")
23
+
24
+ HISTORY_PATH = Path.home() / ".polyfile_history"
25
+
26
+ T = TypeVar("T")
27
+
28
+
29
+ class ANSIColor(Enum):
30
+ BLACK = 30
31
+ RED = 31
32
+ GREEN = 32
33
+ YELLOW = 33
34
+ BLUE = 34
35
+ MAGENTA = 35
36
+ CYAN = 36
37
+ WHITE = 37
38
+
39
+ def to_code(self) -> str:
40
+ return f"\u001b[{self.value}m"
41
+
42
+
43
+ def string_escape(data: Union[bytes, int]) -> str:
44
+ if not isinstance(data, int):
45
+ return "".join(string_escape(d) for d in data)
46
+ elif data == ord('\n'):
47
+ return "\\n"
48
+ elif data == ord('\t'):
49
+ return "\\t"
50
+ elif data == ord('\r'):
51
+ return "\\r"
52
+ elif data == 0:
53
+ return "\\0"
54
+ elif data == ord('\\'):
55
+ return "\\\\"
56
+ elif 32 <= data <= 126:
57
+ return chr(data)
58
+ else:
59
+ return f"\\x{data:02X}"
60
+
61
+
62
+ class ANSIWriter:
63
+ def __init__(self, use_ansi: bool = True, escape_for_readline: bool = False):
64
+ self.use_ansi: bool = use_ansi
65
+ self.escape_for_readline: bool = escape_for_readline
66
+ self.data = StringIO()
67
+
68
+ @staticmethod
69
+ def format(
70
+ message: Any, bold: bool = False, dim: bool = False, color: Optional[ANSIColor] = None,
71
+ escape_for_readline: bool = False
72
+ ) -> str:
73
+ prefixes: List[str] = []
74
+ if bold and not dim:
75
+ prefixes.append("\u001b[1m")
76
+ elif dim and not bold:
77
+ prefixes.append("\u001b[2m")
78
+ if color is not None:
79
+ prefixes.append(color.to_code())
80
+ if prefixes:
81
+ if escape_for_readline:
82
+ message = f"\001{''.join(prefixes)}\002{message!s}\001\u001b[0m\002"
83
+ else:
84
+ message = f"{''.join(prefixes)}{message!s}\u001b[0m"
85
+ else:
86
+ message = str(message)
87
+ return message
88
+
89
+ def write(self, message: Any, bold: bool = False, dim: bool = False, color: Optional[ANSIColor] = None,
90
+ escape_for_readline: Optional[bool] = None) -> str:
91
+ if self.use_ansi:
92
+ if escape_for_readline is None:
93
+ escape_for_readline = self.escape_for_readline
94
+ self.data.write(self.format(message=message, bold=bold, dim=dim, color=color,
95
+ escape_for_readline=escape_for_readline))
96
+ else:
97
+ self.data.write(str(message))
98
+
99
+ def write_context(self, file: Streamable, offset: int, context_bytes: int = 32, num_bytes: int = 1,
100
+ indent: str = "", max_num_bytes: Optional[int] = 80):
101
+ ellipsis = ""
102
+ if max_num_bytes is not None and num_bytes > max_num_bytes:
103
+ ellipsis = "⋯"
104
+ num_bytes = max_num_bytes - 1
105
+ file = make_stream(file)
106
+ bytes_before = min(offset, context_bytes)
107
+ context_before = string_escape(file[offset - bytes_before:offset].content)
108
+ current_byte = string_escape(file[offset:offset + num_bytes].content)
109
+ context_after = string_escape(file[offset + num_bytes:offset + num_bytes + context_bytes].content)
110
+ self.write(indent)
111
+ self.write(context_before)
112
+ self.write(f"{current_byte}", bold=True)
113
+ self.write(ellipsis, dim=True)
114
+ self.write(context_after)
115
+ self.write("\n")
116
+ self.write(indent)
117
+ self.write(f"{' ' * len(context_before)}")
118
+ self.write(f"{'^' * max(len(current_byte), 1)}", bold=True)
119
+ if ellipsis:
120
+ self.write("^", dim=True)
121
+ self.write(f"{' ' * len(context_after)}\n")
122
+
123
+ def __str__(self):
124
+ return self.data.getvalue()
125
+
126
+
127
+ class CommandInfo:
128
+ def __init__(self, name: str, help: str, aliases: Iterable[str], allows_abbreviation: bool = False,
129
+ completer: Optional[Callable[["Command", str, int, int], List[str]]] = None):
130
+ self.name: str = name
131
+ self.help: str = help
132
+ self.aliases: List[str] = list(aliases)
133
+ self.allows_abbreviation: bool = allows_abbreviation
134
+ self.completer: Optional[Callable[["Command", str, int, int], List[str]]] = completer
135
+
136
+
137
+ class Command(ABC):
138
+ def __init__(self, repl: "REPL", name: str, allows_abbreviation: bool = False, aliases: Iterable[str] = ()):
139
+ self.repl: REPL = repl
140
+ self.name: str = name
141
+ self.allows_abbreviation: bool = allows_abbreviation
142
+ self.aliases: Set[str] = set(aliases)
143
+
144
+ @abstractmethod
145
+ def usage(self) -> str:
146
+ raise NotImplementedError()
147
+
148
+ @abstractmethod
149
+ def run(self, arguments: str):
150
+ raise NotImplementedError()
151
+
152
+ def complete(self, args: str, begin_idx: int, end_idx: int) -> List[str]:
153
+ return []
154
+
155
+ def __hash__(self):
156
+ return hash(self.name)
157
+
158
+ def __eq__(self, other):
159
+ return isinstance(other, Command) and other.name == self.name
160
+
161
+ @classmethod
162
+ def wrap(cls: T, function: Callable[["REPL", str], Any], info: CommandInfo) -> T:
163
+ class WrappedCommand(cls):
164
+ def __init__(self, repl: "REPL"):
165
+ super().__init__(
166
+ repl, name=info.name, allows_abbreviation=info.allows_abbreviation, aliases=info.aliases
167
+ )
168
+
169
+ def usage(self) -> str:
170
+ return info.help
171
+
172
+ def run(self, arguments: str):
173
+ return function(self.repl, arguments)
174
+
175
+ def complete(self, args: str, begin_idx: int, end_idx: int) -> List[str]:
176
+ if info.completer is None:
177
+ return []
178
+ else:
179
+ return info.completer(self, args, begin_idx, end_idx)
180
+
181
+ return WrappedCommand
182
+
183
+
184
+ class ExitREPL(Exception):
185
+ pass
186
+
187
+
188
+ def _write_history(repl: "REPL"):
189
+ repl.store_history()
190
+
191
+
192
+ def command(help: str, name: str = "", aliases: Iterable[str] = (), allows_abbreviation: bool = False,
193
+ completer: Optional[Callable[["Command", str, int, int], List[str]]] = None):
194
+ def wrapper(func):
195
+ if not name:
196
+ func_name = func.__name__
197
+ else:
198
+ func_name = name
199
+ setattr(func, "command_info", CommandInfo(
200
+ name=func_name, help=help, aliases=aliases, allows_abbreviation=allows_abbreviation, completer=completer
201
+ ))
202
+ return func
203
+
204
+ return wrapper
205
+
206
+
207
+ def completer(for_command: Union[str, "Command"]):
208
+ def wrapper(func: Callable[["REPL", str, int, int], List[str]]):
209
+ setattr(func, "completer_for", for_command)
210
+ return func
211
+
212
+ return wrapper
213
+
214
+
215
+ def arg_completer(for_command: Union[str, "Command"]):
216
+ def transformer(func: Callable[["REPL", int, str, Tuple[str, ...]], List[str]]):
217
+ @completer(for_command=for_command)
218
+ @wraps(func)
219
+ def wrapper(repl: "REPL", *args, **kwargs):
220
+ if kwargs or args and isinstance(args[0], int):
221
+ # chances are the caller is trying to call using the original function signature
222
+ try:
223
+ return func(repl, *args, **kwargs)
224
+ except TypeError:
225
+ # we were wrong! (probably)
226
+ pass
227
+ if kwargs:
228
+ raise TypeError(f"{func!r} cannot be called with keyword arguments")
229
+ try:
230
+ arguments, begin_idx, end_idx, *remainder = args
231
+ except ValueError:
232
+ raise TypeError(f"{func!r} was expected to have been called with exactly three arguments; got {args!r}")
233
+ if remainder:
234
+ raise TypeError(f"{func!r} received unexpected positional arguments {remainder!r}")
235
+ num_arguments = 0
236
+ last_token_start = 0
237
+ arg_indexes: List[int] = []
238
+ tokens: List[str] = []
239
+ for i, (prev, c) in enumerate(zip(f"\0{arguments[:begin_idx+1]}", arguments[:begin_idx+1])):
240
+ if prev == " " and c != " ":
241
+ tokens.append(arguments[last_token_start:i].rstrip())
242
+ num_arguments += 1
243
+ last_token_start = i
244
+ arg_indexes.append(num_arguments)
245
+ if len(arg_indexes) <= begin_idx:
246
+ arg_indexes.extend([num_arguments] * (1 + begin_idx - len(arg_indexes)))
247
+ return func(repl, arg_indexes[begin_idx], arguments[begin_idx:end_idx], tuple(tokens))
248
+
249
+ return wrapper
250
+
251
+ return transformer
252
+
253
+
254
+ class REPLMeta(type):
255
+ _commands: Dict[str, Type[Command]]
256
+ _completers: Dict[str, Callable[["REPL", str, int, int], List[str]]]
257
+
258
+ def add_command(cls, name: str, command: Type[Command]):
259
+ if name in cls._commands:
260
+ raise ValueError(f"A command named {name} is already registered to {cls}")
261
+ cls._commands[name] = command
262
+
263
+ def add_completer(cls, for_command_name: str, completer: Callable[["REPL", str, int, int], List[str]]):
264
+ if for_command_name in cls._completers:
265
+ raise ValueError(f"A completer for command {for_command_name} is already registered to {cls}")
266
+ cls._completers[for_command_name] = completer
267
+
268
+ @property
269
+ def command_types(self) -> Iterator[Tuple[str, Type[Command]]]:
270
+ yielded_names = set()
271
+ for cls in self.mro():
272
+ if isinstance(cls, REPLMeta):
273
+ for name, cmd in cls._commands.items():
274
+ if name not in yielded_names:
275
+ yield name, cmd
276
+ yielded_names.add(name)
277
+
278
+ @property
279
+ def completers(self) -> Iterator[Tuple[str, Callable[["REPL", str, int, int], List[str]]]]:
280
+ yielded_names = set()
281
+ for cls in self.mro():
282
+ if isinstance(cls, REPLMeta):
283
+ for name, cmd_completer in cls._completers.items():
284
+ if name not in yielded_names:
285
+ yield name, cmd_completer
286
+ yielded_names.add(name)
287
+
288
+ def __new__(mcs, name, bases, namespace, **kwargs):
289
+ cls = super().__new__(mcs, name, bases, namespace, **kwargs)
290
+ cls._commands = {}
291
+ cls._completers = {}
292
+ for func_name, func in namespace.items():
293
+ if hasattr(func, "command_info") and isinstance(func.command_info, CommandInfo):
294
+ try:
295
+ cls.add_command(func.command_info.name, Command.wrap(func, func.command_info))
296
+ except ValueError as e:
297
+ raise TypeError(str(e))
298
+ elif hasattr(func, "completer_for"):
299
+ if isinstance(func.completer_for, Command):
300
+ command_name = func.completer_for.name
301
+ elif isinstance(func.completer_for, str):
302
+ command_name = func.completer_for
303
+ else:
304
+ raise TypeError(f"Unknown command specifier {func.completer_for!r} on function {func.__qualname__}")
305
+ cls.add_completer(command_name, func)
306
+ return cls
307
+
308
+
309
+ class SetCompleter:
310
+ def __init__(self, possibilities: Callable[[], Iterable[str]]):
311
+ self.possibilities: Callable[[], Iterable[str]] = possibilities
312
+
313
+ def __call__(self, args: str, begin_idx: Optional[int] = None, end_idx: Optional[int] = None) -> List[str]:
314
+ if begin_idx is None:
315
+ begin_idx = 0
316
+ if end_idx is None:
317
+ end_idx = len(args)
318
+ to_complete = args[begin_idx:end_idx]
319
+ possibilities = sorted(set(self.possibilities()))
320
+ return [
321
+ p for p in possibilities if p.startswith(to_complete)
322
+ ]
323
+
324
+
325
+ class REPL(metaclass=REPLMeta):
326
+ def __init__(self, name: str, prompt: Optional[str] = None,
327
+ completer: Optional[Callable[[str, int], Optional[str]]] = None):
328
+ self.name: str = name
329
+ self._prev_history_length: int = 0
330
+ if completer is None:
331
+ self.completer: Callable[[str, int], Optional[str]] = REPLCompleter(self).complete
332
+ else:
333
+ self.completer = completer
334
+ self.commands: Dict[str, Command] = {
335
+ name: command_type(self) for name, command_type in self.__class__.command_types
336
+ }
337
+ self.last_command: Optional[str] = None
338
+ if prompt is None:
339
+ if sys.stderr.isatty():
340
+ self.repl_prompt: str = ANSIWriter.format("(polyfile) ", bold=True, escape_for_readline=True)
341
+ else:
342
+ self.repl_prompt = "(polyfile) "
343
+ else:
344
+ self.repl_prompt = prompt
345
+ self._bound_tab_completion: bool = False
346
+
347
+ def command_names(self) -> Iterator[str]:
348
+ yield from self.commands.keys()
349
+ for cmd in self.commands.values():
350
+ yield from cmd.aliases
351
+
352
+ def get_completer(self, for_command: Command) -> Callable[[str, int, int], List[str]]:
353
+ for cmd_name, cmd_completer in self.__class__.completers:
354
+ if cmd_name == for_command.name:
355
+ return partial(cmd_completer, self) # type: ignore
356
+ return for_command.complete
357
+
358
+ @arg_completer(for_command="help")
359
+ def help_completer(self, index: int, arg: str, prev_arguments: Iterable[str]):
360
+ if index == 0:
361
+ return SetCompleter(self.command_names)(arg)
362
+ else:
363
+ return []
364
+
365
+ @command(help="print this message", allows_abbreviation=True)
366
+ def help(self, arguments: str):
367
+ arguments = arguments.strip()
368
+ if arguments:
369
+ if arguments not in self.commands:
370
+ self.write(f"Undefined command: {arguments!r}. Try \"help\".\n", color=ANSIColor.RED)
371
+ else:
372
+ cmd = self.commands[arguments]
373
+ self.write(cmd.usage())
374
+ if cmd.aliases:
375
+ self.write(" (aliases: ", dim=True)
376
+ for i, alt in enumerate(sorted(cmd.aliases)):
377
+ if i > 0 and len(cmd.aliases) > 2:
378
+ self.write(", ", dim=True)
379
+ if i == len(cmd.aliases) - 1 and len(cmd.aliases) > 1:
380
+ self.write(" and ", dim=True)
381
+ self.write(alt, bold=True, color=ANSIColor.BLUE)
382
+ self.write(")", dim=True)
383
+ self.write("\n")
384
+ else:
385
+ usages = {
386
+ cmd.name: cmd.usage() for cmd in self.commands.values()
387
+ }
388
+ usage = [
389
+ (name, usages[name]) for name in sorted(usages.keys())
390
+ ]
391
+ aliases = {
392
+ cmd.name: sorted(cmd.aliases) for cmd in self.commands.values() if cmd.aliases
393
+ }
394
+ left_col_width = max(len(u[0]) for u in usage)
395
+ if any(bool(v) for v in aliases.values()):
396
+ left_col_width = max(left_col_width, max(len(c) for a in aliases.values() for c in a))
397
+ left_col_width += 3
398
+ for command, msg in usage:
399
+ self.write(command, bold=True, color=ANSIColor.BLUE)
400
+ self.write(f" {'.' * (left_col_width - len(command) - 2)} ")
401
+ self.write(msg)
402
+ if command in aliases:
403
+ self.write(" (aliases: ", dim=True)
404
+ alternatives = aliases[command]
405
+ for i, alt in enumerate(alternatives):
406
+ if i > 0 and len(alternatives) > 2:
407
+ self.write(", ", dim=True)
408
+ if i == len(alternatives) - 1 and len(alternatives) > 1:
409
+ self.write(" and ", dim=True)
410
+ self.write(alt, bold=True, color=ANSIColor.BLUE)
411
+ self.write(")", dim=True)
412
+ self.write("\n")
413
+
414
+ def prompt(self, message: str, default: bool = True) -> bool:
415
+ with Unprofiled():
416
+ while True:
417
+ buffer = ANSIWriter(use_ansi=sys.stderr.isatty(), escape_for_readline=True)
418
+ buffer.write(f"{message} ", bold=True)
419
+ buffer.write("[", dim=True)
420
+ if default:
421
+ buffer.write("Y", bold=True, color=ANSIColor.GREEN)
422
+ buffer.write("n", dim=True, color=ANSIColor.RED)
423
+ else:
424
+ buffer.write("y", dim=True, color=ANSIColor.GREEN)
425
+ buffer.write("N", bold=True, color=ANSIColor.RED)
426
+ buffer.write("] ", dim=True)
427
+ try:
428
+ answer = input(str(buffer)).strip().lower()
429
+ except EOFError:
430
+ raise KeyboardInterrupt()
431
+ if not answer:
432
+ return default
433
+ elif answer == "n":
434
+ return False
435
+ elif answer == "y":
436
+ return True
437
+
438
+ def load_history(self):
439
+ try:
440
+ readline.read_history_file(str(HISTORY_PATH))
441
+ self._prev_history_length = readline.get_current_history_length()
442
+ except (FileNotFoundError, OSError):
443
+ open(HISTORY_PATH, 'wb').close()
444
+ self._prev_history_length = 0
445
+ # default history len is -1 (infinite), which may grow unruly
446
+ readline.set_history_length(2048)
447
+
448
+ def store_history(self):
449
+ new_length = readline.get_current_history_length()
450
+ try:
451
+ if hasattr(readline, "append_history_file"):
452
+ readline.append_history_file(max(new_length - self._prev_history_length, 0), HISTORY_PATH)
453
+ self._prev_history_length = readline.get_current_history_length()
454
+ except IOError as e:
455
+ log.warning(f"Unable to save history to {HISTORY_PATH!s}: {e!s}")
456
+
457
+ def input(self, prompt: str = "") -> str:
458
+ if not self._bound_tab_completion:
459
+ self._bound_tab_completion = True
460
+ readline.parse_and_bind("tab: complete")
461
+ self.load_history()
462
+ atexit.register(_write_history, self)
463
+ prev_completer = readline.get_completer()
464
+ readline.set_completer(self.completer)
465
+ try:
466
+ return input(prompt)
467
+ except EOFError:
468
+ # the user pressed ^D to quit
469
+ return self.handle_eof()
470
+ finally:
471
+ readline.set_completer(prev_completer)
472
+
473
+ def write(self, message: Any, bold: bool = False, dim: bool = False, color: Optional[ANSIColor] = None):
474
+ if sys.stdout.isatty():
475
+ message = ANSIWriter.format(message=message, bold=bold, dim=dim, color=color)
476
+ sys.stdout.write(str(message))
477
+
478
+ def handle_eof(self) -> str:
479
+ # called when the user presses ^D on input()
480
+ exit(0)
481
+ return ""
482
+
483
+ def before_prompt(self):
484
+ pass
485
+
486
+ def get_command(self, command_name: str) -> Command:
487
+ if command_name in self.commands:
488
+ return self.commands[command_name]
489
+ for command in self.commands.values():
490
+ if command.allows_abbreviation and command.name.startswith(command_name):
491
+ return command
492
+ # is it an alias?
493
+ for command in self.commands.values():
494
+ if not command.allows_abbreviation:
495
+ if command_name in command.aliases:
496
+ return command
497
+ else:
498
+ continue
499
+ for alias in command.aliases:
500
+ if alias.startswith(command_name):
501
+ return command
502
+ raise KeyError(command_name)
503
+
504
+ def run_command(self, command_str: str):
505
+ command_name = command_str.lstrip()
506
+ space_index = command_name.find(" ")
507
+ if space_index > 0:
508
+ command_name, args = command_name[:space_index], command_name[space_index + 1:].strip()
509
+ else:
510
+ args = ""
511
+
512
+ try:
513
+ return self.get_command(command_name).run(args)
514
+ except KeyError:
515
+ self.write(f"Undefined command: {command_name!r}. Try \"help\".\n", color=ANSIColor.RED)
516
+ raise
517
+
518
+ def repl(self):
519
+ log.clear_status()
520
+ self.before_prompt()
521
+ while True:
522
+ try:
523
+ command_name = self.input(self.repl_prompt)
524
+ except KeyboardInterrupt:
525
+ continue
526
+ if not command_name:
527
+ if self.last_command is None:
528
+ continue
529
+ command_name = self.last_command
530
+ command_name = command_name.lstrip()
531
+ original_command = command_name
532
+
533
+ try:
534
+ self.run_command(command_name)
535
+ except KeyError:
536
+ self.last_command = None
537
+ continue
538
+ except ExitREPL:
539
+ break
540
+ finally:
541
+ self.last_command = original_command
542
+
543
+
544
+ class Quit(Command):
545
+ def __init__(self, repl: REPL):
546
+ super().__init__(repl, name="quit", allows_abbreviation=True)
547
+
548
+ def usage(self) -> str:
549
+ return f"exit {self.repl.name}"
550
+
551
+ def run(self, arguments: str):
552
+ exit(0)
553
+
554
+
555
+ REPL.add_command("quit", Quit)
556
+
557
+
558
+ class REPLCompleter:
559
+ def __init__(self, repl: REPL):
560
+ self.repl: REPL = repl
561
+
562
+ def traverse(self, tokens, tree):
563
+ if tree is None:
564
+ return []
565
+ elif len(tokens) == 0:
566
+ return []
567
+ if len(tokens) == 1:
568
+ return [x+' ' for x in tree if x.startswith(tokens[0])]
569
+ elif tokens[0] in tree.keys():
570
+ return self.traverse(tokens[1:],tree[tokens[0]])
571
+ return []
572
+
573
+ def complete(self, text: str, state: int) -> Optional[str]:
574
+ commandline = readline.get_line_buffer()
575
+ space_index = commandline.find(" ")
576
+ if space_index < 0 or (space_index > 0 and readline.get_endidx() < space_index):
577
+ # we are completing the command name
578
+ possible_names = sorted({
579
+ cmd_name for cmd_name in self.repl.commands.keys()
580
+ if cmd_name.startswith(text)
581
+ } | {
582
+ alias
583
+ for cmd in self.repl.commands.values()
584
+ for alias in cmd.aliases
585
+ if alias.startswith(text)
586
+ }) + [None]
587
+ if state < len(possible_names):
588
+ if state == 0 and len(possible_names) == 2:
589
+ # there is only one possibility, so append it with a space since it is the only choice
590
+ return f"{possible_names[0]} "
591
+ return possible_names[state]
592
+ else:
593
+ return None
594
+ if space_index > 0:
595
+ command_name, args = commandline[:space_index], commandline[space_index + 1:]
596
+ else:
597
+ command_name = ""
598
+ args = ""
599
+ try:
600
+ command = self.repl.get_command(command_name)
601
+ except KeyError:
602
+ return None
603
+ completer = self.repl.get_completer(for_command=command)
604
+ try:
605
+ possibilities = completer(
606
+ args, readline.get_begidx() - space_index - 1, readline.get_endidx() - space_index - 1
607
+ ) + [None] # type: ignore
608
+ except Exception as e:
609
+ traceback.print_tb(e.__traceback__)
610
+ log.warning(f"Command {completer!r}({args!r}, "
611
+ f"{readline.get_begidx() - space_index - 1}, {readline.get_endidx() - space_index - 1}) "
612
+ f"raised an exception: {e!r}")
613
+ return None
614
+
615
+ if state < len(possibilities):
616
+ if state == 0 and len(possibilities) == 2:
617
+ # there is only one possibility, so append it with a space since it is the only choice
618
+ return f"{possibilities[0]} "
619
+ return possibilities[state]
620
+ else:
621
+ log.warning(f"Command {command.__class__.__name__}.complete({args!r}, "
622
+ f"{readline.get_begidx() - space_index - 1}, {readline.get_endidx() - space_index - 1}) "
623
+ f"returned an invalid result: {possibilities[:-1]!r}")
624
+ return None