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
@@ -0,0 +1,346 @@
1
+ from collections import deque
2
+ from enum import Enum
3
+ from io import StringIO
4
+ import itertools
5
+
6
+
7
+ OPERATORS_BY_NAME = {}
8
+
9
+
10
+ def function_call(obj, function_name):
11
+ raise RuntimeError("TODO: Implement")
12
+
13
+
14
+ def to_int(v, byteorder='big') -> int:
15
+ if isinstance(v, int):
16
+ return v
17
+ elif isinstance(v, bytes) or isinstance(v, str) or isinstance(v, bytearray):
18
+ if len(v) == 0:
19
+ return 0
20
+ elif len(v) == 1:
21
+ return int(v[0])
22
+ else:
23
+ # Assume big endian
24
+ return int.from_bytes(v, byteorder=byteorder)
25
+ raise ValueError(f"Cannot convert {v!r} to an integer")
26
+
27
+
28
+ class Operator(Enum):
29
+ ENUM_ACCESSOR = ('::', 0, lambda a, b: a[b.name], True, 2, False, (True, False))
30
+ MEMBER_ACCESS = ('.', 1, lambda a, b: None, True, 2, False, (True, False))
31
+ UNARY_PLUS = ('+', 2, lambda a: a, False, 1, True)
32
+ UNARY_MINUS = ('-', 2, lambda a: -to_int(a), False, 1, True)
33
+ LOGICAL_NOT = ('not', 2, lambda a: not a, False, 1)
34
+ BITWISE_NOT = ('~', 2, lambda a: ~to_int(a), False, 1)
35
+ MULTIPLICATION = ('*', 3, lambda a, b: to_int(a) * to_int(b))
36
+ DIVISION = ('/', 3, lambda a, b: to_int(a) // to_int(b))
37
+ REMAINDER = ('%', 3, lambda a, b: to_int(a) % to_int(b))
38
+ ADDITION = ('+', 4, lambda a, b: a + b)
39
+ SUBTRACTION = ('-', 4, lambda a, b: to_int(a) - to_int(b))
40
+ BITWISE_LEFT_SHIFT = ('<<', 5, lambda a, b: to_int(a) << to_int(b))
41
+ BITWISE_RIGHT_SHIFT = ('>>', 5, lambda a, b: to_int(a) >> to_int(b))
42
+ LESS_THAN = ('<', 6, lambda a, b: a < b)
43
+ GREATER_THAN = ('>', 6, lambda a, b: a > b)
44
+ LESS_THAN_EQUAL = ('<=', 6, lambda a, b: a <= b)
45
+ GREATER_THAN_EQUAL = ('>=', 6, lambda a, b: a >= b)
46
+ EQUALS = ('==', 7, lambda a, b: a == b)
47
+ NOT_EQUAL = ('!=', 7, lambda a, b: a != b)
48
+ BITWISE_AND = ('&', 8, lambda a, b: to_int(a) & to_int(b))
49
+ BITWISE_XOR = ('^', 9, lambda a, b: to_int(a) ^ to_int(b))
50
+ BITWISE_OR = ('|', 10, lambda a, b: to_int(a) | to_int(b))
51
+ LOGICAL_AND = ('and', 11, lambda a, b: a and b)
52
+ LOGICAL_OR = ('or', 12, lambda a, b: a or b)
53
+ TERNARY_ELSE = (':', 13, lambda a, b: (a, b), False)
54
+ TERNARY_CONDITIONAL = ('?', 14, lambda a, b: b[bool(a)], False)
55
+
56
+ def __init__(self,
57
+ token,
58
+ priority,
59
+ execute,
60
+ is_left_associative=True,
61
+ arity=2,
62
+ multiple_arity=False,
63
+ expand=None):
64
+ self.token = token
65
+ self.priority = priority
66
+ self.execute = execute
67
+ self.left_associative = is_left_associative
68
+ self.arity = arity
69
+ self.multiple_arity = multiple_arity
70
+ if expand is None:
71
+ self.expand = (True,) * self.arity
72
+ else:
73
+ self.expand = expand
74
+ if not multiple_arity:
75
+ OPERATORS_BY_NAME[self.token] = self
76
+
77
+
78
+ IDENTIFIER_BYTES = {
79
+ chr(i) for i in range(ord('A'), ord('Z') + 1)
80
+ } | {
81
+ chr(i) for i in range(ord('a'), ord('z') + 1)
82
+ } | {
83
+ chr(i) for i in range(ord('0'), ord('9') + 1)
84
+ } | {
85
+ '-', '_'
86
+ }
87
+
88
+
89
+ class Token:
90
+ def __init__(self, raw_text):
91
+ self._raw = raw_text
92
+
93
+ @property
94
+ def raw_token(self):
95
+ return self._raw
96
+
97
+ def __len__(self):
98
+ return len(self._raw)
99
+
100
+ def __repr__(self):
101
+ return f"{self.__class__.__name__}({self._raw!r})"
102
+
103
+
104
+ class Parenthesis(Token):
105
+ def __init__(self, *args, **kwargs):
106
+ super().__init__(*args, **kwargs)
107
+
108
+ def __repr__(self):
109
+ return f"{self.__class__.__name__}()"
110
+
111
+
112
+ class OpenParen(Parenthesis):
113
+ def __init__(self):
114
+ super().__init__('(')
115
+
116
+
117
+ class CloseParen(Parenthesis):
118
+ def __init__(self):
119
+ super().__init__(')')
120
+
121
+
122
+ class OperatorToken(Token):
123
+ def __init__(self, op):
124
+ if isinstance(op, str):
125
+ op = OPERATORS_BY_NAME[op]
126
+ super().__init__(op.token)
127
+ self.op: Operator = op
128
+
129
+ def __repr__(self):
130
+ return f"{self.__class__.__name__}(op={self.op!r})"
131
+
132
+
133
+ class IdentifierToken(Token):
134
+ def __init__(self, name):
135
+ super().__init__(name)
136
+ self.name = name
137
+
138
+
139
+ class IntegerToken(Token):
140
+ def __init__(self, raw_str, value):
141
+ super().__init__(raw_str)
142
+ self.value = value
143
+
144
+ def __int__(self):
145
+ return self.value
146
+
147
+ def __repr__(self):
148
+ return f"{self.__class__.__name__}(raw_str={self.raw_token!r}, value={self.value!r})"
149
+
150
+
151
+ class Tokenizer:
152
+ def __init__(self, stream):
153
+ if isinstance(stream, str):
154
+ stream = StringIO(stream)
155
+ self._stream = stream
156
+ self._buffer = deque()
157
+ self._next_token = None
158
+ self.prev_token = None
159
+
160
+ def _peek_byte(self, n=1):
161
+ bytes_needed = n - len(self._buffer)
162
+ if bytes_needed > 0:
163
+ b = self._stream.read(bytes_needed)
164
+ self._buffer.extend(b)
165
+ return ''.join(itertools.islice(self._buffer, n))
166
+
167
+ def _pop_byte(self, n=1):
168
+ if len(self._buffer) < n:
169
+ return ''.join(self._buffer) + self._stream.read(1)
170
+ else:
171
+ return ''.join(self._buffer.popleft() for _ in range(n))
172
+
173
+ def peek(self):
174
+ if self._next_token is not None:
175
+ return self._next_token
176
+ ret = None
177
+ operand = None
178
+ # ignore leading whitespace
179
+ while self._peek_byte() == ' ' or self._peek_byte() == '\t':
180
+ self._pop_byte()
181
+ while ret is None:
182
+ c = self._peek_byte(3)
183
+ if len(c) == 0:
184
+ break
185
+ elif operand is not None:
186
+ if c[0] in IDENTIFIER_BYTES:
187
+ operand += self._pop_byte()
188
+ else:
189
+ break
190
+ elif c in OPERATORS_BY_NAME:
191
+ ret = OperatorToken(c)
192
+ elif c[:2] in OPERATORS_BY_NAME:
193
+ ret = OperatorToken(c[:2])
194
+ elif c[0] in OPERATORS_BY_NAME:
195
+ if c[0] == '+':
196
+ if self.prev_token is None or isinstance(self.prev_token, OperatorToken):
197
+ ret = OperatorToken(Operator.UNARY_PLUS)
198
+ else:
199
+ ret = OperatorToken(Operator.ADDITION)
200
+ elif c[0] == '-':
201
+ if self.prev_token is None or isinstance(self.prev_token, OperatorToken):
202
+ ret = OperatorToken(Operator.UNARY_MINUS)
203
+ else:
204
+ ret = OperatorToken(Operator.SUBTRACTION)
205
+ else:
206
+ ret = OperatorToken(c[0])
207
+ elif c[0] == '(':
208
+ ret = OpenParen()
209
+ elif c[0] == ')':
210
+ ret = CloseParen()
211
+ elif c[0] == ' ' or c[0] == '\t':
212
+ break
213
+ else:
214
+ operand = self._pop_byte()
215
+ if operand is not None:
216
+ if operand.startswith('0x'):
217
+ ret = IntegerToken(operand, int(operand, 16))
218
+ elif operand.startswith('0o'):
219
+ ret = IntegerToken(operand, int(operand, 8))
220
+ elif operand.startswith('0b'):
221
+ ret = IntegerToken(operand, int(operand, 2))
222
+ else:
223
+ # Is this an integer?
224
+ try:
225
+ ret = IntegerToken(operand, int(operand))
226
+ except ValueError:
227
+ ret = IdentifierToken(operand)
228
+ elif ret is not None:
229
+ self._pop_byte(len(ret))
230
+ return ret
231
+
232
+ def has_next(self) -> bool:
233
+ return self.peek() is not None
234
+
235
+ def next(self):
236
+ ret = self.peek()
237
+ self.prev_token = ret
238
+ self._next_token = None
239
+ return ret
240
+
241
+ def __iter__(self):
242
+ while True:
243
+ ret = self.next()
244
+ if ret is None:
245
+ break
246
+ yield ret
247
+
248
+
249
+ def tokenize(stream_or_str):
250
+ yield from Tokenizer(stream_or_str)
251
+
252
+
253
+ def infix_to_rpn(tokens):
254
+ """Converts an infix expression to reverse Polish notation using the Shunting Yard algorithm"""
255
+ operators = []
256
+
257
+ for token in tokens:
258
+ if isinstance(token, OpenParen):
259
+ operators.append(token)
260
+ elif isinstance(token, CloseParen):
261
+ while not isinstance(operators[-1], OpenParen):
262
+ yield operators.pop()
263
+ # TODO: Throw a nice mismatched parenthesis exception here instead of relying on operators[-1]
264
+ # to throw an index out of bounds exception
265
+ if operators and isinstance(operators[-1], OpenParen):
266
+ operators.pop()
267
+ elif isinstance(token, OperatorToken):
268
+ while operators and not isinstance(operators[-1], OpenParen) and \
269
+ (operators[-1].op.priority < token.op.priority \
270
+ or \
271
+ (operators[-1].op.priority == token.op.priority and operators[-1].op.left_associative)):
272
+ yield operators.pop()
273
+ operators.append(token)
274
+ else:
275
+ yield token
276
+
277
+ while operators:
278
+ top = operators.pop()
279
+ if isinstance(top, Parenthesis):
280
+ raise RuntimeError("Mismatched parenthesis")
281
+ yield top
282
+
283
+
284
+ class Expression:
285
+ def __init__(self, rpn):
286
+ self.tokens = tuple(rpn)
287
+
288
+ @staticmethod
289
+ def get_value(token: Token, assignments: dict):
290
+ if isinstance(token, IntegerToken):
291
+ return token.value
292
+ elif isinstance(token, IdentifierToken):
293
+ if token.name not in assignments:
294
+ raise KeyError(f'Unknown identifier {token.name}')
295
+ return assignments[token.name]
296
+ elif isinstance(token, int) or isinstance(token, str) or isinstance(token, bytes):
297
+ return token
298
+ else:
299
+ raise ValueError(f"Unexpected token {token!r}")
300
+
301
+ def interpret(self, assignments=None):
302
+ if assignments is None:
303
+ assignments = {}
304
+ values = []
305
+ for t in self.tokens:
306
+ if isinstance(t, OperatorToken):
307
+ args = []
308
+ for expand, v in zip(t.op.expand, values[-t.op.arity:]):
309
+ if expand:
310
+ args.append(self.get_value(v, assignments))
311
+ else:
312
+ args.append(v)
313
+ values = values[:-t.op.arity] + [t.op.execute(*args)]
314
+ else:
315
+ values.append(t)
316
+ if len(values) != 1:
317
+ raise RuntimeError(f"Unexpected extra tokens: {values[:-1]}")
318
+ if isinstance(values[0], IdentifierToken):
319
+ return self.get_value(values[0], assignments)
320
+ return values[0]
321
+
322
+ def __repr__(self):
323
+ return f"{self.__class__.__name__}(rpn={self.tokens!r})"
324
+
325
+
326
+ def parse(expression_str: str) -> Expression:
327
+ return Expression(infix_to_rpn(tokenize(expression_str)))
328
+
329
+
330
+ if __name__ == '__main__':
331
+ assignments = {
332
+ 'sampling_factors': 1234,
333
+ 'thumbnail_x': 5,
334
+ 'thumbnail_y': 7,
335
+ 'marker': 1,
336
+ 'marker_enum': {
337
+ 'soi': 0,
338
+ 'eoi': 3
339
+ }
340
+ }
341
+ for s in (
342
+ '(sampling_factors & -0xf0) >> 4',
343
+ 'thumbnail_x * thumbnail_y * 3',
344
+ 'marker != marker_enum::soi and marker != marker_enum::eoi'
345
+ ):
346
+ print(parse(s).interpret(assignments))
polyfile/fileutils.py ADDED
@@ -0,0 +1,343 @@
1
+ from io import BytesIO, SEEK_END, UnsupportedOperation
2
+ import mmap
3
+ import os
4
+ from pathlib import Path
5
+ import tempfile as tf
6
+ import shutil
7
+ import sys
8
+ from typing import AnyStr, ContextManager, IO, Iterator, Iterable, List, Optional, TextIO, Union
9
+
10
+
11
+ Streamable = Union[str, Path, IO, "FileStream", bytes]
12
+
13
+
14
+ def make_stream(path_or_stream: Streamable, mode: str = 'rb',
15
+ close_on_exit: Optional[bool] = None) -> "FileStream":
16
+ if isinstance(path_or_stream, FileStream):
17
+ return path_or_stream
18
+ else:
19
+ return FileStream(path_or_stream, mode=mode, close_on_exit=close_on_exit)
20
+
21
+
22
+ class Tempfile:
23
+ def __init__(self, contents: bytes, prefix: Optional[str] = None, suffix: Optional[str] = None):
24
+ self._path: Optional[str] = None
25
+ self._data: bytes = contents
26
+ self._prefix: Optional[str] = prefix
27
+ self._suffix: Optional[str] = suffix
28
+
29
+ def __enter__(self) -> str:
30
+ tmp = tf.NamedTemporaryFile(prefix=self._prefix, suffix=self._suffix, delete=False)
31
+ tmp.write(self._data)
32
+ tmp.flush()
33
+ tmp.close()
34
+ self._path = tmp.name
35
+ return tmp.name
36
+
37
+ def __exit__(self, type, value, traceback):
38
+ if self._path is not None:
39
+ os.unlink(self._path)
40
+ self._path = None
41
+
42
+
43
+ class ExactNamedTempfile(Tempfile):
44
+ def __init__(self, contents: bytes, name: str):
45
+ super().__init__(contents)
46
+ self._name: str = name
47
+
48
+ def __enter__(self) -> str:
49
+ tmpdir = Path(tf.mkdtemp())
50
+ file_path = tmpdir / self._name
51
+ with open(file_path, "wb") as f:
52
+ f.write(self._data)
53
+ self._path = str(tmpdir)
54
+ return str(file_path)
55
+
56
+ def __exit__(self, exc_type, exc_val, exc_tb):
57
+ if self._path is not None:
58
+ shutil.rmtree(self._path)
59
+ self._path = None
60
+
61
+
62
+ class PathOrStdin:
63
+ def __init__(self, path: str):
64
+ self.path: str = path
65
+ if self.path == '-':
66
+ self._tempfile: Optional[ExactNamedTempfile] = ExactNamedTempfile(sys.stdin.buffer.read(), "STDIN")
67
+ elif not Path(path).exists():
68
+ raise FileNotFoundError(path)
69
+ else:
70
+ self._tempfile = None
71
+
72
+ def __enter__(self) -> str:
73
+ if self._tempfile is None:
74
+ return self.path
75
+ else:
76
+ return self._tempfile.__enter__()
77
+
78
+ def __exit__(self, *args, **kwargs):
79
+ if self._tempfile is not None:
80
+ return self._tempfile.__exit__(*args, **kwargs)
81
+
82
+
83
+ class PathOrStdout(ContextManager[TextIO]):
84
+ def __init__(self, path: str):
85
+ self.path: str = path
86
+ if self.path == '-':
87
+ self._tempfile: Optional[TextIO] = sys.stdout
88
+ else:
89
+ self._tempfile = None
90
+
91
+ def __enter__(self) -> TextIO:
92
+ if self._tempfile is None:
93
+ self._tempfile = open(self.path, "w")
94
+ return self._tempfile
95
+
96
+ def __exit__(self, *args, **kwargs) -> None: # type: ignore
97
+ if self._tempfile is not None:
98
+ if self._tempfile is not sys.stdout:
99
+ self._tempfile.close()
100
+ self._tempfile = None
101
+ return None
102
+
103
+
104
+ class FileStream(IO):
105
+ def __init__(
106
+ self,
107
+ path_or_stream: Streamable,
108
+ start: int = 0,
109
+ length: Optional[int] = None,
110
+ mode: str = "rb",
111
+ close_on_exit: Optional[bool] = None
112
+ ):
113
+ if isinstance(path_or_stream, Path):
114
+ path_or_stream = str(path_or_stream)
115
+ if isinstance(path_or_stream, str):
116
+ self._stream: IO = open(path_or_stream, mode)
117
+ if close_on_exit is None:
118
+ close_on_exit = True
119
+ else:
120
+ if isinstance(path_or_stream, bytes):
121
+ path_or_stream = BytesIO(path_or_stream)
122
+ setattr(path_or_stream, "name", "bytes")
123
+ elif not path_or_stream.seekable():
124
+ raise ValueError('FileStream can only wrap streams that are seekable')
125
+ elif not path_or_stream.readable():
126
+ raise ValueError('FileStream can only wrap streams that are readable')
127
+ self._stream = path_or_stream
128
+ if isinstance(path_or_stream, FileStream):
129
+ if length is None:
130
+ self._length = len(path_or_stream) - start
131
+ else:
132
+ self._length = min(length, len(path_or_stream))
133
+ else:
134
+ if isinstance(path_or_stream, BytesIO):
135
+ orig_pos = path_or_stream.tell()
136
+ path_or_stream.seek(0, SEEK_END)
137
+ try:
138
+ filesize = path_or_stream.tell()
139
+ finally:
140
+ path_or_stream.seek(orig_pos)
141
+ else:
142
+ filesize = os.path.getsize(self._stream.name)
143
+ if length is None:
144
+ self._length = filesize - start
145
+ else:
146
+ self._length = min(filesize, length) - start
147
+ if close_on_exit is None:
148
+ close_on_exit = False
149
+ self._name = self._stream.name
150
+ self.start = start
151
+ self.close_on_exit = close_on_exit
152
+ self._entries = 0
153
+ self._root = None
154
+
155
+ def __len__(self):
156
+ return self._length
157
+
158
+ def seekable(self):
159
+ return True
160
+
161
+ def writable(self):
162
+ return False
163
+
164
+ def readable(self):
165
+ return True
166
+
167
+ @property
168
+ def name(self):
169
+ return self._name
170
+
171
+ @property
172
+ def root(self):
173
+ if self._root is None:
174
+ if isinstance(self._stream, FileStream):
175
+ self._root = self._stream.root
176
+ else:
177
+ self._root = self._stream
178
+ return self._root
179
+
180
+ def save_pos(self):
181
+ f = self
182
+
183
+ class SP:
184
+ def __init__(self):
185
+ self.pos = f.root.tell()
186
+
187
+ def __enter__(self, *args, **kwargs) -> FileStream:
188
+ return f
189
+
190
+ def __exit__(self, *args, **kwargs):
191
+ f.root.seek(self.pos)
192
+
193
+ return SP()
194
+
195
+ def fileno(self):
196
+ return self._stream.fileno()
197
+
198
+ def offset(self):
199
+ if isinstance(self._stream, FileStream):
200
+ return self._stream.offset() + self.start
201
+ else:
202
+ return self.start
203
+
204
+ def seek(self, offset, from_what=0):
205
+ if from_what == 1:
206
+ offset = self.tell() + offset
207
+ elif from_what == 2:
208
+ offset = len(self) + offset
209
+ if offset - self.start > self._length:
210
+ raise IndexError(f"{self!r} is {len(self)} bytes long, but seek was requested for byte {offset}")
211
+ self._stream.seek(self.start + offset)
212
+
213
+ def tell(self):
214
+ return min(max(self._stream.tell() - self.start, 0), self._length)
215
+
216
+ def read(self, n=None) -> bytes:
217
+ if self._stream.tell() - self.start < 0:
218
+ # another context moved the position, so move it back to our zero index:
219
+ self.seek(0)
220
+ pos = 0
221
+ else:
222
+ pos = self.tell()
223
+ ls = len(self)
224
+ if pos >= ls:
225
+ return b''
226
+ elif n is None:
227
+ return self._stream.read()[:ls - pos]
228
+ else:
229
+ return self._stream.read(min(n, ls - pos))
230
+
231
+ def contains_all(self, *args):
232
+ if args:
233
+ with mmap.mmap(self.fileno(), 0, access=mmap.ACCESS_READ) as filecontent:
234
+ for string in args:
235
+ if filecontent.find(string, self.offset(), self.offset() + len(self)) < 0:
236
+ return False
237
+ return True
238
+
239
+ def first_index_of(self, byte_sequence: bytes) -> int:
240
+ with mmap.mmap(self.fileno(), 0, access=mmap.ACCESS_READ) as filecontent:
241
+ start_offset = self.offset()
242
+ end_offset = start_offset + len(self)
243
+ index = filecontent.find(byte_sequence, start_offset, end_offset)
244
+ if start_offset <= index < end_offset:
245
+ return index - start_offset
246
+ else:
247
+ return -1
248
+
249
+ @property
250
+ def content(self) -> bytes:
251
+ with self.save_pos():
252
+ self.seek(0)
253
+ return self.read(len(self))
254
+
255
+ def __bytes__(self):
256
+ return self.content
257
+
258
+ def tempfile(self, prefix=None, suffix=None):
259
+ class FSTempfile:
260
+ def __init__(self, file_stream: FileStream):
261
+ self._temp = None
262
+ self._fs: FileStream = file_stream
263
+
264
+ def __enter__(self):
265
+ self._temp = tf.NamedTemporaryFile(prefix=prefix, suffix=suffix, delete=False)
266
+ with self._fs.save_pos():
267
+ self._fs.seek(0)
268
+ while True:
269
+ b = self._fs.read(1048576) # write 1 MiB at a time
270
+ if not b:
271
+ break
272
+ self._temp.write(b)
273
+ self._temp.flush()
274
+ self._temp.close()
275
+ return self._temp.name
276
+
277
+ def __exit__(self, type, value, traceback):
278
+ if self._temp is not None:
279
+ os.unlink(self._temp.name)
280
+ self._temp = None
281
+ return FSTempfile(self)
282
+
283
+ def __getitem__(self, index) -> Union[bytes, "FileStream"]:
284
+ if isinstance(index, int):
285
+ with self.save_pos():
286
+ self.seek(index)
287
+ return self.read(1)
288
+ elif not isinstance(index, slice):
289
+ raise ValueError(f"unexpected argument {index}")
290
+ if index.step is not None and index.step != 1:
291
+ raise ValueError(f"Invalid slice step: {index}")
292
+ length=None
293
+ if index.stop is not None:
294
+ if index.stop < 0 and (
295
+ (index.stop < index.start and index.start > 0) or (index.stop > index.start and index.start < 0)):
296
+ length = len(self) + index.stop - index.start
297
+ elif index.stop < index.start:
298
+ length = 0
299
+ else:
300
+ length = index.stop - index.start
301
+ return FileStream(self, start=index.start, length=length, close_on_exit=False)
302
+
303
+ def __enter__(self) -> "FileStream":
304
+ self._entries += 1
305
+ return self
306
+
307
+ def __exit__(self, type, value, traceback):
308
+ self._entries -= 1
309
+ assert self._entries >= 0
310
+ if self._entries == 0 and self.close_on_exit:
311
+ self.close_on_exit = False
312
+ self._stream.close()
313
+
314
+ def close(self) -> None:
315
+ if self._entries == 0:
316
+ self._stream.close()
317
+
318
+ def flush(self):
319
+ self._stream.flush()
320
+
321
+ def isatty(self) -> bool:
322
+ return self._stream.isatty()
323
+
324
+ def readline(self, limit: int = ...) -> AnyStr:
325
+ raise UnsupportedOperation()
326
+
327
+ def readlines(self, hint: int = ...) -> List[AnyStr]:
328
+ raise UnsupportedOperation()
329
+
330
+ def truncate(self, size: int = ...) -> int:
331
+ raise UnsupportedOperation()
332
+
333
+ def write(self, s: AnyStr) -> int:
334
+ raise UnsupportedOperation()
335
+
336
+ def writelines(self, lines: Iterable[AnyStr]) -> None:
337
+ raise UnsupportedOperation()
338
+
339
+ def __next__(self) -> AnyStr:
340
+ raise UnsupportedOperation()
341
+
342
+ def __iter__(self) -> Iterator[AnyStr]:
343
+ raise UnsupportedOperation()