| Offset 1, 121 lines modified | Offset 0, 0 lines modified | ||
| 1 | Key·0x42726577: | ||
| 2 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 3 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 4 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 5 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 6 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 7 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 8 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 9 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 10 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 11 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 12 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 13 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 14 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 15 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 16 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 17 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 18 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 19 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 20 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 21 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 22 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 23 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 24 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 25 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 26 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 27 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 28 | 0000000000000000000000000000000000000000000000000000000000000000000000 | ||
| 29 | 000000000000000000000000000000000000000000 | ||
| 30 | Key·0x7109871a: | ||
| 31 | f7050000f3050000b50300002c0000002800000003010000200000007e5580090011c5 | ||
| 32 | 87afdb2f83c96c16e5bcae1321cf87680d0bcbd6a59091e72e6d030000690300003082 | ||
| 33 | 03653082024da003020102020863707fe532bb2ae7300d06092a864886f70d01010b05 | ||
| 34 | 003060310b300906035504061302554b310c300a060355040813034f5247310c300a06 | ||
| 35 | 0355040713034f524731133011060355040a130a6664726f69642e6f7267310f300d06 | ||
| 36 | 0355040b13064644726f6964310f300d060355040313064644726f69643020170d3236 | ||
| 37 | 303632373135343331325a180f32303533313131323135343331325a3060310b300906 | ||
| 38 | 035504061302554b310c300a060355040813034f5247310c300a060355040713034f52 | ||
| 39 | 4731133011060355040a130a6664726f69642e6f7267310f300d060355040b13064644 | ||
| 40 | 726f6964310f300d060355040313064644726f696430820122300d06092a864886f70d | ||
| 41 | 01010105000382010f003082010a0282010100ac74a8f4fb5ff9c1a0338278598eb9c6 | ||
| 42 | ba0fce0774e5f2dfe7d8aff70c0cb2535a834e125f1581127f7a6f5d3f86dc5195fd7a | ||
| 43 | 4b1c92b26bd6422d7d34de63f255b1782446868cb7bfdc3b992ccb233a52ef9c4d5f81 | ||
| 44 | 954926ca92954b14f8046ec50a095dd5556832565712fd9d41cd934410056864573af7 | ||
| 45 | d8187d1774c6a004b928eb712a907ec5944e75acd901cfb09a1ce230815caae69da3a0 | ||
| 46 | b6bf6fb6d63156b21b8922ed1917331c4f1421eaa8dbb232f7832dcc35e7a6e6907f62 | ||
| 47 | df44fe4a73cd3f238002dfc7a5e2e2fc64ce1596966c7c411f63ad2e19c0339354c530 | ||
| 48 | 83b31e8cfb923799d505bbaa8c2d6bf92187fe3ae13fe30eabe346242d110203010001 | ||
| 49 | a321301f301d0603551d0e04160414ecb0d0226aa2fe884f4897c348146f3ffffc96b7 | ||
| 50 | 300d06092a864886f70d01010b0500038201010048373d1fdd119f7858e6e3c2e5c181 | ||
| 51 | b3ed8072b53c4ab90889efb9b8cd0c23eab3e01752c48305ee01f073d5a108e62196d4 | ||
| 52 | ce553bb0022a0055cac40979bccc03c1a6c90ee4baaad9f217f746731470b128bfd3b2 | ||
| 53 | 4d67879509be45a91d5042396036d3b05594d1f5055dca470801751296b3c5f4d72ece | ||
| 54 | c04320cbbb69ee8a6d9d39309916850db9939afdfca7c90755c57a88fe82343d2b02cb | ||
| 55 | fa45c1467ddc6e81e59fadd39925d9b2e62e85c55625247f04ce42a115ae52a52dec25 | ||
| 56 | f249cf08a392f7efb473a319ea4e410e74bb516475b7c881610fb95a013a9209c4243c | ||
| 57 | 948166bff03e2a50f4c1e6da3bad7c6a918afeeb7472bc45ad09efe63b47200c000000 | ||
| 58 | 080000000df0efbe03000000000000000c010000080100000301000000010000205177 | ||
| 59 | 30f3f50e8c8c1f9c6ab3459b34f575527b2d7d2f505d733e1613c6c312b71db3cdb925 | ||
| 60 | c634733202fa21d240ca9d35bc4a0ff01dc6244d5484eebed587772ac00346d8c9d9bf | ||
| 61 | 92ebe2977cb5696236c9578486aae183bb3676a2d2a51fc91c65f7e8f966f34fbbd0ee | ||
| 62 | 22e0a64e11d629ca8ce15a15d1bffadbd723e1f2ad9c1c9948da08f250637c5988deff | ||
| 63 | 7d37bfa838d19a6b1293e127e5a816abd96b3b096a13d38b85da2352df35e122ec5132 | ||
| 64 | f9fc474b739ca289a681a1ff41eaa79be9b0eda2a7a287af0eadd6c3c57c2c65973ed1 | ||
| 65 | 85ec0dcfa66cb028bb7ef5436f07cc7ec500b31038e3b587212ec0ec04c78a953fd6e6 | ||
| 66 | de6d20f83f7594af2601000030820122300d06092a864886f70d01010105000382010f | ||
| 67 | 003082010a0282010100ac74a8f4fb5ff9c1a0338278598eb9c6ba0fce0774e5f2dfe7 | ||
| 68 | d8aff70c0cb2535a834e125f1581127f7a6f5d3f86dc5195fd7a4b1c92b26bd6422d7d | ||
| 69 | 34de63f255b1782446868cb7bfdc3b992ccb233a52ef9c4d5f81954926ca92954b14f8 | ||
| 70 | 046ec50a095dd5556832565712fd9d41cd934410056864573af7d8187d1774c6a004b9 | ||
| 71 | 28eb712a907ec5944e75acd901cfb09a1ce230815caae69da3a0b6bf6fb6d63156b21b | ||
| 72 | 8922ed1917331c4f1421eaa8dbb232f7832dcc35e7a6e6907f62df44fe4a73cd3f2380 | ||
| 73 | 02dfc7a5e2e2fc64ce1596966c7c411f63ad2e19c0339354c53083b31e8cfb923799d5 | ||
| 74 | 05bbaa8c2d6bf92187fe3ae13fe30eabe346242d110203010001 | ||
| 75 | Key·0xf05368c0: | ||
| 76 | f7050000f3050000ad0300002c0000002800000003010000200000007e5580090011c5 | ||
| 77 | 87afdb2f83c96c16e5bcae1321cf87680d0bcbd6a59091e72e6d030000690300003082 | ||
| 78 | 03653082024da003020102020863707fe532bb2ae7300d06092a864886f70d01010b05 | ||
| 79 | 003060310b300906035504061302554b310c300a060355040813034f5247310c300a06 | ||
| 80 | 0355040713034f524731133011060355040a130a6664726f69642e6f7267310f300d06 | ||
| 81 | 0355040b13064644726f6964310f300d060355040313064644726f69643020170d3236 | ||
| 82 | 303632373135343331325a180f32303533313131323135343331325a3060310b300906 | ||
| 83 | 035504061302554b310c300a060355040813034f5247310c300a060355040713034f52 | ||
| 84 | 4731133011060355040a130a6664726f69642e6f7267310f300d060355040b13064644 | ||
| 85 | 726f6964310f300d060355040313064644726f696430820122300d06092a864886f70d | ||
| 86 | 01010105000382010f003082010a0282010100ac74a8f4fb5ff9c1a0338278598eb9c6 | ||
| 87 | ba0fce0774e5f2dfe7d8aff70c0cb2535a834e125f1581127f7a6f5d3f86dc5195fd7a | ||
| 88 | 4b1c92b26bd6422d7d34de63f255b1782446868cb7bfdc3b992ccb233a52ef9c4d5f81 | ||
| 89 | 954926ca92954b14f8046ec50a095dd5556832565712fd9d41cd934410056864573af7 | ||
| 90 | d8187d1774c6a004b928eb712a907ec5944e75acd901cfb09a1ce230815caae69da3a0 | ||
| 91 | b6bf6fb6d63156b21b8922ed1917331c4f1421eaa8dbb232f7832dcc35e7a6e6907f62 | ||
| 92 | df44fe4a73cd3f238002dfc7a5e2e2fc64ce1596966c7c411f63ad2e19c0339354c530 | ||
| 93 | 83b31e8cfb923799d505bbaa8c2d6bf92187fe3ae13fe30eabe346242d110203010001 | ||
| 94 | a321301f301d0603551d0e04160414ecb0d0226aa2fe884f4897c348146f3ffffc96b7 | ||
| 95 | 300d06092a864886f70d01010b0500038201010048373d1fdd119f7858e6e3c2e5c181 | ||
| 96 | b3ed8072b53c4ab90889efb9b8cd0c23eab3e01752c48305ee01f073d5a108e62196d4 | ||
| 97 | ce553bb0022a0055cac40979bccc03c1a6c90ee4baaad9f217f746731470b128bfd3b2 | ||
| 98 | 4d67879509be45a91d5042396036d3b05594d1f5055dca470801751296b3c5f4d72ece | ||
| 99 | c04320cbbb69ee8a6d9d39309916850db9939afdfca7c90755c57a88fe82343d2b02cb | ||
| 100 | fa45c1467ddc6e81e59fadd39925d9b2e62e85c55625247f04ce42a115ae52a52dec25 | ||
| 101 | f249cf08a392f7efb473a319ea4e410e74bb516475b7c881610fb95a013a9209c4243c | ||
| 102 | 948166bff03e2a50f4c1e6da3bad7c6a918afeeb7472bc45ad09efe63b472018000000 | ||
| 103 | ffffff7f0000000018000000ffffff7f0c0100000801000003010000000100001ae985 | ||
| 104 | 75a47ae7612f46fa567935c45303c28dd28408c8770c010c8ebeae559c3cafd5468ba9 | ||
| 105 | 0b2591b315605c700ebc6447df83f6449056e1b0e2f713db1affddb9661717bd6b98f4 | ||
| 106 | ccf609ed936e0294fe1117c4507c3f25b3f35ef4ffd195cf0e57efb9d435225c2878ed | ||
| 107 | 08bc57844c9db4fca16a15940b67cd398d415b2ee9d4a6431d2eb5217eec22cfbdef1e | ||
| 108 | a2a033100e17705ed71e1ceab8972550165fcadcddc38e1d8e0eac7fbee8ca433f72c4 | ||
| 109 | 8a2109c080ebdcb1295fa1875edaa0eda5bf31481089c637ea408d6513704a1915fa73 | ||
| 110 | df2adef4efbccadaf16efdf165b8550f21324921d6187e69cf75a6364e37a2325adb3c | ||
| 111 | 5e7c62fe13b6d5f52601000030820122300d06092a864886f70d01010105000382010f | ||
| 112 | 003082010a0282010100ac74a8f4fb5ff9c1a0338278598eb9c6ba0fce0774e5f2dfe7 | ||
| 113 | d8aff70c0cb2535a834e125f1581127f7a6f5d3f86dc5195fd7a4b1c92b26bd6422d7d | ||
| 114 | 34de63f255b1782446868cb7bfdc3b992ccb233a52ef9c4d5f81954926ca92954b14f8 | ||
| 115 | 046ec50a095dd5556832565712fd9d41cd934410056864573af7d8187d1774c6a004b9 | ||
| 116 | 28eb712a907ec5944e75acd901cfb09a1ce230815caae69da3a0b6bf6fb6d63156b21b | ||
| 117 | 8922ed1917331c4f1421eaa8dbb232f7832dcc35e7a6e6907f62df44fe4a73cd3f2380 | ||
| 118 | 02dfc7a5e2e2fc64ce1596966c7c411f63ad2e19c0339354c53083b31e8cfb923799d5 | ||
| 119 | 05bbaa8c2d6bf92187fe3ae13fe30eabe346242d110203010001 | ||
| Offset 1, 8 lines modified | Offset 1, 8 lines modified | ||
| 1 | Zip·file·size:·63 | 1 | Zip·file·size:·63428637·bytes,·number·of·entries:·216 |
| 2 | -rw-r--r--··0.0·unx·······56·b-·defN·81-Jan-01·01:01·META-INF/com/android/build/gradle/app-metadata.properties | 2 | -rw-r--r--··0.0·unx·······56·b-·defN·81-Jan-01·01:01·META-INF/com/android/build/gradle/app-metadata.properties |
| 3 | -rw-r--r--··0.0·unx······120·b-·defN·81-Jan-01·01:01·META-INF/version-control-info.textproto | 3 | -rw-r--r--··0.0·unx······120·b-·defN·81-Jan-01·01:01·META-INF/version-control-info.textproto |
| 4 | -rw-r--r--··0.0·unx·····6979·b-·stor·81-Jan-01·01:01·assets/dexopt/baseline.prof | 4 | -rw-r--r--··0.0·unx·····6979·b-·stor·81-Jan-01·01:01·assets/dexopt/baseline.prof |
| 5 | -rw-r--r--··0.0·unx······391·b-·stor·81-Jan-01·01:01·assets/dexopt/baseline.profm | 5 | -rw-r--r--··0.0·unx······391·b-·stor·81-Jan-01·01:01·assets/dexopt/baseline.profm |
| 6 | -rw-r--r--··0.0·unx·13583992·b-·defN·81-Jan-01·01:01·classes.dex | 6 | -rw-r--r--··0.0·unx·13583992·b-·defN·81-Jan-01·01:01·classes.dex |
| 7 | -rw-r--r--··0.0·unx··4070296·b-·defN·81-Jan-01·01:01·classes2.dex | 7 | -rw-r--r--··0.0·unx··4070296·b-·defN·81-Jan-01·01:01·classes2.dex |
| 8 | -rw-r--r--··0.0·unx····10096·b-·stor·81-Jan-01·01:01·lib/arm64-v8a/libandroidx.graphics.path.so | 8 | -rw-r--r--··0.0·unx····10096·b-·stor·81-Jan-01·01:01·lib/arm64-v8a/libandroidx.graphics.path.so |
| Offset 70, 15 lines modified | Offset 70, 15 lines modified | ||
| 70 | -rw-r--r--··0.0·unx····24336·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap-native/x86_64/mmap.so | 70 | -rw-r--r--··0.0·unx····24336·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap-native/x86_64/mmap.so |
| 71 | -rw-r--r--··0.0·unx····37608·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap-native/x86_64/zlib.so | 71 | -rw-r--r--··0.0·unx····37608·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap-native/x86_64/zlib.so |
| 72 | -rw-r--r--··0.0·unx···624933·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap.imy | 72 | -rw-r--r--··0.0·unx···624933·b-·stor·81-Jan-01·01:01·assets/chaquopy/bootstrap.imy |
| 73 | -rw-r--r--··0.0·unx·····4242·b-·defN·81-Jan-01·01:01·assets/chaquopy/build.json | 73 | -rw-r--r--··0.0·unx·····4242·b-·defN·81-Jan-01·01:01·assets/chaquopy/build.json |
| 74 | -rw-r--r--··0.0·unx···299427·b-·defN·81-Jan-01·01:01·assets/chaquopy/cacert.pem | 74 | -rw-r--r--··0.0·unx···299427·b-·defN·81-Jan-01·01:01·assets/chaquopy/cacert.pem |
| 75 | -rw-r--r--··0.0·unx··2594339·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-arm64-v8a.imy | 75 | -rw-r--r--··0.0·unx··2594339·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-arm64-v8a.imy |
| 76 | -rw-r--r--··0.0·unx··2315511·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-armeabi-v7a.imy | 76 | -rw-r--r--··0.0·unx··2315511·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-armeabi-v7a.imy |
| 77 | -rw-r--r--··0.0·unx··3 | 77 | -rw-r--r--··0.0·unx··3810937·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-common.imy |
| 78 | -rw-r--r--··0.0·unx··2725620·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-x86_64.imy | 78 | -rw-r--r--··0.0·unx··2725620·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-x86_64.imy |
| 79 | -rw-r--r--··0.0·unx··1478595·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-arm64-v8a.imy | 79 | -rw-r--r--··0.0·unx··1478595·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-arm64-v8a.imy |
| 80 | -rw-r--r--··0.0·unx··1386480·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-armeabi-v7a.imy | 80 | -rw-r--r--··0.0·unx··1386480·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-armeabi-v7a.imy |
| 81 | -rw-r--r--··0.0·unx··4812526·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-common.imy | 81 | -rw-r--r--··0.0·unx··4812526·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-common.imy |
| 82 | -rw-r--r--··0.0·unx··1508233·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-x86_64.imy | 82 | -rw-r--r--··0.0·unx··1508233·b-·stor·81-Jan-01·01:01·assets/chaquopy/stdlib-x86_64.imy |
| 83 | -rw----·····2.4·fat·····1738·b-·defN·81-Jan-01·01:01·DebugProbesKt.bin | 83 | -rw----·····2.4·fat·····1738·b-·defN·81-Jan-01·01:01·DebugProbesKt.bin |
| 84 | -rw----·····2.4·fat········6·b-·stor·81-Jan-01·01:01·META-INF/androidx.activity_activity-compose.version | 84 | -rw----·····2.4·fat········6·b-·stor·81-Jan-01·01:01·META-INF/androidx.activity_activity-compose.version |
| Offset 211, 11 lines modified | Offset 211, 8 lines modified | ||
| 211 | -rw----·····0.0·fat······225·b-·stor·81-Jan-01·01:01·res/wN.9.png | 211 | -rw----·····0.0·fat······225·b-·stor·81-Jan-01·01:01·res/wN.9.png |
| 212 | -rw----·····0.0·fat·····2456·b-·defN·81-Jan-01·01:01·res/xN.xml | 212 | -rw----·····0.0·fat·····2456·b-·defN·81-Jan-01·01:01·res/xN.xml |
| 213 | -rw----·····0.0·fat······221·b-·stor·81-Jan-01·01:01·res/xa.9.png | 213 | -rw----·····0.0·fat······221·b-·stor·81-Jan-01·01:01·res/xa.9.png |
| 214 | -rw----·····0.0·fat······221·b-·stor·81-Jan-01·01:01·res/z-.9.png | 214 | -rw----·····0.0·fat······221·b-·stor·81-Jan-01·01:01·res/z-.9.png |
| 215 | -rw----·····0.0·fat······206·b-·stor·81-Jan-01·01:01·res/zL.png | 215 | -rw----·····0.0·fat······206·b-·stor·81-Jan-01·01:01·res/zL.png |
| 216 | -rw----·····0.0·fat······884·b-·stor·81-Jan-01·01:01·res/zz.png | 216 | -rw----·····0.0·fat······884·b-·stor·81-Jan-01·01:01·res/zz.png |
| 217 | -rw----·····0.0·fat···416072·b-·stor·81-Jan-01·01:01·resources.arsc | 217 | -rw----·····0.0·fat···416072·b-·stor·81-Jan-01·01:01·resources.arsc |
| 218 | -rw----·····2.0·fat····22728·b-·defN·81-Jan-01·01:01·META-INF/57818ACA.SF | ||
| 219 | -rw----·····2.0·fat·····1344·b-·defN·81-Jan-01·01:01·META-INF/57818ACA.RSA | ||
| 220 | -rw----·····2.0·fat····22601·b-·defN·81-Jan-01·01:01·META-INF/MANIFEST.MF | ||
| 221 | 21 | 218 | 216·files,·74789342·bytes·uncompressed,·62907998·bytes·compressed:··15.9% |
| Offset 1, 8 lines modified | Offset 1, 8 lines modified | ||
| 1 | Zip·file·size:·3 | 1 | Zip·file·size:·3810937·bytes,·number·of·entries:·772 |
| 2 | -rw----·····2.0·fat····34703·b-·defN·80-Feb-01·00:00·six.py | 2 | -rw----·····2.0·fat····34703·b-·defN·80-Feb-01·00:00·six.py |
| 3 | -rw----·····2.0·fat···165012·b-·defN·80-Feb-01·00:00·typing_extensions.py | 3 | -rw----·····2.0·fat···165012·b-·defN·80-Feb-01·00:00·typing_extensions.py |
| 4 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·PIL/ | 4 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·PIL/ |
| 5 | -rw----·····2.0·fat·····3477·b-·defN·80-Feb-01·00:00·PIL/BdfFontFile.py | 5 | -rw----·····2.0·fat·····3477·b-·defN·80-Feb-01·00:00·PIL/BdfFontFile.py |
| 6 | -rw----·····2.0·fat····16584·b-·defN·80-Feb-01·00:00·PIL/BlpImagePlugin.py | 6 | -rw----·····2.0·fat····16584·b-·defN·80-Feb-01·00:00·PIL/BlpImagePlugin.py |
| 7 | -rw----·····2.0·fat····19758·b-·defN·80-Feb-01·00:00·PIL/BmpImagePlugin.py | 7 | -rw----·····2.0·fat····19758·b-·defN·80-Feb-01·00:00·PIL/BmpImagePlugin.py |
| 8 | -rw----·····2.0·fat·····1753·b-·defN·80-Feb-01·00:00·PIL/BufrStubImagePlugin.py | 8 | -rw----·····2.0·fat·····1753·b-·defN·80-Feb-01·00:00·PIL/BufrStubImagePlugin.py |
| Offset 142, 35 lines modified | Offset 142, 35 lines modified | ||
| 142 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·chaquopy_libxml2-2.9.8.dist-info/INSTALLER | 142 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·chaquopy_libxml2-2.9.8.dist-info/INSTALLER |
| 143 | -rw----·····2.0·fat·······86·b-·defN·80-Feb-01·00:00·chaquopy_libxml2-2.9.8.dist-info/METADATA | 143 | -rw----·····2.0·fat·······86·b-·defN·80-Feb-01·00:00·chaquopy_libxml2-2.9.8.dist-info/METADATA |
| 144 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/ | 144 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/ |
| 145 | -rw----·····2.0·fat·····2968·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/COPYING | 145 | -rw----·····2.0·fat·····2968·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/COPYING |
| 146 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/INSTALLER | 146 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/INSTALLER |
| 147 | -rw----·····2.0·fat······129·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/METADATA | 147 | -rw----·····2.0·fat······129·b-·defN·80-Feb-01·00:00·chaquopy_libxslt-1.1.32.dist-info/METADATA |
| 148 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/ | 148 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/ |
| 149 | -rw----·····2.0·fat·····15 | 149 | -rw----·····2.0·fat·····1582·b-·defN·80-Feb-01·00:00·charset_normalizer/__init__.py |
| 150 | -rw----·····2.0·fat······109·b-·defN·80-Feb-01·00:00·charset_normalizer/__main__.py | 150 | -rw----·····2.0·fat······109·b-·defN·80-Feb-01·00:00·charset_normalizer/__main__.py |
| 151 | -rw----·····2.0·fat···· | 151 | -rw----·····2.0·fat····35774·b-·defN·80-Feb-01·00:00·charset_normalizer/api.py |
| 152 | -rw----·····2.0·fat····15980·b-·defN·80-Feb-01·00:00·charset_normalizer/cd.py | 152 | -rw----·····2.0·fat····15980·b-·defN·80-Feb-01·00:00·charset_normalizer/cd.py |
| 153 | -rw----·····2.0·fat···· | 153 | -rw----·····2.0·fat····60812·b-·defN·80-Feb-01·00:00·charset_normalizer/constant.py |
| 154 | -rw----·····2.0·fat·····2651·b-·defN·80-Feb-01·00:00·charset_normalizer/legacy.py | 154 | -rw----·····2.0·fat·····2651·b-·defN·80-Feb-01·00:00·charset_normalizer/legacy.py |
| 155 | -rw----·····2.0·fat····32 | 155 | -rw----·····2.0·fat····35274·b-·defN·80-Feb-01·00:00·charset_normalizer/md.py |
| 156 | -rw----·····2.0·fat····1 | 156 | -rw----·····2.0·fat····13530·b-·defN·80-Feb-01·00:00·charset_normalizer/models.py |
| 157 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/py.typed | 157 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/py.typed |
| 158 | -rw----·····2.0·fat····1 | 158 | -rw----·····2.0·fat····14122·b-·defN·80-Feb-01·00:00·charset_normalizer/utils.py |
| 159 | -rw----·····2.0·fat······115·b-·defN·80-Feb-01·00:00·charset_normalizer/version.py | 159 | -rw----·····2.0·fat······115·b-·defN·80-Feb-01·00:00·charset_normalizer/version.py |
| 160 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/ | 160 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/ |
| 161 | -rw----·····2.0·fat······136·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/__init__.py | 161 | -rw----·····2.0·fat······136·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/__init__.py |
| 162 | -rw----·····2.0·fat····11949·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/__main__.py | 162 | -rw----·····2.0·fat····11949·b-·defN·80-Feb-01·00:00·charset_normalizer/cli/__main__.py |
| 163 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 163 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/ |
| 164 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 164 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/INSTALLER |
| 165 | -rw----·····2.0·fat····4 | 165 | -rw----·····2.0·fat····46395·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/METADATA |
| 166 | -rw----·····2.0·fat·······65·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 166 | -rw----·····2.0·fat·······65·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/entry_points.txt |
| 167 | -rw----·····2.0·fat·······19·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 167 | -rw----·····2.0·fat·······19·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/top_level.txt |
| 168 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 168 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/licenses/ |
| 169 | -rw----·····2.0·fat·····1071·b-·defN·80-Feb-01·00:00·charset_normalizer-3. | 169 | -rw----·····2.0·fat·····1071·b-·defN·80-Feb-01·00:00·charset_normalizer-3.5.2.dist-info/licenses/LICENSE |
| 170 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·css_parser/ | 170 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·css_parser/ |
| 171 | -rw----·····2.0·fat····15860·b-·defN·80-Feb-01·00:00·css_parser/__init__.py | 171 | -rw----·····2.0·fat····15860·b-·defN·80-Feb-01·00:00·css_parser/__init__.py |
| 172 | -rw----·····2.0·fat·····1891·b-·defN·80-Feb-01·00:00·css_parser/_fetch.py | 172 | -rw----·····2.0·fat·····1891·b-·defN·80-Feb-01·00:00·css_parser/_fetch.py |
| 173 | -rw----·····2.0·fat·····2715·b-·defN·80-Feb-01·00:00·css_parser/_fetchgae.py | 173 | -rw----·····2.0·fat·····2715·b-·defN·80-Feb-01·00:00·css_parser/_fetchgae.py |
| 174 | -rw----·····2.0·fat····24413·b-·defN·80-Feb-01·00:00·css_parser/codec.py | 174 | -rw----·····2.0·fat····24413·b-·defN·80-Feb-01·00:00·css_parser/codec.py |
| 175 | -rw----·····2.0·fat·····4929·b-·defN·80-Feb-01·00:00·css_parser/cssproductions.py | 175 | -rw----·····2.0·fat·····4929·b-·defN·80-Feb-01·00:00·css_parser/cssproductions.py |
| 176 | -rw----·····2.0·fat·····4059·b-·defN·80-Feb-01·00:00·css_parser/errorhandler.py | 176 | -rw----·····2.0·fat·····4059·b-·defN·80-Feb-01·00:00·css_parser/errorhandler.py |
| Offset 226, 23 lines modified | Offset 226, 23 lines modified | ||
| 226 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/INSTALLER | 226 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/INSTALLER |
| 227 | -rw----·····2.0·fat·····1582·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/METADATA | 227 | -rw----·····2.0·fat·····1582·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/METADATA |
| 228 | -rw----·····2.0·fat·······11·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/top_level.txt | 228 | -rw----·····2.0·fat·······11·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/top_level.txt |
| 229 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/ | 229 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/ |
| 230 | -rw----·····2.0·fat····35821·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/COPYING | 230 | -rw----·····2.0·fat····35821·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/COPYING |
| 231 | -rw----·····2.0·fat·····7802·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/COPYING.LESSER | 231 | -rw----·····2.0·fat·····7802·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/licenses/COPYING.LESSER |
| 232 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2/ | 232 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2/ |
| 233 | -rw----·····2.0·fat·····42 | 233 | -rw----·····2.0·fat·····4290·b-·defN·80-Feb-01·00:00·cssselect2/__init__.py |
| 234 | -rw----·····2.0·fat····18907·b-·defN·80-Feb-01·00:00·cssselect2/compiler.py | 234 | -rw----·····2.0·fat····18907·b-·defN·80-Feb-01·00:00·cssselect2/compiler.py |
| 235 | -rw----·····2.0·fat····16 | 235 | -rw----·····2.0·fat····16357·b-·defN·80-Feb-01·00:00·cssselect2/parser.py |
| 236 | -rw----·····2.0·fat····13612·b-·defN·80-Feb-01·00:00·cssselect2/tree.py | 236 | -rw----·····2.0·fat····13612·b-·defN·80-Feb-01·00:00·cssselect2/tree.py |
| 237 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2-0. | 237 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/ |
| 238 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·cssselect2-0. | 238 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/INSTALLER |
| 239 | -rw----·····2.0·fat·····29 | 239 | -rw----·····2.0·fat·····2941·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/METADATA |
| 240 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2-0. | 240 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/licenses/ |
| 241 | -rw----·····2.0·fat·····1548·b-·defN·80-Feb-01·00:00·cssselect2-0. | 241 | -rw----·····2.0·fat·····1548·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/licenses/LICENSE |
| 242 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·dateutil/ | 242 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·dateutil/ |
| 243 | -rw----·····2.0·fat······620·b-·defN·80-Feb-01·00:00·dateutil/__init__.py | 243 | -rw----·····2.0·fat······620·b-·defN·80-Feb-01·00:00·dateutil/__init__.py |
| 244 | -rw----·····2.0·fat······932·b-·defN·80-Feb-01·00:00·dateutil/_common.py | 244 | -rw----·····2.0·fat······932·b-·defN·80-Feb-01·00:00·dateutil/_common.py |
| 245 | -rw----·····2.0·fat······166·b-·defN·80-Feb-01·00:00·dateutil/_version.py | 245 | -rw----·····2.0·fat······166·b-·defN·80-Feb-01·00:00·dateutil/_version.py |
| 246 | -rw----·····2.0·fat·····2678·b-·defN·80-Feb-01·00:00·dateutil/easter.py | 246 | -rw----·····2.0·fat·····2678·b-·defN·80-Feb-01·00:00·dateutil/easter.py |
| 247 | -rw----·····2.0·fat····24903·b-·defN·80-Feb-01·00:00·dateutil/relativedelta.py | 247 | -rw----·····2.0·fat····24903·b-·defN·80-Feb-01·00:00·dateutil/relativedelta.py |
| 248 | -rw----·····2.0·fat····66557·b-·defN·80-Feb-01·00:00·dateutil/rrule.py | 248 | -rw----·····2.0·fat····66557·b-·defN·80-Feb-01·00:00·dateutil/rrule.py |
| Offset 276, 42 lines modified | Offset 276, 44 lines modified | ||
| 276 | -rw----·····2.0·fat·····5364·b-·defN·80-Feb-01·00:00·defusedxml/xmlrpc.py | 276 | -rw----·····2.0·fat·····5364·b-·defN·80-Feb-01·00:00·defusedxml/xmlrpc.py |
| 277 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/ | 277 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/ |
| 278 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/INSTALLER | 278 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/INSTALLER |
| 279 | -rw----·····2.0·fat·····2409·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/LICENSE | 279 | -rw----·····2.0·fat·····2409·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/LICENSE |
| 280 | -rw----·····2.0·fat····32518·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/METADATA | 280 | -rw----·····2.0·fat····32518·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/METADATA |
| 281 | -rw----·····2.0·fat·······11·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/top_level.txt | 281 | -rw----·····2.0·fat·······11·b-·defN·80-Feb-01·00:00·defusedxml-0.7.1.dist-info/top_level.txt |
| 282 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/ | 282 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/ |
| 283 | -rw----·····2.0·fat····· | 283 | -rw----·····2.0·fat·····5693·b-·defN·80-Feb-01·00:00·filelock/__init__.py |
| 284 | -rw----·····2.0·fat··· | 284 | -rw----·····2.0·fat···106170·b-·defN·80-Feb-01·00:00·filelock/_api.py |
| 285 | -rw----·····2.0·fat···· | 285 | -rw----·····2.0·fat····20487·b-·defN·80-Feb-01·00:00·filelock/_async.py |
| 286 | -rw----·····2.0·fat····1 | 286 | -rw----·····2.0·fat····17947·b-·defN·80-Feb-01·00:00·filelock/_async_read_write.py |
| 287 | -rw----·····2.0·fat····· | 287 | -rw----·····2.0·fat·····3277·b-·defN·80-Feb-01·00:00·filelock/_descriptor.py |
| 288 | -rw----·····2.0·fat····· | 288 | -rw----·····2.0·fat·····3235·b-·defN·80-Feb-01·00:00·filelock/_error.py |
| 289 | -rw----·····2.0·fat···· | 289 | -rw----·····2.0·fat····17183·b-·defN·80-Feb-01·00:00·filelock/_identity.py |
| 290 | -rw----·····2.0·fat····1 | 290 | -rw----·····2.0·fat····19173·b-·defN·80-Feb-01·00:00·filelock/_lease.py |
| 291 | -rw----·····2.0·fat····· | 291 | -rw----·····2.0·fat·····7896·b-·defN·80-Feb-01·00:00·filelock/_marker.py |
| 292 | -rw----·····2.0·fat···· | 292 | -rw----·····2.0·fat····68071·b-·defN·80-Feb-01·00:00·filelock/_read_write.py |
| 293 | -rw----·····2.0·fat···· | 293 | -rw----·····2.0·fat····33064·b-·defN·80-Feb-01·00:00·filelock/_soft.py |
| 294 | -rw----·····2.0·fat······18 | 294 | -rw----·····2.0·fat······218·b-·defN·80-Feb-01·00:00·filelock/_soft_protocol.py |
| 295 | -rw----·····2.0·fat···· | 295 | -rw----·····2.0·fat····58570·b-·defN·80-Feb-01·00:00·filelock/_strict.py |
| 296 | -rw----·····2.0·fat···· | 296 | -rw----·····2.0·fat····10985·b-·defN·80-Feb-01·00:00·filelock/_unix.py |
| 297 | -rw----·····2.0·fat···· | 297 | -rw----·····2.0·fat····19280·b-·defN·80-Feb-01·00:00·filelock/_util.py |
| 298 | -rw----·····2.0·fat···· | 298 | -rw----·····2.0·fat····38880·b-·defN·80-Feb-01·00:00·filelock/_windows.py |
| 299 | -rw----·····2.0·fat···· | 299 | -rw----·····2.0·fat····42865·b-·defN·80-Feb-01·00:00·filelock/asyncio.py |
| 300 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/py.typed | 300 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/py.typed |
| 301 | -rw----·····2.0·fat······52 | 301 | -rw----·····2.0·fat······520·b-·defN·80-Feb-01·00:00·filelock/version.py |
| 302 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/ | 302 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/ |
| 303 | -rw----·····2.0·fat······ | 303 | -rw----·····2.0·fat······452·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/__init__.py |
| 304 | -rw----·····2.0·fat····1 | 304 | -rw----·····2.0·fat····16939·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_async.py |
| 305 | -rw----·····2.0·fat····30996·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_protocol.py | ||
| 306 | -rw----·····2.0·fat····13691·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_storage.py | ||
| 305 | -rw----·····2.0·fat···· | 307 | -rw----·····2.0·fat····37638·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_sync.py |
| 306 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock- | 308 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/ |
| 307 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·filelock- | 309 | -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/INSTALLER |
| 308 | -rw----·····2.0·fat····· | 310 | -rw----·····2.0·fat·····1976·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/METADATA |
| 309 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock- | 311 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/licenses/ |
| 310 | -rw----·····2.0·fat·····1088·b-·defN·80-Feb-01·00:00·filelock- | 312 | -rw----·····2.0·fat·····1088·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/licenses/LICENSE |
| 311 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·html2text/ | 313 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·html2text/ |
| 312 | -rw----·····2.0·fat····37885·b-·defN·80-Feb-01·00:00·html2text/__init__.py | 314 | -rw----·····2.0·fat····37885·b-·defN·80-Feb-01·00:00·html2text/__init__.py |
| 313 | -rw----·····2.0·fat·······30·b-·defN·80-Feb-01·00:00·html2text/__main__.py | 315 | -rw----·····2.0·fat·······30·b-·defN·80-Feb-01·00:00·html2text/__main__.py |
| 314 | -rw----·····2.0·fat·······63·b-·defN·80-Feb-01·00:00·html2text/_typing.py | 316 | -rw----·····2.0·fat·······63·b-·defN·80-Feb-01·00:00·html2text/_typing.py |
| 315 | -rw----·····2.0·fat······519·b-·defN·80-Feb-01·00:00·html2text/_version.py | 317 | -rw----·····2.0·fat······519·b-·defN·80-Feb-01·00:00·html2text/_version.py |
| 316 | -rw----·····2.0·fat····10300·b-·defN·80-Feb-01·00:00·html2text/cli.py | 318 | -rw----·····2.0·fat····10300·b-·defN·80-Feb-01·00:00·html2text/cli.py |
| 317 | -rw----·····2.0·fat·····4052·b-·defN·80-Feb-01·00:00·html2text/config.py | 319 | -rw----·····2.0·fat·····4052·b-·defN·80-Feb-01·00:00·html2text/config.py |
| Offset 509, 15 lines modified | Offset 511, 15 lines modified | ||
| 509 | -rw----·····2.0·fat·····3284·b-·defN·80-Feb-01·00:00·reportlab/fonts/hb-test.ttf | 511 | -rw----·····2.0·fat·····3284·b-·defN·80-Feb-01·00:00·reportlab/fonts/hb-test.ttf |
| 510 | -rw----·····2.0·fat····34705·b-·defN·80-Feb-01·00:00·reportlab/fonts/sy______.pfb | 512 | -rw----·····2.0·fat····34705·b-·defN·80-Feb-01·00:00·reportlab/fonts/sy______.pfb |
| 511 | -rw----·····2.0·fat····49593·b-·defN·80-Feb-01·00:00·reportlab/fonts/zd______.pfb | 513 | -rw----·····2.0·fat····49593·b-·defN·80-Feb-01·00:00·reportlab/fonts/zd______.pfb |
| 512 | -rw----·····2.0·fat····75573·b-·defN·80-Feb-01·00:00·reportlab/fonts/zx______.pfb | 514 | -rw----·····2.0·fat····75573·b-·defN·80-Feb-01·00:00·reportlab/fonts/zx______.pfb |
| 513 | -rw----·····2.0·fat····96418·b-·defN·80-Feb-01·00:00·reportlab/fonts/zy______.pfb | 515 | -rw----·····2.0·fat····96418·b-·defN·80-Feb-01·00:00·reportlab/fonts/zy______.pfb |
| 514 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·reportlab/graphics/ | 516 | -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·reportlab/graphics/ |
| 515 | -rw----·····2.0·fat······274·b-·defN·80-Feb-01·00:00·reportlab/graphics/__init__.py | 517 | -rw----·····2.0·fat······274·b-·defN·80-Feb-01·00:00·reportlab/graphics/__init__.py |
| 516 | -rw----·····2.0·fat····15 | 518 | -rw----·····2.0·fat····15309·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPDF.py |
| 517 | -rw----·····2.0·fat····30616·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPM.py | 519 | -rw----·····2.0·fat····30616·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPM.py |
| 518 | -rw----·····2.0·fat····37937·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPS.py | 520 | -rw----·····2.0·fat····37937·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPS.py |
| 519 | -rw----·····2.0·fat····38094·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderSVG.py | 521 | -rw----·····2.0·fat····38094·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderSVG.py |
| 520 | -rw----·····2.0·fat····13206·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderbase.py | 522 | -rw----·····2.0·fat····13206·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderbase.py |
| 521 | -rw----·····2.0·fat····59205·b-·defN·80-Feb-01·00:00·reportlab/graphics/shapes.py | 523 | -rw----·····2.0·fat····59205·b-·defN·80-Feb-01·00:00·reportlab/graphics/shapes.py |
| Max diff block lines reached; 12297/26511 bytes (46.38%) of diff not shown. | |||
| Offset 477, 33 lines modified | Offset 477, 33 lines modified | ||
| 477 | Filename:·charset_normalizer/cli/__init__.py | 477 | Filename:·charset_normalizer/cli/__init__.py |
| 478 | Comment:· | 478 | Comment:· |
| 479 | Filename:·charset_normalizer/cli/__main__.py | 479 | Filename:·charset_normalizer/cli/__main__.py |
| 480 | Comment:· | 480 | Comment:· |
| 481 | Filename:·charset_normalizer-3. | 481 | Filename:·charset_normalizer-3.5.2.dist-info/ |
| 482 | Comment:· | 482 | Comment:· |
| 483 | Filename:·charset_normalizer-3. | 483 | Filename:·charset_normalizer-3.5.2.dist-info/INSTALLER |
| 484 | Comment:· | 484 | Comment:· |
| 485 | Filename:·charset_normalizer-3. | 485 | Filename:·charset_normalizer-3.5.2.dist-info/METADATA |
| 486 | Comment:· | 486 | Comment:· |
| 487 | Filename:·charset_normalizer-3. | 487 | Filename:·charset_normalizer-3.5.2.dist-info/entry_points.txt |
| 488 | Comment:· | 488 | Comment:· |
| 489 | Filename:·charset_normalizer-3. | 489 | Filename:·charset_normalizer-3.5.2.dist-info/top_level.txt |
| 490 | Comment:· | 490 | Comment:· |
| 491 | Filename:·charset_normalizer-3. | 491 | Filename:·charset_normalizer-3.5.2.dist-info/licenses/ |
| 492 | Comment:· | 492 | Comment:· |
| 493 | Filename:·charset_normalizer-3. | 493 | Filename:·charset_normalizer-3.5.2.dist-info/licenses/LICENSE |
| 494 | Comment:· | 494 | Comment:· |
| 495 | Filename:·css_parser/ | 495 | Filename:·css_parser/ |
| 496 | Comment:· | 496 | Comment:· |
| 497 | Filename:·css_parser/__init__.py | 497 | Filename:·css_parser/__init__.py |
| 498 | Comment:· | 498 | Comment:· |
| Offset 699, 27 lines modified | Offset 699, 27 lines modified | ||
| 699 | Filename:·cssselect2/parser.py | 699 | Filename:·cssselect2/parser.py |
| 700 | Comment:· | 700 | Comment:· |
| 701 | Filename:·cssselect2/tree.py | 701 | Filename:·cssselect2/tree.py |
| 702 | Comment:· | 702 | Comment:· |
| 703 | Filename:·cssselect2-0. | 703 | Filename:·cssselect2-0.10.1.dist-info/ |
| 704 | Comment:· | 704 | Comment:· |
| 705 | Filename:·cssselect2-0. | 705 | Filename:·cssselect2-0.10.1.dist-info/INSTALLER |
| 706 | Comment:· | 706 | Comment:· |
| 707 | Filename:·cssselect2-0. | 707 | Filename:·cssselect2-0.10.1.dist-info/METADATA |
| 708 | Comment:· | 708 | Comment:· |
| 709 | Filename:·cssselect2-0. | 709 | Filename:·cssselect2-0.10.1.dist-info/licenses/ |
| 710 | Comment:· | 710 | Comment:· |
| 711 | Filename:·cssselect2-0. | 711 | Filename:·cssselect2-0.10.1.dist-info/licenses/LICENSE |
| 712 | Comment:· | 712 | Comment:· |
| 713 | Filename:·dateutil/ | 713 | Filename:·dateutil/ |
| 714 | Comment:· | 714 | Comment:· |
| 715 | Filename:·dateutil/__init__.py | 715 | Filename:·dateutil/__init__.py |
| 716 | Comment:· | 716 | Comment:· |
| Offset 903, 30 lines modified | Offset 903, 36 lines modified | ||
| 903 | Filename:·filelock/_soft_rw/__init__.py | 903 | Filename:·filelock/_soft_rw/__init__.py |
| 904 | Comment:· | 904 | Comment:· |
| 905 | Filename:·filelock/_soft_rw/_async.py | 905 | Filename:·filelock/_soft_rw/_async.py |
| 906 | Comment:· | 906 | Comment:· |
| 907 | Filename:·filelock/_soft_rw/_protocol.py | ||
| 908 | Comment:· | ||
| 909 | Filename:·filelock/_soft_rw/_storage.py | ||
| 910 | Comment:· | ||
| 907 | Filename:·filelock/_soft_rw/_sync.py | 911 | Filename:·filelock/_soft_rw/_sync.py |
| 908 | Comment:· | 912 | Comment:· |
| 909 | Filename:·filelock- | 913 | Filename:·filelock-4.2.4.dist-info/ |
| 910 | Comment:· | 914 | Comment:· |
| 911 | Filename:·filelock- | 915 | Filename:·filelock-4.2.4.dist-info/INSTALLER |
| 912 | Comment:· | 916 | Comment:· |
| 913 | Filename:·filelock- | 917 | Filename:·filelock-4.2.4.dist-info/METADATA |
| 914 | Comment:· | 918 | Comment:· |
| 915 | Filename:·filelock- | 919 | Filename:·filelock-4.2.4.dist-info/licenses/ |
| 916 | Comment:· | 920 | Comment:· |
| 917 | Filename:·filelock- | 921 | Filename:·filelock-4.2.4.dist-info/licenses/LICENSE |
| 918 | Comment:· | 922 | Comment:· |
| 919 | Filename:·html2text/ | 923 | Filename:·html2text/ |
| 920 | Comment:· | 924 | Comment:· |
| 921 | Filename:·html2text/__init__.py | 925 | Filename:·html2text/__init__.py |
| 922 | Comment:· | 926 | Comment:· |
| Offset 2025, 30 lines modified | Offset 2031, 30 lines modified | ||
| 2025 | Filename:·reportlab/platypus/tables.py | 2031 | Filename:·reportlab/platypus/tables.py |
| 2026 | Comment:· | 2032 | Comment:· |
| 2027 | Filename:·reportlab/platypus/xpreformatted.py | 2033 | Filename:·reportlab/platypus/xpreformatted.py |
| 2028 | Comment:· | 2034 | Comment:· |
| 2029 | Filename:·reportlab-5.0. | 2035 | Filename:·reportlab-5.0.1.dist-info/ |
| 2030 | Comment:· | 2036 | Comment:· |
| 2031 | Filename:·reportlab-5.0. | 2037 | Filename:·reportlab-5.0.1.dist-info/INSTALLER |
| 2032 | Comment:· | 2038 | Comment:· |
| 2033 | Filename:·reportlab-5.0. | 2039 | Filename:·reportlab-5.0.1.dist-info/METADATA |
| 2034 | Comment:· | 2040 | Comment:· |
| 2035 | Filename:·reportlab-5.0. | 2041 | Filename:·reportlab-5.0.1.dist-info/top_level.txt |
| 2036 | Comment:· | 2042 | Comment:· |
| 2037 | Filename:·reportlab-5.0. | 2043 | Filename:·reportlab-5.0.1.dist-info/licenses/ |
| 2038 | Comment:· | 2044 | Comment:· |
| 2039 | Filename:·reportlab-5.0. | 2045 | Filename:·reportlab-5.0.1.dist-info/licenses/LICENSE |
| 2040 | Comment:· | 2046 | Comment:· |
| 2041 | Filename:·six-1.17.0.dist-info/ | 2047 | Filename:·six-1.17.0.dist-info/ |
| 2042 | Comment:· | 2048 | Comment:· |
| Max diff block lines reached; 2561/6172 bytes (41.49%) of diff not shown. | |||
| Offset 3532, 35923 lines modified | Offset 3532, 35872 lines modified | ||
| 3532 | 07746D·Extract·Zip·Spec······14·(20)·'2.0' | 3532 | 07746D·Extract·Zip·Spec······14·(20)·'2.0' |
| 3533 | 07746E·Extract·OS············00·(0)·'MS-DOS' | 3533 | 07746E·Extract·OS············00·(0)·'MS-DOS' |
| 3534 | 07746F·General·Purpose·Flag··0800·(2048) | 3534 | 07746F·General·Purpose·Flag··0800·(2048) |
| 3535 | ·······[Bits·1-2]············0·'Normal·Compression' | 3535 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3536 | ·······[Bit·11]··············1·'Language·Encoding' | 3536 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3537 | 077471·Compression·Method····0008·(8)·'Deflated' | 3537 | 077471·Compression·Method····0008·(8)·'Deflated' |
| 3538 | 077473·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' | 3538 | 077473·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' |
| 3539 | 077477·CRC··················· | 3539 | 077477·CRC···················36D9FA28·(920255016) |
| 3540 | 07747B·Compressed·Size·······000003 | 3540 | 07747B·Compressed·Size·······0000031C·(796) |
| 3541 | 07747F·Uncompressed·Size·····000006 | 3541 | 07747F·Uncompressed·Size·····0000062E·(1582) |
| 3542 | 077483·Filename·Length·······001E·(30) | 3542 | 077483·Filename·Length·······001E·(30) |
| 3543 | 077485·Extra·Length··········0014·(20) | 3543 | 077485·Extra·Length··········0014·(20) |
| 3544 | 077487·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' | 3544 | 077487·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3545 | # | 3545 | # |
| 3546 | #·WARNING:·Offset·0x77487:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' | 3546 | #·WARNING:·Offset·0x77487:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3547 | #··········Zero·length·filename | 3547 | #··········Zero·length·filename |
| 3548 | # | 3548 | # |
| 3549 | 0774A5·Extra·ID·#1···········0001·(1)·'ZIP64' | 3549 | 0774A5·Extra·ID·#1···········0001·(1)·'ZIP64' |
| 3550 | 0774A7···Length··············0010·(16) | 3550 | 0774A7···Length··············0010·(16) |
| 3551 | 0774A9···Uncompressed·Size···00000000000006 | 3551 | 0774A9···Uncompressed·Size···000000000000062E·(1582) |
| 3552 | 0774B1···Compressed·Size·····00000000000003 | 3552 | 0774B1···Compressed·Size·····000000000000031C·(796) |
| 3553 | 0774B9·PAYLOAD | 3553 | 0774B9·PAYLOAD | Diff chunk too large, falling back to line-by-line diff (2567 lines added, 2567 lines removed) |
| 3554 | 0777D | 3554 | 0777D5·LOCAL·HEADER·#149·····04034B50·(67324752) |
| 3555 | 0777 | 3555 | 0777D9·Extract·Zip·Spec······14·(20)·'2.0' |
| 3556 | 0777 | 3556 | 0777DA·Extract·OS············00·(0)·'MS-DOS' |
| 3557 | 0777 | 3557 | 0777DB·General·Purpose·Flag··0800·(2048) |
| 3558 | ·······[Bits·1-2]············0·'Normal·Compression' | 3558 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3559 | ·······[Bit·11]··············1·'Language·Encoding' | 3559 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3560 | 0777 | 3560 | 0777DD·Compression·Method····0008·(8)·'Deflated' |
| 3561 | 0777 | 3561 | 0777DF·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' |
| 3562 | 0777E | 3562 | 0777E3·CRC···················35633DF4·(895696372) |
| 3563 | 0777E | 3563 | 0777E7·Compressed·Size·······00000055·(85) |
| 3564 | 0777 | 3564 | 0777EB·Uncompressed·Size·····0000006D·(109) |
| 3565 | 0777 | 3565 | 0777EF·Filename·Length·······001E·(30) |
| 3566 | 0777F | 3566 | 0777F1·Extra·Length··········0014·(20) |
| 3567 | 0777F | 3567 | 0777F3·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3568 | # | 3568 | # |
| 3569 | #·WARNING:·Offset·0x777F | 3569 | #·WARNING:·Offset·0x777F3:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3570 | #··········Zero·length·filename | 3570 | #··········Zero·length·filename |
| 3571 | # | 3571 | # |
| 3572 | 07781 | 3572 | 077811·Extra·ID·#1···········0001·(1)·'ZIP64' |
| 3573 | 07781 | 3573 | 077813···Length··············0010·(16) |
| 3574 | 07781 | 3574 | 077815···Uncompressed·Size···000000000000006D·(109) |
| 3575 | 0778 | 3575 | 07781D···Compressed·Size·····0000000000000055·(85) |
| 3576 | 07782 | 3576 | 077825·PAYLOAD···············XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
| 3577 | 0778 | 3577 | 07787A·LOCAL·HEADER·#150·····04034B50·(67324752) |
| 3578 | 0778 | 3578 | 07787E·Extract·Zip·Spec······14·(20)·'2.0' |
| 3579 | 0778 | 3579 | 07787F·Extract·OS············00·(0)·'MS-DOS' |
| 3580 | 07788 | 3580 | 077880·General·Purpose·Flag··0800·(2048) |
| 3581 | ·······[Bits·1-2]············0·'Normal·Compression' | 3581 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3582 | ·······[Bit·11]··············1·'Language·Encoding' | 3582 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3583 | 07788 | 3583 | 077882·Compression·Method····0008·(8)·'Deflated' |
| 3584 | 07788 | 3584 | 077884·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' |
| 3585 | 0778 | 3585 | 077888·CRC···················155BD86E·(358340718) |
| 3586 | 0778 | 3586 | 07788C·Compressed·Size·······000020BB·(8379) |
| 3587 | 07789 | 3587 | 077890·Uncompressed·Size·····00008BBE·(35774) |
| 3588 | 07789 | 3588 | 077894·Filename·Length·······0019·(25) |
| 3589 | 07789 | 3589 | 077896·Extra·Length··········0014·(20) |
| 3590 | 0778 | 3590 | 077898·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3591 | # | 3591 | # |
| 3592 | #·WARNING:·Offset·0x778 | 3592 | #·WARNING:·Offset·0x77898:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3593 | #··········Zero·length·filename | 3593 | #··········Zero·length·filename |
| 3594 | # | 3594 | # |
| 3595 | 0778B | 3595 | 0778B1·Extra·ID·#1···········0001·(1)·'ZIP64' |
| 3596 | 0778B | 3596 | 0778B3···Length··············0010·(16) |
| 3597 | 0778B | 3597 | 0778B5···Uncompressed·Size···0000000000008BBE·(35774) |
| 3598 | 0778 | 3598 | 0778BD···Compressed·Size·····00000000000020BB·(8379) |
| 3599 | 0778C | 3599 | 0778C5·PAYLOAD |
| 3600 | 079 | 3600 | 079980·LOCAL·HEADER·#151·····04034B50·(67324752) |
| 3601 | 079 | 3601 | 079984·Extract·Zip·Spec······14·(20)·'2.0' |
| 3602 | 079 | 3602 | 079985·Extract·OS············00·(0)·'MS-DOS' |
| 3603 | 079 | 3603 | 079986·General·Purpose·Flag··0800·(2048) |
| 3604 | ·······[Bits·1-2]············0·'Normal·Compression' | 3604 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3605 | ·······[Bit·11]··············1·'Language·Encoding' | 3605 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3606 | 079 | 3606 | 079988·Compression·Method····0008·(8)·'Deflated' |
| 3607 | 079 | 3607 | 07998A·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' |
| 3608 | 079 | 3608 | 07998E·CRC···················16049338·(369398584) |
| 3609 | 079 | 3609 | 079992·Compressed·Size·······000010D3·(4307) |
| 3610 | 079 | 3610 | 079996·Uncompressed·Size·····00003E6C·(15980) |
| 3611 | 079 | 3611 | 07999A·Filename·Length·······0018·(24) |
| 3612 | 079 | 3612 | 07999C·Extra·Length··········0014·(20) |
| 3613 | 079 | 3613 | 07999E·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXX' |
| 3614 | # | 3614 | # |
| 3615 | #·WARNING:·Offset·0x79 | 3615 | #·WARNING:·Offset·0x7999E:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXX' |
| 3616 | #··········Zero·length·filename | 3616 | #··········Zero·length·filename |
| 3617 | # | 3617 | # |
| 3618 | 079 | 3618 | 0799B6·Extra·ID·#1···········0001·(1)·'ZIP64' |
| 3619 | 079 | 3619 | 0799B8···Length··············0010·(16) |
| 3620 | 079 | 3620 | 0799BA···Uncompressed·Size···0000000000003E6C·(15980) |
| 3621 | 079 | 3621 | 0799C2···Compressed·Size·····00000000000010D3·(4307) |
| 3622 | 079 | 3622 | 0799CA·PAYLOAD |
| 3623 | 07A | 3623 | 07AA9D·LOCAL·HEADER·#152·····04034B50·(67324752) |
| 3624 | 07A | 3624 | 07AAA1·Extract·Zip·Spec······14·(20)·'2.0' |
| 3625 | 07A | 3625 | 07AAA2·Extract·OS············00·(0)·'MS-DOS' |
| 3626 | 07A | 3626 | 07AAA3·General·Purpose·Flag··0800·(2048) |
| 3627 | ·······[Bits·1-2]············0·'Normal·Compression' | 3627 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3628 | ·······[Bit·11]··············1·'Language·Encoding' | 3628 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3629 | 07A | 3629 | 07AAA5·Compression·Method····0008·(8)·'Deflated' |
| 3630 | 07A | 3630 | 07AAA7·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980' |
| 3631 | 07A | 3631 | 07AAAB·CRC···················FA97DBAA·(4204256170) |
| 3632 | 07A | 3632 | 07AAAF·Compressed·Size·······00003DB4·(15796) |
| 3633 | 07A | 3633 | 07AAB3·Uncompressed·Size·····0000ED8C·(60812) |
| 3634 | 07A | 3634 | 07AAB7·Filename·Length·······001E·(30) |
| 3635 | 07A | 3635 | 07AAB9·Extra·Length··········0014·(20) |
| 3636 | 07A | 3636 | 07AABB·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3637 | # | 3637 | # |
| 3638 | #·WARNING:·Offset·0x7A | 3638 | #·WARNING:·Offset·0x7AABB:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' |
| 3639 | #··········Zero·length·filename | 3639 | #··········Zero·length·filename |
| 3640 | # | 3640 | # |
| 3641 | 07A | 3641 | 07AAD9·Extra·ID·#1···········0001·(1)·'ZIP64' |
| 3642 | 07A | 3642 | 07AADB···Length··············0010·(16) |
| 3643 | 07A | 3643 | 07AADD···Uncompressed·Size···000000000000ED8C·(60812) |
| 3644 | 07A | 3644 | 07AAE5···Compressed·Size·····0000000000003DB4·(15796) |
| 3645 | 07A | 3645 | 07AAED·PAYLOAD |
| 3646 | 07E | 3646 | 07E8A1·LOCAL·HEADER·#153·····04034B50·(67324752) |
| 3647 | 07E | 3647 | 07E8A5·Extract·Zip·Spec······14·(20)·'2.0' |
| 3648 | 07E | 3648 | 07E8A6·Extract·OS············00·(0)·'MS-DOS' |
| 3649 | 07E | 3649 | 07E8A7·General·Purpose·Flag··0800·(2048) |
| 3650 | ·······[Bits·1-2]············0·'Normal·Compression' | 3650 | ·······[Bits·1-2]············0·'Normal·Compression' |
| 3651 | ·······[Bit·11]··············1·'Language·Encoding' | 3651 | ·······[Bit·11]··············1·'Language·Encoding' |
| 3652 | 07E | 3652 | 07E8A9·Compression·Method····0008·(8)·'Deflated' |
| Max diff block lines reached; 2670775/2891748 bytes (92.36%) of diff not shown. | |||
| Offset 11, 15 lines modified | Offset 11, 15 lines modified | ||
| 11 | ···>>>·results·=·from_bytes('Bсеки·човек·има·право·на·образование.·Oбразованието!'.encode('utf_8')) | 11 | ···>>>·results·=·from_bytes('Bсеки·човек·има·право·на·образование.·Oбразованието!'.encode('utf_8')) |
| 12 | ···>>>·best_guess·=·results.best() | 12 | ···>>>·best_guess·=·results.best() |
| 13 | ···>>>·str(best_guess) | 13 | ···>>>·str(best_guess) |
| 14 | ···'Bсеки·човек·има·право·на·образование.·Oбразованието!' | 14 | ···'Bсеки·човек·има·право·на·образование.·Oбразованието!' |
| 15 | Others·methods·and·usages·are·available·-·see·the·full·documentation | 15 | Others·methods·and·usages·are·available·-·see·the·full·documentation |
| 16 | at·<https://github.com/Ousret/charset_normalizer>. | 16 | at·<https://github.com/Ousret/charset_normalizer>. |
| 17 | :copyright:·(c)· | 17 | :copyright:·(c)·Ahmed·TAHRI |
| 18 | :license:·MIT,·see·LICENSE·for·more·details. | 18 | :license:·MIT,·see·LICENSE·for·more·details. |
| 19 | """ | 19 | """ |
| 20 | from·__future__·import·annotations | 20 | from·__future__·import·annotations |
| 21 | import·logging | 21 | import·logging |
| Offset 136, 24 lines modified | Offset 136, 22 lines modified | ||
| 136 | ····is_too_small_sequence:·bool·=·len(sequences)·<·TOO_SMALL_SEQUENCE | 136 | ····is_too_small_sequence:·bool·=·len(sequences)·<·TOO_SMALL_SEQUENCE |
| 137 | ····is_too_large_sequence:·bool·=·len(sequences)·>=·TOO_BIG_SEQUENCE | 137 | ····is_too_large_sequence:·bool·=·len(sequences)·>=·TOO_BIG_SEQUENCE |
| 138 | ····if·is_too_small_sequence: | 138 | ····if·is_too_small_sequence: |
| 139 | ········logger.log( | 139 | ········logger.log( |
| 140 | ············TRACE, | 140 | ············TRACE, |
| 141 | ············"Trying·to·detect·encoding·from·a·tiny·portion·of·( | 141 | ············"Trying·to·detect·encoding·from·a·tiny·portion·of·(%i)·byte(s).", |
| 142 | ············ | 142 | ············length, |
| 143 | ············), | ||
| 144 | ········) | 143 | ········) |
| 145 | ····elif·is_too_large_sequence: | 144 | ····elif·is_too_large_sequence: |
| 146 | ········logger.log( | 145 | ········logger.log( |
| 147 | ············TRACE, | 146 | ············TRACE, |
| 148 | ············"Using·lazy·str·decoding·because·the·payload·is·quite·large,·( | 147 | ············"Using·lazy·str·decoding·because·the·payload·is·quite·large,·(%i)·byte(s).", |
| 149 | ············ | 148 | ············length, |
| 150 | ············), | ||
| 151 | ········) | 149 | ········) |
| 152 | ····prioritized_encodings:·list[str]·=·[] | 150 | ····prioritized_encodings:·list[str]·=·[] |
| 153 | ····specified_encoding:·str·|·None·=·( | 151 | ····specified_encoding:·str·|·None·=·( |
| 154 | ········any_specified_encoding(sequences)·if·preemptive_behaviour·else·None | 152 | ········any_specified_encoding(sequences)·if·preemptive_behaviour·else·None |
| 155 | ····) | 153 | ····) |
| Offset 166, 20 lines modified | Offset 164, 14 lines modified | ||
| 166 | ············specified_encoding, | 164 | ············specified_encoding, |
| 167 | ········) | 165 | ········) |
| 168 | ····tested:·set[str]·=·set() | 166 | ····tested:·set[str]·=·set() |
| 169 | ····tested_but_hard_failure:·list[str]·=·[] | 167 | ····tested_but_hard_failure:·list[str]·=·[] |
| 170 | ····tested_but_soft_failure:·list[str]·=·[] | 168 | ····tested_but_soft_failure:·list[str]·=·[] |
| 171 | ····soft_failure_skip:·set[str]·=·set() | 169 | ····soft_failure_skip:·set[str]·=·set() |
| 172 | ····success_fast_tracked:·set[str]·=·set() | ||
| 173 | ····#·Cache·for·decoded·payload·deduplication:·hash(decoded_payload)·->·(mean_mess_ratio,·cd_ratios_merged,·passed) | ||
| 174 | ····#·When·multiple·encodings·decode·to·the·exact·same·string,·we·can·skip·the·expensive | ||
| 175 | ····#·mess_ratio·and·coherence_ratio·analysis·and·reuse·the·results·from·the·first·encoding. | ||
| 176 | ····payload_result_cache:·dict[int,·tuple[float,·list[tuple[str,·float]],·bool]]·=·{} | ||
| 177 | ····#·Avoid·unoptimized·RSS·usage. | 170 | ····#·Avoid·unoptimized·RSS·usage. |
| 178 | ····#·this·cache·is·mostly·interesting·for | 171 | ····#·this·cache·is·mostly·interesting·for |
| 179 | ····#·local·usage.·Garbage·collected·at·the | 172 | ····#·local·usage.·Garbage·collected·at·the |
| 180 | ····#·end.·Like·it·should. | 173 | ····#·end.·Like·it·should. |
| 181 | ····cached_mess_ratio·=·lru_cache(maxsize=None)(mess_ratio) | 174 | ····cached_mess_ratio·=·lru_cache(maxsize=None)(mess_ratio) |
| 182 | ····cached_coherence_ratio·=·lru_cache(maxsize=None)(coherence_ratio) | 175 | ····cached_coherence_ratio·=·lru_cache(maxsize=None)(coherence_ratio) |
| Offset 218, 15 lines modified | Offset 210, 15 lines modified | ||
| 218 | ····results:·CharsetMatches·=·CharsetMatches() | 210 | ····results:·CharsetMatches·=·CharsetMatches() |
| 219 | ····early_stop_results:·CharsetMatches·=·CharsetMatches() | 211 | ····early_stop_results:·CharsetMatches·=·CharsetMatches() |
| 220 | ····sig_encoding,·sig_payload·=·identify_sig_or_bom(sequences) | 212 | ····sig_encoding,·sig_payload·=·identify_sig_or_bom(sequences) |
| 221 | ····if·sig_encoding·is·not·None: | 213 | ····if·sig_encoding·is·not·None: |
| 222 | ········prioritized_encodings. | 214 | ········prioritized_encodings.insert(0,·sig_encoding) |
| 223 | ········logger.log( | 215 | ········logger.log( |
| 224 | ············TRACE, | 216 | ············TRACE, |
| 225 | ············"Detected·a·SIG·or·BOM·mark·on·first·%i·byte(s).·Priority·+1·given·for·%s.", | 217 | ············"Detected·a·SIG·or·BOM·mark·on·first·%i·byte(s).·Priority·+1·given·for·%s.", |
| 226 | ············len(sig_payload), | 218 | ············len(sig_payload), |
| 227 | ············sig_encoding, | 219 | ············sig_encoding, |
| 228 | ········) | 220 | ········) |
| Offset 274, 23 lines modified | Offset 266, 14 lines modified | ||
| 274 | ············logger.log( | 266 | ············logger.log( |
| 275 | ················TRACE, | 267 | ················TRACE, |
| 276 | ················"%s·is·deemed·too·similar·to·a·code·page·that·was·already·considered·unsuited.·Continuing!", | 268 | ················"%s·is·deemed·too·similar·to·a·code·page·that·was·already·considered·unsuited.·Continuing!", |
| 277 | ················encoding_iana, | 269 | ················encoding_iana, |
| 278 | ············) | 270 | ············) |
| 279 | ············continue | 271 | ············continue |
| 280 | ········#·Skip·encodings·that·were·already·fast-tracked·from·a·similar·successful·encoding. | ||
| 281 | ········if·encoding_iana·in·success_fast_tracked: | ||
| 282 | ············logger.log( | ||
| 283 | ················TRACE, | ||
| 284 | ················"Skipping·%s:·already·fast-tracked·from·a·similar·successful·encoding.", | ||
| 285 | ················encoding_iana, | ||
| 286 | ············) | ||
| 287 | ············continue | ||
| 288 | ········try: | 272 | ········try: |
| 289 | ············is_multi_byte_decoder:·bool·=·is_multi_byte_encoding(encoding_iana) | 273 | ············is_multi_byte_decoder:·bool·=·is_multi_byte_encoding(encoding_iana) |
| 290 | ········except·(ModuleNotFoundError,·ImportError):··#·Defensive: | 274 | ········except·(ModuleNotFoundError,·ImportError):··#·Defensive: |
| 291 | ············logger.log( | 275 | ············logger.log( |
| 292 | ················TRACE, | 276 | ················TRACE, |
| 293 | ················"Encoding·%s·does·not·provide·an·IncrementalDecoder", | 277 | ················"Encoding·%s·does·not·provide·an·IncrementalDecoder", |
| 294 | ················encoding_iana, | 278 | ················encoding_iana, |
| Offset 480, 44 lines modified | Offset 463, 41 lines modified | ||
| 480 | ················"LazyStr·Loading:·After·MD·chunk·decode,·code·page·%s·does·not·fit·given·bytes·sequence·at·ALL.·%s", | 463 | ················"LazyStr·Loading:·After·MD·chunk·decode,·code·page·%s·does·not·fit·given·bytes·sequence·at·ALL.·%s", |
| 481 | ················encoding_iana, | 464 | ················encoding_iana, |
| 482 | ················str(e), | 465 | ················str(e), |
| 483 | ············) | 466 | ············) |
| 484 | ············early_stop_count·=·max_chunk_gave_up | 467 | ············early_stop_count·=·max_chunk_gave_up |
| 485 | ············lazy_str_hard_failure·=·True | 468 | ············lazy_str_hard_failure·=·True |
| 469 | ········mean_mess_ratio:·float·=·sum(md_ratios)·/·len(md_ratios)·if·md_ratios·else·0.0 | ||
| 486 | ········#·We·might·want·to·check·the·sequence·again·with·the·whole·content | 470 | ········#·We·might·want·to·check·the·sequence·again·with·the·whole·content, |
| 487 | ········#· | 471 | ········#·but·only·if·initial·MD·tests·passed. |
| 488 | ········if·( | 472 | ········if·( |
| 489 | ············not·lazy_str_hard_failure | 473 | ············not·lazy_str_hard_failure |
| 490 | ············and·is_too_large_sequence | 474 | ············and·is_too_large_sequence |
| 491 | ············and·not·is_multi_byte_decoder | 475 | ············and·not·is_multi_byte_decoder |
| 476 | ············and·mean_mess_ratio·<·threshold | ||
| 477 | ············and·early_stop_count·<·max_chunk_gave_up | ||
| 492 | ········): | 478 | ········): |
| 493 | ············try: | 479 | ············try: |
| 494 | ················sequences[int(50e3)·:].decode(encoding_iana,·errors="strict") | 480 | ················sequences[int(50e3)·:].decode(encoding_iana,·errors="strict") |
| 495 | ············except·UnicodeDecodeError·as·e: | 481 | ············except·UnicodeDecodeError·as·e: |
| 496 | ················logger.log( | 482 | ················logger.log( |
| 497 | ····················TRACE, | 483 | ····················TRACE, |
| 498 | ····················"LazyStr·Loading:·After·final·lookup,·code·page·%s·does·not·fit·given·bytes·sequence·at·ALL.·%s", | 484 | ····················"LazyStr·Loading:·After·final·lookup,·code·page·%s·does·not·fit·given·bytes·sequence·at·ALL.·%s", |
| 499 | ····················encoding_iana, | 485 | ····················encoding_iana, |
| 500 | ····················str(e), | 486 | ····················str(e), |
| 501 | ················) | 487 | ················) |
| 502 | ················tested_but_hard_failure.append(encoding_iana) | 488 | ················tested_but_hard_failure.append(encoding_iana) |
| 503 | ················continue | 489 | ················continue |
| 504 | ········mean_mess_ratio:·float·=·sum(md_ratios)·/·len(md_ratios)·if·md_ratios·else·0.0 | ||
| 505 | ········if·mean_mess_ratio·>=·threshold·or·early_stop_count·>=·max_chunk_gave_up: | 490 | ········if·mean_mess_ratio·>=·threshold·or·early_stop_count·>=·max_chunk_gave_up: |
| 506 | ············tested_but_soft_failure.append(encoding_iana) | 491 | ············tested_but_soft_failure.append(encoding_iana) |
| 507 | ············if·encoding_iana·in·IANA_SUPPORTED_SIMILAR: | 492 | ············if·encoding_iana·in·IANA_SUPPORTED_SIMILAR: |
| 508 | ················soft_failure_skip.update(IANA_SUPPORTED_SIMILAR[encoding_iana]) | 493 | ················soft_failure_skip.update(IANA_SUPPORTED_SIMILAR[encoding_iana]) |
| 509 | ············#·Cache·this·soft-failure·so·identical·decoding·from·other·encodings | ||
| 510 | ············#·can·be·skipped·immediately. | ||
| 511 | ············if·decoded_payload·is·not·None·and·not·is_multi_byte_decoder: | ||
| 512 | ················payload_result_cache.setdefault( | ||
| 513 | ····················hash(decoded_payload),·(mean_mess_ratio,·[],·False) | ||
| 514 | ················) | ||
| Max diff block lines reached; 9361/14866 bytes (62.97%) of diff not shown. | |||
| Offset 371, 14 lines modified | Offset 371, 420 lines modified | ||
| 371 | ····"CJK·Unified·Ideographs·Extension·J":·range(205744,·210048), | 371 | ····"CJK·Unified·Ideographs·Extension·J":·range(205744,·210048), |
| 372 | ····"Tags":·range(917504,·917632), | 372 | ····"Tags":·range(917504,·917632), |
| 373 | ····"Variation·Selectors·Supplement":·range(917760,·918000), | 373 | ····"Variation·Selectors·Supplement":·range(917760,·918000), |
| 374 | ····"Supplementary·Private·Use·Area-A":·range(983040,·1048576), | 374 | ····"Supplementary·Private·Use·Area-A":·range(983040,·1048576), |
| 375 | ····"Supplementary·Private·Use·Area-B":·range(1048576,·1114112), | 375 | ····"Supplementary·Private·Use·Area-B":·range(1048576,·1114112), |
| 376 | } | 376 | } |
| 377 | #·Canonical·family·for·every·Unicode·range·above.·Keep·this·exhaustive·and | ||
| 378 | #·explicit:·official·block·names·are·labels,·not·a·grammar·we·should·parse. | ||
| 379 | _RANGE_FAMILIES:·dict[str,·str]·=·{ | ||
| 380 | ····"Control·character":·"Control·character", | ||
| 381 | ····"Basic·Latin":·"Latin", | ||
| 382 | ····"Latin-1·Supplement":·"Latin", | ||
| 383 | ····"Latin·Extended-A":·"Latin", | ||
| 384 | ····"Latin·Extended-B":·"Latin", | ||
| 385 | ····"IPA·Extensions":·"IPA", | ||
| 386 | ····"Spacing·Modifier·Letters":·"Spacing·Modifier·Letters", | ||
| 387 | ····"Combining·Diacritical·Marks":·"Combining", | ||
| 388 | ····"Greek·and·Coptic":·"Greek", | ||
| 389 | ····"Cyrillic":·"Cyrillic", | ||
| 390 | ····"Cyrillic·Supplement":·"Cyrillic", | ||
| 391 | ····"Armenian":·"Armenian", | ||
| 392 | ····"Hebrew":·"Hebrew", | ||
| 393 | ····"Arabic":·"Arabic", | ||
| 394 | ····"Syriac":·"Syriac", | ||
| 395 | ····"Arabic·Supplement":·"Arabic", | ||
| 396 | ····"Thaana":·"Thaana", | ||
| 397 | ····"NKo":·"NKo", | ||
| 398 | ····"Samaritan":·"Samaritan", | ||
| 399 | ····"Mandaic":·"Mandaic", | ||
| 400 | ····"Syriac·Supplement":·"Syriac", | ||
| 401 | ····"Arabic·Extended-B":·"Arabic", | ||
| 402 | ····"Arabic·Extended-A":·"Arabic", | ||
| 403 | ····"Devanagari":·"Devanagari", | ||
| 404 | ····"Bengali":·"Bengali", | ||
| 405 | ····"Gurmukhi":·"Gurmukhi", | ||
| 406 | ····"Gujarati":·"Gujarati", | ||
| 407 | ····"Oriya":·"Oriya", | ||
| 408 | ····"Tamil":·"Tamil", | ||
| 409 | ····"Telugu":·"Telugu", | ||
| 410 | ····"Kannada":·"Kannada", | ||
| 411 | ····"Malayalam":·"Malayalam", | ||
| 412 | ····"Sinhala":·"Sinhala", | ||
| 413 | ····"Thai":·"Thai", | ||
| 414 | ····"Lao":·"Lao", | ||
| 415 | ····"Tibetan":·"Tibetan", | ||
| 416 | ····"Myanmar":·"Myanmar", | ||
| 417 | ····"Georgian":·"Georgian", | ||
| 418 | ····"Hangul·Jamo":·"Hangul", | ||
| 419 | ····"Ethiopic":·"Ethiopic", | ||
| 420 | ····"Ethiopic·Supplement":·"Ethiopic", | ||
| 421 | ····"Cherokee":·"Cherokee", | ||
| 422 | ····"Unified·Canadian·Aboriginal·Syllabics":·"Unified·Canadian·Aboriginal·Syllabics", | ||
| 423 | ····"Ogham":·"Ogham", | ||
| 424 | ····"Runic":·"Runic", | ||
| 425 | ····"Tagalog":·"Tagalog", | ||
| 426 | ····"Hanunoo":·"Hanunoo", | ||
| 427 | ····"Buhid":·"Buhid", | ||
| 428 | ····"Tagbanwa":·"Tagbanwa", | ||
| 429 | ····"Khmer":·"Khmer", | ||
| 430 | ····"Mongolian":·"Mongolian", | ||
| 431 | ····"Unified·Canadian·Aboriginal·Syllabics·Extended":·"Unified·Canadian·Aboriginal·Syllabics", | ||
| 432 | ····"Limbu":·"Limbu", | ||
| 433 | ····"Tai·Le":·"Tai·Le", | ||
| 434 | ····"New·Tai·Lue":·"New·Tai·Lue", | ||
| 435 | ····"Khmer·Symbols":·"Khmer", | ||
| 436 | ····"Buginese":·"Buginese", | ||
| 437 | ····"Tai·Tham":·"Tai·Tham", | ||
| 438 | ····"Combining·Diacritical·Marks·Extended":·"Combining", | ||
| 439 | ····"Balinese":·"Balinese", | ||
| 440 | ····"Sundanese":·"Sundanese", | ||
| 441 | ····"Batak":·"Batak", | ||
| 442 | ····"Lepcha":·"Lepcha", | ||
| 443 | ····"Ol·Chiki":·"Ol·Chiki", | ||
| 444 | ····"Cyrillic·Extended-C":·"Cyrillic", | ||
| 445 | ····"Georgian·Extended":·"Georgian", | ||
| 446 | ····"Sundanese·Supplement":·"Sundanese", | ||
| 447 | ····"Vedic·Extensions":·"Vedic", | ||
| 448 | ····"Phonetic·Extensions":·"Phonetic", | ||
| 449 | ····"Phonetic·Extensions·Supplement":·"Phonetic", | ||
| 450 | ····"Combining·Diacritical·Marks·Supplement":·"Combining", | ||
| 451 | ····"Latin·Extended·Additional":·"Latin", | ||
| 452 | ····"Greek·Extended":·"Greek", | ||
| 453 | ····"General·Punctuation":·"Punctuation", | ||
| 454 | ····"Superscripts·and·Subscripts":·"Superscripts·and·Subscripts", | ||
| 455 | ····"Currency·Symbols":·"Currency·Symbols", | ||
| 456 | ····"Combining·Diacritical·Marks·for·Symbols":·"Combining", | ||
| 457 | ····"Letterlike·Symbols":·"Letterlike·Symbols", | ||
| 458 | ····"Number·Forms":·"Number·Forms", | ||
| 459 | ····"Arrows":·"Arrows", | ||
| 460 | ····"Mathematical·Operators":·"Mathematical", | ||
| 461 | ····"Miscellaneous·Technical":·"Miscellaneous·Technical", | ||
| 462 | ····"Control·Pictures":·"Control·Pictures", | ||
| 463 | ····"Optical·Character·Recognition":·"Optical·Character·Recognition", | ||
| 464 | ····"Enclosed·Alphanumerics":·"Enclosed·Alphanumerics", | ||
| 465 | ····"Box·Drawing":·"Box·Drawing", | ||
| 466 | ····"Block·Elements":·"Block·Elements", | ||
| 467 | ····"Geometric·Shapes":·"Geometric·Shapes", | ||
| 468 | ····"Miscellaneous·Symbols":·"Miscellaneous·Symbols", | ||
| 469 | ····"Dingbats":·"Dingbats", | ||
| 470 | ····"Miscellaneous·Mathematical·Symbols-A":·"Mathematical", | ||
| 471 | ····"Supplemental·Arrows-A":·"Arrows", | ||
| 472 | ····"Braille·Patterns":·"Braille", | ||
| 473 | ····"Supplemental·Arrows-B":·"Arrows", | ||
| 474 | ····"Miscellaneous·Mathematical·Symbols-B":·"Mathematical", | ||
| 475 | ····"Supplemental·Mathematical·Operators":·"Mathematical", | ||
| 476 | ····"Miscellaneous·Symbols·and·Arrows":·"Miscellaneous·Symbols·and·Arrows", | ||
| 477 | ····"Glagolitic":·"Glagolitic", | ||
| 478 | ····"Latin·Extended-C":·"Latin", | ||
| 479 | ····"Coptic":·"Coptic", | ||
| 480 | ····"Georgian·Supplement":·"Georgian", | ||
| 481 | ····"Tifinagh":·"Tifinagh", | ||
| 482 | ····"Ethiopic·Extended":·"Ethiopic", | ||
| 483 | ····"Cyrillic·Extended-A":·"Cyrillic", | ||
| 484 | ····"Supplemental·Punctuation":·"Punctuation", | ||
| 485 | ····"CJK·Radicals·Supplement":·"CJK", | ||
| 486 | ····"Kangxi·Radicals":·"CJK", | ||
| 487 | ····"Ideographic·Description·Characters":·"CJK", | ||
| 488 | ····"CJK·Symbols·and·Punctuation":·"CJK", | ||
| 489 | ····"Hiragana":·"Hiragana", | ||
| 490 | ····"Katakana":·"Katakana", | ||
| 491 | ····"Bopomofo":·"Bopomofo", | ||
| 492 | ····"Hangul·Compatibility·Jamo":·"Hangul", | ||
| 493 | ····"Kanbun":·"Kanbun", | ||
| 494 | ····"Bopomofo·Extended":·"Bopomofo", | ||
| 495 | ····"CJK·Strokes":·"CJK", | ||
| 496 | ····"Katakana·Phonetic·Extensions":·"Katakana", | ||
| Max diff block lines reached; 1565/17703 bytes (8.84%) of diff not shown. | |||
| Offset 1, 37 lines modified | Offset 1, 34 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | import·sys | ||
| 3 | from·functools·import·lru_cache | 2 | from·functools·import·lru_cache |
| 4 | from·logging·import·getLogger | 3 | from·logging·import·getLogger |
| 5 | if·sys.version_info·>=·(3,·8): | ||
| 6 | ····from·typing·import·final | ||
| 7 | else: | ||
| 8 | ····try: | ||
| 9 | ········from·typing_extensions·import·final | ||
| 10 | ····except·ImportError: | ||
| 11 | ········def·final(cls):··#·type:·ignore[misc,no-untyped-def] | ||
| 12 | ············return·cls | ||
| 13 | from·.constant·import·( | 4 | from·.constant·import·( |
| 14 | ····COMMON_CJK_CHARACTERS, | 5 | ····COMMON_CJK_CHARACTERS, |
| 15 | ····COMMON_SAFE_ASCII_CHARACTERS, | 6 | ····COMMON_SAFE_ASCII_CHARACTERS, |
| 16 | ····TRACE, | 7 | ····TRACE, |
| 17 | ···· | 8 | ····CompatibleFamillyRange, |
| 18 | ····_ACCENTUATED, | 9 | ····_ACCENTUATED, |
| 19 | ····_ARABIC, | 10 | ····_ARABIC, |
| 20 | ····_ARABIC_ISOLATED_FORM, | 11 | ····_ARABIC_ISOLATED_FORM, |
| 12 | ····_BASIC_LATIN_COMPATIBLE_RANGE_FAMILIES, | ||
| 21 | ····_CJK, | 13 | ····_CJK, |
| 14 | ····_COMPATIBLE_RANGE_FAMILIES, | ||
| 15 | ····_COMPATIBLE_WITH_ANY_RANGE_FAMILIES, | ||
| 22 | ····_HANGUL, | 16 | ····_HANGUL, |
| 17 | ····_HALFWIDTH_KATAKANA, | ||
| 23 | ····_HIRAGANA, | 18 | ····_HIRAGANA, |
| 24 | ····_KATAKANA, | 19 | ····_KATAKANA, |
| 25 | ····_LATIN, | 20 | ····_LATIN, |
| 21 | ····_LIGATURE, | ||
| 22 | ····_RANGE_FAMILIES, | ||
| 23 | ····_SENTENCE_OPEN_PUNCTUATION, | ||
| 24 | ····_SUPERSCRIPT, | ||
| 26 | ····_THAI, | 25 | ····_THAI, |
| 27 | ) | 26 | ) |
| 28 | from·.utils·import·( | 27 | from·.utils·import·( |
| 29 | ····_character_flags, | 28 | ····_character_flags, |
| 30 | ····is_emoticon, | 29 | ····is_emoticon, |
| 31 | ····is_punctuation, | 30 | ····is_punctuation, |
| 32 | ····is_separator, | 31 | ····is_separator, |
| Offset 40, 15 lines modified | Offset 37, 14 lines modified | ||
| 40 | ····unicode_range, | 37 | ····unicode_range, |
| 41 | ) | 38 | ) |
| 42 | #·Combined·bitmask·for·CJK/Hangul/Katakana/Hiragana/Thai·glyph·detection. | 39 | #·Combined·bitmask·for·CJK/Hangul/Katakana/Hiragana/Thai·glyph·detection. |
| 43 | _GLYPH_MASK:·int·=·_CJK·|·_HANGUL·|·_KATAKANA·|·_HIRAGANA·|·_THAI | 40 | _GLYPH_MASK:·int·=·_CJK·|·_HANGUL·|·_KATAKANA·|·_HIRAGANA·|·_THAI |
| 44 | @final | ||
| 45 | class·CharInfo: | 41 | class·CharInfo: |
| 46 | ····"""Pre-computed·character·properties·shared·across·all·detectors.""" | 42 | ····"""Pre-computed·character·properties·shared·across·all·detectors.""" |
| 47 | ····__slots__·=·( | 43 | ····__slots__·=·( |
| 48 | ········"character", | 44 | ········"character", |
| 49 | ········"printable", | 45 | ········"printable", |
| 50 | ········"alpha", | 46 | ········"alpha", |
| Offset 58, 23 lines modified | Offset 54, 29 lines modified | ||
| 58 | ········"digit", | 54 | ········"digit", |
| 59 | ········"is_ascii", | 55 | ········"is_ascii", |
| 60 | ········"case_variable", | 56 | ········"case_variable", |
| 61 | ········"flags", | 57 | ········"flags", |
| 62 | ········"accentuated", | 58 | ········"accentuated", |
| 63 | ········"latin", | 59 | ········"latin", |
| 64 | ········"is_cjk", | 60 | ········"is_cjk", |
| 61 | ········"is_katakana", | ||
| 62 | ········"is_halfwidth_katakana", | ||
| 65 | ········"is_arabic", | 63 | ········"is_arabic", |
| 64 | ········"is_ligature", | ||
| 65 | ········"is_superscript", | ||
| 66 | ········"is_sentence_open_punctuation", | ||
| 66 | ········"is_glyph", | 67 | ········"is_glyph", |
| 67 | ········"punct", | 68 | ········"punct", |
| 68 | ········"sym", | 69 | ········"sym", |
| 69 | ········"range", | 70 | ········"range", |
| 70 | ········"sep", | 71 | ········"sep", |
| 71 | ········"emoticon", | 72 | ········"emoticon", |
| 72 | ········"safe", | 73 | ········"safe", |
| 73 | ········"common_cjk", | 74 | ········"common_cjk", |
| 75 | ········"unaccented", | ||
| 74 | ····) | 76 | ····) |
| 75 | ····character:·str | 77 | ····character:·str |
| 76 | ····printable:·bool | 78 | ····printable:·bool |
| 77 | ····alpha:·bool | 79 | ····alpha:·bool |
| 78 | ····upper:·bool | 80 | ····upper:·bool |
| 79 | ····lower:·bool | 81 | ····lower:·bool |
| Offset 82, 37 lines modified | Offset 84, 52 lines modified | ||
| 82 | ····digit:·bool | 84 | ····digit:·bool |
| 83 | ····is_ascii:·bool | 85 | ····is_ascii:·bool |
| 84 | ····case_variable:·bool | 86 | ····case_variable:·bool |
| 85 | ····flags:·int | 87 | ····flags:·int |
| 86 | ····accentuated:·bool | 88 | ····accentuated:·bool |
| 87 | ····latin:·bool | 89 | ····latin:·bool |
| 88 | ····is_cjk:·bool | 90 | ····is_cjk:·bool |
| 91 | ····is_katakana:·bool | ||
| 92 | ····is_halfwidth_katakana:·bool | ||
| 89 | ····is_arabic:·bool | 93 | ····is_arabic:·bool |
| 94 | ····is_ligature:·bool | ||
| 95 | ····is_superscript:·bool | ||
| 96 | ····is_sentence_open_punctuation:·bool | ||
| 90 | ····is_glyph:·bool | 97 | ····is_glyph:·bool |
| 91 | ····punct:·bool | 98 | ····punct:·bool |
| 92 | ····sym:·bool | 99 | ····sym:·bool |
| 93 | ····range:·str·|·None | 100 | ····range:·str·|·None |
| 94 | ····sep:·bool | 101 | ····sep:·bool |
| 95 | ····emoticon:·bool | 102 | ····emoticon:·bool |
| 96 | ····safe:·bool | 103 | ····safe:·bool |
| 97 | ····common_cjk:·bool | 104 | ····common_cjk:·bool |
| 105 | ····unaccented:·str | ||
| 98 | ····def·__init__(self,·character:·str)·->·None: | 106 | ····def·__init__(self,·character:·str)·->·None: |
| 99 | ········"""Compute·all·properties·for·*character*·(built·once·per·codepoint, | 107 | ········"""Compute·all·properties·for·*character*·(built·once·per·codepoint, |
| 100 | ········every·branch·assigns·every·slot).""" | 108 | ········every·branch·assigns·every·slot).""" |
| 101 | ········self.character·=·character | 109 | ········self.character·=·character |
| 102 | ········#·ASCII·fast-path:·for·characters·with·ord·<·128,·we·can·skip | 110 | ········#·ASCII·fast-path:·for·characters·with·ord·<·128,·we·can·skip |
| 103 | ········#·_character_flags()·entirely·and·derive·most·properties·from·ord. | 111 | ········#·_character_flags()·entirely·and·derive·most·properties·from·ord. |
| 104 | ········o:·int·=·ord(character) | 112 | ········o:·int·=·ord(character) |
| 105 | ········if·o·<·128: | 113 | ········if·o·<·128: |
| 106 | ············self.is_ascii·=·True | 114 | ············self.is_ascii·=·True |
| 107 | ············self.accentuated·=·False | 115 | ············self.accentuated·=·False |
| 116 | ············self.unaccented·=·character | ||
| Max diff block lines reached; 28287/31487 bytes (89.84%) of diff not shown. | |||
| Offset 36, 15 lines modified | Offset 36, 19 lines modified | ||
| 36 | ········self._string:·str·|·None·=·decoded_payload | 36 | ········self._string:·str·|·None·=·decoded_payload |
| 37 | ········self._preemptive_declaration:·str·|·None·=·preemptive_declaration | 37 | ········self._preemptive_declaration:·str·|·None·=·preemptive_declaration |
| 38 | ····def·__eq__(self,·other:·object)·->·bool: | 38 | ····def·__eq__(self,·other:·object)·->·bool: |
| 39 | ········if·not·isinstance(other,·CharsetMatch): | 39 | ········if·not·isinstance(other,·CharsetMatch): |
| 40 | ············if·isinstance(other,·str): | 40 | ············if·isinstance(other,·str): |
| 41 | ················#·Use·non-strict·iana_name·so·an·operand·that·is·not·a·known | ||
| 42 | ················#·encoding·alias·compares·unequal·instead·of·raising,·keeping | ||
| 43 | ················#·__eq__·total·as·the·data·model·requires·(mirrors·the·lookup | ||
| 44 | ················#·in·CharsetMatches.__getitem__). | ||
| 41 | ················return·iana_name(other)·==·self.encoding | 45 | ················return·iana_name(other,·False)·==·self.encoding |
| 42 | ············return·False | 46 | ············return·False |
| 43 | ········return·self.encoding·==·other.encoding·and·self.fingerprint·==·other.fingerprint | 47 | ········return·self.encoding·==·other.encoding·and·self.fingerprint·==·other.fingerprint |
| 44 | ····def·__lt__(self,·other:·object)·->·bool: | 48 | ····def·__lt__(self,·other:·object)·->·bool: |
| 45 | ········""" | 49 | ········""" |
| 46 | ········Implemented·to·make·sorted·available·upon·CharsetMatches·items. | 50 | ········Implemented·to·make·sorted·available·upon·CharsetMatches·items. |
| 47 | ········""" | 51 | ········""" |
| Offset 64, 15 lines modified | Offset 68, 19 lines modified | ||
| 64 | ················return·self.chaos·<·other.chaos | 68 | ················return·self.chaos·<·other.chaos |
| 65 | ············return·self.multi_byte_usage·>·other.multi_byte_usage | 69 | ············return·self.multi_byte_usage·>·other.multi_byte_usage |
| 66 | ········return·self.chaos·<·other.chaos | 70 | ········return·self.chaos·<·other.chaos |
| 67 | ····@property | 71 | ····@property |
| 68 | ····def·multi_byte_usage(self)·->·float: | 72 | ····def·multi_byte_usage(self)·->·float: |
| 73 | ········#·Empty·payloads·are·valid·(from_bytes(b"")·returns·a·match);·avoid·/0. | ||
| 74 | ········raw_len·=·len(self.raw) | ||
| 75 | ········if·raw_len·==·0: | ||
| 76 | ············return·0.0 | ||
| 69 | ········return·1.0·-·(len(str(self))·/· | 77 | ········return·1.0·-·(len(str(self))·/·raw_len) |
| 70 | ····def·__str__(self)·->·str: | 78 | ····def·__str__(self)·->·str: |
| 71 | ········#·Lazy·Str·Loading | 79 | ········#·Lazy·Str·Loading |
| 72 | ········if·self._string·is·None: | 80 | ········if·self._string·is·None: |
| 73 | ············self._string·=·str(self._payload,·self._encoding,·"strict") | 81 | ············self._string·=·str(self._payload,·self._encoding,·"strict") |
| 74 | ············#·UTF-7·BOM·is·encoded·in·modified·Base64·whose·byte·boundary | 82 | ············#·UTF-7·BOM·is·encoded·in·modified·Base64·whose·byte·boundary |
| 75 | ············#·can·overlap·with·the·next·character,·so·raw-byte·stripping | 83 | ············#·can·overlap·with·the·next·character,·so·raw-byte·stripping |
| Offset 254, 24 lines modified | Offset 262, 32 lines modified | ||
| 254 | ····""" | 262 | ····""" |
| 255 | ····Container·with·every·CharsetMatch·items·ordered·by·default·from·most·probable·to·the·less·one. | 263 | ····Container·with·every·CharsetMatch·items·ordered·by·default·from·most·probable·to·the·less·one. |
| 256 | ····Act·like·a·list(iterable)·but·does·not·implements·all·related·methods. | 264 | ····Act·like·a·list(iterable)·but·does·not·implements·all·related·methods. |
| 257 | ····""" | 265 | ····""" |
| 258 | ····def·__init__(self,·results:·list[CharsetMatch]·|·None·=·None): | 266 | ····def·__init__(self,·results:·list[CharsetMatch]·|·None·=·None): |
| 259 | ········self._results:·list[CharsetMatch]·=·sorted(results)·if·results·else·[] | 267 | ········self._results:·list[CharsetMatch]·=·sorted(results)·if·results·else·[] |
| 268 | ········self._is_sorted:·bool·=·True | ||
| 269 | ····def·_ensure_sorted(self)·->·None: | ||
| 270 | ········if·not·self._is_sorted: | ||
| 271 | ············self._results.sort() | ||
| 272 | ············self._is_sorted·=·True | ||
| 260 | ····def·__iter__(self)·->·Iterator[CharsetMatch]: | 273 | ····def·__iter__(self)·->·Iterator[CharsetMatch]: |
| 274 | ········self._ensure_sorted() | ||
| 261 | ········yield·from·self._results | 275 | ········yield·from·self._results |
| 262 | ····def·__getitem__(self,·item:·int·|·str)·->·CharsetMatch: | 276 | ····def·__getitem__(self,·item:·int·|·str)·->·CharsetMatch: |
| 263 | ········""" | 277 | ········""" |
| 264 | ········Retrieve·a·single·item·either·by·its·position·or·encoding·name·(alias·may·be·used·here). | 278 | ········Retrieve·a·single·item·either·by·its·position·or·encoding·name·(alias·may·be·used·here). |
| 265 | ········Raise·KeyError·upon·invalid·index·or·encoding·not·present·in·results. | 279 | ········Raise·KeyError·upon·invalid·index·or·encoding·not·present·in·results. |
| 266 | ········""" | 280 | ········""" |
| 267 | ········if·isinstance(item,·int): | 281 | ········if·isinstance(item,·int): |
| 282 | ············self._ensure_sorted() | ||
| 268 | ············return·self._results[item] | 283 | ············return·self._results[item] |
| 269 | ········if·isinstance(item,·str): | 284 | ········if·isinstance(item,·str): |
| 270 | ············item·=·iana_name(item,·False) | 285 | ············item·=·iana_name(item,·False) |
| 271 | ············for·result·in·self._results: | 286 | ············for·result·in·self._results: |
| 272 | ················if·item·in·result.could_be_from_charset: | 287 | ················if·item·in·result.could_be_from_charset: |
| 273 | ····················return·result | 288 | ····················return·result |
| 274 | ········raise·KeyError | 289 | ········raise·KeyError |
| Offset 296, 22 lines modified | Offset 312, 23 lines modified | ||
| 296 | ········#·We·should·disable·the·submatch·factoring·when·the·input·file·is·too·heavy·(conserve·RAM·usage) | 312 | ········#·We·should·disable·the·submatch·factoring·when·the·input·file·is·too·heavy·(conserve·RAM·usage) |
| 297 | ········if·len(item.raw)·<·TOO_BIG_SEQUENCE: | 313 | ········if·len(item.raw)·<·TOO_BIG_SEQUENCE: |
| 298 | ············for·match·in·self._results: | 314 | ············for·match·in·self._results: |
| 299 | ················if·match.fingerprint·==·item.fingerprint·and·match.chaos·==·item.chaos: | 315 | ················if·match.fingerprint·==·item.fingerprint·and·match.chaos·==·item.chaos: |
| 300 | ····················match.add_submatch(item) | 316 | ····················match.add_submatch(item) |
| 301 | ····················return | 317 | ····················return |
| 302 | ········self._results.append(item) | 318 | ········self._results.append(item) |
| 303 | ········self._ | 319 | ········self._is_sorted·=·False |
| 304 | ····def·best(self)·->·CharsetMatch·|·None: | 320 | ····def·best(self)·->·CharsetMatch·|·None: |
| 305 | ········""" | 321 | ········""" |
| 306 | ········Simply·return·the·first·match.·Strict·equivalent·to·matches[0]. | 322 | ········Simply·return·the·first·match.·Strict·equivalent·to·matches[0]. |
| 307 | ········""" | 323 | ········""" |
| 308 | ········if·not·self._results: | 324 | ········if·not·self._results: |
| 309 | ············return·None | 325 | ············return·None |
| 326 | ········self._ensure_sorted() | ||
| 310 | ········return·self._results[0] | 327 | ········return·self._results[0] |
| 311 | ····def·first(self)·->·CharsetMatch·|·None: | 328 | ····def·first(self)·->·CharsetMatch·|·None: |
| 312 | ········""" | 329 | ········""" |
| 313 | ········Redundant·method,·call·the·method·best().·Kept·for·BC·reasons. | 330 | ········Redundant·method,·call·the·method·best().·Kept·for·BC·reasons. |
| 314 | ········""" | 331 | ········""" |
| 315 | ········return·self.best() | 332 | ········return·self.best() |
| Offset 1, 37 lines modified | Offset 1, 42 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | import·importlib | 2 | import·importlib |
| 3 | import·logging | 3 | import·logging |
| 4 | import·unicodedata | 4 | import·unicodedata |
| 5 | from·bisect·import·bisect_right | 5 | from·bisect·import·bisect_right |
| 6 | from·codecs·import·IncrementalDecoder | 6 | from·codecs·import·IncrementalDecoder |
| 7 | from·encodings.aliases·import·aliases | ||
| 8 | from·functools·import·lru_cache | 7 | from·functools·import·lru_cache |
| 9 | from·re·import·findall | ||
| 10 | from·typing·import·Generator | 8 | from·typing·import·Generator |
| 11 | from·.constant·import·( | 9 | from·.constant·import·( |
| 12 | ····ENCODING_MARKS, | 10 | ····ENCODING_MARKS, |
| 13 | ····IANA_SUPPORTED_SIMILAR, | 11 | ····IANA_SUPPORTED_SIMILAR, |
| 14 | ····RE_POSSIBLE_ENCODING_INDICATION, | 12 | ····RE_POSSIBLE_ENCODING_INDICATION, |
| 15 | ····UNICODE_RANGES_COMBINED, | 13 | ····UNICODE_RANGES_COMBINED, |
| 16 | ····_SECONDARY_RANGE_NAMES, | 14 | ····_SECONDARY_RANGE_NAMES, |
| 17 | ····UTF8_MAXIMAL_ALLOCATION, | ||
| 18 | ····COMMON_CJK_CHARACTERS, | 15 | ····COMMON_CJK_CHARACTERS, |
| 19 | ····_LATIN, | 16 | ····_LATIN, |
| 20 | ····_CJK, | 17 | ····_CJK, |
| 21 | ····_HANGUL, | 18 | ····_HANGUL, |
| 22 | ····_KATAKANA, | 19 | ····_KATAKANA, |
| 23 | ····_HIRAGANA, | 20 | ····_HIRAGANA, |
| 21 | ····_HALFWIDTH_KATAKANA, | ||
| 24 | ····_THAI, | 22 | ····_THAI, |
| 25 | ····_ARABIC, | 23 | ····_ARABIC, |
| 26 | ····_ARABIC_ISOLATED_FORM, | 24 | ····_ARABIC_ISOLATED_FORM, |
| 25 | ····_LIGATURE, | ||
| 26 | ····_SUPERSCRIPT, | ||
| 27 | ····_SENTENCE_OPEN_PUNCTUATION, | ||
| 27 | ····_ACCENT_KEYWORDS, | 28 | ····_ACCENT_KEYWORDS, |
| 28 | ····_ACCENTUATED, | 29 | ····_ACCENTUATED, |
| 30 | ····_KNOWN_MB_DECODERS, | ||
| 31 | ····_KNOWN_MB_CLASSES, | ||
| 32 | ····_IANA_NAMES, | ||
| 33 | ····_MULTIBYTE_SEARCH_RADIUS, | ||
| 29 | ) | 34 | ) |
| 30 | def·_character_flags(character:·str)·->·int: | 35 | def·_character_flags(character:·str)·->·int: |
| 31 | ····"""Compute·all·name-based·classification·flags·with·a·single·unicodedata.name()·call.""" | 36 | ····"""Compute·all·name-based·classification·flags·with·a·single·unicodedata.name()·call.""" |
| 32 | ····try: | 37 | ····try: |
| 33 | ········desc:·str·=·unicodedata.name(character) | 38 | ········desc:·str·=·unicodedata.name(character) |
| Offset 44, 36 lines modified | Offset 49, 43 lines modified | ||
| 44 | ········flags·|=·_LATIN | 49 | ········flags·|=·_LATIN |
| 45 | ····if·"CJK"·in·desc: | 50 | ····if·"CJK"·in·desc: |
| 46 | ········flags·|=·_CJK | 51 | ········flags·|=·_CJK |
| 47 | ····if·"HANGUL"·in·desc: | 52 | ····if·"HANGUL"·in·desc: |
| 48 | ········flags·|=·_HANGUL | 53 | ········flags·|=·_HANGUL |
| 49 | ····if·"KATAKANA"·in·desc: | 54 | ····if·"KATAKANA"·in·desc: |
| 50 | ········flags·|=·_KATAKANA | 55 | ········flags·|=·_KATAKANA |
| 56 | ········if·"HALFWIDTH"·in·desc: | ||
| 57 | ············flags·|=·_HALFWIDTH_KATAKANA | ||
| 51 | ····if·"HIRAGANA"·in·desc: | 58 | ····if·"HIRAGANA"·in·desc: |
| 52 | ········flags·|=·_HIRAGANA | 59 | ········flags·|=·_HIRAGANA |
| 53 | ····if·"THAI"·in·desc: | 60 | ····if·"THAI"·in·desc: |
| 54 | ········flags·|=·_THAI | 61 | ········flags·|=·_THAI |
| 55 | ····if·"ARABIC"·in·desc: | 62 | ····if·"ARABIC"·in·desc: |
| 56 | ········flags·|=·_ARABIC | 63 | ········flags·|=·_ARABIC |
| 57 | ········if·"ISOLATED·FORM"·in·desc: | 64 | ········if·"ISOLATED·FORM"·in·desc: |
| 58 | ············flags·|=·_ARABIC_ISOLATED_FORM | 65 | ············flags·|=·_ARABIC_ISOLATED_FORM |
| 66 | ····if·"LIGATURE"·in·desc·or·desc.endswith("LETTER·AE"): | ||
| 67 | ········flags·|=·_LIGATURE | ||
| 68 | ····if·"SUPERSCRIPT"·in·desc: | ||
| 69 | ········flags·|=·_SUPERSCRIPT | ||
| 70 | ····if·desc·in·{"INVERTED·QUESTION·MARK",·"INVERTED·EXCLAMATION·MARK"}: | ||
| 71 | ········flags·|=·_SENTENCE_OPEN_PUNCTUATION | ||
| 59 | ····for·kw·in·_ACCENT_KEYWORDS: | 72 | ····for·kw·in·_ACCENT_KEYWORDS: |
| 60 | ········if·kw·in·desc: | 73 | ········if·kw·in·desc: |
| 61 | ············flags·|=·_ACCENTUATED | 74 | ············flags·|=·_ACCENTUATED |
| 62 | ············break | 75 | ············break |
| 63 | ····return·flags | 76 | ····return·flags |
| 64 | def·is_accentuated(character:·str)·->·bool: | 77 | def·is_accentuated(character:·str)·->·bool: |
| 65 | ····return·bool(_character_flags(character)·&·_ACCENTUATED) | 78 | ····return·bool(_character_flags(character)·&·_ACCENTUATED) |
| 66 | @lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) | ||
| 67 | def·remove_accent(character:·str)·->·str: | 79 | def·remove_accent(character:·str)·->·str: |
| 68 | ····decomposed:·str·=·unicodedata.decomposition(character) | 80 | ····decomposed:·str·=·unicodedata.decomposition(character) |
| 69 | ····if·not·decomposed: | 81 | ····if·not·decomposed: |
| 70 | ········return·character | 82 | ········return·character |
| 71 | ····codes:·list[str]·=·decomposed.split("·") | 83 | ····codes:·list[str]·=·decomposed.split("·") |
| Offset 91, 14 lines modified | Offset 103, 19 lines modified | ||
| 91 | def·unicode_range(character:·str)·->·str·|·None: | 103 | def·unicode_range(character:·str)·->·str·|·None: |
| 92 | ····""" | 104 | ····""" |
| 93 | ····Retrieve·the·Unicode·range·official·name·from·a·single·character. | 105 | ····Retrieve·the·Unicode·range·official·name·from·a·single·character. |
| 94 | ····""" | 106 | ····""" |
| 95 | ····character_ord:·int·=·ord(character) | 107 | ····character_ord:·int·=·ord(character) |
| 108 | ····if·character_ord·<·32: | ||
| 109 | ········return·"Control·character" | ||
| 110 | ····if·character_ord·<·128: | ||
| 111 | ········return·"Basic·Latin" | ||
| 96 | ····#·Binary·search:·find·the·rightmost·range·whose·start·<=·character_ord | 112 | ····#·Binary·search:·find·the·rightmost·range·whose·start·<=·character_ord |
| 97 | ····idx·=·bisect_right(_UNICODE_RANGE_STARTS,·character_ord)·-·1 | 113 | ····idx·=·bisect_right(_UNICODE_RANGE_STARTS,·character_ord)·-·1 |
| 98 | ····if·idx·>=·0: | 114 | ····if·idx·>=·0: |
| 99 | ········start,·stop,·name·=·_UNICODE_RANGES_SORTED[idx] | 115 | ········start,·stop,·name·=·_UNICODE_RANGES_SORTED[idx] |
| 100 | ········if·character_ord·<·stop: | 116 | ········if·character_ord·<·stop: |
| 101 | ············return·name | 117 | ············return·name |
| Offset 151, 64 lines modified | Offset 168, 54 lines modified | ||
| 151 | ········return·True | 168 | ········return·True |
| 152 | ····character_category:·str·=·unicodedata.category(character) | 169 | ····character_category:·str·=·unicodedata.category(character) |
| 153 | ····return·"Z"·in·character_category·or·character_category·in·{"Po",·"Pd",·"Pc"} | 170 | ····return·"Z"·in·character_category·or·character_category·in·{"Po",·"Pd",·"Pc"} |
| 154 | @lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) | ||
| 155 | def·is_case_variable(character:·str)·->·bool: | 171 | def·is_case_variable(character:·str)·->·bool: |
| 156 | ····return·character.islower()·!=·character.isupper() | 172 | ····return·character.islower()·!=·character.isupper() |
| 157 | @lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) | ||
| 158 | def·is_cjk(character:·str)·->·bool: | 173 | def·is_cjk(character:·str)·->·bool: |
| 159 | ····return·bool(_character_flags(character)·&·_CJK) | 174 | ····return·bool(_character_flags(character)·&·_CJK) |
| Max diff block lines reached; 8112/11582 bytes (70.04%) of diff not shown. | |||
| Offset 1, 8 lines modified | Offset 1, 8 lines modified | ||
| 1 | """ | 1 | """ |
| 2 | Expose·version | 2 | Expose·version |
| 3 | """ | 3 | """ |
| 4 | from·__future__·import·annotations | 4 | from·__future__·import·annotations |
| 5 | __version__·=·"3. | 5 | __version__·=·"3.5.2" |
| 6 | VERSION·=·__version__.split(".") | 6 | VERSION·=·__version__.split(".") |
| Offset 9, 15 lines modified | Offset 9, 15 lines modified | ||
| 9 | from·webencodings·import·ascii_lower | 9 | from·webencodings·import·ascii_lower |
| 10 | #·Classes·are·imported·here·to·expose·them·at·the·top·level·of·the·module | 10 | #·Classes·are·imported·here·to·expose·them·at·the·top·level·of·the·module |
| 11 | from·.compiler·import·compile_selector_list··#·noqa | 11 | from·.compiler·import·compile_selector_list··#·noqa |
| 12 | from·.parser·import·SelectorError··#·noqa | 12 | from·.parser·import·SelectorError··#·noqa |
| 13 | from·.tree·import·ElementWrapper··#·noqa | 13 | from·.tree·import·ElementWrapper··#·noqa |
| 14 | VERSION·=·__version__·=·'0. | 14 | VERSION·=·__version__·=·'0.10.1' |
| 15 | class·Matcher: | 15 | class·Matcher: |
| 16 | ····"""A·CSS·selectors·storage·that·can·match·against·HTML·elements.""" | 16 | ····"""A·CSS·selectors·storage·that·can·match·against·HTML·elements.""" |
| 17 | ····def·__init__(self): | 17 | ····def·__init__(self): |
| 18 | ········self.id_selectors·=·{} | 18 | ········self.id_selectors·=·{} |
| 19 | ········self.class_selectors·=·{} | 19 | ········self.class_selectors·=·{} |
| Offset 5, 14 lines modified | Offset 5, 16 lines modified | ||
| 5 | SUPPORTED_PSEUDO_ELEMENTS·=·{ | 5 | SUPPORTED_PSEUDO_ELEMENTS·=·{ |
| 6 | ····#·As·per·CSS·Pseudo-Elements·Module·Level·4 | 6 | ····#·As·per·CSS·Pseudo-Elements·Module·Level·4 |
| 7 | ····'first-line',·'first-letter',·'prefix',·'postfix',·'selection', | 7 | ····'first-line',·'first-letter',·'prefix',·'postfix',·'selection', |
| 8 | ····'target-text',·'spelling-error',·'grammar-error',·'before',·'after', | 8 | ····'target-text',·'spelling-error',·'grammar-error',·'before',·'after', |
| 9 | ····'marker',·'placeholder',·'file-selector-button', | 9 | ····'marker',·'placeholder',·'file-selector-button', |
| 10 | ····#·As·per·CSS·Generated·Content·for·Paged·Media·Module | 10 | ····#·As·per·CSS·Generated·Content·for·Paged·Media·Module |
| 11 | ····'footnote-call',·'footnote-marker', | 11 | ····'footnote-call',·'footnote-marker', |
| 12 | ····#·As·per·CSS·Notes | ||
| 13 | ····'note-call',·'note-marker',·'note-callback', | ||
| 12 | ····#·As·per·CSS·Scoping·Module·Level·1 | 14 | ····#·As·per·CSS·Scoping·Module·Level·1 |
| 13 | ····'content',·'shadow', | 15 | ····'content',·'shadow', |
| 14 | } | 16 | } |
| 15 | def·parse(input,·namespaces=None,·forgiving=False,·relative=False): | 17 | def·parse(input,·namespaces=None,·forgiving=False,·relative=False): |
| 16 | ····"""Yield·tinycss2·selectors·found·in·given·``input``. | 18 | ····"""Yield·tinycss2·selectors·found·in·given·``input``. |
| Offset 1, 81 lines modified | Offset 1, 136 lines modified | ||
| 1 | """ | 1 | """ |
| 2 | A·platform·independent·file·lock·that·supports·the·with-statement. | 2 | A·platform·independent·file·lock·that·supports·the·with-statement. |
| 3 | ..·autodata::·filelock.__version__ | 3 | ..·autodata::·filelock.__version__ |
| 4 | ····:no-value: | 4 | ····:no-value: |
| 5 | ..·autodata::·filelock.OwnerMode | ||
| 6 | ..·autodata::·filelock.CompromiseReason | ||
| 5 | """ | 7 | """ |
| 6 | from·__future__·import·annotations | 8 | from·__future__·import·annotations |
| 9 | __lazy_modules__·=·["filelock._descriptor",·"filelock._error",·"importlib"] | ||
| 7 | import·sys | 10 | import·sys |
| 8 | import·warnings | 11 | import·warnings |
| 12 | from·importlib·import·import_module | ||
| 9 | from·typing·import·TYPE_CHECKING,·Final | 13 | from·typing·import·TYPE_CHECKING,·Final |
| 10 | from·._api·import·AcquireReturnProxy,·BaseFileLock,·CloseErrorPolicy,·ContextErrorPolicy,·LockOptions | 14 | from·filelock._api·import·AcquireReturnProxy,·BaseFileLock,·CloseErrorPolicy,·ContextErrorPolicy,·LockOptions |
| 11 | from·._descriptor·import·lock_descriptor,·unlock_descriptor | 15 | from·filelock._descriptor·import·lock_descriptor,·unlock_descriptor |
| 12 | from·._error·import·LeaseSettingsMismatch,·SoftFileLockLifetimeWarning,·SoftFileLockProtocolError,·Timeout | 16 | from·filelock._error·import·LeaseSettingsMismatch,·SoftFileLockLifetimeWarning,·SoftFileLockProtocolError,·Timeout |
| 13 | from·._lease·import·LeaseCompromise,·SoftFileLease | ||
| 14 | from· | 17 | from·filelock._unix·import·UnixFileLock |
| 18 | from·filelock._unix·import·has_fcntl·as·_has_fcntl | ||
| 19 | from·filelock._windows·import·WindowsFileLock | ||
| 20 | #·Keeps·``filelock.version``·the·string·4.0.12·exposed·rather·than·the·submodule. | ||
| 21 | from·filelock.version·import·version | ||
| 15 | if·TYPE_CHECKING: | 22 | if·TYPE_CHECKING: |
| 16 | ····from· | 23 | ····from·filelock·import·asyncio |
| 24 | ····from·filelock._async_read_write·import·AsyncAcquireReadWriteReturnProxy,·AsyncReadWriteLock | ||
| 25 | ····from·filelock._lease·import·CompromiseReason,·LeaseCompromise,·SoftFileLease | ||
| 26 | ····from·filelock._marker·import·MarkerSoftFileLock,·OwnerMode,·OwnerRecord | ||
| 27 | ····from·filelock._read_write·import·ReadWriteLock | ||
| 28 | ····from·filelock._soft·import·SoftFileLock | ||
| 29 | ····from·filelock._soft_rw·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock,·SoftReadWriteLock | ||
| 30 | ····from·filelock._strict·import·StrictSoftFileClaim,·StrictSoftFileClaimState,·StrictSoftFileLock | ||
| 31 | ····from·filelock.asyncio·import·( | ||
| 17 | ········AsyncAcquireRe | 32 | ········AsyncAcquireReturnProxy, |
| 33 | ········AsyncSoftFileLease, | ||
| 18 | ········Async | 34 | ········AsyncSoftFileLock, |
| 35 | ········AsyncStrictSoftFileLock, | ||
| 36 | ········AsyncUnixFileLock, | ||
| 37 | ········AsyncWindowsFileLock, | ||
| 38 | ········BaseAsyncFileLock, | ||
| 19 | ····) | 39 | ····) |
| 20 | ····from·._read_write·import·ReadWriteLock | ||
| 21 | else: | ||
| 22 | ····try: | ||
| 23 | ········from·._async_read_write·import·AsyncAcquireReadWriteReturnProxy,·AsyncReadWriteLock | ||
| 24 | ········from·._read_write·import·ReadWriteLock | ||
| 25 | ····except·ImportError:··#·pragma:·lacks·sqlite3 | ||
| 26 | ········AsyncAcquireReadWriteReturnProxy·=·None | ||
| 27 | ········AsyncReadWriteLock·=·None | ||
| 28 | ········ReadWriteLock·=·None | ||
| 29 | from·._soft·import·SoftFileLock | ||
| 30 | from·._soft_rw·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock,·SoftReadWriteLock | ||
| 31 | from·._strict·import·StrictSoftFileClaim,·StrictSoftFileClaimState,·StrictSoftFileLock | ||
| 32 | from·._unix·import·UnixFileLock,·has_fcntl | ||
| 33 | from·._windows·import·WindowsFileLock | ||
| 34 | from·.asyncio·import·( | ||
| 35 | ····AsyncAcquireReturnProxy, | ||
| 36 | ····AsyncSoftFileLease, | ||
| 37 | ····AsyncSoftFileLock, | ||
| 38 | ····AsyncStrictSoftFileLock, | ||
| 39 | ····AsyncUnixFileLock, | ||
| 40 | ····AsyncWindowsFileLock, | ||
| 41 | ····BaseAsyncFileLock, | ||
| 42 | ) | ||
| 43 | from·.version·import·version | ||
| 44 | #:·version·of·the·project·as·a·string | 40 | #:·version·of·the·project·as·a·string |
| 45 | __version__:·Final[str]·=·version | 41 | __version__:·Final[str]·=·version |
| 42 | #:·``True``·when·:func:`fcntl.flock`·is·available.·Off·Windows,·:data:`FileLock`·then·resolves·to | ||
| 43 | #:·:class:`UnixFileLock`,·otherwise·to·:class:`SoftFileLock`.·Always·``False``·on·Windows. | ||
| 44 | #: | ||
| 45 | #:·:meta·hide-value: | ||
| 46 | has_fcntl:·Final[bool]·=·_has_fcntl | ||
| 46 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | 47 | if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 47 | ····_FileLock:·type[BaseFileLock]·=·WindowsFileLock | 48 | ····_FileLock:·type[BaseFileLock]·=·WindowsFileLock |
| 48 | ····_AsyncFileLock:·type[BaseAsyncFileLock]·=·AsyncWindowsFileLock | ||
| 49 | else:··#·pragma:·win32·no·cover·#·ruff:ignore[collapsible-else-if]··#·the·else·carries·the·win32·no-cover·pragma | 49 | else:··#·pragma:·win32·no·cover·#·ruff:ignore[collapsible-else-if]··#·the·else·carries·the·win32·no-cover·pragma |
| 50 | ····if·has_fcntl: | 50 | ····if·has_fcntl: |
| 51 | ········_FileLock:·type[BaseFileLock]·=·UnixFileLock | 51 | ········_FileLock:·type[BaseFileLock]·=·UnixFileLock |
| 52 | ········_AsyncFileLock:·type[BaseAsyncFileLock]·=·AsyncUnixFileLock | ||
| 53 | ····else: | 52 | ····else: |
| 53 | ········from·filelock._soft·import·SoftFileLock | ||
| 54 | ········_FileLock·=·SoftFileLock | 54 | ········_FileLock·=·SoftFileLock |
| 55 | ········_AsyncFileLock·=·AsyncSoftFileLock | ||
| 56 | ········warnings.warn("only·soft·file·lock·is·available",·stacklevel=2) | 55 | ········warnings.warn("only·soft·file·lock·is·available",·stacklevel=2) |
| 57 | if·TYPE_CHECKING: | 56 | if·TYPE_CHECKING: |
| 58 | ····FileLock·=·SoftFileLock | 57 | ····FileLock·=·SoftFileLock |
| 59 | ····AsyncFileLock·=·AsyncSoftFileLock | 58 | ····AsyncFileLock·=·AsyncSoftFileLock |
| 60 | else: | 59 | else: |
| 61 | ····#:·Alias·for·the·lock,·which·should·be·used·for·the·current·platform. | 60 | ····#:·Alias·for·the·lock,·which·should·be·used·for·the·current·platform. |
| 62 | ····FileLock·=·_FileLock | 61 | ····FileLock·=·_FileLock |
| 63 | ····AsyncFileLock·=·_AsyncFileLock | ||
| 62 | #·Importing·asyncio·and·sqlite3·costs·more·than·the·rest·of·the·package,·so·names·that·need·them·load·on·first·access. | ||
| 63 | _LAZY_ATTRIBUTES:·Final[dict[str,·str]]·=·{ | ||
| 64 | ····"AsyncAcquireReadWriteReturnProxy":·"._async_read_write", | ||
| 65 | ····"AsyncAcquireReturnProxy":·".asyncio", | ||
| 66 | ····"AsyncAcquireSoftReadWriteReturnProxy":·"._soft_rw", | ||
| 67 | ····"AsyncFileLock":·".asyncio", | ||
| 68 | ····"AsyncReadWriteLock":·"._async_read_write", | ||
| 69 | ····"AsyncSoftFileLease":·".asyncio", | ||
| 70 | ····"AsyncSoftFileLock":·".asyncio", | ||
| 71 | ····"AsyncSoftReadWriteLock":·"._soft_rw", | ||
| 72 | ····"AsyncStrictSoftFileLock":·".asyncio", | ||
| 73 | ····"AsyncUnixFileLock":·".asyncio", | ||
| 74 | ····"AsyncWindowsFileLock":·".asyncio", | ||
| 75 | ····"BaseAsyncFileLock":·".asyncio", | ||
| 76 | ····"CompromiseReason":·"._lease", | ||
| 77 | ····"LeaseCompromise":·"._lease", | ||
| 78 | ····"MarkerSoftFileLock":·"._marker", | ||
| 79 | ····"OwnerMode":·"._marker", | ||
| 80 | ····"OwnerRecord":·"._marker", | ||
| 81 | ····"ReadWriteLock":·"._read_write", | ||
| Max diff block lines reached; 996/7426 bytes (13.41%) of diff not shown. | |||
| Offset 1, 52 lines modified | Offset 1, 77 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·[ | ||
| 3 | ····"atexit", | ||
| 4 | ····"decimal", | ||
| 5 | ····"filelock._error", | ||
| 6 | ····"filelock._util", | ||
| 7 | ····"inspect", | ||
| 8 | ····"math", | ||
| 9 | ····"numbers", | ||
| 10 | ····"secrets", | ||
| 11 | ····"types", | ||
| 12 | ····"warnings", | ||
| 13 | ] | ||
| 14 | import·atexit | ||
| 2 | import·contextlib | 15 | import·contextlib |
| 3 | import·inspect | 16 | import·inspect |
| 4 | import·logging | 17 | import·logging |
| 5 | import·math | 18 | import·math |
| 6 | import·os | 19 | import·os |
| 7 | import·secrets | 20 | import·secrets |
| 21 | import·stat | ||
| 8 | import·sys | 22 | import·sys |
| 9 | import·time | 23 | import·time |
| 24 | import·types | ||
| 10 | import·warnings | 25 | import·warnings |
| 11 | from·abc·import·ABCMeta,·abstractmethod | 26 | from·abc·import·ABCMeta,·abstractmethod |
| 12 | from·collections.abc·import·Callable,·Hashable | 27 | from·collections.abc·import·Callable,·Hashable |
| 13 | from·contextlib·import·contextmanager | 28 | from·contextlib·import·contextmanager |
| 14 | from·dataclasses·import·dataclass | 29 | from·dataclasses·import·dataclass,·fields |
| 30 | from·decimal·import·Decimal | ||
| 31 | from·functools·import·cache,·partial | ||
| 15 | from·itertools·import·count,·starmap | 32 | from·itertools·import·count,·starmap |
| 33 | from·numbers·import·Real | ||
| 16 | from·threading·import·Condition,·RLock,·get_ident,·local | 34 | from·threading·import·TIMEOUT_MAX,·Condition,·RLock,·Thread,·current_thread,·get_ident,·local |
| 17 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·NoReturn,·TypedDict,·TypeVar,·cast | 35 | from·typing·import·TYPE_CHECKING,·Final,·Generic,·Literal,·NoReturn,·TypedDict,·TypeVar,·cast |
| 18 | from·weakref·import·WeakKeyDictionary,·WeakValueDictionary | 36 | from·weakref·import·WeakKeyDictionary,·WeakValueDictionary,·ref |
| 19 | from·._error·import·SoftFileLockLifetimeWarning,·Timeout | 37 | from·filelock._error·import·SoftFileLockLifetimeWarning,·Timeout |
| 20 | from·._util·import· | 38 | from·filelock._util·import·ensure_directory_exists |
| 21 | #:·No·explicit·file·permission·mode·was·passed.·Lock·files·then·open·with·0o666·so·umask·and·default·ACLs·pick | 39 | #:·No·explicit·file·permission·mode·was·passed.·Lock·files·then·open·with·0o666·so·umask·and·default·ACLs·pick |
| 22 | #:·the·final·permissions,·and·fchmod·is·skipped·to·preserve·POSIX·default·ACL·inheritance. | 40 | #:·the·final·permissions,·and·fchmod·is·skipped·to·preserve·POSIX·default·ACL·inheritance. |
| 23 | _UNSET_FILE_MODE:·Final[int]·=·-1 | 41 | _UNSET_FILE_MODE:·Final[int]·=·-1 |
| 42 | _PERMISSION_BITS:·Final[int]·=·stat.S_IRWXU·|·stat.S_IRWXG·|·stat.S_IRWXO | ||
| 24 | #:·Ceiling·on·the·retry·counter·used·as·a·power·of·two,·so·a·long·contended·wait·cannot·overflow·the·backoff·multiply. | 43 | #:·Ceiling·on·the·retry·counter·used·as·a·power·of·two,·so·a·long·contended·wait·cannot·overflow·the·backoff·multiply. |
| 25 | _MAX_BACKOFF_EXPONENT:·Final[int]·=·20 | 44 | _MAX_BACKOFF_EXPONENT:·Final[int]·=·20 |
| 26 | #:·How·a·context·manager·reconciles·a·body·failure·with·a·release·failure·on·exit·(see·the·property·of·this·name). | 45 | #:·How·a·context·manager·reconciles·a·body·failure·with·a·release·failure·on·exit·(see·the·property·of·this·name). |
| 27 | ContextErrorPolicy·=·Literal["chain",·"group"] | 46 | ContextErrorPolicy·=·Literal["chain",·"group"] |
| 28 | _CONTEXT_ERROR_POLICIES:·Final[frozenset[str]]·=·frozenset({"chain",·"group"}) | 47 | _CONTEXT_ERROR_POLICIES:·Final[frozenset[str]]·=·frozenset({"chain",·"group"}) |
| 29 | #:·What·a·descriptor-owning·backend·does·with·an·``os.close``·failure·after·relinquishing·ownership·(see·the·property). | 48 | #:·What·a·descriptor-owning·backend·does·with·an·``os.close``·failure·after·relinquishing·ownership·(see·the·property). |
| 30 | CloseErrorPolicy·=·Literal["default",·"raise",·"suppress"] | 49 | CloseErrorPolicy·=·Literal["default",·"raise",·"suppress"] |
| 31 | _CLOSE_ERROR_POLICIES:·Final[frozenset[str]]·=·frozenset({"default",·"raise",·"suppress"}) | 50 | _CLOSE_ERROR_POLICIES:·Final[frozenset[str]]·=·frozenset({"default",·"raise",·"suppress"}) |
| 32 | if·TYPE_CHECKING: | 51 | if·TYPE_CHECKING: |
| 33 | ····from·collections.abc·import·Generator | 52 | ····from·collections.abc·import·Generator,·Mapping |
| 53 | ····from·threading·import·Lock | ||
| 34 | ····from·types·import·TracebackType | 54 | ····from·types·import·FrameType,·TracebackType |
| 35 | ····from·typing·import·Protocol | 55 | ····from·typing·import·Protocol |
| 56 | ····from·_typeshed·import·Unused | ||
| 57 | ····from·filelock._lease·import·_LeaseClaim | ||
| 36 | ····from·._read_write·import·ReadWriteLock | 58 | ····from·filelock._read_write·import·ReadWriteLock |
| 37 | ····from·._soft_rw·import·SoftReadWriteLock | 59 | ····from·filelock._soft_rw·import·SoftReadWriteLock |
| 38 | ····class·_ForkResettable(Protocol): | 60 | ····class·_ForkResettable(Protocol): |
| 39 | ········def·_reset_after_fork_in_child(self)·->·None:·... | 61 | ········def·_reset_after_fork_in_child(self)·->·None:·... |
| 40 | ····class·_ForkDescriptorOwner(Protocol): | 62 | ····class·_ForkDescriptorOwner(Protocol): |
| 41 | ········def·_descriptors_for_fork(self)·->·tuple[tuple[int,·tuple[int,·int]·|·None],·...]:·... | 63 | ········def·_descriptors_for_fork(self)·->·tuple[tuple[int,·tuple[int,·int]·|·None],·...]:·... |
| Offset 60, 18 lines modified | Offset 85, 15 lines modified | ||
| 60 | ············self, | 85 | ············self, |
| 61 | ············*, | 86 | ············*, |
| 62 | ············before:·Callable[[],·None]·|·None·=·None, | 87 | ············before:·Callable[[],·None]·|·None·=·None, |
| 63 | ············after_in_parent:·Callable[[],·None]·|·None·=·None, | 88 | ············after_in_parent:·Callable[[],·None]·|·None·=·None, |
| 64 | ············after_in_child:·Callable[[],·None]·|·None·=·None, | 89 | ············after_in_child:·Callable[[],·None]·|·None·=·None, |
| 65 | ········)·->·None:·... | 90 | ········)·->·None:·... |
| 66 | ····if·sys.version_info·>=·(3,·11):··#·pragma:·no·cover·(py311+) | ||
| 67 | ···· | 91 | ····from·typing·import·Self |
| 68 | ····else:··#·pragma:·no·cover·(<py311) | ||
| 69 | ········from·typing_extensions·import·Self | ||
| 70 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") | 92 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") |
| 71 | _REGISTER_AT_FORK:·Final[_RegisterAtFork·|·None]·=·cast("_RegisterAtFork·|·None",·getattr(os,·"register_at_fork",·None)) | 93 | _REGISTER_AT_FORK:·Final[_RegisterAtFork·|·None]·=·cast("_RegisterAtFork·|·None",·getattr(os,·"register_at_fork",·None)) |
| 72 | _HAS_REGISTER_AT_FORK:·Final[bool]·=·_REGISTER_AT_FORK·is·not·None | 94 | _HAS_REGISTER_AT_FORK:·Final[bool]·=·_REGISTER_AT_FORK·is·not·None |
| 73 | _ExtraValue·=·TypeVar("_ExtraValue") | 95 | _ExtraValue·=·TypeVar("_ExtraValue") |
| 74 | _MarkerValue·=·TypeVar("_MarkerValue") | 96 | _MarkerValue·=·TypeVar("_MarkerValue") |
| Offset 92, 37 lines modified | Offset 114, 28 lines modified | ||
| 92 | ····context_error_policy:·ContextErrorPolicy | 114 | ····context_error_policy:·ContextErrorPolicy |
| 93 | ····close_error_policy:·CloseErrorPolicy | 115 | ····close_error_policy:·CloseErrorPolicy |
| 94 | ····fallback_to_soft:·bool | 116 | ····fallback_to_soft:·bool |
| 95 | ····preserve_lock_file:·bool | 117 | ····preserve_lock_file:·bool |
| 96 | ····on_acquired:·Callable[[int],·None]·|·None | 118 | ····on_acquired:·Callable[[int],·None]·|·None |
| 119 | def·_is_exception_group(error:·BaseException)·->·bool: | ||
| 120 | ····return·isinstance(error,·BaseExceptionGroup) | ||
| 97 | def·_exception_group_cls()·->·type[BaseException]: | ||
| 98 | ····#·BaseExceptionGroup·is·a·builtin·on·3.11+;·on·3.10·it·needs·the·exceptiongroup·backport.·filelock·keeps·zero | ||
| 99 | ····#·runtime·dependencies,·so·the·backport·is·imported·lazily·rather·than·required,·and·only·group·mode·needs·it. | ||
| 100 | ····if·sys.version_info·>=·(3,·11):··#·pragma:·no·cover·(py311+) | ||
| 101 | ········return·BaseExceptionGroup··#·ruff:ignore[undefined-name]··#·builtin·on·3.11+ | ||
| 102 | ····#·Alias·the·import·so·BaseExceptionGroup·above·stays·the·builtin·rather·than·an·unbound·local·of·this·function. | ||
| 103 | ····from·exceptiongroup·import·(··#·ruff:ignore[import-outside-top-level]··#·pragma:·no·cover·(<py311) | ||
| 104 | ········BaseExceptionGroup·as·_Backport, | ||
| 105 | ····) | ||
| 106 | ····return·_Backport··#·pragma:·no·cover·(<py311) | ||
| 107 | def·_raise_grouped_errors( | 121 | def·_raise_grouped_errors( |
| 108 | ····message:·str, | 122 | ····message:·str, |
| 109 | ····first_error:·BaseException, | 123 | ····first_error:·BaseException, |
| 110 | ····second_error:·BaseException, | 124 | ····second_error:·BaseException, |
| 111 | ····*additional_errors:·BaseException, | 125 | ····*additional_errors:·BaseException, |
| 112 | ····marker:·tuple[str,·_MarkerValue]·|·None·=·None, | 126 | ····marker:·tuple[str,·_MarkerValue]·|·None·=·None, |
| 113 | )·->·NoReturn: | 127 | )·->·NoReturn: |
| 114 | ····errors·=·(first_error,·second_error,·*additional_errors) | 128 | ····errors·=·(first_error,·second_error,·*additional_errors) |
| Max diff block lines reached; 93016/98460 bytes (94.47%) of diff not shown. | |||
| Offset 1, 117 lines modified | Offset 1, 429 lines modified | ||
| 1 | """Separate·caller·cancellation·from·backend·task·and·executor-future·results.""" | 1 | """Separate·caller·cancellation·from·backend·task·and·executor-future·results.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·["asyncio",·"collections",·"concurrent.futures",·"filelock._error"] | ||
| 3 | import·asyncio | 4 | import·asyncio |
| 4 | import·contextlib | 5 | import·contextlib |
| 5 | import·time | 6 | import·time |
| 7 | from·collections·import·deque | ||
| 6 | from·concurrent.futures·import·Future·as·ConcurrentFuture | 8 | from·concurrent.futures·import·Future·as·ConcurrentFuture |
| 7 | from·dataclasses·import·dataclass | 9 | from·dataclasses·import·dataclass |
| 8 | from·threading·import·Lock | 10 | from·threading·import·Lock |
| 9 | from·typing·import·TYPE_CHECKING,·Final,·Generic,·NoReturn,·TypeVar,·cast | 11 | from·typing·import·TYPE_CHECKING,·Final,·Generic,·Literal,·NoReturn,·TypeVar,·cast |
| 12 | from·weakref·import·WeakKeyDictionary | ||
| 10 | from· | 13 | from·filelock._api·import·( |
| 14 | ····_append_exception_context, | ||
| 15 | ····_fork_transition, | ||
| 16 | ····_raise_chained_errors, | ||
| 17 | ····_resolve_read_write_timeout, | ||
| 18 | ) | ||
| 19 | from·filelock._error·import·Timeout | ||
| 11 | if·TYPE_CHECKING: | 20 | if·TYPE_CHECKING: |
| 12 | ····from·collections.abc·import·Async | 21 | ····from·collections.abc·import·AsyncGenerator,·Awaitable,·Callable |
| 22 | ····from·concurrent.futures·import·Executor | ||
| 23 | ····from·filelock._read_write·import·ReadWriteLock | ||
| 24 | ····from·filelock._soft_rw·import·SoftReadWriteLock | ||
| 13 | _T·=·TypeVar("_T") | 25 | _T·=·TypeVar("_T") |
| 26 | #:·The·holder·an·async·wrapper·records·its·backend·level·under.·No·thread·has·this·identifier,·so·sync·code·on·the | ||
| 27 | #:·executor·thread·that·took·the·level·cannot·re-enter·or·release·it. | ||
| 28 | _TASKS_THREAD_ID:·Final[int]·=·0 | ||
| 14 | class·_AsyncTransitionUnavailableError(Exception): | 29 | class·_AsyncTransitionUnavailableError(Exception): |
| 15 | ····pass | 30 | ····pass |
| 16 | @dataclass(frozen=True) | 31 | @dataclass(frozen=True) |
| 17 | class·_BackendOutcome(Generic[_T]): | 32 | class·_BackendOutcome(Generic[_T]): |
| 18 | ····value:·_T·|·None·=·None | 33 | ····value:·_T·|·None·=·None |
| 19 | ····error:·BaseException·|·None·=·None | 34 | ····error:·BaseException·|·None·=·None |
| 20 | class·_AsyncTransitionGate: | 35 | class·_AsyncTransitionGate: |
| 36 | ····""" | ||
| 37 | ····First-in,·first-out·admission·for·the·calls·that·transition·one·lock·context. | ||
| 38 | ····Each·call·queues·a·ticket,·and·the·head·of·the·queue·holds·the·gate.·A·call·that·gives·up·removes·its·own·ticket, | ||
| 39 | ····so·abandoned·calls·do·not·pile·up·behind·a·long·holder. | ||
| 40 | ····""" | ||
| 21 | ····def·__init__(self)·->·None: | 41 | ····def·__init__(self)·->·None: |
| 22 | ········self._ | 42 | ········self._queue_lock:·Final[Lock]·=·Lock() |
| 23 | ········self._ | 43 | ········self._queue:·Final[deque[ConcurrentFuture[None]]]·=·deque() |
| 24 | ····@contextlib.asynccontextmanager | 44 | ····@contextlib.asynccontextmanager |
| 25 | ····async·def·hold(self)·->·Async | 45 | ····async·def·hold(self)·->·AsyncGenerator[None]: |
| 26 | ········ticket:·ConcurrentFuture[None]·=·ConcurrentFuture() | 46 | ········ticket:·ConcurrentFuture[None]·=·ConcurrentFuture() |
| 27 | ········with·self._tail_lock: | ||
| 28 | ············predecessor·=·self._tail | ||
| 29 | ············self._tail·=·ticket | ||
| 30 | ········if·predecessor·is·not·None: | ||
| 31 | ············try: | ||
| 32 | ················await·_wait_until_done(asyncio.wrap_future(predecessor)) | ||
| 33 | ············except·asyncio.CancelledError: | ||
| 34 | ················predecessor.add_done_callback(lambda·_predecessor:·self._leave(ticket)) | ||
| 35 | ················raise | ||
| 36 | ········try: | 47 | ········try: |
| 48 | ············self._join(ticket) | ||
| 49 | ············if·not·ticket.done(): | ||
| 50 | ················await·self._wait_for_turn(ticket,·blocking=True,·cancel_check=None,·deadline=None,·poll_interval=0.05) | ||
| 37 | ············yield | 51 | ············yield |
| 38 | ········finally: | 52 | ········finally: |
| 39 | ············self._leave(ticket) | 53 | ············self._leave(ticket) |
| 40 | ····@contextlib.asynccontextmanager | 54 | ····@contextlib.asynccontextmanager |
| 41 | ····async·def·hold_for_acquire( | 55 | ····async·def·hold_for_acquire( |
| 42 | ········self, | 56 | ········self, |
| 43 | ········*, | 57 | ········*, |
| 44 | ········blocking:·bool, | 58 | ········blocking:·bool, |
| 45 | ········cancel_check:·Callable[[],·bool]·|·None, | 59 | ········cancel_check:·Callable[[],·bool]·|·None, |
| 46 | ········deadline:·float·|·None, | 60 | ········deadline:·float·|·None, |
| 47 | ········poll_interval:·float, | 61 | ········poll_interval:·float, |
| 48 | ····)·->·Async | 62 | ····)·->·AsyncGenerator[None]: |
| 49 | ········ticket:·ConcurrentFuture[None]·=·ConcurrentFuture() | 63 | ········ticket:·ConcurrentFuture[None]·=·ConcurrentFuture() |
| 50 | ········with·self._tail_lock: | ||
| 51 | ············predecessor·=·self._tail | ||
| 52 | ············self._tail·=·ticket | ||
| 53 | ········if·predecessor·is·not·None·and·not·predecessor.done(): | ||
| 54 | ········ | 64 | ········try: |
| 65 | ············self._join(ticket) | ||
| 66 | ············if·not·ticket.done(): | ||
| 55 | ················await·self._wait_for_ | 67 | ················await·self._wait_for_turn( |
| 56 | ···················· | 68 | ····················ticket, |
| 57 | ····················blocking=blocking, | 69 | ····················blocking=blocking, |
| 58 | ····················cancel_check=cancel_check, | 70 | ····················cancel_check=cancel_check, |
| 59 | ····················deadline=deadline, | 71 | ····················deadline=deadline, |
| 60 | ····················poll_interval=poll_interval, | 72 | ····················poll_interval=poll_interval, |
| 61 | ················) | 73 | ················) |
| 62 | ············except·BaseException: | ||
| 63 | ················predecessor.add_done_callback(lambda·_predecessor:·self._leave(ticket)) | ||
| 64 | ················raise | ||
| 65 | ········try: | ||
| 66 | ············yield | 74 | ············yield |
| 67 | ········finally: | 75 | ········finally: |
| 68 | ············self._leave(ticket) | 76 | ············self._leave(ticket) |
| 69 | ····@staticmethod | ||
| 70 | ····async·def·_wait_for_ | 77 | ····async·def·_wait_for_turn( |
| 78 | ········self, | ||
| 71 | ········ | 79 | ········ticket:·ConcurrentFuture[None], |
| 72 | ········*, | 80 | ········*, |
| 73 | ········blocking:·bool, | 81 | ········blocking:·bool, |
| 74 | ········cancel_check:·Callable[[],·bool]·|·None, | 82 | ········cancel_check:·Callable[[],·bool]·|·None, |
| 75 | ········deadline:·float·|·None, | 83 | ········deadline:·float·|·None, |
| 76 | ········poll_interval:·float, | 84 | ········poll_interval:·float, |
| 77 | ····)·->·None: | 85 | ····)·->·None: |
| 78 | ········if·not·blocking: | 86 | ········if·not·blocking: |
| 79 | ············raise·_AsyncTransitionUnavailableError | 87 | ············raise·_AsyncTransitionUnavailableError |
| 80 | ········waiter·=·asyncio.wrap_future( | 88 | ········waiter·=·asyncio.wrap_future(ticket) |
| 81 | ········while·not· | 89 | ········while·not·ticket.done(): |
| 82 | ············if·cancel_check·is·not·None·and·cancel_check(): | 90 | ············if·cancel_check·is·not·None·and·cancel_check(): |
| Max diff block lines reached; 16554/21567 bytes (76.76%) of diff not shown. | |||
| Offset 1, 56 lines modified | Offset 1, 66 lines modified | ||
| 1 | """Async·wrapper·around·:class:`ReadWriteLock`·for·use·with·``asyncio``.""" | 1 | """Async·wrapper·around·:class:`ReadWriteLock`·for·use·with·``asyncio``.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·["asyncio",·"concurrent.futures",·"filelock._async",·"filelock._error",·"functools",·"threading"] | ||
| 3 | import·asyncio | 4 | import·asyncio |
| 4 | import·functools | 5 | import·functools |
| 5 | import·os | 6 | import·os |
| 6 | import·sqlite3 | 7 | import·sqlite3 |
| 8 | import·threading | ||
| 7 | from·concurrent.futures·import·ThreadPoolExecutor | 9 | from·concurrent.futures·import·ThreadPoolExecutor |
| 10 | from·concurrent.futures·import·thread·as·executor_threads | ||
| 8 | from·contextlib·import·asynccontextmanager | 11 | from·contextlib·import·asynccontextmanager |
| 9 | from·typing·import·TYPE_CHECKING,·ParamSpec,·TypeVar | 12 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·ParamSpec,·TypeVar,·cast |
| 10 | from·._api·import·( | 13 | from·filelock._api·import·( |
| 11 | ····_append_exception_context, | 14 | ····_append_exception_context, |
| 12 | ····_ensure_current_process, | 15 | ····_ensure_current_process, |
| 13 | ····_fork_transition, | 16 | ····_fork_transition, |
| 14 | ····_register_fork_object, | 17 | ····_register_fork_object, |
| 15 | ) | 18 | ) |
| 16 | from·._async·import·( | 19 | from·filelock._async·import·( |
| 20 | ····_TASKS_THREAD_ID, | ||
| 17 | ····_BackendOutcome, | 21 | ····_BackendOutcome, |
| 18 | ····_capture_call, | 22 | ····_capture_call, |
| 19 | ····_drain_future, | 23 | ····_drain_future, |
| 20 | ····_future_result, | 24 | ····_future_result, |
| 21 | ····_raise_cancelled_error, | 25 | ····_raise_cancelled_error, |
| 26 | ····_task_owners_for, | ||
| 22 | ····_wait_until_done, | 27 | ····_wait_until_done, |
| 23 | ) | 28 | ) |
| 29 | from·filelock._error·import·Timeout | ||
| 24 | from·._read_write·import·ReadWriteLock | 30 | from·filelock._read_write·import·ReadWriteLock |
| 25 | if·TYPE_CHECKING: | 31 | if·TYPE_CHECKING: |
| 26 | ····from·collections.abc·import·AsyncGenerator,·Callable | 32 | ····from·collections.abc·import·AsyncGenerator,·Callable,·MutableMapping |
| 27 | ····from·concurrent·import·futures | 33 | ····from·concurrent·import·futures |
| 28 | ····from·types·import·TracebackType | 34 | ····from·types·import·TracebackType |
| 29 | ····from·._api·import·AcquireReturnProxy | 35 | ····from·filelock._api·import·AcquireReturnProxy |
| 30 | _P·=·ParamSpec("_P") | 36 | _P·=·ParamSpec("_P") |
| 31 | _R·=·TypeVar("_R") | 37 | _R·=·TypeVar("_R") |
| 32 | class·AsyncReadWriteLock: | 38 | class·AsyncReadWriteLock: |
| 33 | ····""" | 39 | ····""" |
| 34 | ····Async·wrapper·around·:class:`ReadWriteLock`·for·use·in·``asyncio``·applications. | 40 | ····Async·wrapper·around·:class:`ReadWriteLock`·for·use·in·``asyncio``·applications. |
| 35 | ····This·wrapper·dispatches·every·blocking·SQLite·operation·to·a·thread·pool·via·``loop.run_in_executor()``·because | 41 | ····This·wrapper·dispatches·every·blocking·SQLite·operation·to·a·thread·pool·via·``loop.run_in_executor()``·because |
| 36 | ····Python's·:mod:`sqlite3`·module·has·no·async·API.·It·delegates·reentrancy,·upgrade/downgrade·rules,·and·singleton | ||
| 37 | ···· | 42 | ····Python's·:mod:`sqlite3`·module·has·no·async·API.·Each·``asyncio``·task·owns·its·own·hold.·Tasks·share·a·read·lock, |
| 43 | ····and·a·task·asking·for·the·write·lock·waits·until·the·other·holders·release,·with·waiting·writers·ahead·of·new | ||
| 44 | ····readers.·As·with·:class:`ReadWriteLock`,·upgrading·or·downgrading·a·held·lock·raises·:class:`RuntimeError`. | ||
| 45 | ····Singleton·wrappers·over·one·path·share·their·task·holds,·and·closing·one·ends·only·the·holds·taken·through·it. | ||
| 38 | ····:param·lock_file:·path·to·the·SQLite·database·file·used·as·the·lock | 46 | ····:param·lock_file:·path·to·the·SQLite·database·file·used·as·the·lock |
| 39 | ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``· | 47 | ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``·waits·up·to·SQLite's·busy-timeout·cap·of·about·23·days |
| 40 | ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·when·the·lock·is·unavailable | 48 | ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·when·the·lock·is·unavailable |
| 41 | ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`ReadWriteLock`·instances·for·the·same·resolved·path | 49 | ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`ReadWriteLock`·instances·for·the·same·resolved·path |
| 42 | ····:param·loop:·event·loop·for·``run_in_executor``;·``None``·uses·the·running·loop | 50 | ····:param·loop:·event·loop·for·``run_in_executor``;·``None``·uses·the·running·loop |
| 43 | ····:param·executor:·executor·for·``run_in_executor``.·When·``None``·this·lock·creates·and·owns·a·dedicated | 51 | ····:param·executor:·executor·for·``run_in_executor``.·When·``None``·this·lock·creates·and·owns·a·dedicated |
| 44 | ········single-thread·executor·so·every·operation·runs·on·the·same·thread·(SQLite·affinity·requires·this)·and·shuts·it | 52 | ········single-thread·executor·so·every·operation·runs·on·the·same·thread·(SQLite·affinity·requires·this)·and·shuts·it |
| 45 | ········down·in·:meth:`close`.·This·lock·uses·a·caller-supplied·executor·as-is·and·never·shuts·it·down,·so·after·passing | 53 | ········down·in·:meth:`close`.·This·lock·uses·a·caller-supplied·executor·as-is·and·never·shuts·it·down,·so·after·passing |
| 46 | ········no·executor·call·:meth:`close`·to·release·the·owned·one. | 54 | ········no·executor·call·:meth:`close`·to·release·the·owned·one. |
| Offset 69, 17 lines modified | Offset 79, 21 lines modified | ||
| 69 | ········loop:·asyncio.AbstractEventLoop·|·None·=·None, | 79 | ········loop:·asyncio.AbstractEventLoop·|·None·=·None, |
| 70 | ········executor:·futures.Executor·|·None·=·None, | 80 | ········executor:·futures.Executor·|·None·=·None, |
| 71 | ····)·->·None: | 81 | ····)·->·None: |
| 72 | ········creator_pid·=·os.getpid() | 82 | ········creator_pid·=·os.getpid() |
| 73 | ········self._creator_pid·=·creator_pid | 83 | ········self._creator_pid·=·creator_pid |
| 74 | ········self._fork_invalidated·=·False | 84 | ········self._fork_invalidated·=·False |
| 75 | ········self._closed·=·False | 85 | ········self._closed·=·False |
| 86 | ········self._owns_backend·=·not·is_singleton | ||
| 87 | ········#:·Marks·the·task·holds·taken·through·this·wrapper,·which·its·close()·ends. | ||
| 88 | ········self._via:·Final·=·object() | ||
| 76 | ········_register_fork_object(self) | 89 | ········_register_fork_object(self) |
| 77 | ········with·_fork_transition(): | 90 | ········with·_fork_transition(): |
| 78 | ············self._lock·=·ReadWriteLock(lock_file,·timeout,·blocking=blocking,·is_singleton=is_singleton) | 91 | ············self._lock·=·ReadWriteLock(lock_file,·timeout,·blocking=blocking,·is_singleton=is_singleton) |
| 92 | ············self._owners·=·_task_owners_for(self._lock) | ||
| 79 | ············self._loop·=·loop | 93 | ············self._loop·=·loop |
| 80 | ············self._owns_executor·=·executor·is·None | 94 | ············self._owns_executor·=·executor·is·None |
| 81 | ············self._executor·=·executor·or·ThreadPoolExecutor(max_workers=1) | 95 | ············self._executor·=·executor·or·ThreadPoolExecutor(max_workers=1) |
| 82 | ············if·os.getpid()·!=·creator_pid:··#·pragma:·forked·child | 96 | ············if·os.getpid()·!=·creator_pid:··#·pragma:·forked·child |
| 83 | ················msg·=·"AsyncReadWriteLock·construction·cannot·continue·after·fork" | 97 | ················msg·=·"AsyncReadWriteLock·construction·cannot·continue·after·fork" |
| 84 | ················raise·RuntimeError(msg) | 98 | ················raise·RuntimeError(msg) |
| Offset 115, 18 lines modified | Offset 129, 14 lines modified | ||
| 115 | ········Falls·back·to·instance·defaults·for·*timeout*·and·*blocking*·when·``None``. | 129 | ········Falls·back·to·instance·defaults·for·*timeout*·and·*blocking*·when·``None``. |
| 116 | ········:param·timeout:·maximum·wait·time·in·seconds,·or·``None``·to·use·the·instance·default | 130 | ········:param·timeout:·maximum·wait·time·in·seconds,·or·``None``·to·use·the·instance·default |
| 117 | ········:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately;·``None``·uses·the·instance·default | 131 | ········:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately;·``None``·uses·the·instance·default |
| 118 | ········""" | 132 | ········""" |
| 119 | ········if·timeout·is·None: | ||
| 120 | ············timeout·=·self._lock.timeout | ||
| 121 | ········if·blocking·is·None: | ||
| 122 | ············blocking·=·self._lock.blocking | ||
| 123 | ········await·self.acquire_read(timeout,·blocking=blocking) | 133 | ········await·self.acquire_read(timeout,·blocking=blocking) |
| 124 | ········body_error:·BaseException·|·None·=·None | 134 | ········body_error:·BaseException·|·None·=·None |
| 125 | ········try: | 135 | ········try: |
| 126 | ············yield | 136 | ············yield |
| 127 | ········except·BaseException·as·error: | 137 | ········except·BaseException·as·error: |
| 128 | ············body_error·=·error | 138 | ············body_error·=·error |
| 129 | ············raise | 139 | ············raise |
| Offset 140, 18 lines modified | Offset 150, 14 lines modified | ||
| 140 | ········Falls·back·to·instance·defaults·for·*timeout*·and·*blocking*·when·``None``. | 150 | ········Falls·back·to·instance·defaults·for·*timeout*·and·*blocking*·when·``None``. |
| 141 | ········:param·timeout:·maximum·wait·time·in·seconds,·or·``None``·to·use·the·instance·default | 151 | ········:param·timeout:·maximum·wait·time·in·seconds,·or·``None``·to·use·the·instance·default |
| 142 | ········:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately;·``None``·uses·the·instance·default | 152 | ········:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately;·``None``·uses·the·instance·default |
| 143 | ········""" | 153 | ········""" |
| 144 | ········if·timeout·is·None: | ||
| 145 | ············timeout·=·self._lock.timeout | ||
| 146 | ········if·blocking·is·None: | ||
| 147 | ············blocking·=·self._lock.blocking | ||
| 148 | ········await·self.acquire_write(timeout,·blocking=blocking) | 154 | ········await·self.acquire_write(timeout,·blocking=blocking) |
| 149 | ········body_error:·BaseException·|·None·=·None | 155 | ········body_error:·BaseException·|·None·=·None |
| 150 | ········try: | 156 | ········try: |
| 151 | ············yield | 157 | ············yield |
| 152 | ········except·BaseException·as·error: | 158 | ········except·BaseException·as·error: |
| 153 | ············body_error·=·error | 159 | ············body_error·=·error |
| 154 | ············raise | 160 | ············raise |
| Max diff block lines reached; 13240/19148 bytes (69.15%) of diff not shown. | |||
| Offset 1, 20 lines modified | Offset 1, 24 lines modified | ||
| 1 | """A·minimal·native·lock·over·a·caller-owned·file·descriptor,·contending·with·:class:`FileLock`·on·the·same·file.""" | 1 | """A·minimal·native·lock·over·a·caller-owned·file·descriptor,·contending·with·:class:`FileLock`·on·the·same·file.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·["filelock._unix",·"threading",·"typing"] | ||
| 3 | import·sys | 4 | import·sys |
| 4 | import·time | 5 | import·time |
| 5 | from· | 6 | from·threading·import·TIMEOUT_MAX |
| 6 | from·typing·import·Final | 7 | from·typing·import·Final |
| 8 | from·filelock._api·import·_seconds | ||
| 7 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | 9 | if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 8 | ····from·._windows·import·_lock_fd_nonblocking,·_unlock_fd | 10 | ····from·filelock._windows·import·_lock_fd_nonblocking,·_unlock_fd |
| 9 | else:··#·pragma:·win32·no·cover | 11 | else:··#·pragma:·win32·no·cover |
| 10 | ····from·._unix·import·_lock_fd_nonblocking,·_unlock_fd | 12 | ····from·filelock._unix·import·_lock_fd_nonblocking,·_unlock_fd |
| 11 | def·lock_descriptor(fd:·int,·*,·blocking:·bool·=·True,·poll_interval:·float·=·0.05)·->·bool: | 13 | def·lock_descriptor(fd:·int,·*,·blocking:·bool·=·True,·poll_interval:·float·=·0.05)·->·bool: |
| 12 | ····""" | 14 | ····""" |
| 13 | ····Take·the·native·OS·lock·on·*fd*,·a·file·descriptor·the·caller·opened·and·owns. | 15 | ····Take·the·native·OS·lock·on·*fd*,·a·file·descriptor·the·caller·opened·and·owns. |
| 14 | ····This·is·the·same·one-byte·exclusive·lock·:class:`FileLock`·uses,·so·a·descriptor·lock·and·a·path·lock·on·the·same | 16 | ····This·is·the·same·one-byte·exclusive·lock·:class:`FileLock`·uses,·so·a·descriptor·lock·and·a·path·lock·on·the·same |
| Offset 24, 30 lines modified | Offset 28, 31 lines modified | ||
| 24 | ····For·timeout,·reentrancy,·singleton,·lifetime,·or·stale-break·behavior,·use·:class:`FileLock`.·There·is·no·async | 28 | ····For·timeout,·reentrancy,·singleton,·lifetime,·or·stale-break·behavior,·use·:class:`FileLock`.·There·is·no·async |
| 25 | ····wrapper.·Run·this·in·an·executor,·or·drive·``blocking=False``·from·your·own·polling·loop. | 29 | ····wrapper.·Run·this·in·an·executor,·or·drive·``blocking=False``·from·your·own·polling·loop. |
| 26 | ····:param·fd:·an·open·file·descriptor·the·caller·owns. | 30 | ····:param·fd:·an·open·file·descriptor·the·caller·owns. |
| 27 | ····:param·blocking:·when·``True``·(default),·retry·the·nonblocking·attempt·every·*poll_interval*·seconds·until·it | 31 | ····:param·blocking:·when·``True``·(default),·retry·the·nonblocking·attempt·every·*poll_interval*·seconds·until·it |
| 28 | ········succeeds;·when·``False``,·make·one·attempt. | 32 | ········succeeds;·when·``False``,·make·one·attempt. |
| 29 | ····:param·poll_interval:·finite,·positive·seconds·between·attempts·while·blocking;·ignored·when·*blocking*·is | ||
| 30 | ········ | 33 | ····:param·poll_interval:·positive·seconds·between·attempts·while·blocking,·at·most·:data:`threading.TIMEOUT_MAX`; |
| 34 | ········ignored·when·*blocking*·is·``False``. | ||
| 31 | ····:returns:·``True``·once·the·lock·is·held,·or·``False``·on·contention·when·``blocking``·is·``False``. | 35 | ····:returns:·``True``·once·the·lock·is·held,·or·``False``·on·contention·when·``blocking``·is·``False``. |
| 32 | ····:raises·OSError:·for·a·permanent·native·failure,·such·as·an·invalid·descriptor,·or·with·``errno.ENOSYS``·when·the | 36 | ····:raises·OSError:·for·a·permanent·native·failure,·such·as·an·invalid·descriptor,·or·with·``errno.ENOSYS``·when·the |
| 33 | ········Python·build·lacks·the·native·locking·primitive.·The·descriptor·is·left·open. | 37 | ········Python·build·lacks·the·native·locking·primitive.·The·descriptor·is·left·open. |
| 34 | ····:raises·ValueError:·if·a·blocking·call·receives·a· | 38 | ····:raises·ValueError:·if·a·blocking·call·receives·a·*poll_interval*·outside·that·range,·including·``nan``. |
| 35 | ····..·versionadded::·3.30.0 | 39 | ····..·versionadded::·3.30.0 |
| 36 | ····""" | 40 | ····""" |
| 37 | ····if·not·blocking: | 41 | ····if·not·blocking: |
| 38 | ········return·_lock_fd_nonblocking(fd) | 42 | ········return·_lock_fd_nonblocking(fd) |
| 39 | ····i | 43 | ····#·time.sleep·raises·OverflowError·past·TIMEOUT_MAX;·nan·fails·both·comparisons. |
| 44 | ····if·not·0·<·(poll_interval·:=·_seconds("poll_interval",·poll_interval))·<=·TIMEOUT_MAX: | ||
| 40 | ········msg:·Final[str]·=·f"poll_interval·must·be· | 45 | ········msg:·Final[str]·=·f"poll_interval·must·be·greater·than·0·and·at·most·{TIMEOUT_MAX},·got·{poll_interval}" |
| 41 | ········raise·ValueError(msg) | 46 | ········raise·ValueError(msg) |
| 42 | ····while·not·_lock_fd_nonblocking(fd): | 47 | ····while·not·_lock_fd_nonblocking(fd): |
| 43 | ········time.sleep(poll_interval) | 48 | ········time.sleep(poll_interval) |
| 44 | ····return·True | 49 | ····return·True |
| 45 | def·unlock_descriptor(fd:·int)·->·None: | 50 | def·unlock_descriptor(fd:·int)·->·None: |
| Offset 1, 35 lines modified | Offset 1, 49 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["typing"] | ||
| 3 | from·typing·import·Final | ||
| 2 | class·Timeout(TimeoutError):··#·ruff:ignore[error-suffix-on-exception-name]··#·public·exception·name;·renaming·breaks·the·API | 4 | class·Timeout(TimeoutError):··#·ruff:ignore[error-suffix-on-exception-name]··#·public·exception·name;·renaming·breaks·the·API |
| 3 | ····"""Raised·when·the·lock·could·not·be·acquired·in·*timeout*·seconds.""" | 5 | ····"""Raised·when·the·lock·could·not·be·acquired·in·*timeout*·seconds.""" |
| 4 | ····def·__init__(self,·lock_file:·str)·->·None: | 6 | ····def·__init__(self,·lock_file:·str,·holder:·str·|·None·=·None)·->·None: |
| 5 | ········super().__init__() | 7 | ········super().__init__() |
| 6 | ········self._lock_file·=·lock_file | 8 | ········self._lock_file·=·lock_file |
| 9 | ········self._holder·=·holder | ||
| 7 | ····def·__reduce__(self)·->·tuple[type[Timeout],·tuple[str]]: | 10 | ····def·__reduce__(self)·->·tuple[type[Timeout],·tuple[str],·dict[str,·object]]: |
| 8 | ········#· | 11 | ········#·holder·rides·in·the·state·so·a·subclass·taking·only·lock_file,·and·a·4.0.12·reader,·can·still·unpickle·it. |
| 9 | ········return·self.__class__,·(self._lock_file,) | 12 | ········return·self.__class__,·(self._lock_file,),·self.__dict__ |
| 10 | ····def·__str__(self)·->·str:··#·pragma:·needs·hard-link | 13 | ····def·__str__(self)·->·str:··#·pragma:·needs·hard-link |
| 11 | ········ | 14 | ········message:·Final·=·f"The·file·lock·'{self._lock_file}'·could·not·be·acquired." |
| 15 | ········if·self._holder·is·None: | ||
| 16 | ············return·message | ||
| 17 | ········return·f"{message}·It·is·held·by·{self._holder},·which·this·host·cannot·probe." | ||
| 12 | ····def·__repr__(self)·->·str: | 18 | ····def·__repr__(self)·->·str: |
| 13 | ········return·f"{self.__class__.__name__}({self.lock_file!r})" | 19 | ········return·f"{self.__class__.__name__}({self.lock_file!r})" |
| 14 | ····@property | 20 | ····@property |
| 15 | ····def·lock_file(self)·->·str: | 21 | ····def·lock_file(self)·->·str: |
| 16 | ········"""The·path·of·the·file·lock.""" | 22 | ········"""The·path·of·the·file·lock.""" |
| 17 | ········return·self._lock_file | 23 | ········return·self._lock_file |
| 18 | class·SoftFileLockLifetimeWarning( | 24 | class·SoftFileLockLifetimeWarning(FutureWarning): |
| 25 | ····""" | ||
| 19 | ···· | 26 | ····The·configured·soft-lock·lifetime·permits·overlapping·live·holders·after·expiry. |
| 27 | ····A·:class:`FutureWarning`·shows·by·default·wherever·the·lock·is·configured;·a·:class:`DeprecationWarning`·shows·only | ||
| 28 | ····in·``__main__``. | ||
| 29 | ····""" | ||
| 20 | class·LeaseSettingsMismatch(ValueError):··#·ruff:ignore[error-suffix-on-exception-name]··#·public·exception·name;·renaming·breaks·the·API | 30 | class·LeaseSettingsMismatch(ValueError):··#·ruff:ignore[error-suffix-on-exception-name]··#·public·exception·name;·renaming·breaks·the·API |
| 21 | ····"""A·lease·contender·disagrees·with·the·published·claim·about·how·long·the·lease·lasts.""" | 31 | ····"""A·lease·contender·disagrees·with·the·published·claim·about·how·long·the·lease·lasts.""" |
| 22 | class·SoftFileLockProtocolError(OSError): | 32 | class·SoftFileLockProtocolError(OSError): |
| Offset 39, 16 lines modified | Offset 53, 18 lines modified | ||
| 39 | ········self._lock_file·=·lock_file | 53 | ········self._lock_file·=·lock_file |
| 40 | ········self._claim_name·=·claim_name | 54 | ········self._claim_name·=·claim_name |
| 41 | ········self._reason·=·reason | 55 | ········self._reason·=·reason |
| 42 | ········super().__init__(self.__str__()) | 56 | ········super().__init__(self.__str__()) |
| 43 | ····def·__reduce__( | 57 | ····def·__reduce__( |
| 44 | ········self, | 58 | ········self, |
| 45 | ····)·->·tuple[ | 59 | ····)·->·tuple[ |
| 60 | ········type[SoftFileLockProtocolError],·tuple[str,·str·|·None,·str],·dict[str,·object] | ||
| 61 | ····]:··#·pragma:·needs·hard-link | ||
| 46 | ········return·self.__class__,·(self._lock_file,·self._claim_name,·self._reason) | 62 | ········return·self.__class__,·(self._lock_file,·self._claim_name,·self._reason),·self.__dict__ |
| 47 | ····def·__str__(self)·->·str: | 63 | ····def·__str__(self)·->·str: |
| 48 | ········location·=·self._lock_file·if·self._claim_name·is·None·else·f"{self._lock_file}:·claim·{self._claim_name!r}" | 64 | ········location·=·self._lock_file·if·self._claim_name·is·None·else·f"{self._lock_file}:·claim·{self._claim_name!r}" |
| 49 | ········return·f"Invalid·strict·soft-lock·state·at·{location}:·{self._reason}" | 65 | ········return·f"Invalid·strict·soft-lock·state·at·{location}:·{self._reason}" |
| 50 | ····@property | 66 | ····@property |
| 51 | ····def·lock_file(self)·->·str:··#·pragma:·needs·hard-link | 67 | ····def·lock_file(self)·->·str:··#·pragma:·needs·hard-link |
| Offset 1, 40 lines modified | Offset 1, 111 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["hashlib",·"pathlib",·"socket",·"typing"] | ||
| 3 | import·hashlib | ||
| 2 | import·os | 4 | import·os |
| 3 | import·socket | 5 | import·socket |
| 4 | import·sys | 6 | import·sys |
| 5 | from·errno·import·EPERM,·ESRCH | 7 | from·errno·import·EPERM,·ESRCH |
| 6 | from·pathlib·import·Path | 8 | from·pathlib·import·Path |
| 7 | from·typing·import·Final | 9 | from·typing·import·Final |
| 10 | #:·Every·marker·format·in·this·package·caps·the·hostname·at·the·RFC·1123·limit·and·reads·a·longer·one·as·malformed. | ||
| 11 | _HOST_NAME_LIMIT:·Final[int]·=·253 | ||
| 12 | #:·The·bytes·those·formats·carry·verbatim:·printable·non-space·ASCII,·less·the·``?``·reserved·for·the·escape. | ||
| 13 | _HOST_NAME_VERBATIM:·Final[frozenset[int]]·=·frozenset(range(0x21,·0x7F))·-·{ord("?")} | ||
| 14 | #:·The·characters·at·the·end·of·an·over-long·name·that·carry·a·digest·of·the·part·cut·off. | ||
| 15 | _HOST_NAME_DIGEST_LEN:·Final[int]·=·8 | ||
| 16 | #:·The·kernel·ABI·fixes·the·initial·PID·namespace's·inode·(``PID_NS_INIT_INO``·in·``linux/nsfs.h``);·every·namespace | ||
| 17 | #:·created·later·draws·one·from·``0xF0000000``·up,·so·this·value·names·the·host's·own·namespace. | ||
| 18 | _INITIAL_PID_NAMESPACE:·Final[int]·=·0xEFFFFFFC | ||
| 19 | _NAMESPACE_MARK:·Final[str]·=·"?pidns-" | ||
| 8 | def·host_name()·->·str: | 20 | def·host_name()·->·str: |
| 21 | ····""" | ||
| 9 | ···· | 22 | ····The·hostname·recorded·alongside·an·owner,·so·a·marker·written·on·another·machine·is·never·probed·here. |
| 10 | ····return·socket.gethostname() | ||
| 23 | ····Marker·formats·here·hold·the·field·to·printable·non-space·ASCII,·while·``socket.gethostname()``·reports·whatever | ||
| 24 | ····the·kernel·stores:·a·space,·a·newline·that·forges·an·extra·marker·line,·or·a·byte·no·codec·encodes,·which·Python | ||
| 25 | ····hands·back·as·a·surrogate.·A·holder·that·publishes·one·raw·writes·a·marker·it·cannot·read·back,·and·loses·the·lock | ||
| 26 | ····to·the·first·peer·that·ages·it·out·as·malformed.·``?``·is·illegal·in·a·hostname,·so·escaping·it·along·with·every | ||
| 27 | ····out-of-grammar·byte·as·``?<hex>``·leaves·a·real·name·untouched·and·still·keeps·two·hosts·apart,·which | ||
| 28 | ····:func:`owner_is_stale`·relies·on·to·refuse·to·probe·a·foreign·PID. | ||
| 29 | ····Linux·appends·the·PID·namespace,·as·Mercurial's·lock·prefix·does.·Two·containers·in·one·pod·share·the·hostname·and | ||
| 30 | ····the·boot·id·but·not·the·PID·namespace,·so·a·PID·recorded·in·one·names·another·process,·or·none,·in·the·other.·The | ||
| 31 | ····suffix·starts·with·a·``?``·no·escape·can·produce,·so·``a``·in·a·namespace·never·reads·as·a·host·literally·named | ||
| 32 | ····``a?pidns-...``.·The·initial·namespace·adds·nothing,·which·keeps·a·host's·name·what·older·releases·recorded. | ||
| 33 | ····An·over-long·name·ends·in·a·digest·of·the·part·cut·to·fit·the·limit.·A·bare·cut·gives·every·name·that·shares·the | ||
| 34 | ····kept·prefix·one·identity,·and·:func:`owner_is_stale`·would·then·probe·a·local·PID·for·another·host's·holder. | ||
| 35 | ····""" | ||
| 36 | ····name·=·( | ||
| 37 | ········"".join( | ||
| 38 | ············chr(byte)·if·byte·in·_HOST_NAME_VERBATIM·else·f"?{byte:02x}" | ||
| 39 | ············for·byte·in·socket.gethostname().encode("utf-8",·"surrogateescape") | ||
| 40 | ········) | ||
| 41 | ········+·_pid_namespace_suffix() | ||
| 42 | ····) | ||
| 43 | ····if·len(name)·>·_HOST_NAME_LIMIT: | ||
| 44 | ········keep·=·_HOST_NAME_LIMIT·-·_HOST_NAME_DIGEST_LEN·-·1 | ||
| 45 | ········name·=·f"{name[:keep]}-{hashlib.sha256(name[keep:].encode()).hexdigest()[:_HOST_NAME_DIGEST_LEN]}" | ||
| 46 | ····#·An·escape·is·three·characters·and·a·kept·byte·is·never·'?',·so·a·bare·'?'·can·only·mean·an·empty·hostname. | ||
| 47 | ····return·name·or·"?" | ||
| 48 | def·_pid_namespace_suffix()·->·str: | ||
| 49 | ····try: | ||
| 50 | ········namespace:·Final·=·Path("/proc/self/ns/pid").stat().st_ino | ||
| 51 | ····except·OSError:··#·only·Linux·3.8+·has·the·file,·and·a·sandbox·may·hide·it;·nothing·else·tells·namespaces·apart | ||
| 52 | ········return·"" | ||
| 53 | ····return·""·if·namespace·==·_INITIAL_PID_NAMESPACE·else·f"{_NAMESPACE_MARK}{namespace:x}" | ||
| 11 | def·owner_is_stale(pid:·int,·hostname:·str,·start_token:·int·|·None)·->·bool: | 54 | def·owner_is_stale(pid:·int,·hostname:·str,·start_token:·int·|·None)·->·bool: |
| 12 | ····""" | 55 | ····""" |
| 13 | ····Whether·the·recorded·owner·is·provably·gone,·so·reclaiming·its·marker·cannot·detach·a·live·holder. | 56 | ····Whether·the·recorded·owner·is·provably·gone,·so·reclaiming·its·marker·cannot·detach·a·live·holder. |
| 14 | ····Fail·closed:·return·``True``·only·when·this·process·can·prove·the·exact·recorded·owner·is·dead.·A·marker·from | 57 | ····Fail·closed:·return·``True``·only·when·this·process·can·prove·the·exact·recorded·owner·is·dead.·A·marker·from |
| 15 | ····another·host·cannot·be·probed;·a·live·PID·whose·start·token·still·matches,·or·whose·token·cannot·be·read,·is·the | 58 | ····another·host·cannot·be·probed;·a·live·PID·whose·start·token·still·matches,·or·whose·token·cannot·be·read,·is·the |
| 16 | ····holder·or·is·indistinguishable·from·it;·a·live·PID·whose·start·token·differs·is·a·recycled·PID,·so·the·process·that | 59 | ····holder·or·is·indistinguishable·from·it;·a·live·PID·whose·start·token·differs·is·a·recycled·PID,·so·the·process·that |
| 17 | ····wrote·the·marker·is·gone.·PostgreSQL,·Qt·``QLockFile``·and·Mercurial·all·break·a·stale·lock·only·on·proof·of·death | 60 | ····wrote·the·marker·is·gone.·PostgreSQL,·Qt·``QLockFile``·and·Mercurial·all·break·a·stale·lock·only·on·proof·of·death |
| 18 | ····and·treat·an·unreadable·or·foreign·owner·as·still·holding. | 61 | ····and·treat·an·unreadable·or·foreign·owner·as·still·holding. |
| 19 | ····""" | 62 | ····""" |
| 20 | ····if·hostname·!=·host_name(): | 63 | ····if·hostname·!=·host_name(): |
| 21 | ········return·False | 64 | ········return·False |
| 22 | ····if· | 65 | ····if·process_alive(pid)·and·( |
| 23 | ········return·True | ||
| 24 | ····i | 66 | ········start_token·is·None·or·(current·:=·process_start_token(pid))·is·None·or·_same_start(current,·start_token) |
| 67 | ····): | ||
| 25 | ········return·False | 68 | ········return·False |
| 26 | ····current·=·process_start_token(pid) | ||
| 27 | ····ret | 69 | ····#·Only·a·bare·hostname·can·be·an·older·release's,·written·from·a·container·that·shares·this·host's·name. |
| 70 | ····return·_NAMESPACE_MARK·in·hostname·or·not·_owner_runs_elsewhere(pid,·start_token) | ||
| 71 | def·owner_is_current_process(pid:·int,·hostname:·str,·start_token:·int·|·None)·->·bool: | ||
| 72 | ····""" | ||
| 73 | ····Whether·the·recorded·owner·is·this·process,·so·a·marker·a·recycled·PID·left·behind·never·reads·as·ours. | ||
| 74 | ····Fail·closed:·a·recorded·start·token·must·match·this·process's.·One·that·differs·was·written·by·an·earlier·process | ||
| 75 | ····that·reused·this·PID,·and·when·this·process·cannot·read·its·own·token·nothing·proves·the·marker·is·ours.·A·marker | ||
| 76 | ····without·a·token·falls·back·to·the·PID·and·hostname. | ||
| 77 | ····""" | ||
| 78 | ····if·pid·!=·os.getpid()·or·hostname·!=·host_name(): | ||
| 79 | ········return·False | ||
| 80 | ····return·start_token·is·None·or·start_token·==·process_start_token(pid) | ||
| 81 | def·_same_start(current:·int,·recorded:·int)·->·bool: | ||
| 82 | ····#·A·Linux·token·carries·the·boot·id·in·its·high·64·bits,·or·0·there·when·the·process·could·not·read·the·boot·id. | ||
| 83 | ····#·systemd's·ProcSubset=pid·hides·/proc/sys·from·one·unit,·so·one·process·may·lack·the·boot·id·while·its·peer·has | ||
| 84 | ····#·it.·A·missing·boot·id·then·proves·nothing,·and·only·starttime·is·compared.·Other·platforms'·tokens·fit·in·the | ||
| 85 | ····#·low·bits. | ||
| 86 | ····return·current·==·recorded·or·(0·in·{current·>>·64,·recorded·>>·64}·and·current·%·2**64·==·recorded·%·2**64) | ||
| 28 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | 87 | if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 29 | ····import·ctypes | 88 | ····import·ctypes |
| 30 | ····from·ctypes·import·wintypes | 89 | ····from·ctypes·import·wintypes |
| 31 | ····_KERNEL32:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("kernel32",·use_last_error=True) | 90 | ····_KERNEL32:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("kernel32",·use_last_error=True) |
| Offset 103, 41 lines modified | Offset 174, 112 lines modified | ||
| 103 | ········#·comm·(field·2)·is·wrapped·in·parentheses·and·may·itself·contain·spaces·or·a·')',·so·the·fixed·fields·start | 174 | ········#·comm·(field·2)·is·wrapped·in·parentheses·and·may·itself·contain·spaces·or·a·')',·so·the·fixed·fields·start |
| 104 | ········#·after·the·final·')'.·starttime·is·field·22·overall,·the·twentieth·of·those·trailing·fields·(index·19). | 175 | ········#·after·the·final·')'.·starttime·is·field·22·overall,·the·twentieth·of·those·trailing·fields·(index·19). |
| 105 | ········_STARTTIME_INDEX:·Final[int]·=·19 | 176 | ········_STARTTIME_INDEX:·Final[int]·=·19 |
| 106 | ········def·_read_boot_id()·->·int: | 177 | ········def·_read_boot_id()·->·int: |
| 107 | ············#·starttime·is·measured·in·clock·ticks·since·boot,·so·on·its·own·it·repeats·across·a·reboot.·Folding·the | 178 | ············#·starttime·is·measured·in·clock·ticks·since·boot,·so·on·its·own·it·repeats·across·a·reboot.·Folding·the |
| 108 | ············#·boot·id·into·the·high·bits·makes·the·Linux·token·reboot-safe·like·the·absolute·clocks·macOS·and·Windows | 179 | ············#·boot·id·into·the·high·bits·makes·the·Linux·token·reboot-safe·like·the·absolute·clocks·macOS·and·Windows |
| 109 | ············#·expose,·while·staying·a·single·integer·so·a·3.29·reader·still·parses·the·third·marker·line.·0·when·th | 180 | ············#·expose,·while·staying·a·single·integer·so·a·3.29·reader·still·parses·the·third·marker·line.·0·when·this |
| 181 | ············#·process·cannot·read·the·boot·id·leaves·the·bare·starttime,·which·_same_start·compares·alone. | ||
| 110 | ············#·kernel·does·not·expose·a·boot·id·degrades·to·bare·starttime,·which·stays·safe·(a·reboot·collision·fails | ||
| 111 | ············#·closed·rather·than·reclaiming·a·live·marker). | ||
| 112 | ············try: | 182 | ············try: |
| 113 | ················boot_id·=·Path("/proc/sys/kernel/random/boot_id").read_text(encoding="ascii") | 183 | ················boot_id·=·Path("/proc/sys/kernel/random/boot_id").read_text(encoding="ascii") |
| Max diff block lines reached; 6404/14093 bytes (45.44%) of diff not shown. | |||
| Offset 1, 47 lines modified | Offset 1, 61 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·[ | ||
| 3 | ····"contextlib", | ||
| 4 | ····"filelock._error", | ||
| 5 | ····"filelock._identity", | ||
| 6 | ····"filelock._soft", | ||
| 7 | ····"filelock._util", | ||
| 8 | ····"math", | ||
| 9 | ····"secrets", | ||
| 10 | ····"threading", | ||
| 11 | ····"weakref", | ||
| 12 | ] | ||
| 2 | import·os | 13 | import·os |
| 3 | import·secrets | 14 | import·secrets |
| 15 | import·sys | ||
| 4 | import·time | 16 | import·time |
| 5 | from·contextlib·import·suppress | 17 | from·contextlib·import·suppress |
| 6 | from·dataclasses·import·dataclass | 18 | from·dataclasses·import·dataclass |
| 19 | from·math·import·isfinite | ||
| 7 | from·threading·import·Event,·Thread,·current_thread | 20 | from·threading·import·Event,·Thread,·current_thread |
| 8 | from·typing·import·TYPE_CHECKING,·Literal | 21 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·cast |
| 22 | from·weakref·import·WeakMethod | ||
| 23 | from·filelock._api·import·_check_timeout_max,·_seconds | ||
| 9 | from·._error·import·LeaseSettingsMismatch | 24 | from·filelock._error·import·LeaseSettingsMismatch |
| 10 | from·._identity·import·owner_is_stale | 25 | from·filelock._identity·import·owner_is_stale |
| 11 | from·._marker·import·MarkerSoftFileLock,·OwnerMode,·OwnerRecord,·parse_marker | 26 | from·filelock._marker·import·MarkerSoftFileLock,·OwnerMode,·OwnerRecord,·parse_marker |
| 12 | from·._soft·import·_read_lock_file | 27 | from·filelock._soft·import·_read_lock_file |
| 13 | from·._util·import· | 28 | from·filelock._util·import·pin_inode,·touch |
| 14 | if·TYPE_CHECKING: | 29 | if·TYPE_CHECKING: |
| 15 | ····import·sys | ||
| 16 | ····from·collections.abc·import·Callable | 30 | ····from·collections.abc·import·Callable,·Mapping |
| 31 | ····from·typing·import·Unpack | ||
| 17 | ····from·._api·import·LockOptions | ||
| 32 | ····from·filelock._api·import·LockOptions,·_ExtraValue | ||
| 18 | ····if·sys.version_info·>=·(3,·11):··#·pragma:·no·cover·(py311+) | ||
| 19 | ········from·typing·import·Unpack | ||
| 20 | ····else:··#·pragma:·no·cover·(<py311) | ||
| 21 | ········from·typing_extensions·import·Unpack | ||
| 33 | #:·``evicted``·is·a·:class:`~filelock.SoftReadWriteLock`·loss:·a·peer·waited·out·the·stale·threshold·and·committed·a | ||
| 34 | #:·generation·without·this·holder. | ||
| 22 | CompromiseReason·=·Literal["marker-missing",·"owner-changed",·"refresh-failed"] | 35 | CompromiseReason·=·Literal["marker-missing",·"owner-changed",·"refresh-failed",·"evicted"] |
| 23 | _RefreshOutcome·=·Literal["ok",·" | 36 | _RefreshOutcome·=·Literal["ok",·"transient",·"marker-missing",·"owner-changed"] |
| 37 | _DEFAULT_LEASE_DURATION:·Final[float]·=·30.0 | ||
| 24 | @dataclass(frozen=True) | 38 | @dataclass(frozen=True) |
| 25 | class·LeaseCompromise: | 39 | class·LeaseCompromise: |
| 26 | ····"""Why·a·held·lease·stopped·being·this·process's·to·hold.""" | 40 | ····"""Why·a·held·lease·stopped·being·this·process's·to·hold,·and·the·error·that·ended·its·refresh,·if·any.""" |
| 27 | ····lock_file:·str | 41 | ····lock_file:·str |
| 28 | ····token:·str | 42 | ····token:·str |
| 29 | ····reason:·CompromiseReason | 43 | ····reason:·CompromiseReason |
| 30 | ····error:· | 44 | ····error:·Exception·|·None·=·None |
| 31 | @dataclass(frozen=True) | 45 | @dataclass(frozen=True) |
| 32 | class·_Heartbeat: | 46 | class·_Heartbeat: |
| 33 | ····"""A·running·heartbeat·and·the·event·that·stops·it,·which·only·ever·exist·together.""" | 47 | ····"""A·running·heartbeat·and·the·event·that·stops·it,·which·only·ever·exist·together.""" |
| 34 | ····thread:·Thread | 48 | ····thread:·Thread |
| Offset 53, 36 lines modified | Offset 67, 23 lines modified | ||
| 53 | ····"""The·state·of·one·claim:·its·token,·its·heartbeat,·and·how·that·claim·was·lost.""" | 67 | ····"""The·state·of·one·claim:·its·token,·its·heartbeat,·and·how·that·claim·was·lost.""" |
| 54 | ····token:·str·|·None·=·None | 68 | ····token:·str·|·None·=·None |
| 55 | ····compromise:·LeaseCompromise·|·None·=·None | 69 | ····compromise:·LeaseCompromise·|·None·=·None |
| 56 | ····heartbeat:·_Heartbeat·|·None·=·None | 70 | ····heartbeat:·_Heartbeat·|·None·=·None |
| 57 | class·_LeaseClaimHolder: | ||
| 58 | ····"""Holds·the·claim·its·owning·context·acquired.""" | ||
| 59 | ····#·Only·the·holder·is·thread-local,·mirroring·FileLockContext:·the·claim·stays·an·ordinary·object,·so·the·heartbeat | ||
| 60 | ····#·thread·records·a·compromise·where·the·thread·that·acquired·the·lease·reads·it. | ||
| 61 | ····def·__init__(self)·->·None: | ||
| 62 | ········self.claim·=·_LeaseClaim() | ||
| 63 | class·_ThreadLocalLeaseClaimHolder(_LeaseClaimHolder,·local): | ||
| 64 | ····"""A·thread·local·version·of·the·``_LeaseClaimHolder``·class.""" | ||
| 65 | class·SoftFileLease(MarkerSoftFileLock): | 71 | class·SoftFileLease(MarkerSoftFileLock): |
| 66 | ····""" | 72 | ····""" |
| 67 | ····Existence·lock·whose·claim·expires,·so·a·peer·may·take·it·while·the·previous·holder·still·runs. | 73 | ····Existence·lock·whose·claim·expires,·so·a·peer·may·take·it·while·the·previous·holder·still·runs. |
| 68 | ····A·lease·trades·mutual·exclusion·for·progress.·The·holder·publishes·a·claim·and·refreshes·it·every | 74 | ····A·lease·trades·mutual·exclusion·for·progress.·The·holder·publishes·a·claim·and·refreshes·it·every |
| 69 | ····``heartbeat_interval``·seconds;·a·contender·takes·the·marker·once·it· | 75 | ····``heartbeat_interval``·seconds;·a·contender·takes·the·marker·once·it·has·seen·no·refresh·for·``lease_duration`` |
| 76 | ····seconds·of·its·own·monotonic·clock,·so·clock·skew·between·hosts·cannot·expire·a·live·claim.·Nothing·stops·the | ||
| 70 | ···· | 77 | ····expired·holder:·it·keeps·running,·and·it·keeps·using·whatever·the·lock·protects.·Treat·the·lease·as·a·hint·about |
| 71 | ···· | 78 | ····who·*should*·be·working,·not·as·a·guarantee·that·only·one·worker·is. |
| 72 | ····To·make·a·protected·resource·reject·a·superseded·holder,·that·resource·must·be·linearizable·and·must·fence·on·a | 79 | ····To·make·a·protected·resource·reject·a·superseded·holder,·that·resource·must·be·linearizable·and·must·fence·on·a |
| 73 | ····monotonic·generation·it·controls.·:attr:`token`·names·a·claim;·it·does·not·fence·one.·Where·overlap·is·unacceptable, | 80 | ····monotonic·generation·it·controls.·:attr:`token`·names·a·claim;·it·does·not·fence·one.·Where·overlap·is·unacceptable, |
| 74 | ····use·:class:`StrictSoftFileLock·<filelock.StrictSoftFileLock>`·instead. | 81 | ····use·:class:`StrictSoftFileLock·<filelock.StrictSoftFileLock>`·instead. |
| 75 | ····Every·contender·for·a·path·must·agree·on·``lease_duration``.·A·contender·that·finds·a·claim·published·under·a | 82 | ····Every·contender·for·a·path·must·agree·on·``lease_duration``.·A·contender·that·finds·a·claim·published·under·a |
| 76 | ····different·duration·raises·:class:`LeaseSettingsMismatch·<filelock.LeaseSettingsMismatch>`·rather·than·apply·its·own | 83 | ····different·duration·raises·:class:`LeaseSettingsMismatch·<filelock.LeaseSettingsMismatch>`·rather·than·apply·its·own |
| Offset 108, 54 lines modified | Offset 109, 80 lines modified | ||
| 108 | ····_lifetime_supported:·bool·=·False | 109 | ····_lifetime_supported:·bool·=·False |
| 109 | ····_lifetime_unsupported_reason:·str·=·"lease_duration·sets·when·a·lease·expires" | 110 | ····_lifetime_unsupported_reason:·str·=·"lease_duration·sets·when·a·lease·expires" |
| 110 | ····def·__init__( | 111 | ····def·__init__( |
| 111 | ········self, | 112 | ········self, |
| 112 | ········lock_file:·str·|·os.PathLike[str], | 113 | ········lock_file:·str·|·os.PathLike[str], |
| 113 | ········*, | 114 | ········*, |
| 114 | ········lease_duration:·float·=· | 115 | ········lease_duration:·float·=·_DEFAULT_LEASE_DURATION, |
| 115 | ········heartbeat_interval:·float·|·None·=·None, | 116 | ········heartbeat_interval:·float·|·None·=·None, |
| 116 | ········on_compromise:·Callable[[LeaseCompromise],·None]·|·None·=·None, | 117 | ········on_compromise:·Callable[[LeaseCompromise],·None]·|·None·=·None, |
| 117 | ········**kwargs:·Unpack[LockOptions], | 118 | ········**kwargs:·Unpack[LockOptions], |
| 118 | ····)·->·None: | 119 | ····)·->·None: |
| 119 | ········""" | 120 | ········""" |
| 120 | ········Create·a·lease. | 121 | ········Create·a·lease. |
| 121 | ········:param·lease_duration:·seconds· | 122 | ········:param·lease_duration:·seconds·a·contender·must·see·the·marker·go·unrefreshed·before·it·may·take·the·claim. |
| 122 | ············for·the·path·must·pass·the·same·value. | 123 | ············Every·contender·for·the·path·must·pass·the·same·value. |
| 123 | ········:param·heartbeat_interval:·seconds·between·refreshes.·Defaults·to·a·third·of·``lease_duration``,·leaving·room | 124 | ········:param·heartbeat_interval:·seconds·between·refreshes.·Defaults·to·a·third·of·``lease_duration``,·leaving·room |
| 124 | ············for·two·missed·refreshes·before·a·peer·may·take·the·claim.·Must·be·shorter·than·``lease_duration`` | 125 | ············for·two·missed·refreshes·before·a·peer·may·take·the·claim.·Must·be·shorter·than·``lease_duration``·and·at |
| 126 | ············most·:data:`threading.TIMEOUT_MAX`. | ||
| Max diff block lines reached; 18842/25278 bytes (74.54%) of diff not shown. | |||
| Offset 1, 46 lines modified | Offset 1, 41 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["contextlib",·"filelock._identity",·"filelock._util",·"math"] | ||
| 2 | import·math | 3 | import·math |
| 3 | import·os | 4 | import·os |
| 5 | import·re | ||
| 4 | from·contextlib·import·suppress | 6 | from·contextlib·import·suppress |
| 5 | from·typing·import·Final,·Literal,·NamedTuple | 7 | from·typing·import·Final,·Literal,·NamedTuple |
| 6 | from·._identity·import·host_name,·process_start_token | 8 | from·filelock._identity·import·host_name,·owner_is_current_process,·owner_is_stale,·process_start_token |
| 7 | from·._soft·import·SoftFileLock,·_read_lock_file | 9 | from·filelock._soft·import·SoftFileLock,·_read_lock_file,·parse_decimal |
| 8 | from·._util·import·write_all | 10 | from·filelock._util·import·pin_inode,·write_all |
| 9 | #:·Protocol·1·is·the·legacy·``<pid>\n<hostname>\n[<start_token>\n]``·marker·that·:class:`SoftFileLock`·still·writes. | 11 | #:·Protocol·1·is·the·legacy·``<pid>\n<hostname>\n[<start_token>\n]``·marker·that·:class:`SoftFileLock`·still·writes. |
| 10 | #:·Protocol·2·carries·the·owner·mode·and·the·lease·claim.·A·protocol·1·reader·treats·a·protocol·2·marker·as·malformed | 12 | #:·Protocol·2·carries·the·owner·mode·and·the·lease·claim.·A·protocol·1·reader·treats·a·protocol·2·marker·as·malformed |
| 11 | #:·and·evicts·it·after·its·grace·period,·so·the·two·never·guarantee·mutual·exclusion·against·each·other. | 13 | #:·and·evicts·it·after·its·grace·period,·so·the·two·never·guarantee·mutual·exclusion·against·each·other. |
| 12 | _PROTOCOL:·Final[str]·=·"filelock/2" | 14 | _PROTOCOL:·Final[str]·=·"filelock/2" |
| 13 | _MAX_PID:·Final[int]·=·2**31·-·1 | 15 | _MAX_PID:·Final[int]·=·2**31·-·1 |
| 14 | #:·``unknown``·is·never·published:·it·names·a·mode·some·other·filelock·wrote·that·this·version·cannot·interpret.·Such·a | ||
| 15 | #:·record·still·identifies·a·live·owner,·so·it·is·parsed·rather·than·read·as·malformed·and·aged·out. | ||
| 16 | 16 | #:·The·forms·``repr``·gives·a·non-negative·finite·float·or·int;·``float()``·would·also·accept·whitespace,·underscores | |
| 17 | #:·and·non-ASCII·digits. | ||
| 18 | _DURATION:·Final[re.Pattern[str]]·=·re.compile(r"[0-9]+(?:\.[0-9]+)?(?:e[+-][0-9]+)?",·re.ASCII) | ||
| 19 | #:·Preserve·unknown·contracts·so·contenders·cannot·mistake·them·for·malformed,·reclaimable·markers. | ||
| 20 | OwnerMode·=·Literal["lease",·"exclusive",·"unknown"] | ||
| 17 | class·OwnerRecord(NamedTuple): | ||
| 18 | ····"""The·owner·published·in·a·protocol·2·marker.""" | ||
| 19 | ····pid:·int | ||
| 20 | ····hostname:·str | ||
| 21 | ····mode:·OwnerMode | ||
| 22 | ····token:·str·|·None·=·None | ||
| 23 | ····lease_duration:·float·|·None·=·None | ||
| 24 | ····start:·int·|·None·=·None | ||
| 25 | class·MarkerSoftFileLock(SoftFileLock): | 21 | class·MarkerSoftFileLock(SoftFileLock): |
| 26 | ····"""An·existence·lock·whose·marker·carries·a·protocol·2·owner·record.""" | 22 | ····"""An·existence·lock·whose·marker·carries·a·protocol·2·owner·record.""" |
| 27 | ····#:· | 23 | ····#:·Age-based·expiry·requires·a·lease·contract;·an·exclusive·holder·grants·none. |
| 28 | ····_owner_mode:·OwnerMode | 24 | ····_owner_mode:·OwnerMode·=·"exclusive" |
| 29 | ····@property | 25 | ····@property |
| 30 | ····def·owner(self)·->·OwnerRecord·|·None: | 26 | ····def·owner(self)·->·OwnerRecord·|·None: |
| 31 | ········""" | 27 | ········""" |
| 32 | ········The·owner·named·by·the·marker·on·disk. | 28 | ········The·owner·named·by·the·marker·on·disk. |
| 33 | ········:returns:·the·published·record,·or·``None``·when·no·marker·exists·or·its·record·is·malformed·or·protocol·1 | 29 | ········:returns:·the·published·record,·or·``None``·when·no·marker·exists·or·its·record·is·malformed·or·protocol·1 |
| Offset 59, 61 lines modified | Offset 54, 99 lines modified | ||
| 59 | ········return·None·if·(owner·:=·self._read_owner())·is·None·else·owner.pid | 54 | ········return·None·if·(owner·:=·self._read_owner())·is·None·else·owner.pid |
| 60 | ····@property | 55 | ····@property |
| 61 | ····def·is_lock_held_by_us(self)·->·bool: | 56 | ····def·is_lock_held_by_us(self)·->·bool: |
| 62 | ········""" | 57 | ········""" |
| 63 | ········Whether·the·marker·on·disk·names·this·process. | 58 | ········Whether·the·marker·on·disk·names·this·process. |
| 64 | ········:returns:·``True``·when·the·marker | 59 | ········:returns:·``True``·when·the·marker·names·this·process's·PID,·hostname·and,·when·recorded,·start·token |
| 65 | ········""" | 60 | ········""" |
| 66 | ········owner·=·self._read_owner() | 61 | ········owner·=·self._read_owner() |
| 67 | ········return·owner·is·not·None·and·owner | 62 | ········return·owner·is·not·None·and·owner_is_current_process(owner.pid,·owner.hostname,·owner.start) |
| 68 | ····def·force_break(self)·->·None: | 63 | ····def·force_break(self)·->·None: |
| 69 | ········""" | 64 | ········""" |
| 70 | ········Remove·the·marker·whoever·holds·it,·so·a·later·contender·can·acquire. | 65 | ········Remove·the·marker·whoever·holds·it,·so·a·later·contender·can·acquire. |
| 71 | ········Forced·breaking·voids·mutual·exclusion:·the·previous·holder·keeps·running·and·keeps·using·whatever·the·lock | 66 | ········Forced·breaking·voids·mutual·exclusion:·the·previous·holder·keeps·running·and·keeps·using·whatever·the·lock |
| 72 | ········protects.·Reserve·it·for·an·operator·clearing·a·marker·whose·holder·is·known·to·be·gone. | 67 | ········protects.·Reserve·it·for·an·operator·clearing·a·marker·whose·holder·is·known·to·be·gone. |
| 73 | ········""" | 68 | ········""" |
| 74 | ········self.break_lock() | 69 | ········self.break_lock() |
| 70 | ····def·_try_break_stale_lock(self)·->·None: | ||
| 71 | ········with·suppress(OSError,·ValueError),·pin_inode(self._lock_path)·as·pinned: | ||
| 72 | ············content,·marker·=·_read_lock_file(self._lock_path) | ||
| 73 | ············owner:·Final[OwnerRecord·|·None] | ||
| 74 | ············if·pinned·not·in·{None,·marker.st_ino}:··#·pragma:·win32·no·cover··#·Windows·pins·nothing | ||
| 75 | ················return··#·replaced·before·the·read,·so·nothing·keeps·the·number·read·from·reuse | ||
| 76 | ············if·(owner·:=·parse_marker(content))·is·None: | ||
| 77 | ················super()._try_break_stale_lock() | ||
| 78 | ············elif·owner.mode·!=·"unknown"·and·owner_is_stale(owner.pid,·owner.hostname,·owner.start): | ||
| 79 | ················self._take_over(marker,·owner.pid) | ||
| 80 | ····@classmethod | ||
| 81 | ····def·_recorded_holder(cls,·content:·str·|·None)·->·tuple[int,·str]·|·None: | ||
| 82 | ········if·(owner·:=·parse_marker(content))·is·not·None: | ||
| 83 | ············return·owner.pid,·owner.hostname | ||
| 84 | ········return·super()._recorded_holder(content) | ||
| 85 | ····@classmethod | ||
| 86 | ····def·_marker_is_live(cls,·content:·str·|·None,·breaker_pid:·int)·->·bool:··#·pragma:·win32·no·cover | ||
| 87 | ········if·(owner·:=·parse_marker(content))·is·None: | ||
| 88 | ············return·super()._marker_is_live(content,·breaker_pid) | ||
| 89 | ········return·owner.mode·==·"unknown"·or·( | ||
| 90 | ············(owner.pid·!=·breaker_pid·or·owner.hostname·!=·host_name()) | ||
| 91 | ············and·not·owner_is_stale(owner.pid,·owner.hostname,·owner.start) | ||
| 92 | ········) | ||
| 75 | ····def·_read_owner(self)·->·OwnerRecord·|·None: | 93 | ····def·_read_owner(self)·->·OwnerRecord·|·None: |
| 76 | ········with·suppress(OSError,·ValueError): | 94 | ········with·suppress(OSError,·ValueError): |
| 77 | ············return·parse_marker(_read_lock_file(self.lock_ | 95 | ············return·parse_marker(_read_lock_file(self._lock_path)[0]) |
| 78 | ········return·None | 96 | ········return·None |
| 79 | ····def·_write_lock_info(self,·fd:·int)·->·None: | 97 | ····def·_write_lock_info(self,·fd:·int)·->·None: |
| 80 | ········write_all(fd,·encode_marker(self._published_record())) | 98 | ········write_all(fd,·encode_marker(self._published_record())) |
| 81 | ····def·_published_record(self)·->·OwnerRecord: | 99 | ····def·_published_record(self)·->·OwnerRecord: |
| 82 | ········return·OwnerRecord( | 100 | ········return·OwnerRecord( |
| 83 | ············pid=os.getpid(), | 101 | ············pid=os.getpid(), |
| 84 | ············hostname=host_name(), | 102 | ············hostname=host_name(), |
| 85 | ············mode=self._owner_mode, | 103 | ············mode=self._owner_mode, |
| 86 | ············start=process_start_token(os.getpid()), | 104 | ············start=process_start_token(os.getpid()), |
| 87 | ········) | 105 | ········) |
| 106 | class·OwnerRecord(NamedTuple): | ||
| 107 | ····"""Keep·optional·metadata·when·reading·unknown·lock·modes.""" | ||
| 108 | ····pid:·int | ||
| 109 | ····hostname:·str | ||
| 110 | ····mode:·OwnerMode | ||
| 111 | ····token:·str·|·None·=·None | ||
| 112 | ····lease_duration:·float·|·None·=·None | ||
| Max diff block lines reached; 3521/9488 bytes (37.11%) of diff not shown. | |||
| Offset 1, 52 lines modified | Offset 1, 99 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·[ | ||
| 3 | ····"collections", | ||
| 4 | ····"filelock._error", | ||
| 5 | ····"filelock._identity", | ||
| 6 | ····"hashlib", | ||
| 7 | ····"itertools", | ||
| 8 | ····"pathlib", | ||
| 9 | ····"secrets", | ||
| 10 | ····"tempfile", | ||
| 11 | ] | ||
| 12 | import·hashlib | ||
| 2 | import·logging | 13 | import·logging |
| 3 | import·os | 14 | import·os |
| 4 | import·pathlib | 15 | import·pathlib |
| 16 | import·secrets | ||
| 5 | import·sqlite3 | 17 | import·sqlite3 |
| 18 | import·stat | ||
| 6 | import·sys | 19 | import·sys |
| 20 | import·tempfile | ||
| 7 | import·threading | 21 | import·threading |
| 8 | import·time | 22 | import·time |
| 23 | from·collections·import·deque | ||
| 9 | from·contextlib·import·contextmanager,·suppress | 24 | from·contextlib·import·contextmanager,·suppress |
| 25 | from·dataclasses·import·dataclass,·field | ||
| 26 | from·itertools·import·count | ||
| 10 | from·typing·import·TYPE_CHECKING,·ClassVar,·Final,·Literal,·TypeAlias,·cast | 27 | from·typing·import·TYPE_CHECKING,·ClassVar,·Final,·Literal,·NamedTuple,·TypeAlias,·cast |
| 11 | from·weakref·import·WeakValueDictionary | 28 | from·weakref·import·WeakValueDictionary |
| 12 | from·._api·import·( | 29 | from·filelock._api·import·( |
| 13 | ····AcquireReturnProxy, | 30 | ····AcquireReturnProxy, |
| 31 | ····_acquire_thread_lock, | ||
| 32 | ····_canonical, | ||
| 14 | ····_ensure_current_process, | 33 | ····_ensure_current_process, |
| 15 | ····_fork_transition, | 34 | ····_fork_transition, |
| 16 | ····_raise_chained_errors, | 35 | ····_raise_chained_errors, |
| 17 | ····_register_fork_class, | 36 | ····_register_fork_class, |
| 18 | ····_register_fork_object, | 37 | ····_register_fork_object, |
| 38 | ····_register_owned_descriptor, | ||
| 39 | ····_resolve_lazy_imports_before_shutdown, | ||
| 40 | ····_resolve_read_write_timeout, | ||
| 41 | ····_seconds, | ||
| 42 | ····_timeout_behavior, | ||
| 43 | ····_unregister_owned_descriptor, | ||
| 19 | ) | 44 | ) |
| 20 | from·._error·import·Timeout | 45 | from·filelock._error·import·Timeout |
| 46 | from·filelock._identity·import·host_name,·owner_is_stale,·process_start_token | ||
| 47 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | ||
| 48 | ····from·filelock._windows·import·( | ||
| 49 | ········_directory_is_private, | ||
| 50 | ········_identity_at, | ||
| 51 | ········_identity_of_fd, | ||
| 52 | ········_make_private_directory, | ||
| 53 | ········_open_non_reparse_fd, | ||
| 54 | ········_pinned, | ||
| 55 | ····) | ||
| 21 | if·TYPE_CHECKING: | 56 | if·TYPE_CHECKING: |
| 22 | ····from·collections.abc·import·Callable,·Generator | 57 | ····from·collections.abc·import·Callable,·Generator |
| 58 | ····from·typing·import·Self | ||
| 59 | ····from·_typeshed·import·Unused | ||
| 23 | ····if·sys.version_info·>=·(3,·11): | ||
| 24 | ········from·typing·import·Self | ||
| 25 | ····else: | ||
| 26 | ········from·typing_extensions·import·Self | ||
| 27 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") | 60 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") |
| 28 | _GETPID:·Final[Callable[[],·int]]·=·os.getpid | 61 | _GETPID:·Final[Callable[[],·int]]·=·os.getpid |
| 29 | _IS_PYPY:·Final[bool]·=·sys.implementation.name·==·"pypy" | 62 | _IS_PYPY:·Final[bool]·=·sys.implementation.name·==·"pypy" |
| 30 | _NEEDS_CONNECTION_ESCROW:·Final[bool]·=·( | 63 | _NEEDS_CONNECTION_ESCROW:·Final[bool]·=·( |
| 31 | ····hasattr(os,·"register_at_fork")·and·sys.implementation.name·==·"cpython"·and·sys.version_info·<·(3,·12) | 64 | ····hasattr(os,·"register_at_fork")·and·sys.implementation.name·==·"cpython"·and·sys.version_info·<·(3,·12) |
| 32 | ) | 65 | ) |
| 33 | _ConnectionParameter:·TypeAlias·=·( | 66 | _ConnectionParameter:·TypeAlias·=·( |
| 34 | ····str·|·bytes·|·os.PathLike[str]·|·os.PathLike[bytes]·|·float·|·int·|·type[sqlite3.Connection]·|·None | 67 | ····str·|·bytes·|·os.PathLike[str]·|·os.PathLike[bytes]·|·float·|·int·|·type[sqlite3.Connection]·|·None |
| 35 | ) | 68 | ) |
| 36 | _DatabaseIdentity:·TypeAlias·=·tuple[int,·int] | 69 | _DatabaseIdentity:·TypeAlias·=·tuple[int,·int] |
| 37 | #·sqlite3_busy_timeout()·accepts·a·C·int,·max·2_147_483_647·on·32-bit.·Use·a·lower·value·to·be·safe·(~23·days). | 70 | #·sqlite3_busy_timeout()·accepts·a·C·int,·max·2_147_483_647·on·32-bit.·Use·a·lower·value·to·be·safe·(~23·days). |
| 38 | _MAX_SQLITE_TIMEOUT_MS:·Final[int]·=·2_000_000_000·-·1 | 71 | _MAX_SQLITE_TIMEOUT_MS:·Final[int]·=·2_000_000_000·-·1 |
| 72 | #·How·long·a·wait·that·its·caller·may·abandon·runs·before·it·checks·whether·it·should·stop. | ||
| 73 | _CANCEL_POLL_INTERVAL:·Final[float]·=·0.1 | ||
| 39 | _UNSAFE_FORK_EXIT_STATUS:·Final[int]·=·70 | 74 | _UNSAFE_FORK_EXIT_STATUS:·Final[int]·=·70 |
| 75 | #:·The·longest·a·contended·acquisition·waits·for·the·database·inside·one·fork·transition,·in·seconds. | ||
| 76 | _MAX_TRANSITION_WAIT:·Final[float]·=·0.05 | ||
| 77 | #·O_NONBLOCK·keeps·an·open·from·blocking·on·a·FIFO·planted·at·the·path;·the·regular-file·check·then·rejects·it. | ||
| 78 | _DB_OPEN_FLAGS:·Final[int]·=·os.O_RDWR·|·os.O_CREAT·|·getattr(os,·"O_NOFOLLOW",·0)·|·getattr(os,·"O_NONBLOCK",·0) | ||
| 79 | _DIRECTORY_FLAGS:·Final[int]·=·os.O_RDONLY·|·getattr(os,·"O_DIRECTORY",·0)·|·getattr(os,·"O_NOFOLLOW",·0) | ||
| 80 | #·Header·bytes·18·and·19·hold·the·file·format·versions,·2·in·WAL·mode:·https://www.sqlite.org/fileformat.html | ||
| 81 | _SQLITE_MAGIC:·Final[bytes]·=·b"SQLite·format·3\x00" | ||
| 82 | _FORMAT_VERSIONS:·Final[slice]·=·slice(18,·20) | ||
| 83 | _HEADER_SIZE:·Final[int]·=·20 | ||
| 84 | _WAL_FORMAT_VERSION:·Final[int]·=·2 | ||
| 40 | class·_SQLiteTransitionContext(threading.local): | 85 | class·_SQLiteTransitionContext(threading.local): |
| 41 | ····depth:·int·=·0 | 86 | ····depth:·int·=·0 |
| 42 | _SQLITE_TRANSITION_CONTEXT:·Final·=·_SQLiteTransitionContext() | 87 | _SQLITE_TRANSITION_CONTEXT:·Final·=·_SQLiteTransitionContext() |
| Offset 130, 54 lines modified | Offset 177, 203 lines modified | ||
| 130 | ········except·OSError: | 177 | ········except·OSError: |
| 131 | ············return·None | 178 | ············return·None |
| 132 | ········return·stat_result.st_dev,·stat_result.st_ino | 179 | ········return·stat_result.st_dev,·stat_result.st_ino |
| 133 | _FORKED_DATABASES:·Final·=·_ForkedDatabaseRegistry() | 180 | _FORKED_DATABASES:·Final·=·_ForkedDatabaseRegistry() |
| 181 | _LINK_PREFIX:·Final[str]·=·".filelock-" | ||
| 182 | _LINK_NAME:·Final[str]·=·"lock.db" | ||
| 183 | _SWEPT_DATABASES:·Final[set[_DatabaseIdentity]]·=·set() | ||
| 184 | #·POSIX·locks·belong·to·the·process·and·the·inode,·so·closing·any·descriptor·on·the·inode·drops·the·locks·every·other | ||
| 185 | #·connection·of·this·process·holds·there.·SQLite·defers·its·own·closes·for·this·reason·(section·2.2·of | ||
| 186 | #·https://www.sqlite.org/howtocorrupt.html);·the·probes·stay·open·until·the·last·connection·on·their·inode·closes. | ||
| 187 | class·_ProbeDescriptors: | ||
| 188 | ····def·__init__(self)·->·None: | ||
| 189 | ········self._lock·=·threading.Lock() | ||
| 190 | ········self._inodes:·dict[_DatabaseIdentity,·_InodeProbes]·=·{} | ||
| 191 | ········self._releases:·deque[_Probe]·=·deque() | ||
| 192 | ········self._leases·=·count() | ||
| 193 | ····def·adopt(self,·database:·str,·claimed:·list[_Probe])·->·_Probe·|·None:··#·pragma:·win32·no·cover | ||
| Max diff block lines reached; 59914/68691 bytes (87.22%) of diff not shown. | |||
| Offset 1, 27 lines modified | Offset 1, 63 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·[ | ||
| 3 | ····"contextlib", | ||
| 4 | ····"filelock._identity", | ||
| 5 | ····"filelock._soft_protocol", | ||
| 6 | ····"filelock._util", | ||
| 7 | ····"itertools", | ||
| 8 | ····"pathlib", | ||
| 9 | ····"re", | ||
| 10 | ····"secrets", | ||
| 11 | ····"typing", | ||
| 12 | ] | ||
| 2 | import·os | 13 | import·os |
| 14 | import·re | ||
| 15 | import·secrets | ||
| 3 | import·stat | 16 | import·stat |
| 4 | import·sys | 17 | import·sys |
| 18 | import·threading | ||
| 5 | import·time | 19 | import·time |
| 6 | from·contextlib·import·suppress | 20 | from·contextlib·import·suppress |
| 7 | from·errno·import·EACCES,·EEXIST,·EPERM | 21 | from·errno·import·EACCES,·EEXIST,·EPERM |
| 22 | from·itertools·import·islice | ||
| 8 | from·pathlib·import·Path | 23 | from·pathlib·import·Path |
| 9 | from·typing·import·Final | 24 | from·typing·import·Final |
| 10 | from·._api·import·BaseFileLock,·_raise_grouped_errors | 25 | from·filelock._api·import·BaseFileLock,·_raise_grouped_errors |
| 11 | from·._identity·import·host_name,·owner_is_stale,·process_start_token | 26 | from·filelock._identity·import·host_name,·owner_is_current_process,·owner_is_stale,·process_start_token |
| 12 | from·._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD | 27 | from·filelock._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD |
| 13 | from· | 28 | from·filelock._util·import·( |
| 29 | ····break_lock_file, | ||
| 30 | ····exchange_names, | ||
| 31 | ····exchange_supported, | ||
| 32 | ····pin_inode, | ||
| 33 | ····raise_on_not_writable_file, | ||
| 34 | ····remove_own_file, | ||
| 35 | ····write_all, | ||
| 36 | ) | ||
| 37 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | ||
| 38 | ····from·filelock._windows·import·open_read_without_oplock_wait | ||
| 39 | ····from·filelock._windows·import·unlink_without_oplock_wait·as·unlink_path | ||
| 40 | else:··#·pragma:·win32·no·cover | ||
| 41 | ····from·filelock._util·import·unlink_path | ||
| 14 | 42 | MALFORMED_LOCK_AGE_THRESHOLD:·Final[float]·=·2.0 | |
| 15 | _MAX_LOCK_FILE_SIZE:·Final[int]·=·1024 | 43 | _MAX_LOCK_FILE_SIZE:·Final[int]·=·1024 |
| 16 | _UNLINK_MAX_RETRIES:·Final[int]·=·10 | 44 | _UNLINK_MAX_RETRIES:·Final[int]·=·10 |
| 17 | _MARKER_WITH_START_TOKEN_LINE_COUNT:·Final[int]·=·3 | 45 | _MARKER_WITH_START_TOKEN_LINE_COUNT:·Final[int]·=·3 |
| 46 | #:·Contenders·act·on·the·record·in·the·marker,·so·no·other·account·may·write·it,·whatever·the·mode·or·umask. | ||
| 47 | _OTHERS_WRITE:·Final[int]·=·stat.S_IWGRP·|·stat.S_IWOTH | ||
| 48 | #:·All·a·SoftFileLock·before·3.22·writes,·and·what·a·current·one·shows·between·creating·its·marker·and·writing·it. | ||
| 49 | _RECORDLESS_MARKER:·Final[str]·=·"" | ||
| 50 | _CLAIMS_IN_PROGRESS:·Final[set[str]]·=·set() | ||
| 51 | _CLAIMS_LOCK:·Final[threading.Lock]·=·threading.Lock() | ||
| 18 | class·SoftFileLock(BaseFileLock): | 52 | class·SoftFileLock(BaseFileLock): |
| 19 | ····""" | 53 | ····""" |
| 20 | ····Cooperative·file·lock·based·on·a·shared·existence·marker. | 54 | ····Cooperative·file·lock·based·on·a·shared·existence·marker. |
| 21 | ····Unlike·:class:`UnixFileLock·<filelock.UnixFileLock>`·and·:class:`WindowsFileLock·<filelock.WindowsFileLock>`,·this | 55 | ····Unlike·:class:`UnixFileLock·<filelock.UnixFileLock>`·and·:class:`WindowsFileLock·<filelock.WindowsFileLock>`,·this |
| Offset 44, 68 lines modified | Offset 80, 277 lines modified | ||
| 44 | ····#:·An·existence·lock·unlinks·its·marker·to·release,·so·it·cannot·promise·to·keep·the·pathname. | 80 | ····#:·An·existence·lock·unlinks·its·marker·to·release,·so·it·cannot·promise·to·keep·the·pathname. |
| 45 | ····_preserve_lock_file_supported:·bool·=·False | 81 | ····_preserve_lock_file_supported:·bool·=·False |
| 46 | ····#:·An·existence·lock·keeps·protocol·state·in·its·marker,·so·it·cannot·lend·the·descriptor·to·an·on_acquired·hook. | 82 | ····#:·An·existence·lock·keeps·protocol·state·in·its·marker,·so·it·cannot·lend·the·descriptor·to·an·on_acquired·hook. |
| 47 | ····_on_acquired_supported:·bool·=·False | 83 | ····_on_acquired_supported:·bool·=·False |
| 84 | ····#:·The·marker's·(mtime,·inode,·ctime)·when·this·instance·last·saw·it·change,·and·when,·on·its·monotonic·clock. | ||
| 85 | ····_marker_seen:·tuple[tuple[float,·int,·int],·float]·|·None·=·None | ||
| 86 | ····#:·The·identity·of·a·marker·a·Windows·release·relinquished·but·has·not·unlinked·yet. | ||
| 87 | ····_marker_cleanup:·tuple[int,·int]·|·None·=·None | ||
| 88 | ····#:·The·descriptor·of·that·marker·while·its·close·has·not·run·yet,·as·a·list·so·one·C·call·can·take·it. | ||
| 89 | ····_marker_fds:·list[int] | ||
| 48 | ····def·_acquire(self)·->·None: | 90 | ····def·_acquire(self)·->·None: |
| 91 | ········self._finish_marker_cleanup() | ||
| 49 | ········raise_on_not_writable_file(self.lock_ | 92 | ········raise_on_not_writable_file(self._lock_path) |
| 50 | ········ensure_directory_exists(self.lock_file) | ||
| 51 | ········#·O_CREAT·|·O_EXCL·makes·the·create·fail·with·EEXIST·when·the·file·already·exists,·so·a·successful·open | 93 | ········#·O_CREAT·|·O_EXCL·makes·the·create·fail·with·EEXIST·when·the·file·already·exists,·so·a·successful·open |
| 52 | ········#·means·this·process·now·holds·the·lock. | 94 | ········#·means·this·process·now·holds·the·lock. |
| 53 | ········flags·=·os.O_WRONLY·|·os.O_CREAT·|·os.O_EXCL·|·os.O_TRUNC | 95 | ········flags·=·os.O_WRONLY·|·os.O_CREAT·|·os.O_EXCL·|·os.O_TRUNC |
| 54 | ········if·(o_nofollow·:=·getattr(os,·"O_NOFOLLOW",·None))·is·not·None:··#·pragma:·needs·o-nofollow | 96 | ········if·(o_nofollow·:=·getattr(os,·"O_NOFOLLOW",·None))·is·not·None:··#·pragma:·needs·o-nofollow |
| 55 | ············flags·|=·o_nofollow | 97 | ············flags·|=·o_nofollow |
| 56 | ········try: | 98 | ········try: |
| 57 | ············fd·=·os.open(self.lock_ | 99 | ············fd·=·os.open(self._lock_path,·flags,·self._open_mode()·&·~_OTHERS_WRITE) |
| 58 | ········except·OSError·as·exception: | 100 | ········except·OSError·as·exception: |
| 59 | ············if·not·( | 101 | ············if·not·( |
| 60 | ················exception.errno·==·EEXIST·or·(exception.errno·==·EACCES·and·sys.platform·==·"win32") | 102 | ················exception.errno·==·EEXIST·or·(exception.errno·==·EACCES·and·sys.platform·==·"win32") |
| 61 | ············):··#·pragma:·win32·no·cover | 103 | ············):··#·pragma:·win32·no·cover |
| 62 | ················raise | 104 | ················raise |
| 63 | ············self._try_break_stale_lock() | 105 | ············self._try_break_stale_lock() |
| 64 | ············return | 106 | ············return |
| 65 | ········self._mark_descriptor_pending(fd) | ||
| 66 | ········self._publish_held_marker(fd) | ||
| 67 | ····def·_publish_held_marker(self,·fd:·int)·->·None: | ||
| 68 | ········#·Publish·held·state·only·once·the·record·is· | 107 | ········#·Publish·held·state·only·once·the·record·is·on·disk.·On·failure,·cancellation·included,·close·the·descriptor |
| 69 | ········#·descriptor·and·unlink·the·path·only·while·it·still·names·the·file·we·opened,·so·a·rollback·never·deletes·a | ||
| 70 | ········#· | 108 | ········#·and·unlink·the·path·only·while·it·still·names·the·file·we·opened:·after·an·expired·lease·a·successor's |
| 109 | ········#·marker·may·sit·at·the·same·path.·The·guard·starts·at·the·open,·so·a·signal·handler·that·raises·before | ||
| 110 | ········#·_mark_descriptor_owned·leaves·no·marker·behind. | ||
| 71 | ········identity:·tuple[int,·int]·|·None·=·None | 111 | ········identity:·tuple[int,·int]·|·None·=·None |
| 72 | ········try: | 112 | ········try: |
| 73 | ············identity·=·_file_identity(os.fstat(fd)) | 113 | ············identity·=·_file_identity(os.fstat(fd)) |
| 114 | ············self._mark_descriptor_pending(fd) | ||
| 115 | ············self._apply_explicit_mode(fd) | ||
| 74 | ············self._write_lock_info(fd) | 116 | ············self._write_lock_info(fd) |
| 117 | ············self._mark_descriptor_owned(fd,·identity) | ||
| 75 | ········except·BaseException: | 118 | ········except·BaseException: |
| 76 | ············self._mark_descriptor_released() | 119 | ············self._mark_descriptor_released() |
| 77 | ············ | 120 | ············try: |
| 121 | ················if·sys.platform·!=·"win32":··#·pragma:·win32·no·cover | ||
| 122 | ····················#·Before·the·close:·our·open·descriptor·keeps·the·inode·allocated,·so·a·successor's·marker·cannot | ||
| 123 | ····················#·carry·its·number. | ||
| 78 | ············with·suppress(OSError): | 124 | ····················with·suppress(OSError): |
| 79 | ················if·identity·is·not·None·and·_file_identity(os.lstat(self.lock_file))·==·identity: | ||
| 80 | ···················· | 125 | ························remove_own_file(self._lock_path,·fd) |
| 126 | ············finally: | ||
| 127 | ················try: | ||
| 128 | ····················os.close(fd) | ||
| 129 | ················finally: | ||
| Max diff block lines reached; 30656/36960 bytes (82.94%) of diff not shown. | |||
| Offset 1, 9 lines modified | Offset 1, 11 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["typing"] | ||
| 2 | from·typing·import·Final | 3 | from·typing·import·Final |
| 3 | STRICT_SOFT_SENTINEL_RECORD:·Final[str]·=·"1\nfilelock-strict-v1\x00\n0\n" | 4 | STRICT_SOFT_SENTINEL_RECORD:·Final[str]·=·"1\nfilelock-strict-v1\x00\n0\n" |
| 4 | __all__·=·[ | 5 | __all__·=·[ |
| 5 | ····"STRICT_SOFT_SENTINEL_RECORD", | 6 | ····"STRICT_SOFT_SENTINEL_RECORD", |
| 6 | ] | 7 | ] |
| Offset 1, 32 lines modified | Offset 1, 52 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·[ | ||
| 3 | ····"contextlib", | ||
| 4 | ····"filelock._error", | ||
| 5 | ····"filelock._identity", | ||
| 6 | ····"filelock._marker", | ||
| 7 | ····"filelock._soft", | ||
| 8 | ····"filelock._util", | ||
| 9 | ····"functools", | ||
| 10 | ····"pathlib", | ||
| 11 | ····"secrets", | ||
| 12 | ····"tempfile", | ||
| 13 | ] | ||
| 2 | import·contextlib | 14 | import·contextlib |
| 3 | import·errno | 15 | import·errno |
| 16 | import·functools | ||
| 4 | import·os | 17 | import·os |
| 5 | import·secrets | 18 | import·secrets |
| 6 | import·stat | 19 | import·stat |
| 7 | import·sys | 20 | import·sys |
| 8 | import·tempfile | 21 | import·tempfile |
| 9 | import·time | 22 | import·time |
| 10 | from·dataclasses·import·dataclass | 23 | from·dataclasses·import·dataclass |
| 11 | from·errno·import·EACCES,·EEXIST,·ENOENT,·ENOSYS,·EPERM,·ESTALE,·EXDEV | 24 | from·errno·import·EACCES,·EEXIST,·ENOENT,·ENOSYS,·EPERM,·ESTALE,·EXDEV |
| 12 | from·pathlib·import·Path | 25 | from·pathlib·import·Path |
| 13 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·cast | 26 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·cast |
| 14 | from·._api·import·BaseFileLock,·_canonical,·_raise_cleanup_errors | 27 | from·filelock._api·import·BaseFileLock,·ThreadLocalFileContext,·_canonical,·_raise_cleanup_errors |
| 15 | from·._error·import·SoftFileLockProtocolError | 28 | from·filelock._error·import·SoftFileLockProtocolError |
| 16 | from·._identity·import·host_name,·process_start_token | 29 | from·filelock._identity·import·host_name,·owner_is_stale,·process_start_token |
| 30 | from·filelock._marker·import·parse_marker | ||
| 31 | from·filelock._soft·import·MALFORMED_LOCK_AGE_THRESHOLD,·_parse_lock_holder | ||
| 17 | from·._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD | 32 | from·filelock._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD |
| 18 | from·._util·import· | 33 | from·filelock._util·import·foreign_directory_owner,·write_all |
| 34 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | ||
| 35 | ····from·filelock._windows·import·_is_unlinked,·_open_deletable_for_reading,·_pin_directory,·_unpin_directory | ||
| 19 | if·TYPE_CHECKING: | 36 | if·TYPE_CHECKING: |
| 20 | ····from·collections.abc·import·Iterator | 37 | ····from·collections.abc·import·Callable,·Iterator |
| 21 | StrictSoftFileClaimState·=·Literal["intent",·"held"] | 38 | StrictSoftFileClaimState·=·Literal["intent",·"held"] |
| 39 | _OccupantState·=·Literal["sentinel",·"held",·"exited",·"damaged",·"unparsable"] | ||
| 22 | _CLAIM_STATES:·Final[frozenset[str]]·=·frozenset({"intent",·"held"}) | 40 | _CLAIM_STATES:·Final[frozenset[str]]·=·frozenset({"intent",·"held"}) |
| 23 | _COORDINATION_SUFFIX:·Final[str]·=·".filelock" | 41 | _COORDINATION_SUFFIX:·Final[str]·=·".filelock" |
| 24 | _CLAIM_DIRECTORY_NAME:·Final[str]·=·"claims" | 42 | _CLAIM_DIRECTORY_NAME:·Final[str]·=·"claims" |
| 25 | _CLAIM_MAGIC:·Final[str]·=·"filelock-strict-v1" | 43 | _CLAIM_MAGIC:·Final[str]·=·"filelock-strict-v1" |
| 26 | _CLAIM_RECORD_LIMIT:·Final[int]·=·1024 | 44 | _CLAIM_RECORD_LIMIT:·Final[int]·=·1024 |
| 27 | _CLAIM_NAME_PART_COUNT:·Final[int]·=·3 | 45 | _CLAIM_NAME_PART_COUNT:·Final[int]·=·3 |
| Offset 35, 14 lines modified | Offset 55, 17 lines modified | ||
| 35 | _PRIVATE_RECORD_SUFFIX:·Final[str]·=·".tmp" | 55 | _PRIVATE_RECORD_SUFFIX:·Final[str]·=·".tmp" |
| 36 | _PRIVATE_RECORD_RANDOM_HEX_LENGTH:·Final[int]·=·32 | 56 | _PRIVATE_RECORD_RANDOM_HEX_LENGTH:·Final[int]·=·32 |
| 37 | _PRIVATE_RECORD_GRACE:·Final[float]·=·2.0 | 57 | _PRIVATE_RECORD_GRACE:·Final[float]·=·2.0 |
| 38 | _UNLINK_MAX_RETRIES:·Final[int]·=·10 | 58 | _UNLINK_MAX_RETRIES:·Final[int]·=·10 |
| 39 | #:·How·long·a·scan·waits·out·a·claim·held·in·Windows'·delete-pending·state·before·treating·it·as·unreadable. | 59 | #:·How·long·a·scan·waits·out·a·claim·held·in·Windows'·delete-pending·state·before·treating·it·as·unreadable. |
| 40 | _CLAIM_READ_GRACE:·Final[float]·=·0.5 | 60 | _CLAIM_READ_GRACE:·Final[float]·=·0.5 |
| 41 | _CLAIM_READ_RETRY:·Final[float]·=·0.002 | 61 | _CLAIM_READ_RETRY:·Final[float]·=·0.002 |
| 62 | #:·Rides·out·a·peer·replacing·the·lock·path·mid-inspection;·a·foreign·node·or·unreadable·record·outlasting·it·is·damage. | ||
| 63 | _SENTINEL_READ_GRACE:·Final[float]·=·0.5 | ||
| 64 | _NODE_DESCRIPTIONS:·Final[dict[int,·str]]·=·{stat.S_IFDIR:·"a·directory",·stat.S_IFLNK:·"a·symlink"} | ||
| 42 | #:·Windows·opens·descriptors·in·text·mode·by·default,·which·rewrites·newlines·and·truncates·a·record·at·a·control·byte. | 65 | #:·Windows·opens·descriptors·in·text·mode·by·default,·which·rewrites·newlines·and·truncates·a·record·at·a·control·byte. |
| 43 | #:·The·claim·and·sentinel·records·are·exact·binary,·so·every·record·descriptor·must·be·binary;·POSIX·ignores·the·flag. | 66 | #:·The·claim·and·sentinel·records·are·exact·binary,·so·every·record·descriptor·must·be·binary;·POSIX·ignores·the·flag. |
| 44 | _O_BINARY:·Final[int]·=·getattr(os,·"O_BINARY",·0) | 67 | _O_BINARY:·Final[int]·=·getattr(os,·"O_BINARY",·0) |
| 45 | _LEGACY_SENTINEL:·Final[bytes]·=·STRICT_SOFT_SENTINEL_RECORD.encode() | 68 | _LEGACY_SENTINEL:·Final[bytes]·=·STRICT_SOFT_SENTINEL_RECORD.encode() |
| 46 | _WINDOWS_HARD_LINK_UNSUPPORTED:·Final[frozenset[int]]·=·frozenset({1,·17,·50}) | 69 | _WINDOWS_HARD_LINK_UNSUPPORTED:·Final[frozenset[int]]·=·frozenset({1,·17,·50}) |
| 47 | #·Termux/Android·CPython·ships·without·os.link·(bionic·long·had·only·linkat),·so·the·strict·backend's·whole·hard-link | 70 | #·Termux/Android·CPython·ships·without·os.link·(bionic·long·had·only·linkat),·so·the·strict·backend's·whole·hard-link |
| Offset 52, 14 lines modified | Offset 75, 16 lines modified | ||
| 52 | #·Probe·dir_fd·capability·once·at·import.·A·per-call·``os.unlink·in·os.supports_dir_fd``·check·flips·to·False·the·moment | 75 | #·Probe·dir_fd·capability·once·at·import.·A·per-call·``os.unlink·in·os.supports_dir_fd``·check·flips·to·False·the·moment |
| 53 | #·a·test·mocks·os.unlink,·silently·diverting·the·code·to·a·different·branch·than·the·one·under·test. | 76 | #·a·test·mocks·os.unlink,·silently·diverting·the·code·to·a·different·branch·than·the·one·under·test. |
| 54 | _OPEN_SUPPORTS_DIR_FD:·Final[bool]·=·os.open·in·os.supports_dir_fd | 77 | _OPEN_SUPPORTS_DIR_FD:·Final[bool]·=·os.open·in·os.supports_dir_fd |
| 55 | _UNLINK_SUPPORTS_DIR_FD:·Final[bool]·=·os.unlink·in·os.supports_dir_fd | 78 | _UNLINK_SUPPORTS_DIR_FD:·Final[bool]·=·os.unlink·in·os.supports_dir_fd |
| 56 | _STAT_SUPPORTS_DIR_FD:·Final[bool]·=·os.stat·in·os.supports_dir_fd | 79 | _STAT_SUPPORTS_DIR_FD:·Final[bool]·=·os.stat·in·os.supports_dir_fd |
| 57 | _LINK_SUPPORTS_DIR_FD:·Final[bool]·=·_HAS_LINK·and·os.link·in·os.supports_dir_fd | 80 | _LINK_SUPPORTS_DIR_FD:·Final[bool]·=·_HAS_LINK·and·os.link·in·os.supports_dir_fd |
| 81 | _MKDIR_SUPPORTS_DIR_FD:·Final[bool]·=·os.mkdir·in·os.supports_dir_fd | ||
| 82 | _SCANDIR_SUPPORTS_FD:·Final[bool]·=·os.scandir·in·os.supports_fd | ||
| 58 | def·_probe_link_follow_symlinks()·->·bool: | 83 | def·_probe_link_follow_symlinks()·->·bool: |
| 59 | ····#·os.supports_follow_symlinks·lists·os.link·on·PyPy,·but·its·linkat·then·rejects·follow_symlinks=False·with·EINVAL, | 84 | ····#·os.supports_follow_symlinks·lists·os.link·on·PyPy,·but·its·linkat·then·rejects·follow_symlinks=False·with·EINVAL, |
| 60 | ····#·and·Windows·raises·NotImplementedError·for·the·option·outright.·Link·a·throwaway·file·for·real·so·the·answer | 85 | ····#·and·Windows·raises·NotImplementedError·for·the·option·outright.·Link·a·throwaway·file·for·real·so·the·answer |
| 61 | ····#·reflects·the·runtime·rather·than·its·advertisement,·and·treat·any·failure·as·"not·honored":·the·option·only | 86 | ····#·reflects·the·runtime·rather·than·its·advertisement,·and·treat·any·failure·as·"not·honored":·the·option·only |
| 62 | ····#·hardens·a·source·this·process·created·with·O_EXCL,·so·skipping·it·is·safe,·and·a·real·environment·fault·surfaces | 87 | ····#·hardens·a·source·this·process·created·with·O_EXCL,·so·skipping·it·is·safe,·and·a·real·environment·fault·surfaces |
| Offset 97, 166 lines modified | Offset 122, 230 lines modified | ||
| 97 | ····_preserve_lock_file_supported:·bool·=·True | 122 | ····_preserve_lock_file_supported:·bool·=·True |
| 98 | ····_on_acquired_supported:·bool·=·False | 123 | ····_on_acquired_supported:·bool·=·False |
| 99 | ····#:·Age·cannot·clear·a·strict·claim:·expiring·one·on·a·clock·is·the·overlap·the·fail-closed·contract·exists·to·rule | 124 | ····#:·Age·cannot·clear·a·strict·claim:·expiring·one·on·a·clock·is·the·overlap·the·fail-closed·contract·exists·to·rule |
| 100 | ····#:·out,·so·only·force_break()·removes·it. | 125 | ····#:·out,·so·only·force_break()·removes·it. |
| 101 | ····_lifetime_supported:·bool·=·False | 126 | ····_lifetime_supported:·bool·=·False |
| 102 | ····_lifetime_unsupported_reason:·str·=·"a·strict·claim·is·never·broken·by·age,·only·by·force_break()" | 127 | ····_lifetime_unsupported_reason:·str·=·"a·strict·claim·is·never·broken·by·age,·only·by·force_break()" |
| 103 | ····#:·The·claim·doorway·publishes·an·intent·and·a·held·record·per·owner,·so·a·shared·instance·must·serialize·them. | ||
| 104 | ····_serialize_transitions:·bool·=·True | ||
| 105 | ····#:·Contending·processes·each·publish·and·rescan·several·files,·so· | 128 | ····#:·Contending·processes·each·publish·and·rescan·several·files,·so·jitter·their·retries.·Seconds.·Only·a |
| 106 | ····#:· | 129 | ····#:·poll_interval·below·this·cap·jitters;·the·default·equals·it·and·keeps·a·fixed·cadence. |
| 107 | ····_poll_backoff_cap:·float·=·0.05 | 130 | ····_poll_backoff_cap:·float·=·0.05 |
| 131 | ····_occupant_seen:·tuple[tuple[float,·int,·int],·float]·|·None·=·None | ||
| 132 | ····#:·Set·by·the·finalizer,·after·which·no·retry·of·a·failed·cleanup·can·run. | ||
| 133 | ····_finalizing:·bool·=·False | ||
| 108 | ····def·_acquire(self)·->·None: | 134 | ····def·_acquire(self)·->·None: |
| 135 | ········#·Finish·a·doorway·whose·claim·cleanup·failed·before·publishing,·so·this·owner·never·contends·with·leftovers. | ||
| 136 | ········self._discard_pending_doorways(exited_only=True) | ||
| 109 | ········#·Resolve·once·per·acquisition,·not·per·poll:·a·waiter·on·a·relative·path·must·keep·publishing·into·the | ||
| 110 | ········#·directory·it·started·waiting·in·even·when·another·thread·changes·the·working·directory·mid-wait. | ||
| 111 | ········if·(claim_root·:=·self._context.claim_root)·is·None: | ||
| 112 | ············claim_root·=·self._context.claim_root·=·_canonical(self.lock_file) | ||
| 113 | ········lock_path·=·Path( | 137 | ········lock_path·=·Path(self._lock_path) |
| 114 | ········coordination_directory·=·Path(f"{lock_path}{_COORDINATION_SUFFIX}") | 138 | ········coordination_directory·=·Path(f"{lock_path}{_COORDINATION_SUFFIX}") |
| 115 | ········claim_directory·=·coordination_directory·/·_CLAIM_DIRECTORY_NAME | 139 | ········claim_directory·=·coordination_directory·/·_CLAIM_DIRECTORY_NAME |
| 116 | ········en | 140 | ········#·A·process·that·can·write·these·directories·can·remove·claims·from·them,·so·they·take·the·lock's·mode·plus |
| 141 | ········#·search·permission·where·the·mode·grants·read. | ||
| 142 | ········directory_mode:·Final·=·(mode·:=·self._open_mode())·|·(mode·&·0o444)·>>·2 | ||
| 117 | ········_ensure_protocol_directory(self.lock_file,·coordination_directory) | 143 | ········_ensure_protocol_directory(self.lock_file,·coordination_directory,·directory_mode) |
| 118 | ········_ensure_ | 144 | ········_ensure_claim_directory(self.lock_file,·claim_directory,·directory_mode) |
| 119 | ········if·( | 145 | ········if·( |
| 146 | ············sentinel_fd·:=·_open_or_create_sentinel( | ||
| 147 | ················self.lock_file,·lock_path,·self._open_mode(),·self._occupant_unchanged_for | ||
| 148 | ············) | ||
| 149 | ········)·is·None: | ||
| 120 | ············return | 150 | ············return |
| 121 | ········try: | 151 | ········try: |
| 122 | ············sentinel_identity·=·_file_identity(os.fstat(sentinel_fd)) | 152 | ············sentinel_identity·=·_file_identity(os.fstat(sentinel_fd)) |
| Max diff block lines reached; 50467/58145 bytes (86.80%) of diff not shown. | |||
| Offset 1, 19 lines modified | Offset 1, 21 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["contextlib",·"filelock._util",·"pathlib",·"typing",·"warnings"] | ||
| 2 | import·os | 3 | import·os |
| 3 | import·sys | 4 | import·sys |
| 4 | import·warnings | 5 | import·warnings |
| 5 | from·contextlib·import·suppress | 6 | from·contextlib·import·suppress |
| 6 | from·errno·import·EACCES,·EAGAIN,·ENOSYS,·EWOULDBLOCK | 7 | from·errno·import·EACCES,·EAGAIN,·ENOSYS,·EWOULDBLOCK |
| 7 | from·pathlib·import·Path | 8 | from·pathlib·import·Path |
| 8 | from·typing·import·Final,·cast | 9 | from·typing·import·Final,·cast |
| 9 | from·._api·import·BaseFileLock | 10 | from·filelock._api·import·BaseFileLock |
| 10 | from·._util·import· | 11 | from·filelock._util·import·remove_own_file |
| 11 | has_fcntl·=·False | 12 | has_fcntl·=·False |
| 12 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | 13 | if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 13 | ····class·UnixFileLock(BaseFileLock): | 14 | ····class·UnixFileLock(BaseFileLock): |
| 14 | ········"""Uses·the·:func:`fcntl.flock`·to·hard·lock·the·lock·file·on·unix·systems.""" | 15 | ········"""Uses·the·:func:`fcntl.flock`·to·hard·lock·the·lock·file·on·unix·systems.""" |
| Offset 53, 124 lines modified | Offset 55, 154 lines modified | ||
| 53 | ····················return·False | 55 | ····················return·False |
| 54 | ················raise | 56 | ················raise |
| 55 | ············return·True | 57 | ············return·True |
| 56 | ········def·_unlock_fd(fd:·int)·->·None: | 58 | ········def·_unlock_fd(fd:·int)·->·None: |
| 57 | ············fcntl.flock(fd,·fcntl.LOCK_UN) | 59 | ············fcntl.flock(fd,·fcntl.LOCK_UN) |
| 60 | ····def·_flock_is_missing(fd:·int)·->·bool: | ||
| 61 | ········try: | ||
| 62 | ············_lock_fd_nonblocking(fd) | ||
| 63 | ········except·OSError·as·exception: | ||
| 64 | ············return·exception.errno·==·ENOSYS | ||
| 65 | ········return·False··#·a·flock·the·probe·won·is·released·when·the·caller·closes·fd | ||
| 58 | ····class·UnixFileLock(BaseFileLock): | 66 | ····class·UnixFileLock(BaseFileLock): |
| 59 | ········""" | 67 | ········""" |
| 60 | ········Uses·the·:func:`fcntl.flock`·to·hard·lock·the·lock·file·on·unix·systems. | 68 | ········Uses·the·:func:`fcntl.flock`·to·hard·lock·the·lock·file·on·unix·systems. |
| 61 | ········We·leave·the·lock·file·in·place·after·release.·Unlinking·a·locked·file·on·Unix·splits | 69 | ········We·leave·the·lock·file·in·place·after·release.·Unlinking·a·locked·file·on·Unix·splits |
| 62 | ········waiters·across·inodes·and·breaks·mutual·exclusion·for·processes·that·coordinate·via·the | 70 | ········waiters·across·inodes·and·breaks·mutual·exclusion·for·processes·that·coordinate·via·the |
| 63 | ········same·path. | 71 | ········same·path. |
| 64 | ········""" | 72 | ········""" |
| 65 | ········def·_acquire(self)·->·None: | 73 | ········def·_acquire(self)·->·None: |
| 66 | ············missing_flock·=·self._acquire_native() | 74 | ············if·(missing_flock·:=·self._acquire_native())·is·not·None: |
| 67 | ············if·missing_flock·is·not·None: | ||
| 68 | ················ | 75 | ················fd,·exception,·created·=·missing_flock |
| 76 | ················self._switch_to_soft_lock(fd,·exception,·created=created) | ||
| 69 | ········def·_acquire_native(self)·->·tuple[int,·OSError]·|·None: | 77 | ········def·_acquire_native(self)·->·tuple[int,·OSError,·bool]·|·None: |
| 70 | ············ensure_directory_exists(self.lock_file) | ||
| 71 | ············#·Open·without·O_TRUNC·and·defer·truncation·and·fchmod·until·after·flock·succeeds:·a·contender·that·loses | ||
| 72 | ············#·the·lock·must·not·truncate·the·holder's·file·(erasing·caller·diagnostics)·or·change·its·mode.·The·winner | ||
| 73 | ············ | 78 | ············if·(opened·:=·self._open_lock_file())·is·None: |
| 79 | ················return·None | ||
| 80 | ············fd,·created·=·opened | ||
| 81 | ············self._mark_descriptor_pending(fd) | ||
| 82 | ············if·created: | ||
| 83 | ················#·Before·the·flock:·a·peer·may·win·it·first,·and·only·the·creator·may·set·the·mode.·Outside·the·flock | ||
| 84 | ················#·handler·below:·an·fchmod·that·answers·ENOSYS·says·nothing·about·flock. | ||
| 85 | ················try: | ||
| 86 | ····················self._apply_explicit_mode(fd) | ||
| 87 | ················except·BaseException: | ||
| 88 | ····················self._mark_descriptor_released() | ||
| 89 | ····················os.close(fd) | ||
| 90 | ····················raise | ||
| 91 | ············#·One·guard·covers·the·flock·through·the·recording·of·the·hold.·A·signal·handler·that·raises·in·between | ||
| 92 | ············#·would·otherwise·leave·an·unreferenced·descriptor,·and·its·flock,·open·until·the·process·exits. | ||
| 93 | ············locked·=·False | ||
| 94 | ············try: | ||
| 95 | ················locked·=·_lock_fd_nonblocking(fd) | ||
| 96 | ················if·locked·and·self._finalize_locked_fd(fd): | ||
| 97 | ····················return·None | ||
| 98 | ············except·BaseException·as·exception: | ||
| 99 | ················if·not·locked·and·isinstance(exception,·OSError)·and·exception.errno·==·ENOSYS: | ||
| 100 | ····················return·fd,·exception,·created | ||
| 101 | ················#·Contention·returns·False·from·_lock_fd_nonblocking,·so·a·raise·here·is·a·failure. | ||
| 102 | ················self._mark_descriptor_released() | ||
| 103 | ················os.close(fd) | ||
| 104 | ················raise | ||
| 105 | ············self._mark_descriptor_released() | ||
| 106 | ············os.close(fd)··#·contention·or·an·unlinked·inode;·let·the·retry·loop·try·again | ||
| 107 | ············return·None | ||
| 108 | ········def·_open_lock_file(self)·->·tuple[int,·bool]·|·None: | ||
| 109 | ············#·No·O_TRUNC:·a·contender·that·loses·the·flock·must·not·truncate·the·holder's·file·(#591),·and·neither·may | ||
| 110 | ············#·the·winner,·since·a·file·renamed·or·hard-linked·to·the·lock·path·is·indistinguishable·from·a·lock·file. | ||
| 111 | ············#·O_EXCL·tells·whether·this·attempt·created·the·inode:·only·then·does·it·get·the·explicit·mode,·and·the | ||
| 112 | ············#·ENOSYS·fallback·removes·only·its·own·placeholder.·O_NONBLOCK:·a·lease·(Linux·F_SETLEASE)·on·the·file·would | ||
| 113 | ············#·otherwise·block·the·open·for·up·to·fs.lease-break-time,·beyond·timeout,·blocking=False·and·cancel_check. | ||
| 74 | ············open_flags·=·os.O_RDWR | 114 | ············open_flags·=·os.O_RDWR·|·os.O_NONBLOCK |
| 75 | ············if·(o_nofollow·:=·getattr(os,·"O_NOFOLLOW",·None))·is·not·None: | 115 | ············if·(o_nofollow·:=·getattr(os,·"O_NOFOLLOW",·None))·is·not·None: |
| 76 | ················open_flags·|=·o_nofollow | 116 | ················open_flags·|=·o_nofollow |
| 77 | ············open_flags·|=·os.O_CREAT | ||
| 78 | ············open_mode·=·self._open_mode() | 117 | ············open_mode·=·self._open_mode() |
| 79 | ············try: | 118 | ············try: |
| 80 | ················ | 119 | ················return·os.open(self._lock_path,·open_flags·|·os.O_CREAT·|·os.O_EXCL,·open_mode),·True |
| 120 | ············except·FileExistsError: | ||
| 121 | ················pass | ||
| 81 | ············except·FileNotFoundError: | 122 | ············except·FileNotFoundError: |
| 82 | ················#·On·FUSE/NFS,·os.open(O_CREAT)·is·not·atomic;·a·split·LOOKUP·+·CREATE·lets·a·concurrent·unlink() | ||
| 83 | ················#·delete·the·file·between·them.·For·a·valid·path,·treat·ENOENT·as·transient·contention.·For·an | ||
| 84 | ················#·invalid·path·(e.g.·empty·string),·re-raise·to·avoid·an·infinite·retry·loop. | ||
| 85 | ················ | 123 | ················#·On·FUSE/NFS·a·split·LOOKUP·+·CREATE·lets·a·concurrent·unlink()·race·the·create,·so·ENOENT·is·transient |
| 124 | ················#·contention.·An·empty·or·separator-terminated·path·(Path()·strips·the·separator)·fails·this·way·on | ||
| 125 | ················#·every·attempt·on·macOS,·so·re-raise·rather·than·retry·forever. | ||
| 126 | ················if·self._lock_path·and·not·self._lock_path.endswith(os.sep)·and·Path(self._lock_path).parent.exists(): | ||
| 86 | ····················return·None | 127 | ····················return·None |
| 87 | ················raise | 128 | ················raise |
| 88 | ············except·PermissionError: | 129 | ············except·PermissionError: |
| 89 | ················#·Sticky-bit·dirs·(e.g.·/tmp):·O_CREAT·fails·if·the | 130 | ················#·Sticky-bit·dirs·(e.g.·/tmp):·O_CREAT·fails·if·another·user·owns·the·file·(#317). |
| 90 | ················#·Fall·back·to·opening·the·existing·file·without·O_CREAT. | ||
| 91 | ················if·not·Path(self.lock_ | 131 | ················if·not·Path(self._lock_path).exists(): |
| 92 | ····················raise | 132 | ····················raise |
| 133 | ············return·self._open_existing_lock_file(open_flags,·open_mode) | ||
| 134 | ········def·_open_existing_lock_file(self,·open_flags:·int,·open_mode:·int)·->·tuple[int,·bool]·|·None: | ||
| 135 | ············try: | ||
| 136 | ················return·os.open(self._lock_path,·open_flags,·open_mode),·False | ||
| 137 | ············except·FileNotFoundError: | ||
| 138 | ················return·None··#·unlinked·since·the·create·attempt;·let·the·retry·loop·start·over | ||
| 139 | ············except·BlockingIOError: | ||
| 140 | ················return·None··#·a·lease·is·breaking:·contention,·so·the·retry·loop·keeps·the·deadline | ||
| 141 | ············except·PermissionError: | ||
| 142 | ················#·A·marker·another·account·left·is·readable·but·not·writable.·Without·flock,·waiting·on·it·only·needs | ||
| Max diff block lines reached; 6442/13888 bytes (46.39%) of diff not shown. | |||
| Offset 1, 25 lines modified | Offset 1, 36 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["pathlib",·"platform",·"secrets"] | ||
| 3 | import·errno | ||
| 2 | import·os | 4 | import·os |
| 5 | import·platform | ||
| 3 | import·secrets | 6 | import·secrets |
| 4 | import·stat | 7 | import·stat |
| 5 | import·sys | 8 | import·sys |
| 9 | from·contextlib·import·contextmanager,·suppress | ||
| 6 | from·errno·import·EACCES,·EIO,·EISDIR | 10 | from·errno·import·EACCES,·EINVAL,·EIO,·EISDIR,·ENOSYS,·EXDEV |
| 11 | from·functools·import·cache | ||
| 7 | from·pathlib·import·Path | 12 | from·pathlib·import·Path |
| 8 | from·typing·import·Final | 13 | from·typing·import·TYPE_CHECKING,·Final,·cast |
| 14 | if·TYPE_CHECKING: | ||
| 15 | ····import·ctypes | ||
| 16 | ····from·collections.abc·import·Callable,·Generator | ||
| 17 | ····from·contextlib·import·AbstractContextManager | ||
| 9 | def·write_all(fd:·int,·data:·bytes)·->·None: | 18 | def·write_all(fd:·int,·data:·bytes)·->·None: |
| 10 | ····""" | 19 | ····""" |
| 11 | ····Write·the·whole·buffer·to·*fd*,·looping·over·the·short·writes· | 20 | ····Write·the·whole·buffer·to·*fd*,·looping·over·the·short·writes·POSIX·lets·``os.write``·make. |
| 12 | ····A·marker·written·with·a·bare·``os.write``·can·land·partially:·a·peer·reading·it·mid-write·parses·a·truncated·record | ||
| 13 | ····as·malformed·or·as·a·foreign·holder.·Looping·until·the·buffer·drains·keeps·the·record·atomic·in·the·process·and | ||
| 14 | ···· | 21 | ····A·caller·that·stopped·after·one·short·write·would·leave·a·truncated·marker·behind.·A·peer·that·reads·between·two |
| 22 | ····writes·sees·a·prefix·of·the·record;·each·caller·has·to·tolerate·that.·Lock·records·need·not·survive·a·power·loss,·so | ||
| 23 | ····we·skip·``fsync``. | ||
| 15 | ····:param·fd:·file·descriptor·open·for·writing. | 24 | ····:param·fd:·file·descriptor·open·for·writing. |
| 16 | ····:param·data:·bytes·to·write·in·full. | 25 | ····:param·data:·bytes·to·write·in·full. |
| 17 | ····:raises·OSError:·if·a·write·reports·zero·progress·before·the·record·is·complete. | 26 | ····:raises·OSError:·if·a·write·reports·zero·progress·before·the·record·is·complete. |
| 18 | ····""" | 27 | ····""" |
| Offset 46, 92 lines modified | Offset 57, 343 lines modified | ||
| 46 | ········#·make·stat·inspect·the·link·target,·letting·an·attacker·turn·a·contended·acquire·into·a·misleading | 57 | ········#·make·stat·inspect·the·link·target,·letting·an·attacker·turn·a·contended·acquire·into·a·misleading |
| 47 | ········#·PermissionError·/·IsADirectoryError·and·probe·that·target's·attributes.·The·real·open·passes·O_NOFOLLOW·and | 58 | ········#·PermissionError·/·IsADirectoryError·and·probe·that·target's·attributes.·The·real·open·passes·O_NOFOLLOW·and |
| 48 | ········#·refuses·the·symlink·anyway. | 59 | ········#·refuses·the·symlink·anyway. |
| 49 | ········file_stat·=·os.lstat(filename) | 60 | ········file_stat·=·os.lstat(filename) |
| 50 | ····except·OSError: | 61 | ····except·OSError: |
| 51 | ········return··#·does·not·exist,·or·an·error·the·caller·cannot·act·on | 62 | ········return··#·does·not·exist,·or·an·error·the·caller·cannot·act·on |
| 52 | ····#·No·mtime·guard:·the·old·`if·st_mtime·!=·0`·skip·covered·NFS/Linux·quirks·where·os.lstat·returned·an·all-zero | ||
| 53 | ····#·struct,·which·it·no·longer·does.·Skipping·on·mtime·0·let·a·read-only·file·or·a·directory·at·the·lock·path·pass | ||
| 54 | ····#·as·missing,·so·acquire()·blocked·forever·on·an·open·that·cannot·succeed. | ||
| 55 | ····if·not·(file_stat.st_mode·&·stat.S_IWUSR): | ||
| 56 | ········raise·PermissionError(EACCES,·"Permission·denied",·filename) | ||
| 57 | ····if·stat.S_ISDIR(file_stat.st_mode): | 63 | ····if·stat.S_ISDIR(file_stat.st_mode): |
| 58 | ········if·sys.platform·==·"win32":··#·pragma:·win32·cover | 64 | ········if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 59 | ············raise·PermissionError(EACCES,·"Permission·denied",·filename) | 65 | ············raise·PermissionError(EACCES,·"Permission·denied",·filename) |
| 60 | ········raise·IsADirectoryError(EISDIR,·"Is·a·directory",·filename)··#·pragma:·win32·no·cover | 66 | ········raise·IsADirectoryError(EISDIR,·"Is·a·directory",·filename)··#·pragma:·win32·no·cover |
| 67 | ····#·No·mtime·guard:·the·old·`if·st_mtime·!=·0`·skip·covered·NFS/Linux·quirks·where·os.lstat·returned·an·all-zero | ||
| 68 | ····#·struct,·which·it·no·longer·does.·Skipping·on·mtime·0·let·a·read-only·file·or·a·directory·at·the·lock·path·pass | ||
| 69 | ····#·as·missing,·so·acquire()·blocked·forever·on·an·open·that·cannot·succeed. | ||
| 70 | ····#·Match·open()·credentials·where·supported;·group·permissions·and·ACLs·can·grant·access·without·S_IWUSR.·Do·not | ||
| 71 | ····#·follow·a·symlink,·as·the·lstat·above·does·not:·one·swapped·in·since·would·be·judged·by·its·target. | ||
| 72 | ····if·not·(file_stat.st_mode·&·stat.S_IWUSR)·and·not·os.access( | ||
| 73 | ········filename, | ||
| 74 | ········os.W_OK, | ||
| 75 | ········effective_ids=os.access·in·os.supports_effective_ids, | ||
| 76 | ········follow_symlinks=os.access·not·in·os.supports_follow_symlinks, | ||
| 77 | ····): | ||
| 78 | ········try: | ||
| 79 | ············os.lstat(filename) | ||
| 80 | ········except·FileNotFoundError: | ||
| 81 | ············#·A·holder·may·unlink·its·marker·between·lstat()·and·access();·let·the·caller·attempt·creation. | ||
| 82 | ············return | ||
| 83 | ········raise·PermissionError(EACCES,·"Permission·denied",·filename) | ||
| 61 | def·ensure_directory_exists(filename:·Path·|·str)·->·None: | 84 | def·ensure_directory_exists(filename:·Path·|·str)·->·None: |
| 62 | ····""" | 85 | ····""" |
| 63 | ····Ensure·the·directory·containing·the·file·exists·(create·it·if·necessary). | 86 | ····Ensure·the·directory·containing·the·file·exists·(create·it·if·necessary). |
| 64 | ····:param·filename:·file. | 87 | ····:param·filename:·file. |
| 65 | ····""" | 88 | ····""" |
| 66 | ····Path(filename).parent.mkdir(parents=True,·exist_ok=True) | 89 | ····Path(filename).parent.mkdir(parents=True,·exist_ok=True) |
| 90 | @contextmanager | ||
| 91 | def·pin_inode(lock_file:·str)·->·Generator[int·|·None]: | ||
| 92 | ····""" | ||
| 93 | ····Keep·the·file·at·*lock_file*·allocated·for·the·length·of·the·block·and·yield·its·inode·number. | ||
| 94 | ····An·inode·is·the·kernel's·identity·for·a·file,·independent·of·its·name,·and·its·number·names·a·file·only·while·the | ||
| 95 | ····inode·stays·allocated.·ext4·hands·a·freed·number·to·the·next·file·created.·Once·a·stale·marker·is·unlinked,·the·next | ||
| 96 | ····holder's·marker·can·therefore·carry·the·number·a·contender·read·a·moment·ago.·A·caller·that·reads·the·marker·inside | ||
| 97 | ····the·block,·gives·up·unless·it·read·the·yielded·inode,·and·breaks·the·marker·before·leaving·can·rely·on·the·number. | ||
| 98 | ····:param·lock_file:·path·to·the·lock·file·about·to·be·read·and·perhaps·broken. | ||
| 99 | ····:returns:·the·pinned·inode·number,·or·``None``·where·nothing·can·be·pinned.·Windows·cannot·rename·a·file·this | ||
| 100 | ········process·holds·open,·so·it·needs·no·pin.·Without·``O_PATH``·a·symlink·or·a·socket·cannot·be·opened. | ||
| 101 | ····:raises·FileNotFoundError:·if·the·path·is·gone. | ||
| 102 | ····""" | ||
| 103 | ····if·sys.platform·==·"win32":··#·pragma:·win32·cover | ||
| 104 | ········yield·None | ||
| 105 | ····else:··#·pragma:·win32·no·cover | ||
| 106 | ········#·O_PATH·pins·any·node,·a·symlink·or·socket·included,·without·read·permission·and·without·the·filesystem·seeing | ||
| 107 | ········#·an·open;·elsewhere·a·nonblocking·read-only·open·pins·what·it·can. | ||
| 108 | ········flags:·Final·=·getattr(os,·"O_PATH",·os.O_RDONLY·|·getattr(os,·"O_NONBLOCK",·0))·|·getattr(os,·"O_NOFOLLOW",·0) | ||
| 109 | ········try: | ||
| 110 | ············fd·=·os.open(lock_file,·flags) | ||
| 111 | ········except·FileNotFoundError: | ||
| 112 | ············raise | ||
| 113 | ········except·OSError: | ||
| 114 | ············yield·None | ||
| 115 | ············return | ||
| 116 | ········try: | ||
| 117 | ············yield·os.fstat(fd).st_ino | ||
| 118 | ········finally: | ||
| 119 | ············os.close(fd) | ||
| 120 | def·remove_own_file(lock_file:·str,·fd:·int)·->·None:··#·pragma:·win32·no·cover | ||
| 121 | ····""" | ||
| 122 | ····Remove·*lock_file*·while·it·still·names·the·file·open·as·*fd*;·the·caller·closes·the·descriptor·afterwards. | ||
| Max diff block lines reached; 14156/22246 bytes (63.63%) of diff not shown. | |||
| Offset 1, 61 lines modified | Offset 1, 102 lines modified | ||
| 1 | from·__future__·import·annotations | 1 | from·__future__·import·annotations |
| 2 | __lazy_modules__·=·["filelock._util",·"msvcrt",·"struct"] | ||
| 2 | import·os | 3 | import·os |
| 4 | import·struct | ||
| 3 | import·sys | 5 | import·sys |
| 6 | import·time | ||
| 4 | from·contextlib·import·suppress | 7 | from·contextlib·import·contextmanager,·suppress |
| 5 | from· | 8 | from·errno·import·ENOENT,·ENOTDIR,·EWOULDBLOCK |
| 9 | from·functools·import·cache | ||
| 6 | from·typing·import·Final,·cast | 10 | from·typing·import·TYPE_CHECKING,·Final,·cast |
| 11 | from·filelock._api·import·BaseFileLock | ||
| 12 | from·filelock._util·import·raise_on_not_writable_file | ||
| 7 | from·._api·import·BaseFileLock | ||
| 8 | 13 | if·TYPE_CHECKING: | |
| 14 | ····from·collections.abc·import·Generator | ||
| 9 | if·sys.platform·==·"win32":··#·pragma:·win32·cover | 15 | if·sys.platform·==·"win32":··#·pragma:·win32·cover |
| 10 | ····import·ctypes | 16 | ····import·ctypes |
| 11 | ····import·msvcrt | 17 | ····import·msvcrt |
| 12 | ····from·ctypes·import·wintypes | 18 | ····from·ctypes·import·wintypes |
| 13 | ····_GENERIC_READ:·Final[int]·=·0x80000000 | 19 | ····_GENERIC_READ:·Final[int]·=·0x80000000 |
| 14 | ····_GENERIC_WRITE:·Final[int]·=·0x40000000 | 20 | ····_GENERIC_WRITE:·Final[int]·=·0x40000000 |
| 15 | ····_SYNCHRONIZE:·Final[int]·=·0x00100000 | 21 | ····_SYNCHRONIZE:·Final[int]·=·0x00100000 |
| 22 | ····_DELETE:·Final[int]·=·0x00010000 | ||
| 16 | ····_DESIRED_ACCESS:·Final[int]·=·_GENERIC_READ·|·_GENERIC_WRITE·|·_SYNCHRONIZE | 23 | ····_DESIRED_ACCESS:·Final[int]·=·_GENERIC_READ·|·_GENERIC_WRITE·|·_SYNCHRONIZE |
| 17 | ····_FILE_SHARE_READ_WRITE:·Final[int]·=·( | 24 | ····_FILE_SHARE_READ_WRITE:·Final[int]·=·( |
| 18 | ········0x00000001·|·0x00000002 | 25 | ········0x00000001·|·0x00000002 |
| 19 | ····)··#·read·|·write;·matches·os.open·(_SH_DENYNO),·no·delete | 26 | ····)··#·read·|·write;·matches·os.open·(_SH_DENYNO),·no·delete |
| 27 | ····_FILE_OPEN:·Final[int]·=·1··#·open·the·file·only·if·it·exists;·the·NtCreateFile·OPEN_EXISTING | ||
| 20 | ····_FILE_OPEN_IF:·Final[int]·=·3··#·open·the·file·if·it·exists,·create·it·otherwise;·the·NtCreateFile·OPEN_ALWAYS | 28 | ····_FILE_OPEN_IF:·Final[int]·=·3··#·open·the·file·if·it·exists,·create·it·otherwise;·the·NtCreateFile·OPEN_ALWAYS |
| 29 | ····#·Attribute-only·access·skips·share-mode·checks,·so·the·probe·sees·a·name's·deletion·state·rather·than·a·reader. | ||
| 30 | ····_FILE_READ_ATTRIBUTES:·Final[int]·=·0x00000080 | ||
| 31 | ····_FILE_SHARE_ALL:·Final[int]·=·0x00000001·|·0x00000002·|·0x00000004··#·read·|·write·|·delete | ||
| 21 | ····_FILE_ATTRIBUTE_READONLY:·Final[int]·=·0x00000001 | 32 | ····_FILE_ATTRIBUTE_READONLY:·Final[int]·=·0x00000001 |
| 22 | ····_FILE_ATTRIBUTE_NORMAL:·Final[int]·=·0x00000080 | 33 | ····_FILE_ATTRIBUTE_NORMAL:·Final[int]·=·0x00000080 |
| 23 | ····_FILE_ATTRIBUTE_REPARSE_POINT:·Final[int]·=·0x00000400 | 34 | ····_FILE_ATTRIBUTE_REPARSE_POINT:·Final[int]·=·0x00000400 |
| 24 | ····#·CreateOptions:·keep·the·handle·synchronous·(the·CRT·and·msvcrt.locking·rely·on·a·maintained·file·position), | 35 | ····#·CreateOptions:·keep·the·handle·synchronous·(the·CRT·and·msvcrt.locking·rely·on·a·maintained·file·position), |
| 36 | ····#·refuse·a·directory,·return·at·once·instead·of·waiting·for·an·oplock·holder·to·answer·the·break,·and·open·a | ||
| 25 | ····#·re | 37 | ····#·reparse·point·rather·than·following·it·so·the·check·below·acts·on·the·link·itself. |
| 26 | ····_FILE_SYNCHRONOUS_IO_NONALERT:·Final[int]·=·0x00000020 | 38 | ····_FILE_SYNCHRONOUS_IO_NONALERT:·Final[int]·=·0x00000020 |
| 27 | ····_FILE_NON_DIRECTORY_FILE:·Final[int]·=·0x00000040 | 39 | ····_FILE_NON_DIRECTORY_FILE:·Final[int]·=·0x00000040 |
| 40 | ····_FILE_DELETE_ON_CLOSE:·Final[int]·=·0x00001000 | ||
| 41 | ····_FILE_COMPLETE_IF_OPLOCKED:·Final[int]·=·0x00000100 | ||
| 28 | ····_FILE_OPEN_REPARSE_POINT:·Final[int]·=·0x00200000 | 42 | ····_FILE_OPEN_REPARSE_POINT:·Final[int]·=·0x00200000 |
| 43 | ····_CREATE_OPTIONS:·Final[int]·=·( | ||
| 44 | ········_FILE_SYNCHRONOUS_IO_NONALERT·|·_FILE_NON_DIRECTORY_FILE·|·_FILE_COMPLETE_IF_OPLOCKED·|·_FILE_OPEN_REPARSE_POINT | ||
| 45 | ····) | ||
| 46 | ····#·Listing·access·takes·part·in·share-mode·checks,·unlike·attribute-only·access,·so·a·handle·that·holds·it·without | ||
| 47 | ····#·FILE_SHARE_DELETE·blocks·renames·and·removals·of·the·directory·until·it·closes. | ||
| 48 | ····_FILE_LIST_DIRECTORY:·Final[int]·=·0x00000001 | ||
| 49 | ····_FILE_DIRECTORY_FILE:·Final[int]·=·0x00000001 | ||
| 29 | ····_ | 50 | ····_DIRECTORY_OPTIONS:·Final[int]·=·_FILE_SYNCHRONOUS_IO_NONALERT·|·_FILE_DIRECTORY_FILE·|·_FILE_OPEN_REPARSE_POINT |
| 30 | ····_OBJ_CASE_INSENSITIVE:·Final[int]·=·0x00000040··#·Win32·name·lookups·are·case-insensitive | 51 | ····_OBJ_CASE_INSENSITIVE:·Final[int]·=·0x00000040··#·Win32·name·lookups·are·case-insensitive |
| 31 | ····_OWNER_WRITE:·Final[int]·=·0o200 | 52 | ····_OWNER_WRITE:·Final[int]·=·0o200 |
| 53 | ····_GROUP_AND_OTHERS:·Final[int]·=·0o077 | ||
| 54 | ····#·The·DACL·os.mkdir(mode=0o700)·applies,·less·the·inheritance·flags·a·file·has·no·use·for:·protected,·so·the | ||
| 55 | ····#·directory's·inheritable·entries·stay·out,·with·full·access·for·SYSTEM,·Administrators·and·the·owner. | ||
| 56 | ····_OWNER_ONLY_SDDL:·Final[str]·=·"D:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;OW)" | ||
| 57 | ····_SDDL_REVISION_1:·Final[int]·=·1 | ||
| 58 | ····_INVALID_HANDLE_VALUE:·Final[int·|·None]·=·ctypes.c_void_p(-1).value | ||
| 32 | ····#·LockFileEx·locks·a·byte·range·at·an·offset·carried·in·OVERLAPPED,·independent·of·the·descriptor's·file·position. | 59 | ····#·LockFileEx·locks·a·byte·range·at·an·offset·carried·in·OVERLAPPED,·independent·of·the·descriptor's·file·position. |
| 33 | ····#·msvcrt.locking·starts·at·the·current·position·instead,·so·a·metadata·write·between·lock·and·unlock·could·shift | 60 | ····#·msvcrt.locking·starts·at·the·current·position·instead,·so·a·metadata·write·between·lock·and·unlock·could·shift |
| 34 | ····#·the·byte·a·later·unlock·targets;·the·explicit·offset·removes·that·hazard·for·both·the·path·lock·and·#608's | 61 | ····#·the·byte·a·later·unlock·targets;·the·explicit·offset·removes·that·hazard·for·both·the·path·lock·and·#608's |
| 35 | ····#·descriptor·lock. | 62 | ····#·descriptor·lock. |
| 36 | ····_LOCKFILE_FAIL_IMMEDIATELY:·Final[int]·=·0x00000001 | 63 | ····_LOCKFILE_FAIL_IMMEDIATELY:·Final[int]·=·0x00000001 |
| 37 | ····_LOCKFILE_EXCLUSIVE_LOCK:·Final[int]·=·0x00000002 | 64 | ····_LOCKFILE_EXCLUSIVE_LOCK:·Final[int]·=·0x00000002 |
| 65 | ····_ERROR_ACCESS_DENIED:·Final[int]·=·5 | ||
| 38 | ····_ERROR_LOCK_VIOLATION:·Final[int]·=·33··#·another·handle·holds·the·byte·range | 66 | ····_ERROR_LOCK_VIOLATION:·Final[int]·=·33··#·another·handle·holds·the·byte·range |
| 67 | ····_ERROR_NOT_LOCKED:·Final[int]·=·158··#·the·byte·range·is·not·locked | ||
| 39 | ····#·NtCreateFile·returns·the·raw·NTSTATUS·as·its·value,·where·CreateFileW·collapses·several·of·these·into·one | 68 | ····#·NtCreateFile·returns·the·raw·NTSTATUS·as·its·value,·where·CreateFileW·collapses·several·of·these·into·one |
| 40 | ····#·ERROR_ACCESS_DENIED.·Telling·them·apart·is·the·point·(#604):·a·name·pending·deletion·or·a·share·conflict·is | 69 | ····#·ERROR_ACCESS_DENIED.·Telling·them·apart·is·the·point·(#604):·a·name·pending·deletion·or·a·share·conflict·is |
| 41 | ····#·transient·and·worth·a·retry,·a·real·access·denial·is·not. | 70 | ····#·transient·and·worth·a·retry,·a·real·access·denial·is·not. |
| 42 | ····_STATUS_SUCCESS:·Final[int]·=·0x00000000 | 71 | ····_STATUS_SUCCESS:·Final[int]·=·0x00000000 |
| 72 | ····#·A·success·code·that·comes·with·a·handle:·another·handle's·oplock·is·breaking·and·its·holder·has·not·answered·yet. | ||
| 73 | ····_STATUS_OPLOCK_BREAK_IN_PROGRESS:·Final[int]·=·0x00000108 | ||
| 43 | ····_STATUS_ACCESS_DENIED:·Final[int]·=·0xC0000022 | 74 | ····_STATUS_ACCESS_DENIED:·Final[int]·=·0xC0000022 |
| 75 | ····_STATUS_OBJECT_NAME_NOT_FOUND:·Final[int]·=·0xC0000034 | ||
| 76 | ····_STATUS_OBJECT_PATH_NOT_FOUND:·Final[int]·=·0xC000003A | ||
| 44 | ····_STATUS_SHARING_VIOLATION:·Final[int]·=·0xC0000043 | 77 | ····_STATUS_SHARING_VIOLATION:·Final[int]·=·0xC0000043 |
| 45 | ····_STATUS_DELETE_PENDING:·Final[int]·=·0xC0000056 | 78 | ····_STATUS_DELETE_PENDING:·Final[int]·=·0xC0000056 |
| 79 | ····#:·Probes,·2·ms·apart,·for·transient·STATUS_ACCESS_DENIED·while·a·peer·unlinks·the·name·(#604).·A·count·ensures | ||
| 80 | ····#:·every·probe·runs·even·when·the·process·stalls;·oplock·breaks·use·the·caller's·wait·instead. | ||
| 81 | ····_ACCESS_DENIED_PROBES:·Final[int]·=·250 | ||
| 82 | ····_ACCESS_DENIED_GRACE:·Final[float]·=·0.5 | ||
| 83 | ····_ACCESS_DENIED_RETRY:·Final[float]·=·0.002 | ||
| 46 | ····_ntdll:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("ntdll") | 84 | ····_ntdll:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("ntdll") |
| 47 | ····_kernel32:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("kernel32",·use_last_error=True) | 85 | ····_kernel32:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("kernel32",·use_last_error=True) |
| 86 | ····_advapi32:·Final[ctypes.WinDLL]·=·ctypes.WinDLL("advapi32",·use_last_error=True) | ||
| 48 | ····class·_UNICODE_STRING(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name | 87 | ····class·_UNICODE_STRING(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name |
| 49 | ········_fields_·=·( | 88 | ········_fields_·=·( |
| 50 | ············("Length",·wintypes.USHORT),··#·byte·length,·not·character·count | 89 | ············("Length",·wintypes.USHORT),··#·byte·length,·not·character·count |
| 51 | ············("MaximumLength",·wintypes.USHORT), | 90 | ············("MaximumLength",·wintypes.USHORT), |
| 52 | ············("Buffer",·wintypes.LPWSTR), | 91 | ············("Buffer",·wintypes.LPWSTR), |
| 53 | ········) | 92 | ········) |
| Offset 72, 14 lines modified | Offset 113, 21 lines modified | ||
| 72 | ····class·_IO_STATUS_BLOCK(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name | 113 | ····class·_IO_STATUS_BLOCK(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name |
| 73 | ········_fields_·=·( | 114 | ········_fields_·=·( |
| 74 | ············("Status",·ctypes.c_void_p),··#·a·union·of·NTSTATUS·and·PVOID,·so·it·is·pointer-sized | 115 | ············("Status",·ctypes.c_void_p),··#·a·union·of·NTSTATUS·and·PVOID,·so·it·is·pointer-sized |
| 75 | ············("Information",·ctypes.c_void_p), | 116 | ············("Information",·ctypes.c_void_p), |
| 76 | ········) | 117 | ········) |
| 118 | ····class·_SECURITY_ATTRIBUTES(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name | ||
| 119 | ········_fields_·=·( | ||
| 120 | ············("nLength",·wintypes.DWORD), | ||
| 121 | ············("lpSecurityDescriptor",·ctypes.c_void_p), | ||
| 122 | ············("bInheritHandle",·wintypes.BOOL), | ||
| 123 | ········) | ||
| 77 | ····class·_OVERLAPPED(ctypes.Structure):··#·mirrors·the·Win32·struct·name | 124 | ····class·_OVERLAPPED(ctypes.Structure):··#·mirrors·the·Win32·struct·name |
| 78 | ········_fields_·=·( | 125 | ········_fields_·=·( |
| 79 | ············("Internal",·ctypes.c_void_p),··#·ULONG_PTR:·pointer-sized,·not·DWORD,·or·the·x64·layout·corrupts·Offset | 126 | ············("Internal",·ctypes.c_void_p),··#·ULONG_PTR:·pointer-sized,·not·DWORD,·or·the·x64·layout·corrupts·Offset |
| 80 | ············("InternalHigh",·ctypes.c_void_p), | 127 | ············("InternalHigh",·ctypes.c_void_p), |
| 81 | ············("Offset",·wintypes.DWORD),··#·the·DUMMYUNIONNAME·struct,·flattened:·low·32·bits·of·the·byte·offset | 128 | ············("Offset",·wintypes.DWORD),··#·the·DUMMYUNIONNAME·struct,·flattened:·low·32·bits·of·the·byte·offset |
| 82 | ············("OffsetHigh",·wintypes.DWORD), | 129 | ············("OffsetHigh",·wintypes.DWORD), |
| 83 | ············("hEvent",·wintypes.HANDLE), | 130 | ············("hEvent",·wintypes.HANDLE), |
| Offset 142, 14 lines modified | Offset 190, 65 lines modified | ||
| 142 | ········wintypes.HANDLE, | 190 | ········wintypes.HANDLE, |
| Max diff block lines reached; 31085/38526 bytes (80.69%) of diff not shown. | |||
| Offset 1, 75 lines modified | Offset 1, 93 lines modified | ||
| 1 | """An·asyncio-based·implementation·of·the·file·lock.""" | 1 | """An·asyncio-based·implementation·of·the·file·lock.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·[ | ||
| 4 | ····"asyncio", | ||
| 5 | ····"concurrent", | ||
| 6 | ····"contextlib", | ||
| 7 | ····"filelock._async", | ||
| 8 | ····"filelock._error", | ||
| 9 | ····"filelock._util", | ||
| 10 | ····"functools", | ||
| 11 | ····"inspect", | ||
| 12 | ····"threading", | ||
| 13 | ] | ||
| 3 | import·asyncio | 14 | import·asyncio |
| 4 | import·contextlib | 15 | import·contextlib |
| 16 | import·functools | ||
| 5 | import·logging | 17 | import·logging |
| 6 | import·os | 18 | import·os |
| 19 | import·sys | ||
| 7 | import·time | 20 | import·time |
| 21 | from·concurrent·import·futures | ||
| 8 | from·dataclasses·import·dataclass | 22 | from·dataclasses·import·dataclass,·field,·fields |
| 9 | from·inspect·import·iscoroutinefunction | 23 | from·inspect·import·iscoroutinefunction |
| 10 | from·threading·import· | 24 | from·threading·import·RLock |
| 11 | from·typing·import·TYPE_CHECKING,·Final,·NoReturn,·TypeVar,·cast | 25 | from·typing·import·TYPE_CHECKING,·Final,·NoReturn,·TypeVar,·cast |
| 12 | from·._api·import·( | 26 | from·filelock._api·import·( |
| 13 | ····_UNSET_FILE_MODE, | 27 | ····_UNSET_FILE_MODE, |
| 14 | ····BaseFileLock, | 28 | ····BaseFileLock, |
| 15 | ····CloseErrorPolicy, | 29 | ····CloseErrorPolicy, |
| 16 | ····ContextErrorPolicy, | 30 | ····ContextErrorPolicy, |
| 17 | ····FileLockContext, | 31 | ····FileLockContext, |
| 18 | ····FileLockMeta, | 32 | ····FileLockMeta, |
| 33 | ····ThreadLocalFileContext, | ||
| 19 | ····_append_exception_context, | 34 | ····_append_exception_context, |
| 20 | ····_canonical, | 35 | ····_canonical, |
| 36 | ····_delegate_to_current, | ||
| 21 | ····_ExtraValue, | 37 | ····_ExtraValue, |
| 22 | ····_fork_transition, | 38 | ····_fork_transition, |
| 23 | ····_grouped_errors, | 39 | ····_grouped_errors, |
| 40 | ····_is_system_call_failure, | ||
| 24 | ····_raise_body_and_release, | 41 | ····_raise_body_and_release, |
| 25 | ····_raise_chained_errors, | 42 | ····_raise_chained_errors, |
| 26 | ····_raise_cleanup_errors, | 43 | ····_raise_cleanup_errors, |
| 27 | ····_raise_grouped_errors, | 44 | ····_raise_grouped_errors, |
| 28 | ····_register_fork_object, | 45 | ····_register_fork_object, |
| 46 | ····_resolve_poll_interval, | ||
| 47 | ····_resolve_timeout, | ||
| 29 | ) | 48 | ) |
| 30 | from·._async·import·( | 49 | from·filelock._async·import·( |
| 31 | ····_AsyncTransitionGate, | 50 | ····_AsyncTransitionGate, |
| 32 | ····_AsyncTransitionUnavailableError, | 51 | ····_AsyncTransitionUnavailableError, |
| 33 | ····_BackendOutcome, | 52 | ····_BackendOutcome, |
| 34 | ····_capture_awaitable, | 53 | ····_capture_awaitable, |
| 35 | ····_capture_call, | 54 | ····_capture_call, |
| 36 | ····_drain_future, | 55 | ····_drain_future, |
| 37 | ····_future_result, | 56 | ····_future_result, |
| 57 | ····_run_in_executor, | ||
| 38 | ····_wait_until_done, | 58 | ····_wait_until_done, |
| 39 | ) | 59 | ) |
| 40 | from·._error·import·Timeout | 60 | from·filelock._error·import·Timeout |
| 41 | from·._lease·import·SoftFileLease | 61 | from·filelock._lease·import·SoftFileLease |
| 42 | from·._soft·import·SoftFileLock | 62 | from·filelock._soft·import·SoftFileLock |
| 43 | from·._strict·import·StrictSoftFileLock | 63 | from·filelock._strict·import·StrictSoftFileLock |
| 44 | from·._unix·import·UnixFileLock | 64 | from·filelock._unix·import·UnixFileLock |
| 65 | from·filelock._util·import·ensure_directory_exists | ||
| 45 | from·._windows·import·WindowsFileLock | 66 | from·filelock._windows·import·WindowsFileLock |
| 46 | if·TYPE_CHECKING: | 67 | if·TYPE_CHECKING: |
| 47 | ····import·sys | ||
| 48 | ····from·collections.abc·import·Awaitable,·Callable,·Coroutine,·Hashable | 68 | ····from·collections.abc·import·Awaitable,·Callable,·Coroutine,·Hashable,·Mapping |
| 49 | ····from·concurrent·import·futures | ||
| 50 | ····from·types·import·TracebackType | 69 | ····from·types·import·TracebackType |
| 51 | ····if·sys.version_info·>=·(3,·11):··#·pragma:·no·cover·(py311+) | ||
| 52 | ···· | 70 | ····from·typing·import·Self |
| 53 | ····else:··#·pragma:·no·cover·(<py311) | ||
| 54 | ········from·typing_extensions·import·Self | ||
| 55 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") | 71 | _LOGGER:·Final[logging.Logger]·=·logging.getLogger("filelock") |
| 56 | _ASYNC_RELEASE_CANCELLATION_ERRORS:·Final[str]·=·"lock·release·cancellation·and·backend·release·both·failed" | 72 | _ASYNC_RELEASE_CANCELLATION_ERRORS:·Final[str]·=·"lock·release·cancellation·and·backend·release·both·failed" |
| 57 | _ASYNC_CONTEXT_RELEASE_ERRORS:·Final[str]·=·"context·body,·release·cancellation,·and·backend·release·failed" | 73 | _ASYNC_CONTEXT_RELEASE_ERRORS:·Final[str]·=·"context·body,·release·cancellation,·and·backend·release·failed" |
| 58 | _ASYNC_RELEASE_CANCELLATION_MARKER_ATTR:·Final[str]·=·"_filelock_async_release_cancellation" | 74 | _ASYNC_RELEASE_CANCELLATION_MARKER_ATTR:·Final[str]·=·"_filelock_async_release_cancellation" |
| 59 | _ASYNC_RELEASE_CANCELLATION_MARKER:·Final[list[None]]·=·[] | 75 | _ASYNC_RELEASE_CANCELLATION_MARKER:·Final[list[None]]·=·[] |
| 76 | _FINALIZER_RELEASES:·Final[set[asyncio.Task[None]·|·futures.Future[None]]]·=·set() | ||
| 60 | _AT·=·TypeVar("_AT",·bound="BaseAsyncFileLock") | 77 | _AT·=·TypeVar("_AT",·bound="BaseAsyncFileLock") |
| 78 | _T·=·TypeVar("_T") | ||
| 61 | class·AsyncFileLockMeta(FileLockMeta): | 79 | class·AsyncFileLockMeta(FileLockMeta): |
| 62 | ····def·__call__(··#·ruff:ignore[too-many-arguments]··#·forwards·the·public·constructor's·documented·parameters | 80 | ····def·__call__(··#·ruff:ignore[too-many-arguments]··#·forwards·the·public·constructor's·documented·parameters |
| 63 | ········cls:·type[_AT],··#·ruff:ignore[invalid-first-argument-name-for-method]··#·metaclass·__call__·receives·the·class·being·constructed | 81 | ········cls:·type[_AT],··#·ruff:ignore[invalid-first-argument-name-for-method]··#·metaclass·__call__·receives·the·class·being·constructed |
| 64 | ········lock_file:·str·|·os.PathLike[str], | 82 | ········lock_file:·str·|·os.PathLike[str], |
| 65 | ········timeout:·float·=·-1, | 83 | ········timeout:·float·=·-1, |
| Offset 159, 20 lines modified | Offset 177, 20 lines modified | ||
| 159 | ········:param·lock_file:·path·to·the·file | 177 | ········:param·lock_file:·path·to·the·file |
| 160 | ········:param·timeout:·default·timeout·when·acquiring·the·lock,·in·seconds.·It·will·be·used·as·fallback·value·in·the | 178 | ········:param·timeout:·default·timeout·when·acquiring·the·lock,·in·seconds.·It·will·be·used·as·fallback·value·in·the |
| 161 | ············acquire·method,·if·no·timeout·value·(``None``)·is·given.·If·you·want·to·disable·the·timeout,·set·it·to·a | 179 | ············acquire·method,·if·no·timeout·value·(``None``)·is·given.·If·you·want·to·disable·the·timeout,·set·it·to·a |
| 162 | ············negative·value.·A·timeout·of·0·means·that·there·is·exactly·one·attempt·to·acquire·the·file·lock. | 180 | ············negative·value.·A·timeout·of·0·means·that·there·is·exactly·one·attempt·to·acquire·the·file·lock. |
| 163 | ········:param·mode:·file·permissions·for·the·lockfile.·When·not·specified,·the·OS·controls·permissions·via·umask·and | 181 | ········:param·mode:·file·permissions·for·the·lockfile.·When·not·specified,·the·OS·controls·permissions·via·umask·and |
| 164 | ············default·ACLs,·preserving·POSIX·default·ACL·inheritance·in·shared·directories. | 182 | ············default·ACLs,·preserving·POSIX·default·ACL·inheritance·in·shared·directories. |
| 165 | ········:param·thread_local:·Whether·this·object's·internal·context·should·be·thread·local·or·not.·If·this·is·set·to | 183 | ········:param·thread_local:·Whether·this·object's·internal·context·should·be·thread·local·or·not.·If·this·is·set·to |
| 166 | ············``False``·then·the·lock·will·be·reentrant·across·threads.·When·``True`` | 184 | ············``False``·(the·default)·then·the·lock·will·be·reentrant·across·threads.·When·``True``,·**all·fields·of·the |
| 167 | ············lock's·internal·context·are·per-thread**,·including·the·configuration·values·``poll_interval``,·``timeout``, | 185 | ············lock's·internal·context·are·per-thread**,·including·the·configuration·values·``poll_interval``,·``timeout``, |
| 168 | ············``blocking``,·``mode``,·and·``lifetime``.·Setting·one·of·these·properties·from·one·thread·does·not·change | 186 | ············``blocking``,·``mode``,·and·``lifetime``.·Setting·one·of·these·properties·from·one·thread·does·not·change |
| 169 | ············the·value·seen·by·another·thread;·threads·that·did·not·perform·the·write·continue·to·see·the·value·supplied | 187 | ············the·value·seen·by·another·thread;·threads·that·did·not·perform·the·write·continue·to·see·the·value·supplied |
| 170 | ············at·construction·time.·If·you·need·configuration·values·to·be·visible·across·threads,·construct·the·lock | ||
| 171 | ············ | 188 | ············at·construction·time.·``mode``·has·no·setter,·so·construction·is·the·only·place·it·is·ever·set.·If·you·need |
| 189 | ············configuration·values·to·be·visible·across·threads,·construct·the·lock·with·``thread_local=False``. | ||
| 172 | ········:param·blocking:·whether·the·lock·should·be·blocking·or·not | 190 | ········:param·blocking:·whether·the·lock·should·be·blocking·or·not |
| 173 | ········:param·is_singleton:·If·this·is·set·to·``True``·then·only·one·instance·of·this·class·will·be·created·per·lock | 191 | ········:param·is_singleton:·If·this·is·set·to·``True``·then·only·one·instance·of·this·class·will·be·created·per·lock |
| 174 | ············file.·This·is·useful·if·you·want·to·use·the·lock·object·for·reentrant·locking·without·needing·to·pass·the | 192 | ············file.·This·is·useful·if·you·want·to·use·the·lock·object·for·reentrant·locking·without·needing·to·pass·the |
| 175 | ············same·object·around. | 193 | ············same·object·around. |
| 176 | ········:param·poll_interval:·default·interval·for·polling·the·lock·file,·in·seconds.·It·will·be·used·as·fallback·value | 194 | ········:param·poll_interval:·default·interval·for·polling·the·lock·file,·in·seconds.·It·will·be·used·as·fallback·value |
| 177 | ············in·the·acquire·method,·if·no·poll_interval·value·(``None``)·is·given. | 195 | ············in·the·acquire·method,·if·no·poll_interval·value·(``None``)·is·given. |
| 178 | ········:param·lifetime:·for·:class:`AsyncSoftFileLock`,·the·age·in·seconds·after·which·a·waiting·process·may·delete | 196 | ········:param·lifetime:·for·:class:`AsyncSoftFileLock`,·the·age·in·seconds·after·which·a·waiting·process·may·delete |
| Offset 193, 66 lines modified | Offset 211, 88 lines modified | ||
| 193 | ············identity·(Windows·skips·its·unlink,·Unix·refuses·the·``ENOSYS``·soft·fallback).·:class:`AsyncSoftFileLock` | 211 | ············identity·(Windows·skips·its·unlink,·Unix·refuses·the·``ENOSYS``·soft·fallback).·:class:`AsyncSoftFileLock` |
| 194 | ············rejects·``True``. | 212 | ············rejects·``True``. |
| 195 | ········:param·on_acquired:·for·native·locks·(:class:`AsyncFileLock`),·a·callable·invoked·with·the·borrowed·lock | 213 | ········:param·on_acquired:·for·native·locks·(:class:`AsyncFileLock`),·a·callable·invoked·with·the·borrowed·lock |
| 196 | ············descriptor·once·per·physical·acquisition,·after·the·lock·is·held·but·before | 214 | ············descriptor·once·per·physical·acquisition,·after·the·lock·is·held·but·before |
| 197 | ············:meth:`~BaseAsyncFileLock.acquire`·returns.·With·``run_in_executor=True``·(the·default)·it·runs·in·the | 215 | ············:meth:`~BaseAsyncFileLock.acquire`·returns.·With·``run_in_executor=True``·(the·default)·it·runs·in·the |
| Max diff block lines reached; 22781/29310 bytes (77.72%) of diff not shown. | |||
| Offset 14, 11 lines modified | Offset 14, 11 lines modified | ||
| 14 | version:·str | 14 | version:·str |
| 15 | __version__:·str | 15 | __version__:·str |
| 16 | __version_tuple__:·tuple[int·|·str,·...] | 16 | __version_tuple__:·tuple[int·|·str,·...] |
| 17 | version_tuple:·tuple[int·|·str,·...] | 17 | version_tuple:·tuple[int·|·str,·...] |
| 18 | commit_id:·str·|·None | 18 | commit_id:·str·|·None |
| 19 | __commit_id__:·str·|·None | 19 | __commit_id__:·str·|·None |
| 20 | __version__·=·version·=·' | 20 | __version__·=·version·=·'4.2.4' |
| 21 | __version_tuple__·=·version_tuple·=·( | 21 | __version_tuple__·=·version_tuple·=·(4,·2,·4) |
| 22 | __commit_id__·=·commit_id·=·None | 22 | __commit_id__·=·commit_id·=·None |
| Offset 1, 12 lines modified | Offset 1, 14 lines modified | ||
| 1 | """Cross-process·and·cross-host·reader/writer·lock·o | 1 | """Cross-process·and·cross-host·reader/writer·lock·over·a·generation·log·of·immutable·snapshots.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·["filelock._soft_rw._async"] | ||
| 3 | from·._async·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock | 4 | from·filelock._soft_rw._async·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock |
| 4 | from·._sync·import·SoftReadWriteLock | 5 | from·filelock._soft_rw._sync·import·SoftReadWriteLock |
| 5 | __all__·=·[ | 6 | __all__·=·[ |
| 6 | ····"AsyncAcquireSoftReadWriteReturnProxy", | 7 | ····"AsyncAcquireSoftReadWriteReturnProxy", |
| 7 | ····"AsyncSoftReadWriteLock", | 8 | ····"AsyncSoftReadWriteLock", |
| 8 | ····"SoftReadWriteLock", | 9 | ····"SoftReadWriteLock", |
| 9 | ] | 10 | ] |
| Offset 1, 54 lines modified | Offset 1, 65 lines modified | ||
| 1 | """Async·wrapper·around·:class:`SoftReadWriteLock`·for·use·with·``asyncio``.""" | 1 | """Async·wrapper·around·:class:`SoftReadWriteLock`·for·use·with·``asyncio``.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·["asyncio",·"filelock._async",·"filelock._error",·"functools",·"threading"] | ||
| 3 | import·asyncio | 4 | import·asyncio |
| 4 | import·functools | 5 | import·functools |
| 5 | import·os | 6 | import·os |
| 7 | import·threading | ||
| 6 | from·contextlib·import·asynccontextmanager | 8 | from·contextlib·import·asynccontextmanager |
| 7 | from·typing·import·TYPE_CHECKING,·ParamSpec,·TypeVar | 9 | from·typing·import·TYPE_CHECKING,·Final,·Literal,·ParamSpec,·TypeVar |
| 8 | from·filelock._async·import·( | 10 | from·filelock._async·import·( |
| 11 | ····_TASKS_THREAD_ID, | ||
| 9 | ····_BackendOutcome, | 12 | ····_BackendOutcome, |
| 10 | ····_capture_call, | 13 | ····_capture_call, |
| 11 | ····_drain_future, | 14 | ····_drain_future, |
| 12 | ····_future_result, | 15 | ····_future_result, |
| 13 | ····_raise_cancelled_error, | 16 | ····_raise_cancelled_error, |
| 17 | ····_task_owners_for, | ||
| 14 | ····_wait_until_done, | 18 | ····_wait_until_done, |
| 15 | ) | 19 | ) |
| 16 | from· | 20 | from·filelock._error·import·Timeout |
| 21 | from·filelock._soft_rw._sync·import·SoftReadWriteLock,·_lost_hold_error | ||
| 17 | if·TYPE_CHECKING: | 22 | if·TYPE_CHECKING: |
| 18 | ····from·collections.abc·import·AsyncGenerator,·Callable | 23 | ····from·collections.abc·import·AsyncGenerator,·Callable |
| 19 | ····from·concurrent·import·futures | 24 | ····from·concurrent·import·futures |
| 20 | ····from·types·import·TracebackType | 25 | ····from·types·import·TracebackType |
| 21 | ····from·filelock._api·import·AcquireReturnProxy | 26 | ····from·filelock._api·import·AcquireReturnProxy |
| 27 | ····from·filelock._lease·import·LeaseCompromise | ||
| 22 | _P·=·ParamSpec("_P") | 28 | _P·=·ParamSpec("_P") |
| 23 | _R·=·TypeVar("_R") | 29 | _R·=·TypeVar("_R") |
| 24 | class·AsyncSoftReadWriteLock: | 30 | class·AsyncSoftReadWriteLock: |
| 25 | ····""" | 31 | ····""" |
| 26 | ····Async·wrapper·around·:class:`SoftReadWriteLock`·for·``asyncio``·applications. | 32 | ····Async·wrapper·around·:class:`SoftReadWriteLock`·for·``asyncio``·applications. |
| 27 | ····The·sync·class's·blocking·filesystem·operations·run·on·a·thread·pool·via·``loop.run_in_executor()``.· | 33 | ····The·sync·class's·blocking·filesystem·operations·run·on·a·thread·pool·via·``loop.run_in_executor()``.·Each |
| 28 | ····underlying·:class:`SoftReadWriteLock`·handles·reentrancy,·upgrade/downgrade·rules,·fork·handling,·heartbeat·and | ||
| 29 | ····T | 34 | ····``asyncio``·task·owns·its·own·hold.·Tasks·share·a·read·lock,·and·a·task·asking·for·the·write·lock·waits·until·the |
| 35 | ····other·holders·release,·with·waiting·writers·ahead·of·new·readers.·Upgrading·or·downgrading·a·held·lock·raises | ||
| 36 | ····:class:`RuntimeError`.·The·underlying·:class:`SoftReadWriteLock`·handles·forks,·the·heartbeat,·and·stale·eviction. | ||
| 37 | ····Singleton·wrappers·share·one·sync·lock·and·its·task·holds,·and·closing·one·ends·only·the·holds·taken·through·it. | ||
| 30 | ····:param·lock_file:·path·to·the·lock·file;· | 38 | ····:param·lock_file:·path·to·the·lock·file;·the·protocol·directory·lives·next·to·it·as·``<lock_file>.rw`` |
| 31 | ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``·means·block·indefinitely | 39 | ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``·means·block·indefinitely |
| 32 | ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·on·contention | 40 | ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·on·contention |
| 33 | ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`SoftReadWriteLock`·instances·per·resolved·path | 41 | ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`SoftReadWriteLock`·instances·per·resolved·path |
| 34 | ····:param·heartbeat_interval:·seconds·between·heartbeat·refreshes;·default·30·s | 42 | ····:param·heartbeat_interval:·seconds·between·heartbeat·refreshes;·default·30·s |
| 35 | ····:param·stale_threshold:·seconds· | 43 | ····:param·stale_threshold:·seconds·a·holder·record·may·stay·unchanged·before·a·contender·evicts·it;·defaults·to |
| 44 | ········``3·*·heartbeat_interval`` | ||
| 36 | ····:param·poll_interval:·seconds·between·acquire·retries·under·contention;·default·0.25·s | 45 | ····:param·poll_interval:·seconds·between·acquire·retries·under·contention;·default·0.25·s |
| 46 | ····:param·on_compromise:·called·from·the·heartbeat·thread·with·a·:class:`~filelock.LeaseCompromise`·when·the·hold·is | ||
| 47 | ········lost | ||
| 37 | ····:param·loop:·event·loop·for·``run_in_executor``;·``None``·uses·the·running·loop | 48 | ····:param·loop:·event·loop·for·``run_in_executor``;·``None``·uses·the·running·loop |
| 38 | ····:param·executor:·executor·for·``run_in_executor``;·``None``·uses·the·default·executor | 49 | ····:param·executor:·executor·for·``run_in_executor``;·``None``·uses·the·default·executor |
| 39 | ····..·versionadded::·3.27.0 | 50 | ····..·versionadded::·3.27.0 |
| 40 | ····""" | 51 | ····""" |
| Offset 58, 27 lines modified | Offset 69, 34 lines modified | ||
| 58 | ········timeout:·float·=·-1, | 69 | ········timeout:·float·=·-1, |
| 59 | ········*, | 70 | ········*, |
| 60 | ········blocking:·bool·=·True, | 71 | ········blocking:·bool·=·True, |
| 61 | ········is_singleton:·bool·=·True, | 72 | ········is_singleton:·bool·=·True, |
| 62 | ········heartbeat_interval:·float·=·30.0, | 73 | ········heartbeat_interval:·float·=·30.0, |
| 63 | ········stale_threshold:·float·|·None·=·None, | 74 | ········stale_threshold:·float·|·None·=·None, |
| 64 | ········poll_interval:·float·=·0.25, | 75 | ········poll_interval:·float·=·0.25, |
| 76 | ········on_compromise:·Callable[[LeaseCompromise],·None]·|·None·=·None, | ||
| 65 | ········loop:·asyncio.AbstractEventLoop·|·None·=·None, | 77 | ········loop:·asyncio.AbstractEventLoop·|·None·=·None, |
| 66 | ········executor:·futures.Executor·|·None·=·None, | 78 | ········executor:·futures.Executor·|·None·=·None, |
| 67 | ····)·->·None: | 79 | ····)·->·None: |
| 68 | ········self._creator_pid·=·os.getpid() | 80 | ········self._creator_pid·=·os.getpid() |
| 81 | ········self._closed·=·False | ||
| 82 | ········self._owns_backend·=·not·is_singleton | ||
| 83 | ········#:·Marks·the·task·holds·taken·through·this·wrapper,·which·its·close()·ends. | ||
| 84 | ········self._via:·Final·=·object() | ||
| 69 | ········self._lock·=·SoftReadWriteLock( | 85 | ········self._lock·=·SoftReadWriteLock( |
| 70 | ············lock_file, | 86 | ············lock_file, |
| 71 | ············timeout, | 87 | ············timeout, |
| 72 | ············blocking=blocking, | 88 | ············blocking=blocking, |
| 73 | ············is_singleton=is_singleton, | 89 | ············is_singleton=is_singleton, |
| 74 | ············heartbeat_interval=heartbeat_interval, | 90 | ············heartbeat_interval=heartbeat_interval, |
| 75 | ············stale_threshold=stale_threshold, | 91 | ············stale_threshold=stale_threshold, |
| 76 | ············poll_interval=poll_interval, | 92 | ············poll_interval=poll_interval, |
| 93 | ············on_compromise=on_compromise, | ||
| 77 | ········) | 94 | ········) |
| 95 | ········self._owners·=·_task_owners_for(self._lock) | ||
| 78 | ········self._loop·=·loop | 96 | ········self._loop·=·loop |
| 79 | ········self._executor·=·executor | 97 | ········self._executor·=·executor |
| 80 | ····@property | 98 | ····@property |
| 81 | ····def·lock_file(self)·->·str: | 99 | ····def·lock_file(self)·->·str: |
| 82 | ········"""The·path·to·the·lock·file·passed·to·the·constructor.""" | 100 | ········"""The·path·to·the·lock·file·passed·to·the·constructor.""" |
| 83 | ········return·self._lock.lock_file | 101 | ········return·self._lock.lock_file |
| Offset 90, 14 lines modified | Offset 108, 24 lines modified | ||
| 90 | ····@property | 108 | ····@property |
| 91 | ····def·blocking(self)·->·bool: | 109 | ····def·blocking(self)·->·bool: |
| 92 | ········"""Whether·``acquire_*``·defaults·to·blocking;·``False``·makes·contention·raise·immediately.""" | 110 | ········"""Whether·``acquire_*``·defaults·to·blocking;·``False``·makes·contention·raise·immediately.""" |
| 93 | ········return·self._lock.blocking | 111 | ········return·self._lock.blocking |
| 94 | ····@property | 112 | ····@property |
| 113 | ····def·generation(self)·->·int·|·None: | ||
| 114 | ········"""The·generation·the·current·hold·was·granted·at,·a·fencing·token;·``None``·when·no·lock·is·held.""" | ||
| 115 | ········return·self._lock.generation | ||
| 116 | ····@property | ||
| 117 | ····def·compromise(self)·->·LeaseCompromise·|·None: | ||
| 118 | ········"""How·the·current·hold·was·lost,·or·``None``·while·it·stands;·acquiring·raises·until·the·hold·is·released.""" | ||
| 119 | ········return·self._lock.compromise | ||
| 120 | ····@property | ||
| 95 | ····def·loop(self)·->·asyncio.AbstractEventLoop·|·None: | 121 | ····def·loop(self)·->·asyncio.AbstractEventLoop·|·None: |
| 96 | ········"""The·event·loop·used·for·``run_in_executor``,·or·``None``·for·the·running·loop.""" | 122 | ········"""The·event·loop·used·for·``run_in_executor``,·or·``None``·for·the·running·loop.""" |
| 97 | ········return·self._loop | 123 | ········return·self._loop |
| 98 | ····@property | 124 | ····@property |
| 99 | ····def·executor(self)·->·futures.Executor·|·None: | 125 | ····def·executor(self)·->·futures.Executor·|·None: |
| 100 | ········"""The·executor·used·for·``run_in_executor``,·or·``None``·for·the·default·executor.""" | 126 | ········"""The·executor·used·for·``run_in_executor``,·or·``None``·for·the·default·executor.""" |
| Max diff block lines reached; 13672/19425 bytes (70.38%) of diff not shown. | |||
| Offset 1, 241 lines modified | Offset 1, 294 lines modified | ||
| 1 | """Cross-process·and·cross-host·reader/writer·lock· | 1 | """Cross-process·and·cross-host·reader/writer·lock·over·a·generation·log·of·immutable·snapshots.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | __lazy_modules__·=·[ | ||
| 4 | ····"filelock._error", | ||
| 5 | ····"filelock._lease", | ||
| 6 | ····"filelock._soft_rw._protocol", | ||
| 7 | ····"filelock._soft_rw._storage", | ||
| 8 | ····"math", | ||
| 9 | ] | ||
| 3 | import·atexit | 10 | import·atexit |
| 4 | import·hmac | ||
| 5 | import·os | 11 | import·os |
| 6 | import·re | ||
| 7 | import·secrets | ||
| 8 | import·socket | ||
| 9 | import·stat | ||
| 10 | import·sys | ||
| 11 | import·threading | 12 | import·threading |
| 12 | import·time | 13 | import·time |
| 13 | import·uuid | ||
| 14 | from·contextlib·import·c | 14 | from·contextlib·import·contextmanager,·suppress |
| 15 | from·dataclasses·import·dataclass | 15 | from·dataclasses·import·dataclass |
| 16 | from· | 16 | from·math·import·isfinite |
| 17 | from·typing·import·TYPE_CHECKING,· | 17 | from·typing·import·TYPE_CHECKING,·ClassVar,·Final |
| 18 | from·weakref·import·WeakValueDictionary | 18 | from·weakref·import·WeakValueDictionary |
| 19 | from·filelock._api·import·( | 19 | from·filelock._api·import·( |
| 20 | ····AcquireReturnProxy, | 20 | ····AcquireReturnProxy, |
| 21 | ····_acquire_thread_lock, | ||
| 22 | ····_canonical, | ||
| 23 | ····_check_timeout_max, | ||
| 21 | ····_ensure_current_process, | 24 | ····_ensure_current_process, |
| 22 | ····_fork_transition, | ||
| 23 | ····_raise_grouped_errors, | ||
| 24 | ····_register_fork_class, | 25 | ····_register_fork_class, |
| 25 | ····_register_fork_object, | 26 | ····_register_fork_object, |
| 26 | ····_register_owned_descriptor, | ||
| 27 | ····_ | 27 | ····_resolve_read_write_timeout, |
| 28 | ····_seconds, | ||
| 29 | ····_timeout_behavior, | ||
| 28 | ) | 30 | ) |
| 29 | from·filelock._error·import·Timeout | 31 | from·filelock._error·import·Timeout |
| 30 | from·filelock._soft·import·SoftFileLock | ||
| 31 | from·filelock._ | 32 | from·filelock._lease·import·LeaseCompromise |
| 33 | from·filelock._soft_rw._protocol·import·GenerationLog,·Ledger,·Mode,·Participant | ||
| 34 | from·filelock._soft_rw._storage·import·OsFiles | ||
| 32 | if·TYPE_CHECKING: | 35 | if·TYPE_CHECKING: |
| 33 | ····from·collections.abc·import·Callable,·Generator | 36 | ····from·collections.abc·import·Callable,·Generator |
| 37 | ····from·filelock._lease·import·CompromiseReason | ||
| 34 | _Mode·=·Literal["read",·"write"] | ||
| 35 | _BREAK_SUFFIX:·Final[str]·=·".break" | ||
| 36 | _MAX_MARKER_SIZE:·Final[int]·=·1024 | ||
| 37 | _O_NOFOLLOW:·Final[int]·=·getattr(os,·"O_NOFOLLOW",·0) | ||
| 38 | _O_NONBLOCK:·Final[int]·=·getattr(os,·"O_NONBLOCK",·0) | ||
| 39 | #·dirfd-relative·I/O·is·a·Unix-only·optimization;·Windows·cannot·``os.open()``·a·directory·at·all,·and | ||
| 40 | #·its·``os``·module·skips·dir_fd·support·entirely.·When·disabled,·callers·fall·back·to·full-path·ops. | ||
| 41 | _SUPPORTS_DIR_FD:·Final[bool]·=·sys.platform·!=·"win32"·and·os.open·in·os.supports_dir_fd | ||
| 42 | _ALL_INSTANCES:·Final[WeakValueDictionary[int,·SoftReadWriteLock]]·=·WeakValueDictionary() | 38 | _ALL_INSTANCES:·Final[WeakValueDictionary[int,·SoftReadWriteLock]]·=·WeakValueDictionary() |
| 43 | _ALL_INSTANCES_LOCK:·threading.Lock·=·threading.Lock() | 39 | _ALL_INSTANCES_LOCK:·threading.Lock·=·threading.Lock() |
| 44 | _SINGLETONS_UNDER_CONSTRUCTION:·Final[set[Path]]·=·set() | ||
| 45 | class·_SoftRWMeta(type): | 40 | class·_SoftRWMeta(type): |
| 46 | ····_instances:·WeakValueDictionary[ | 41 | ····_instances:·WeakValueDictionary[str,·SoftReadWriteLock] |
| 47 | ····_instances_lock:·threading.RLock | 42 | ····_instances_lock:·threading.RLock |
| 43 | ····_instances_under_construction:·set[str] | ||
| 48 | ····def·__call__(··#·ruff:ignore[too-many-arguments]··#·forwards·the·public·constructor's·documented·parameters | 44 | ····def·__call__(··#·ruff:ignore[too-many-arguments]··#·forwards·the·public·constructor's·documented·parameters |
| 49 | ········cls, | 45 | ········cls, |
| 50 | ········lock_file:·str·|·os.PathLike[str], | 46 | ········lock_file:·str·|·os.PathLike[str], |
| 51 | ········timeout:·float·=·-1, | 47 | ········timeout:·float·=·-1, |
| 52 | ········*, | 48 | ········*, |
| 53 | ········blocking:·bool·=·True, | 49 | ········blocking:·bool·=·True, |
| 54 | ········is_singleton:·bool·=·True, | 50 | ········is_singleton:·bool·=·True, |
| 55 | ········heartbeat_interval:·float·=·30.0, | 51 | ········heartbeat_interval:·float·=·30.0, |
| 56 | ········stale_threshold:·float·|·None·=·None, | 52 | ········stale_threshold:·float·|·None·=·None, |
| 57 | ········poll_interval:·float·=·0.25, | 53 | ········poll_interval:·float·=·0.25, |
| 54 | ········on_compromise:·Callable[[LeaseCompromise],·None]·|·None·=·None, | ||
| 58 | ····)·->·SoftReadWriteLock: | 55 | ····)·->·SoftReadWriteLock: |
| 59 | ········_ensure_current_process() | 56 | ········_ensure_current_process() |
| 57 | ········timeout·=·_seconds("timeout",·timeout) | ||
| 58 | ········#·Passed·through·only·when·set,·so·a·subclass·that·declares·its·own·constructor·without·it·keeps·working. | ||
| 59 | ········extra·=·{}·if·on_compromise·is·None·else·{"on_compromise":·on_compromise} | ||
| 60 | ········if·not·is_singleton: | 60 | ········if·not·is_singleton: |
| 61 | ············return·super().__call__( | 61 | ············return·super().__call__( |
| 62 | ················lock_file, | 62 | ················lock_file, |
| 63 | ················timeout, | 63 | ················timeout, |
| 64 | ················blocking=blocking, | 64 | ················blocking=blocking, |
| 65 | ················is_singleton=is_singleton, | 65 | ················is_singleton=is_singleton, |
| 66 | ················heartbeat_interval=heartbeat_interval, | 66 | ················heartbeat_interval=heartbeat_interval, |
| 67 | ················stale_threshold=stale_threshold, | 67 | ················stale_threshold=stale_threshold, |
| 68 | ················poll_interval=poll_interval, | 68 | ················poll_interval=poll_interval, |
| 69 | ················**extra, | ||
| 69 | ············) | 70 | ············) |
| 71 | ········#·Keyed·like·the·log·root,·so·one·instance·never·spans·two·logs. | ||
| 70 | ········normalized·=· | 72 | ········normalized·=·_canonical(lock_file) |
| 71 | ········with·cls._instances_lock: | 73 | ········with·cls._instances_lock: |
| 72 | ············instance·=·cls._instances.get(normalized) | 74 | ············instance·=·cls._instances.get(normalized) |
| 73 | ············if·instance·is·None: | 75 | ············if·instance·is·None: |
| 74 | ················if·normalized·in· | 76 | ················if·normalized·in·cls._instances_under_construction: |
| 75 | ····················msg·=·f"Singleton·lock·construction·is·already·active·for·{lock_file!s}" | 77 | ····················msg·=·f"Singleton·lock·construction·is·already·active·for·{lock_file!s}" |
| 76 | ····················raise·RuntimeError(msg) | 78 | ····················raise·RuntimeError(msg) |
| 77 | ················construction_pid·=·os.getpid() | 79 | ················construction_pid·=·os.getpid() |
| 78 | ················ | 80 | ················construction_registry·=·cls._instances_under_construction |
| 81 | ················construction_registry.add(normalized) | ||
| 79 | ················try: | 82 | ················try: |
| 80 | ····················instance·=·super().__call__( | 83 | ····················instance·=·super().__call__( |
| 81 | ························lock_file, | 84 | ························lock_file, |
| 82 | ························timeout, | 85 | ························timeout, |
| 83 | ························blocking=blocking, | 86 | ························blocking=blocking, |
| 84 | ························is_singleton=is_singleton, | 87 | ························is_singleton=is_singleton, |
| 85 | ························heartbeat_interval=heartbeat_interval, | 88 | ························heartbeat_interval=heartbeat_interval, |
| 86 | ························stale_threshold=stale_threshold, | 89 | ························stale_threshold=stale_threshold, |
| 87 | ························poll_interval=poll_interval, | 90 | ························poll_interval=poll_interval, |
| 91 | ························**extra, | ||
| 88 | ····················) | 92 | ····················) |
| 89 | ················finally: | 93 | ················finally: |
| 90 | ···················· | 94 | ····················construction_registry.discard(normalized) |
| 91 | ················if·os.getpid()·!=·construction_pid:··#·pragma:·needs·fork | 95 | ················if·os.getpid()·!=·construction_pid:··#·pragma:·needs·fork |
| Max diff block lines reached; 61623/67182 bytes (91.73%) of diff not shown. | |||
| Offset 1, 13 lines modified | Offset 1, 13 lines modified | ||
| 1 | #Copyright·ReportLab·Europe·Ltd.·2000-2026 | 1 | #Copyright·ReportLab·Europe·Ltd.·2000-2026 |
| 2 | #see·license.txt·for·license·details | 2 | #see·license.txt·for·license·details |
| 3 | __doc__="""The·Reportlab·PDF·generation·library.""" | 3 | __doc__="""The·Reportlab·PDF·generation·library.""" |
| 4 | Version·=·"5.0. | 4 | Version·=·"5.0.1" |
| 5 | __version__=Version | 5 | __version__=Version |
| 6 | __date__='20260 | 6 | __date__='20260820' |
| 7 | import·sys,·os | 7 | import·sys,·os |
| 8 | __min_python_version__·=·(3,9) | 8 | __min_python_version__·=·(3,9) |
| 9 | if·sys.version_info<·__min_python_version__: | 9 | if·sys.version_info<·__min_python_version__: |
| 10 | ····raise·ImportError("""reportlab·requires·%s.%s+;·other·versions·are·unsupported. | 10 | ····raise·ImportError("""reportlab·requires·%s.%s+;·other·versions·are·unsupported. |
| 11 | If·you·want·to·try·with·other·python·versions·edit·line·10·of·reportlab/__init__ | 11 | If·you·want·to·try·with·other·python·versions·edit·line·10·of·reportlab/__init__ |
| Offset 291, 15 lines modified | Offset 291, 15 lines modified | ||
| 291 | ····an·A4·page·with·a·title·above·it·-·possibly·overflowing | 291 | ····an·A4·page·with·a·title·above·it·-·possibly·overflowing |
| 292 | ····if·too·big.""" | 292 | ····if·too·big.""" |
| 293 | ····d·=·renderScaledDrawing(d) | 293 | ····d·=·renderScaledDrawing(d) |
| 294 | ····for·x·in·('Name','Size'): | 294 | ····for·x·in·('Name','Size'): |
| 295 | ········a·=·'initialFont'+x | 295 | ········a·=·'initialFont'+x |
| 296 | ········kwds[a]·=·getattr(d,a,kwds.pop(a,STATE_DEFAULTS['font'+x])) | 296 | ········kwds[a]·=·getattr(d,a,kwds.pop(a,STATE_DEFAULTS['font'+x])) |
| 297 | ····metadataPath·=·kwds.pop('metadataPath',None) | 297 | ····metadataPath·=·kwds.pop('metadataPath',None) |
| 298 | ····c·=·Canvas(fn,**kwds) | 298 | ····c·=·kwds.pop('canvasMaker',Canvas)(fn,**kwds) |
| 299 | ····if·msg: | 299 | ····if·msg: |
| 300 | ········c.setFont(rl_config.defaultGraphicsFontName,·36) | 300 | ········c.setFont(rl_config.defaultGraphicsFontName,·36) |
| 301 | ········c.drawString(80,·750,·msg) | 301 | ········c.drawString(80,·750,·msg) |
| 302 | ····c.setTitle(msg) | 302 | ····c.setTitle(msg) |
| 303 | ····if·autoSize: | 303 | ····if·autoSize: |
| 304 | ········c.setPageSize((d.width,·d.height)) | 304 | ········c.setPageSize((d.width,·d.height)) |
| Offset 5, 14 lines modified | Offset 5, 19 lines modified | ||
| 5 | #hopefully·we·are·standing·on·giants'·shoulders | 5 | #hopefully·we·are·standing·on·giants'·shoulders |
| 6 | import·sys,·os,·ast,·re,·weakref,·time,·copy,·math,·types | 6 | import·sys,·os,·ast,·re,·weakref,·time,·copy,·math,·types |
| 7 | eval_debug·=·int(os.environ.get('EVAL_DEBUG','0')) | 7 | eval_debug·=·int(os.environ.get('EVAL_DEBUG','0')) |
| 8 | strTypes·=·(bytes,str) | 8 | strTypes·=·(bytes,str) |
| 9 | isPy39·=·sys.version_info[:2]>=(3,9) | 9 | isPy39·=·sys.version_info[:2]>=(3,9) |
| 10 | isPy313·=·sys.version_info[:2]>=(3,13) | 10 | isPy313·=·sys.version_info[:2]>=(3,13) |
| 11 | try: | ||
| 12 | » GenericAlias·=·types.GenericAlias | ||
| 13 | except: | ||
| 14 | » GenericAlias·=·None | ||
| 11 | import·textwrap | 15 | import·textwrap |
| 12 | class·BadCode(ValueError): | 16 | class·BadCode(ValueError): |
| 13 | » pass | 17 | » pass |
| 14 | #·For·AugAssign·the·operator·must·be·converted·to·a·string. | 18 | #·For·AugAssign·the·operator·must·be·converted·to·a·string. |
| 15 | augOps·=·{ | 19 | augOps·=·{ |
| Offset 915, 24 lines modified | Offset 920, 26 lines modified | ||
| 915 | » » #these·are·used·in·the·tree·visitor | 920 | » » #these·are·used·in·the·tree·visitor |
| 916 | » » __rl_builtins__['__rl_add__']·=·self.__rl_add__ | 921 | » » __rl_builtins__['__rl_add__']·=·self.__rl_add__ |
| 917 | » » __rl_builtins__['__rl_mult__']·=·self.__rl_mult__ | 922 | » » __rl_builtins__['__rl_mult__']·=·self.__rl_mult__ |
| 918 | » » __rl_builtins__['__rl_pow__']·=·self.__rl_pow__ | 923 | » » __rl_builtins__['__rl_pow__']·=·self.__rl_pow__ |
| 919 | » » __rl_builtins__['__rl_sd__']·=·self.__rl_sd__ | 924 | » » __rl_builtins__['__rl_sd__']·=·self.__rl_sd__ |
| 920 | » » __rl_builtins__['__rl_augAssign__']·=·self.__rl_augAssign__ | 925 | » » __rl_builtins__['__rl_augAssign__']·=·self.__rl_augAssign__ |
| 921 | » » __rl_builtins__['__rl_getitem__']·=·self.__rl_getitem__ | 926 | » » __rl_builtins__['__rl_getitem__']·=·self.__rl_getitem__ |
| 927 | » » __rl_builtins__['__rl_setattr__']·=·self.__rl_setattr__ | ||
| 922 | » » __rl_builtins__['__rl_getattr__']·=·self.__rl_getattr__ | 928 | » » __rl_builtins__['__rl_getattr__']·=·self.__rl_getattr__ |
| 923 | » » __rl_builtins__['__rl_getiter__']·=·self.__rl_getiter__ | 929 | » » __rl_builtins__['__rl_getiter__']·=·self.__rl_getiter__ |
| 924 | » » __rl_builtins__['__rl_max_len__']·=·self.__rl_max_len__ | 930 | » » __rl_builtins__['__rl_max_len__']·=·self.__rl_max_len__ |
| 925 | » » __rl_builtins__['__rl_max_pow_digits__']·=·self.__rl_max_pow_digits__ | 931 | » » __rl_builtins__['__rl_max_pow_digits__']·=·self.__rl_max_pow_digits__ |
| 926 | » » __rl_builtins__['__rl_iter_unpack_sequence__']·=·self.__rl_iter_unpack_sequence__ | 932 | » » __rl_builtins__['__rl_iter_unpack_sequence__']·=·self.__rl_iter_unpack_sequence__ |
| 927 | » » __rl_builtins__['__rl_unpack_sequence__']·=·self.__rl_unpack_sequence__ | 933 | » » __rl_builtins__['__rl_unpack_sequence__']·=·self.__rl_unpack_sequence__ |
| 928 | » » __rl_builtins__['__rl_apply__']·=·lambda·func,*args,**kwds:·self.__rl_apply__(func,args,kwds) | 934 | » » __rl_builtins__['__rl_apply__']·=·lambda·func,*args,**kwds:·self.__rl_apply__(func,args,kwds) |
| 929 | » » __rl_builtins__['__rl_SafeIter__']·=·__rl_SafeIter__ | 935 | » » __rl_builtins__['__rl_SafeIter__']·=·__rl_SafeIter__ |
| 930 | » » #these·are·tested·builtins | 936 | » » #these·are·tested·builtins |
| 937 | » » __rl_builtins__['setattr']·=·self.__rl_setattr__ | ||
| 931 | » » __rl_builtins__['getattr']·=·self.__rl_getattr__ | 938 | » » __rl_builtins__['getattr']·=·self.__rl_getattr__ |
| 932 | » » __rl_builtins__['dict']·=·__rl_dict__ | 939 | » » __rl_builtins__['dict']·=·__rl_dict__ |
| 933 | » » __rl_builtins__['iter']·=·self.__rl_getiter__ | 940 | » » __rl_builtins__['iter']·=·self.__rl_getiter__ |
| 934 | » » __rl_builtins__['pow']·=·self.__rl_pow__ | 941 | » » __rl_builtins__['pow']·=·self.__rl_pow__ |
| 935 | » » __rl_builtins__['list']·=·self.__rl_list__ | 942 | » » __rl_builtins__['list']·=·self.__rl_list__ |
| 936 | » » __rl_builtins__['type']·=·self.__rl_type__ | 943 | » » __rl_builtins__['type']·=·self.__rl_type__ |
| 937 | » » __rl_builtins__['max']·=·self.__rl_max__ | 944 | » » __rl_builtins__['max']·=·self.__rl_max__ |
| Offset 1071, 15 lines modified | Offset 1078, 20 lines modified | ||
| 1071 | » def·__rl_getattr__(self,·obj,·a,·*args): | 1078 | » def·__rl_getattr__(self,·obj,·a,·*args): |
| 1072 | » » if·isinstance(obj,·strTypes)·and·a=='format': | 1079 | » » if·isinstance(obj,·strTypes)·and·a=='format': |
| 1073 | » » » raise·BadCode('%s.format·is·not·implemented'·%·type(obj)) | 1080 | » » » raise·BadCode('%s.format·is·not·implemented'·%·type(obj)) |
| 1074 | » » self.__rl_is_allowed_name__(a) | 1081 | » » self.__rl_is_allowed_name__(a) |
| 1075 | » » return·getattr(obj,a,*args) | 1082 | » » return·getattr(obj,a,*args) |
| 1083 | » def·__rl_setattr__(self,·obj,·a,·v,·*args): | ||
| 1084 | » » #remediation·for·using·odd·magics | ||
| 1085 | » » self.__rl_is_allowed_name__(a) | ||
| 1086 | » » return·setattr(obj,a,v,*args) | ||
| 1076 | » def·__rl_getitem__(self,·obj,·a): | 1087 | » def·__inner_rl_getitem__(self,·obj,·a): |
| 1077 | » » if·type(a)·is·self.__slicetype__: | 1088 | » » if·type(a)·is·self.__slicetype__: |
| 1078 | » » » if·a.step·is·not·None: | 1089 | » » » if·a.step·is·not·None: |
| 1079 | » » » » v·=·obj[a] | 1090 | » » » » v·=·obj[a] |
| 1080 | » » » else: | 1091 | » » » else: |
| 1081 | » » » » start·=·a.start | 1092 | » » » » start·=·a.start |
| 1082 | » » » » stop·=·a.stop | 1093 | » » » » stop·=·a.stop |
| 1083 | » » » » if·start·is·None: | 1094 | » » » » if·start·is·None: |
| Offset 1090, 14 lines modified | Offset 1102, 25 lines modified | ||
| 1090 | » » » » » v·=·obj[start:stop] | 1102 | » » » » » v·=·obj[start:stop] |
| 1091 | » » » return·v | 1103 | » » » return·v |
| 1092 | » » elif·isinstance(a,strTypes): | 1104 | » » elif·isinstance(a,strTypes): |
| 1093 | » » » self.__rl_is_allowed_name__(a) | 1105 | » » » self.__rl_is_allowed_name__(a) |
| 1094 | » » » return·obj[a] | 1106 | » » » return·obj[a] |
| 1095 | » » return·obj[a] | 1107 | » » return·obj[a] |
| 1108 | » def·__rl_getitem__(self,·obj,·a): | ||
| 1109 | » » try: | ||
| 1110 | » » » v·=·self.__inner_rl_getitem__(obj,a) | ||
| 1111 | » » except·(IndexError,KeyError,KeyboardInterrupt,ValueError,TypeError): | ||
| 1112 | » » » raise | ||
| 1113 | » » except: | ||
| 1114 | » » » raise·BadCode("subscript·operation·%s[%r]·failed"·%·(obj.__class__.__name__,a)) | ||
| 1115 | » » if·isinstance(v,GenericAlias): | ||
| 1116 | » » » raise·BadCode("subscript·operation·%s[%r]·created·a·GenericAlias"·%·(obj.__class__.__name__,a)) | ||
| 1117 | » » return·v | ||
| 1096 | » __rl_tmax__·=·5 | 1118 | » __rl_tmax__·=·5 |
| 1097 | » __rl_max_len__·=·100000 | 1119 | » __rl_max_len__·=·100000 |
| 1098 | » __rl_max_pow_digits__·=·100 | 1120 | » __rl_max_pow_digits__·=·100 |
| 1099 | » def·__rl_add__(self,·a,·b): | 1121 | » def·__rl_add__(self,·a,·b): |
| 1100 | » » if·(hasattr(a,·'__len__')·and·hasattr(b,·'__len__') | 1122 | » » if·(hasattr(a,·'__len__')·and·hasattr(b,·'__len__') |
| 1101 | » » » » and·(len(a)·+·len(b))·>·self.__rl_max_len__): | 1123 | » » » » and·(len(a)·+·len(b))·>·self.__rl_max_len__): |
| Offset 467, 21 lines modified | Offset 467, 16 lines modified | ||
| 467 | ········#the·dirname(reportlab.__file__)·or·is·relative | 467 | ········#the·dirname(reportlab.__file__)·or·is·relative |
| 468 | ········name·=·_startswith_rl(name) | 468 | ········name·=·_startswith_rl(name) |
| 469 | ········s·=·__rl_loader__.get_data(name) | 469 | ········s·=·__rl_loader__.get_data(name) |
| 470 | ········if·'b'·not·in·mode·and·os.linesep!='\n':·s·=·s.replace(os.linesep,'\n') | 470 | ········if·'b'·not·in·mode·and·os.linesep!='\n':·s·=·s.replace(os.linesep,'\n') |
| 471 | ········return·BytesIO(s) | 471 | ········return·BytesIO(s) |
| 472 | from·urllib.parse·import·unquote,·urlparse | 472 | from·urllib.parse·import·unquote,·urlparse |
| 473 | 473 | _tHaS·=·{}··#cache·for·(trustedHosts,trustedSchemes) | |
| 474 | def·rlUrlRead( | 474 | def·rlUrlRead(url,·headers=None): |
| 475 | ····if·headers==None:·headers·=·{} | ||
| 476 | ····headers.setdefault('User-Agent','ReportLabAgent') | ||
| 477 | ····return·urlopen(Request(name,headers=headers)).read() | ||
| 478 | def·open_for_read(name,mode='b'): | ||
| 479 | ····#auto·initialized·function` | 475 | ····#auto·initialized·function` |
| 480 | ····#copied·here·from·urllib.URLopener.open_data·because | 476 | ····#copied·here·from·urllib.URLopener.open_data·because |
| 481 | ····#·1)·they·want·to·remove·it | 477 | ····#·1)·they·want·to·remove·it |
| 482 | ····#·2)·the·existing·one·is·borken | 478 | ····#·2)·the·existing·one·is·borken |
| 483 | ····def·datareader(url,·unquote=unquote): | 479 | ····def·datareader(url,·unquote=unquote): |
| 484 | ········"""Use·"data"·URL.""" | 480 | ········"""Use·"data"·URL.""" |
| 485 | ········#·ignore·POSTed·data | 481 | ········#·ignore·POSTed·data |
| Offset 505, 49 lines modified | Offset 500, 77 lines modified | ||
| 505 | ············encoding·=·'' | 500 | ············encoding·=·'' |
| 506 | ········if·encoding·==·'base64': | 501 | ········if·encoding·==·'base64': |
| 507 | ············#·XXX·is·this·encoding/decoding·ok? | 502 | ············#·XXX·is·this·encoding/decoding·ok? |
| 508 | ············data·=·base64_decodebytes(data.encode('ascii')) | 503 | ············data·=·base64_decodebytes(data.encode('ascii')) |
| 509 | ········else: | 504 | ········else: |
| 510 | ············data·=·unquote(data).encode('latin-1') | 505 | ············data·=·unquote(data).encode('latin-1') |
| 511 | ········return·data | 506 | ········return·data |
| 512 | ····from·reportlab.rl_config·import·trustedHosts,·trustedSchemes | ||
| 513 | ····i | 507 | ····import·socket |
| 508 | ····from·urllib.request·import·OpenerDirector,·build_opener,·Request | ||
| 514 | ···· | 509 | ····import·re,·fnmatch |
| 515 | ···· | 510 | ····def·xre(s): |
| 516 | ········ | 511 | ········s·=·fnmatch.translate(s) |
| 517 | ········ | 512 | ········return·s[4:-3]·if·s.startswith('(?s:')·else·s[:-7] |
| 513 | ····def·keyval(v): | ||
| 514 | ········return·v·if·v·is·None·else·tuple(v) | ||
| 515 | ····class·RLOpenerDirector(OpenerDirector): | ||
| 516 | ········def·open(self,·req,·data=None,·timeout=socket._GLOBAL_DEFAULT_TIMEOUT): | ||
| 517 | ············if·isinstance(req,·str): | ||
| 518 | ················req·=·Request(url,·data) | ||
| 519 | ············url·=·req.full_url | ||
| 520 | ············if·data·is·not·None: | ||
| 521 | ················req.data·=·data | ||
| 522 | ············#do·the·import·here·in·case·these·change·between·calls | ||
| 523 | ············from·reportlab.rl_config·import·trustedHosts,·trustedSchemes | ||
| 524 | ············key·=·keyval(trustedHosts),keyval(trustedSchemes) | ||
| 525 | ············if·key·not·in·_tHaS: | ||
| 526 | ················if·trustedHosts: | ||
| 518 | ········ | 527 | ····················tHosts·=·re.compile(''.join(('^(?:', |
| 519 | ································'|'.join(map(xre,trustedHosts)), | 528 | ············································'|'.join(map(xre,trustedHosts)), |
| 529 | ············································')\\Z'))) | ||
| 530 | ················_tHaS.clear() | ||
| 531 | ················_tHaS[key]·=·(tHosts,trustedSchemes) | ||
| 532 | ············tHosts,·tSchemes·=_tHaS[key] | ||
| 533 | ············if·not·tHosts:·raise·ValueError | ||
| 534 | ············netloc·=·urlparse(url) | ||
| 535 | ············scheme·=·netloc.scheme | ||
| 536 | ············netloc·=·netloc.netloc.lower() | ||
| 537 | ············if·(not·scheme· | ||
| 538 | ················or·scheme·not·in·tSchemes· | ||
| 539 | ················or·(scheme=='file'·and·not·( | ||
| 540 | ································(netloc==''·and·tHosts.match('localhost')) | ||
| 541 | ································or | ||
| 542 | ································(netloc!=''·and·tHosts.match(netloc)) | ||
| 520 | ································ | 543 | ································)) |
| 521 | ····def·open_for_read(name,mode='b'): | ||
| 522 | ········'''attempt·to·open·a·file·or·URL·for·reading''' | ||
| 523 | ········ | 544 | ················or·(scheme·not·in·('data','file')·and·not·tHosts.match(netloc))): |
| 545 | ················raise·ValueError· | ||
| 546 | ············if·scheme=='data': | ||
| 547 | ················return·datareader(url) | ||
| 548 | ············else: | ||
| 549 | ················return·super().open(req,data=data,timeout=timeout) | ||
| 550 | ····_rlOpener·=·build_opener() | ||
| 551 | ····_rlOpener.__class__·=·RLOpenerDirector | ||
| 552 | ····def·rlUrlRead(url,·headers=None): | ||
| 524 | ········try: | 553 | ········try: |
| 525 | ············ | 554 | ············if·headers==None:·headers·=·{} |
| 555 | ············headers.setdefault('User-Agent','ReportLabAgent') | ||
| 556 | ············return·_rlOpener.open(Request(url,headers=headers)) | ||
| 526 | ········except: | 557 | ········except: |
| 527 | ············try: | ||
| 528 | ················if·not·trustedHosts:·raise·ValueError | ||
| 529 | ················netloc·=·urlparse(name) | ||
| 530 | ················scheme·=·netloc.scheme | ||
| 531 | ················netloc·=·netloc.netloc.lower() | ||
| 532 | ················if·(not·scheme· | ||
| 533 | ····················or·scheme·not·in·trustedSchemes· | ||
| 534 | ····················or·(scheme=='file'·and·not·( | ||
| 535 | ····································(netloc==''·and·trustedHosts.match('localhost')) | ||
| 536 | ····································or | ||
| 537 | ····································(netloc!=''·and·trustedHosts.match(netloc)) | ||
| 538 | ····································)) | ||
| 539 | ····················or·(scheme·not·in·('data','file')·and·not·trustedHosts.match(netloc))): | ||
| 540 | ····················raise·ValueError· | ||
| 541 | ················return·BytesIO((datareader·if·scheme=='data'·else·rlUrlRead)(name)) | ||
| 542 | ············except: | ||
| 543 | ············ | 558 | ············raise·IOError(f'Cannot·open·resource·{url!r}') |
| 544 | ····globals()[' | 559 | ····globals()['rlUrlRead']·=·rlUrlRead |
| 560 | ····return·rlUrlRead(url,headers=headers) | ||
| 561 | def·open_for_read(name,mode='b'): | ||
| 562 | ····'''attempt·to·open·a·file·or·URL·for·reading''' | ||
| 563 | ····if·hasattr(name,'read'):·return·name | ||
| 564 | ····try: | ||
| 545 | ····return·open_for_read(name,mode) | 565 | ········return·open_for_read_by_name(name,mode) |
| 566 | ····except: | ||
| 567 | ········r·=·rlUrlRead(name) | ||
| 568 | ········return·BytesIO(r.fp.read())·if·not·isinstance(r,bytes)·else·BytesIO(r) | ||
| 546 | def·open_and_read(name,mode='b'): | 569 | def·open_and_read(name,mode='b'): |
| 547 | ····f·=·open_for_read(name,mode) | 570 | ····f·=·open_for_read(name,mode) |
| 548 | ····if·name·is·not·f·and·hasattr(f,'__exit__'): | 571 | ····if·name·is·not·f·and·hasattr(f,'__exit__'): |
| 549 | ········with·f: | 572 | ········with·f: |
| 550 | ············return·f.read() | 573 | ············return·f.read() |
| 551 | ····else: | 574 | ····else: |
| Offset 652, 15 lines modified | Offset 675, 18 lines modified | ||
| 652 | ········else: | 675 | ········else: |
| 653 | ············try: | 676 | ············try: |
| 654 | ················from·reportlab.rl_config·import·imageReaderFlags | 677 | ················from·reportlab.rl_config·import·imageReaderFlags |
| 655 | ················if·imageReaderFlags·!=·0: | 678 | ················if·imageReaderFlags·!=·0: |
| 656 | ····················raise·ValueError('imageReaderFlags·values·other·than·0·are·no·longer·supported;·all·images·are·interned·now') | 679 | ····················raise·ValueError('imageReaderFlags·values·other·than·0·are·no·longer·supported;·all·images·are·interned·now') |
| 657 | ················fp·=·open_for_read(fileName,'b') | 680 | ················fp·=·open_for_read(fileName,'b') |
| 658 | ················if·not·isinstance(fp,·BytesIO): | 681 | ················if·not·isinstance(fp,·BytesIO): |
| Max diff block lines reached; 333/6655 bytes (5.00%) of diff not shown. | |||
| Offset 1304, 15 lines modified | Offset 1304, 15 lines modified | ||
| 1304 | ····def·getpdfdata(self): | 1304 | ····def·getpdfdata(self): |
| 1305 | ········"""Returns·the·PDF·data·that·would·normally·be·written·to·a·file. | 1305 | ········"""Returns·the·PDF·data·that·would·normally·be·written·to·a·file. |
| 1306 | ········If·there·is·current·data·a·ShowPage·is·executed·automatically. | 1306 | ········If·there·is·current·data·a·ShowPage·is·executed·automatically. |
| 1307 | ········After·this·operation·the·canvas·must·not·be·used·further.""" | 1307 | ········After·this·operation·the·canvas·must·not·be·used·further.""" |
| 1308 | ········if·len(self._code):·self.showPage() | 1308 | ········if·len(self._code):·self.showPage() |
| 1309 | ········s·=·self._doc.GetPDFData(self) | 1309 | ········s·=·self._doc.GetPDFData(self) |
| 1310 | ········if·isUnicode(s): | 1310 | ········if·isUnicode(s): |
| 1311 | ············s·=·s.encode(' | 1311 | ············s·=·s.encode('latin1')··#this·is·what·pdfdoc.py·uses;·could·not·detect·need·in·tests |
| 1312 | ········return·s | 1312 | ········return·s |
| 1313 | ····def·setPageSize(self,·size): | 1313 | ····def·setPageSize(self,·size): |
| 1314 | ········"""accepts·a·2-tuple·in·points·for·paper·size·for·this | 1314 | ········"""accepts·a·2-tuple·in·points·for·paper·size·for·this |
| 1315 | ········and·subsequent·pages""" | 1315 | ········and·subsequent·pages""" |
| 1316 | ········self._pagesize·=·size | 1316 | ········self._pagesize·=·size |
| 1317 | ········self._make_preamble() | 1317 | ········self._make_preamble() |
| Offset 26, 33 lines modified | Offset 26, 35 lines modified | ||
| 26 | SOFTWARE. | 26 | SOFTWARE. |
| 27 | """ | 27 | """ |
| 28 | from·__future__·import·annotations | 28 | from·__future__·import·annotations |
| 29 | from·.__meta__·import·__version__,·__version_info__··#·noqa:·F401 | 29 | from·.__meta__·import·__version__,·__version_info__··#·noqa:·F401 |
| 30 | from·.·import·css_parser·as·cp | 30 | from·.·import·css_parser·as·cp |
| 31 | from·.·import·css_match·as·cm | 31 | from·.·import·css_match·as·cm |
| 32 | from·.·import·css_types·as·ct | 32 | from·.·import·css_types·as·ct |
| 33 | from·.util·import·DEBUG,·SelectorSyntaxError··#·noqa:·F401 | 33 | from·.util·import·DEBUG,·NOCACHE,·NOSTRICT,·SelectorSyntaxError··#·noqa:·F401 |
| 34 | import·bs4 | 34 | import·bs4 |
| 35 | from·typing·import·Any,·Iterator,·Iterable | 35 | from·typing·import·Any,·Mapping,·Iterator,·Iterable,·cast |
| 36 | __all__·=·( | 36 | __all__·=·( |
| 37 | ····'DEBUG',·'NOCACHE',·'NOSTRICT',·'SelectorSyntaxError',·'CustomSelectors',·'SoupSieve', | ||
| 38 | ····'closest',·'compile',·'filter',·'iselect',·'match',·'select',·'select_one' | ||
| 37 | ····'DEBUG',·'SelectorSyntaxError',·'SoupSieve', | ||
| 38 | ····'closest',·'compile',·'filter',·'iselect', | ||
| 39 | ····'match',·'select',·'select_one' | ||
| 40 | ) | 39 | ) |
| 41 | SoupSieve·=·cm.SoupSieve | 40 | SoupSieve·=·cm.SoupSieve |
| 41 | CustomSelectors·=·ct.CustomSelectors | ||
| 42 | def·compile(··#·noqa:·A001 | 42 | def·compile(··#·noqa:·A001 |
| 43 | ····pattern:·str, | 43 | ····pattern:·str, |
| 44 | ····namespaces:·dict[str,·str]·|·None·=·None, | 44 | ····namespaces:·dict[str,·str]·|·None·=·None, |
| 45 | ····flags:·int·=·0, | 45 | ····flags:·int·=·0, |
| 46 | ····*, | 46 | ····*, |
| 47 | ····custom:· | 47 | ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None, |
| 48 | ····ignore:·Iterable[str]·|·None·=·None, | ||
| 49 | ····max_selectors:·int·=·cp.SELECTOR_LIMIT, | ||
| 48 | ····**kwargs:·Any | 50 | ····**kwargs:·Any |
| 49 | )·->·cm.SoupSieve: | 51 | )·->·cm.SoupSieve: |
| 50 | ····"""Compile·CSS·pattern.""" | 52 | ····"""Compile·CSS·pattern.""" |
| 51 | ····if·isinstance(pattern,·SoupSieve): | 53 | ····if·isinstance(pattern,·SoupSieve): |
| 52 | ········if·flags: | 54 | ········if·flags: |
| 53 | ············raise·ValueError("Cannot·process·'flags'·argument·on·a·compiled·selector·list") | 55 | ············raise·ValueError("Cannot·process·'flags'·argument·on·a·compiled·selector·list") |
| Offset 61, 16 lines modified | Offset 63, 20 lines modified | ||
| 61 | ········elif·custom·is·not·None: | 63 | ········elif·custom·is·not·None: |
| 62 | ············raise·ValueError("Cannot·process·'custom'·argument·on·a·compiled·selector·list") | 64 | ············raise·ValueError("Cannot·process·'custom'·argument·on·a·compiled·selector·list") |
| 63 | ········return·pattern | 65 | ········return·pattern |
| 64 | ····return·cp._cached_css_compile( | 66 | ····return·cp._cached_css_compile( |
| 65 | ········pattern, | 67 | ········pattern, |
| 66 | ········ct.Namespaces(namespaces)·if·namespaces·is·not·None·else·namespaces, | 68 | ········ct.Namespaces(namespaces)·if·namespaces·is·not·None·else·namespaces, |
| 67 | ········ct.CustomSelectors( | 69 | ········ct.CustomSelectors( |
| 70 | ············cast('dict[str,·str·|·ct.SelectorList]',·custom),·max_selectors=max_selectors | ||
| 71 | ········)·if·custom·is·not·None·and·not·isinstance(custom,·ct.CustomSelectors)·else·custom, | ||
| 72 | ········tuple(i.lower()·for·i·in·ignore)·if·ignore·is·not·None·else·ignore, | ||
| 68 | ········flags | 73 | ········flags, |
| 74 | ········max_selectors | ||
| 69 | ····) | 75 | ····) |
| 70 | def·purge()·->·None: | 76 | def·purge()·->·None: |
| 71 | ····"""Purge·cached·patterns.""" | 77 | ····"""Purge·cached·patterns.""" |
| 72 | ····cp._purge_cache() | 78 | ····cp._purge_cache() |
| Offset 78, 91 lines modified | Offset 84, 151 lines modified | ||
| 78 | def·closest( | 84 | def·closest( |
| 79 | ····select:·str, | 85 | ····select:·str, |
| 80 | ····tag:·bs4.Tag, | 86 | ····tag:·bs4.Tag, |
| 81 | ····namespaces:·dict[str,·str]·|·None·=·None, | 87 | ····namespaces:·dict[str,·str]·|·None·=·None, |
| 82 | ····flags:·int·=·0, | 88 | ····flags:·int·=·0, |
| 83 | ····*, | 89 | ····*, |
| 84 | ····custom:· | 90 | ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None, |
| 91 | ····ignore:·Iterable[str]·|·None·=·None, | ||
| 92 | ····max_selectors:·int·=·cp.SELECTOR_LIMIT, | ||
| 85 | ····**kwargs:·Any | 93 | ····**kwargs:·Any |
| 86 | )·->·bs4.Tag·|·None: | 94 | )·->·bs4.Tag·|·None: |
| 87 | ····"""Match·closest·ancestor.""" | 95 | ····"""Match·closest·ancestor.""" |
| 88 | ····return·compile( | 96 | ····return·compile( |
| 97 | ········select, | ||
| 98 | ········namespaces, | ||
| 99 | ········flags, | ||
| 100 | ········custom=custom, | ||
| 101 | ········ignore=ignore, | ||
| 102 | ········max_selectors=max_selectors, | ||
| 103 | ········**kwargs | ||
| 104 | ····).closest(tag) | ||
| 89 | def·match( | 105 | def·match( |
| 90 | ····select:·str, | 106 | ····select:·str, |
| 91 | ····tag:·bs4.Tag, | 107 | ····tag:·bs4.Tag, |
| 92 | ····namespaces:·dict[str,·str]·|·None·=·None, | 108 | ····namespaces:·dict[str,·str]·|·None·=·None, |
| 93 | ····flags:·int·=·0, | 109 | ····flags:·int·=·0, |
| 94 | ····*, | 110 | ····*, |
| 95 | ····custom:· | 111 | ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None, |
| 112 | ····ignore:·Iterable[str]·|·None·=·None, | ||
| 113 | ····max_selectors:·int·=·cp.SELECTOR_LIMIT, | ||
| 96 | ····**kwargs:·Any | 114 | ····**kwargs:·Any |
| 97 | )·->·bool: | 115 | )·->·bool: |
| 98 | ····"""Match·node.""" | 116 | ····"""Match·node.""" |
| 99 | ····return·compile( | 117 | ····return·compile( |
| 118 | ········select, | ||
| 119 | ········namespaces, | ||
| 120 | ········flags, | ||
| 121 | ········custom=custom, | ||
| 122 | ········ignore=ignore, | ||
| 123 | ········max_selectors=max_selectors, | ||
| 124 | ········**kwargs | ||
| 125 | ····).match(tag) | ||
| 100 | def·filter(··#·noqa:·A001 | 126 | def·filter(··#·noqa:·A001 |
| 101 | ····select:·str, | 127 | ····select:·str, |
| 102 | ····iterable:·Iterable[bs4.Tag], | 128 | ····iterable:·Iterable[bs4.Tag], |
| 103 | ····namespaces:·dict[str,·str]·|·None·=·None, | 129 | ····namespaces:·dict[str,·str]·|·None·=·None, |
| 104 | ····flags:·int·=·0, | 130 | ····flags:·int·=·0, |
| 105 | ····*, | 131 | ····*, |
| 106 | ····custom:· | 132 | ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None, |
| 133 | ····ignore:·Iterable[str]·|·None·=·None, | ||
| 134 | ····max_selectors:·int·=·cp.SELECTOR_LIMIT, | ||
| 107 | ····**kwargs:·Any | 135 | ····**kwargs:·Any |
| 108 | )·->·list[bs4.Tag]: | 136 | )·->·list[bs4.Tag]: |
| 109 | ····"""Filter·list·of·nodes.""" | 137 | ····"""Filter·list·of·nodes.""" |
| 110 | ····return·compile( | 138 | ····return·compile( |
| 139 | ········select, | ||
| 140 | ········namespaces, | ||
| 141 | ········flags, | ||
| 142 | ········custom=custom, | ||
| Max diff block lines reached; 2201/6480 bytes (33.97%) of diff not shown. | |||
| Offset 189, 9 lines modified | Offset 189, 9 lines modified | ||
| 189 | ····#·Handle·post | 189 | ····#·Handle·post |
| 190 | ····post·=·int(m.group('post'))·if·m.group('post')·else·0 | 190 | ····post·=·int(m.group('post'))·if·m.group('post')·else·0 |
| 191 | ····return·Version(major,·minor,·micro,·release,·pre,·post,·dev) | 191 | ····return·Version(major,·minor,·micro,·release,·pre,·post,·dev) |
| 192 | __version_info__·=·Version( | 192 | __version_info__·=·Version(3,·0,·3,·"final") |
| 193 | __version__·=·__version_info__._get_canonical() | 193 | __version__·=·__version_info__._get_canonical() |
| Offset 1, 16 lines modified | Offset 1, 28 lines modified | ||
| 1 | """CSS·matcher.""" | 1 | """CSS·matcher.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | from·datetime·import·datetime | 3 | from·datetime·import·datetime |
| 4 | from·collections.abc·import·Hashable | ||
| 4 | from·.·import·util | 5 | from·.·import·util |
| 5 | import·re | 6 | import·re |
| 6 | from·.·import·css_types·as·ct | 7 | from·.·import·css_types·as·ct |
| 7 | import·unicodedata | 8 | import·unicodedata |
| 8 | import·bs4 | 9 | import·bs4 |
| 9 | from·typing·import· | 10 | from·typing·import·( |
| 11 | ····Generator, | ||
| 12 | ····Iterator, | ||
| 13 | ····Iterable, | ||
| 14 | ····Any, | ||
| 15 | ····Callable, | ||
| 16 | ····Sequence, | ||
| 17 | ····overload, | ||
| 18 | ····Literal, | ||
| 19 | ····cast, | ||
| 20 | ····TYPE_CHECKING | ||
| 21 | )··#·noqa:·F401,·F811 | ||
| 10 | #·Empty·tag·pattern·(whitespace·okay) | 22 | #·Empty·tag·pattern·(whitespace·okay) |
| 11 | RE_NOT_EMPTY·=·re.compile('[^·\t\r\n\f]') | 23 | RE_NOT_EMPTY·=·re.compile('[^·\t\r\n\f]') |
| 12 | RE_NOT_WS·=·re.compile('[^·\t\r\n\f]+') | 24 | RE_NOT_WS·=·re.compile('[^·\t\r\n\f]+') |
| 13 | #·Relationships | 25 | #·Relationships |
| Offset 21, 14 lines modified | Offset 33, 20 lines modified | ||
| 21 | #·Relationships·for·:has()·(forward·looking) | 33 | #·Relationships·for·:has()·(forward·looking) |
| 22 | REL_HAS_PARENT·=·':·' | 34 | REL_HAS_PARENT·=·':·' |
| 23 | REL_HAS_CLOSE_PARENT·=·':>' | 35 | REL_HAS_CLOSE_PARENT·=·':>' |
| 24 | REL_HAS_SIBLING·=·':~' | 36 | REL_HAS_SIBLING·=·':~' |
| 25 | REL_HAS_CLOSE_SIBLING·=·':+' | 37 | REL_HAS_CLOSE_SIBLING·=·':+' |
| 38 | #·`bs4`·imports·this·module·while·it·is·still·initializing, | ||
| 39 | #·so·these·must·only·be·evaluated·when·type·checking. | ||
| 40 | if·TYPE_CHECKING:··#·pragma:·no·cover | ||
| 41 | ····MatchRequest·=·tuple[bs4.Tag,·ct.SelectorList] | ||
| 42 | ····MatchGenerator·=·Generator[MatchRequest,·bool,·bool] | ||
| 26 | NS_XHTML·=·'http://www.w3.org/1999/xhtml' | 43 | NS_XHTML·=·'http://www.w3.org/1999/xhtml' |
| 27 | NS_XML·=·'http://www.w3.org/XML/1998/namespace' | 44 | NS_XML·=·'http://www.w3.org/XML/1998/namespace' |
| 28 | DIR_FLAGS·=·ct.SEL_DIR_LTR·|·ct.SEL_DIR_RTL | 45 | DIR_FLAGS·=·ct.SEL_DIR_LTR·|·ct.SEL_DIR_RTL |
| 29 | RANGES·=·ct.SEL_IN_RANGE·|·ct.SEL_OUT_OF_RANGE | 46 | RANGES·=·ct.SEL_IN_RANGE·|·ct.SEL_OUT_OF_RANGE |
| 30 | DIR_MAP·=·{ | 47 | DIR_MAP·=·{ |
| Offset 52, 32 lines modified | Offset 70, 19 lines modified | ||
| 52 | SHORT_MONTH·=·30 | 70 | SHORT_MONTH·=·30 |
| 53 | LONG_MONTH·=·31 | 71 | LONG_MONTH·=·31 |
| 54 | FEB_MONTH·=·28 | 72 | FEB_MONTH·=·28 |
| 55 | FEB_LEAP_MONTH·=·29 | 73 | FEB_LEAP_MONTH·=·29 |
| 56 | DAYS_IN_WEEK·=·7 | 74 | DAYS_IN_WEEK·=·7 |
| 75 | def·within(target:·bs4.Tag,·parent:·bs4.Tag·|·bs4.BeautifulSoup,·start:·int,·end:·int·|·None·=·None)·->·bool: | ||
| 76 | ····"""Check·if·target·is·within·data.""" | ||
| 57 | class·_FakeParent: | ||
| 58 | ····""" | ||
| 59 | ····Fake·parent·class. | ||
| 60 | ····When·we·have·a·fragment·with·no·`BeautifulSoup`·document·object, | ||
| 61 | ····we·can't·evaluate·`nth`·selectors·properly.··Create·a·temporary | ||
| 62 | ····fake·parent·so·we·can·traverse·the·root·element·as·a·child. | ||
| 63 | ····""" | ||
| 64 | ····def·__init__(self,·element:·bs4.Tag)·->·None: | ||
| 65 | ········"""Initialize.""" | ||
| 66 | ········self.contents·=·[element] | ||
| 67 | ····def·__len__(self)·->·int: | ||
| 68 | ········"""Length.""" | ||
| 69 | ···· | 77 | ····contents·=·parent.contents |
| 78 | ····return·any(contents[i]·is·target·for·i·in·range(start,·end·if·end·is·not·None·else·len(contents))) | ||
| 70 | class·_DocumentNav: | 79 | class·_DocumentNav: |
| 71 | ····"""Navigate·a·Beautiful·Soup·document.""" | 80 | ····"""Navigate·a·Beautiful·Soup·document.""" |
| 72 | ····@classmethod | 81 | ····@classmethod |
| 73 | ····def·assert_valid_input(cls,·tag:·Any)·->·None: | 82 | ····def·assert_valid_input(cls,·tag:·Any)·->·None: |
| Offset 125, 20 lines modified | Offset 130, 14 lines modified | ||
| 125 | ····@classmethod | 130 | ····@classmethod |
| 126 | ····def·is_content_string(cls,·obj:·bs4.element.PageElement·|·None)·->·bool: | 131 | ····def·is_content_string(cls,·obj:·bs4.element.PageElement·|·None)·->·bool: |
| 127 | ········"""Check·if·node·is·content·string.""" | 132 | ········"""Check·if·node·is·content·string.""" |
| 128 | ········return·cls.is_navigable_string(obj)·and·not·cls.is_special_string(obj) | 133 | ········return·cls.is_navigable_string(obj)·and·not·cls.is_special_string(obj) |
| 129 | ····@staticmethod | 134 | ····@staticmethod |
| 130 | ····def·create_fake_parent(el:·bs4.Tag)·->·_FakeParent: | ||
| 131 | ········"""Create·fake·parent·for·a·given·element.""" | ||
| 132 | ········return·_FakeParent(el) | ||
| 133 | ····@staticmethod | ||
| 134 | ····def·is_xml_tree(el:·bs4.Tag·|·None)·->·bool: | 135 | ····def·is_xml_tree(el:·bs4.Tag·|·None)·->·bool: |
| 135 | ········"""Check·if·element·(or·document)·is·from·a·XML·tree.""" | 136 | ········"""Check·if·element·(or·document)·is·from·a·XML·tree.""" |
| 136 | ········return·el·is·not·None·and·bool(el._is_xml) | 137 | ········return·el·is·not·None·and·bool(el._is_xml) |
| 137 | ····def·is_iframe(self,·el:·bs4.Tag·|·None)·->·bool: | 138 | ····def·is_iframe(self,·el:·bs4.Tag·|·None)·->·bool: |
| 138 | ········"""Check·if·element·is·an·`iframe`.""" | 139 | ········"""Check·if·element·is·an·`iframe`.""" |
| Offset 177, 39 lines modified | Offset 176, 60 lines modified | ||
| 177 | ········el:·bs4.Tag·|·None, | 176 | ········el:·bs4.Tag·|·None, |
| 178 | ········start:·int·|·None·=·None, | 177 | ········start:·int·|·None·=·None, |
| 179 | ········reverse:·bool·=·False, | 178 | ········reverse:·bool·=·False, |
| 180 | ········no_iframe:·bool·=·False | 179 | ········no_iframe:·bool·=·False |
| 181 | ····)·->·Iterator[bs4.Tag]: | 180 | ····)·->·Iterator[bs4.Tag]: |
| 182 | ········"""Get·tag·children.""" | 181 | ········"""Get·tag·children.""" |
| 183 | ········return·self.get_children(el,·start,·reverse,·True,·no_iframe) | 182 | ········return·self.get_children(el,·start,·reverse,·True,·no_iframe) |
| 183 | ····@overload | ||
| 184 | ····def·get_children( | 184 | ····def·get_children( |
| 185 | ········self, | 185 | ········self, |
| 186 | ········el:·bs4.Tag·|·None, | 186 | ········el:·bs4.Tag·|·None, |
| 187 | ········start:·int·|·None·=·None, | 187 | ········start:·int·|·None·=·None, |
| 188 | ········reverse:·bool·=·False, | 188 | ········reverse:·bool·=·False, |
| 189 | ········tags:·Literal[True]·=·..., | ||
| 190 | ········no_iframe:·bool·=·False | ||
| 191 | ····)·->·Iterator[bs4.Tag]: | ||
| 192 | ········... | ||
| Max diff block lines reached; 45372/49602 bytes (91.47%) of diff not shown. | |||
| Offset 3, 19 lines modified | Offset 3, 21 lines modified | ||
| 3 | import·re | 3 | import·re |
| 4 | from·functools·import·lru_cache | 4 | from·functools·import·lru_cache |
| 5 | from·.·import·util | 5 | from·.·import·util |
| 6 | from·.·import·css_match·as·cm | 6 | from·.·import·css_match·as·cm |
| 7 | from·.·import·css_types·as·ct | 7 | from·.·import·css_types·as·ct |
| 8 | from·.util·import·SelectorSyntaxError | 8 | from·.util·import·SelectorSyntaxError |
| 9 | import·warnings | 9 | import·warnings |
| 10 | from·typing·import·Match,·Any,·Iterator,·cast | 10 | from·typing·import·Match,·Any,·Callable,·Iterator,·Iterable,·Mapping,·cast |
| 11 | from·dataclasses·import·dataclass | 11 | from·dataclasses·import·dataclass |
| 12 | from·collections·import·UserDict | 12 | from·collections·import·UserDict |
| 13 | import·threading | 13 | import·threading |
| 14 | __all__·=·('SelectorSyntaxError',) | ||
| 14 | RE_LOCK·=·threading.Lock() | 15 | RE_LOCK·=·threading.Lock() |
| 15 | SEL_LOCK·=·threading.RLock() | 16 | SEL_LOCK·=·threading.RLock() |
| 16 | UNICODE_REPLACEMENT_CHAR·=·0xFFFD | 17 | UNICODE_REPLACEMENT_CHAR·=·0xFFFD |
| 17 | SELECTOR_LIMIT·=·8192 | 18 | SELECTOR_LIMIT·=·8192 |
| Offset 105, 91 lines modified | Offset 107, 98 lines modified | ||
| 105 | ····':nth-of-type' | 107 | ····':nth-of-type' |
| 106 | } | 108 | } |
| 107 | PSEUDO_SUPPORTED·=·PSEUDO_SIMPLE·|·PSEUDO_SIMPLE_NO_MATCH·|·PSEUDO_COMPLEX·|·PSEUDO_COMPLEX_NO_MATCH·|·PSEUDO_SPECIAL | 109 | PSEUDO_SUPPORTED·=·PSEUDO_SIMPLE·|·PSEUDO_SIMPLE_NO_MATCH·|·PSEUDO_COMPLEX·|·PSEUDO_COMPLEX_NO_MATCH·|·PSEUDO_SPECIAL |
| 108 | #·Sub-patterns·parts | 110 | #·Sub-patterns·parts |
| 109 | #·Whitespace | 111 | #·Whitespace |
| 110 | NEWLINE·=·r'(? | 112 | NEWLINE·=·r'(?>\r\n|[\n\f\r])' |
| 111 | WS·=·fr'(?:[·\t]|{NEWLINE})' | 113 | WS·=·fr'(?:[·\t]|{NEWLINE})' |
| 112 | #·Comments | 114 | #·Comments |
| 113 | COMMENTS·=·r'(?:/\*(?:[^*]|\*(?!/))*\*/)' | 115 | COMMENTS·=·r'(?:/\*(?:[^*]|\*(?!/))*+\*/)' |
| 114 | #·Whitespace·with·comments·included | 116 | #·Whitespace·with·comments·included |
| 115 | WSC·=·fr'(?:{WS}|{COMMENTS})' | 117 | WSC·=·fr'(?:{WS}|{COMMENTS})' |
| 116 | #·CSS·escapes | 118 | #·CSS·escapes |
| 117 | CSS_ESCAPES·=·fr'(?:\\(?:[a-f0-9]{{1,6}}{WS}?|[^\r\n\f]|$))' | 119 | CSS_ESCAPES·=·fr'(?:\\(?:[a-f0-9]{{1,6}}+{WS}?+|[^\r\n\f]|$))' |
| 118 | CSS_STRING_ESCAPES·=·fr'(?:\\(?:[a-f0-9]{{1,6}}{WS}?| | 120 | CSS_STRING_ESCAPES·=·fr'(?:\\(?:[a-f0-9]{{1,6}}+{WS}?+|{NEWLINE}|[^\r\n\f]|$))' |
| 119 | #·CSS·Identifier | 121 | #·CSS·Identifier |
| 120 | IDENTIFIER·=·fr''' | 122 | IDENTIFIER·=·fr''' |
| 121 | (?:(?:--|-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})) | 123 | (?:(?:--|-?+(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})) |
| 122 | (?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*) | 124 | (?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*+) |
| 123 | ''' | 125 | ''' |
| 124 | #·`nth`·content | 126 | #·`nth`·content |
| 125 | NTH·=·fr' | 127 | NTH·=·fr'[-+]?+(?:[0-9]++n?+|n)(?:(?<=n){WSC}*+[-+]{WSC}*+[0-9]++)?+' |
| 126 | #·Value:·quoted·string·or·identifier | 128 | #·Value:·quoted·string·or·identifier |
| 127 | VALUE·=·fr''' | 129 | VALUE·=·fr''' |
| 130 | (?:"(?:\\(?:{NEWLINE}|[^\r\n\f])|[^\\"\r\n\f])*+"| | ||
| 131 | '(?:\\(?:{NEWLINE}|[^\r\n\f])|[^\\'\r\n\f])*+'| | ||
| 132 | {IDENTIFIER}) | ||
| 133 | ''' | ||
| 128 | #·Attribute·value·comparison.·`!=`·is·handled·special·as·it·is·non-standard. | 134 | #·Attribute·value·comparison.·`!=`·is·handled·special·as·it·is·non-standard. |
| 129 | ATTR·=·fr'(?:{WSC}*(?P<cmp>[!~^|*$]?=){WSC}*(?P<value>{VALUE})(?:{WSC}*(?P<case>[is]))?)? | 135 | ATTR·=·fr'(?:{WSC}*+(?P<cmp>[!~^|*$]?+=){WSC}*+(?P<value>{VALUE})(?:{WSC}*+(?P<case>[is]))?+)?+' |
| 130 | #·Selector·patterns | 136 | #·Selector·patterns |
| 131 | #·IDs·(`#id`) | 137 | #·IDs·(`#id`) |
| 132 | PAT_ID·=·fr'\#{IDENTIFIER}' | 138 | PAT_ID·=·fr'\#{IDENTIFIER}' |
| 133 | #·Classes·(`.class`) | 139 | #·Classes·(`.class`) |
| 134 | PAT_CLASS·=·fr'\.{IDENTIFIER}' | 140 | PAT_CLASS·=·fr'\.{IDENTIFIER}' |
| 135 | #·Prefix:Tag·(`prefix|tag`) | 141 | #·Prefix:Tag·(`prefix|tag`) |
| 136 | PAT_TAG·=·fr'(?P<tag_ns>(?:{IDENTIFIER}|\*)?\|)?(?P<tag_name>{IDENTIFIER}|\*)' | 142 | PAT_TAG·=·fr'(?P<tag_ns>(?:{IDENTIFIER}|\*)?+\|)?+(?P<tag_name>{IDENTIFIER}|\*)' |
| 137 | #·Attributes·(`[attr]`,·`[attr=value]`,·etc.) | 143 | #·Attributes·(`[attr]`,·`[attr=value]`,·etc.) |
| 138 | PAT_ATTR·=·fr'\[{WSC}*(?P<attr_ns>(?:{IDENTIFIER}|\*)?\|)?(?P<attr_name>{IDENTIFIER}){ATTR}\]' | 144 | PAT_ATTR·=·fr'\[{WSC}*+(?P<attr_ns>(?:{IDENTIFIER}|\*)?+\|(?!=))?+(?P<attr_name>{IDENTIFIER}){ATTR}{WSC}*+\]' |
| 139 | #·Pseudo·class·(`:pseudo-class`,·`:pseudo-class(`) | 145 | #·Pseudo·class·(`:pseudo-class`,·`:pseudo-class(`) |
| 140 | PAT_PSEUDO_CLASS·=·fr'(?P<name>:{IDENTIFIER})(?P<open>\({WSC}*)?' | 146 | PAT_PSEUDO_CLASS·=·fr'(?P<name>:{IDENTIFIER})(?P<open>\({WSC}*+)?+' |
| 141 | #·Pseudo·class·special·patterns.·Matches·`:pseudo-class(`·for·special·case·pseudo·classes. | 147 | #·Pseudo·class·special·patterns.·Matches·`:pseudo-class(`·for·special·case·pseudo·classes. |
| 142 | PAT_PSEUDO_CLASS_SPECIAL·=·fr'(?P<name>:{IDENTIFIER})(?P<open>\({WSC}*)' | 148 | PAT_PSEUDO_CLASS_SPECIAL·=·fr'(?P<name>:{IDENTIFIER})(?P<open>\({WSC}*+)' |
| 143 | #·Custom·pseudo·class·(`:--custom-pseudo`) | 149 | #·Custom·pseudo·class·(`:--custom-pseudo`) |
| 144 | PAT_PSEUDO_CLASS_CUSTOM·=·fr'(?P<name>:(?=--){IDENTIFIER})' | 150 | PAT_PSEUDO_CLASS_CUSTOM·=·fr'(?P<name>:(?=--){IDENTIFIER})' |
| 145 | #·Nesting·ampersand·selector.·Matches·`&` | 151 | #·Nesting·ampersand·selector.·Matches·`&` |
| 146 | PAT_AMP·=·r'&' | 152 | PAT_AMP·=·r'&' |
| 147 | #·Closing·pseudo·group·(`)`) | 153 | #·Closing·pseudo·group·(`)`) |
| 148 | PAT_PSEUDO_CLOSE·=·fr'{WSC}*\)' | 154 | PAT_PSEUDO_CLOSE·=·fr'{WSC}*+\)' |
| 149 | #·Pseudo·element·(`::pseudo-element`) | 155 | #·Pseudo·element·(`::pseudo-element`) |
| 150 | PAT_PSEUDO_ELEMENT·=·fr':{PAT_PSEUDO_CLASS}' | 156 | PAT_PSEUDO_ELEMENT·=·fr':{PAT_PSEUDO_CLASS}' |
| 151 | #·At·rule·(`@page`,·etc.)·(not·supported) | 157 | #·At·rule·(`@page`,·etc.)·(not·supported) |
| 152 | PAT_AT_RULE·=·fr'@P{IDENTIFIER}' | 158 | PAT_AT_RULE·=·fr'@P{IDENTIFIER}' |
| 153 | #·Pseudo·class·`nth-child`·(`:nth-child(an+b·[of·S]?)`,·`:first-child`,·etc.) | 159 | #·Pseudo·class·`nth-child`·(`:nth-child(an+b·[of·S]?)`,·`:first-child`,·etc.) |
| 154 | PAT_PSEUDO_NTH_CHILD·=·fr''' | 160 | PAT_PSEUDO_NTH_CHILD·=·fr''' |
| 155 | (?P<pseudo_nth_child>{PAT_PSEUDO_CLASS_SPECIAL} | 161 | (?P<pseudo_nth_child>{PAT_PSEUDO_CLASS_SPECIAL} |
| 156 | (?P<nth_child>{NTH}|even|odd))(?:{WSC}*\)|(?P<of>{COMMENTS}*{WS}{WSC}*of{COMMENTS}*{WS}{WSC}*)) | 162 | (?P<nth_child>{NTH}|even|odd))(?:{WSC}*+\)|(?P<of>{COMMENTS}*+{WS}{WSC}*+of{COMMENTS}*+{WS}{WSC}*+)) |
| 157 | ''' | 163 | ''' |
| 158 | #·Pseudo·class·`nth-of-type`·(`:nth-of-type(an+b)`,·`:first-of-type`,·etc.) | 164 | #·Pseudo·class·`nth-of-type`·(`:nth-of-type(an+b)`,·`:first-of-type`,·etc.) |
| 159 | PAT_PSEUDO_NTH_TYPE·=·fr''' | 165 | PAT_PSEUDO_NTH_TYPE·=·fr''' |
| 160 | (?P<pseudo_nth_type>{PAT_PSEUDO_CLASS_SPECIAL} | 166 | (?P<pseudo_nth_type>{PAT_PSEUDO_CLASS_SPECIAL} |
| 161 | (?P<nth_type>{NTH}|even|odd)){WSC}*\) | 167 | (?P<nth_type>{NTH}|even|odd)){WSC}*+\) |
| 162 | ''' | 168 | ''' |
| 163 | #·Pseudo·class·language·(`:lang("*-de",·en)`) | 169 | #·Pseudo·class·language·(`:lang("*-de",·en)`) |
| 164 | PAT_PSEUDO_LANG·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*,{WSC}*{VALUE})*){WSC}*\)' | 170 | PAT_PSEUDO_LANG·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*+,{WSC}*+{VALUE})*+){WSC}*+\)' |
| 165 | #·Pseudo·class·direction·(`:dir(ltr)`) | 171 | #·Pseudo·class·direction·(`:dir(ltr)`) |
| 166 | PAT_PSEUDO_DIR·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<dir>ltr|rtl){WSC}*\)' | 172 | PAT_PSEUDO_DIR·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<dir>ltr|rtl){WSC}*+\)' |
| 167 | #·Combining·characters·(`>`,·`~`,·`·`,·`+`,·`,`) | 173 | #·Combining·characters·(`>`,·`~`,·`·`,·`+`,·`,`) |
| 168 | PAT_COMBINE·=·fr'{ | 174 | PAT_COMBINE·=·fr'{COMMENTS}*+(?={WS}|[,+>~]){WSC}*+(?P<relation>[,+>~])?+{WSC}*+' |
| 169 | #·Extra:·Contains·(`:contains(text)`) | 175 | #·Extra:·Contains·(`:contains(text)`) |
| 170 | PAT_PSEUDO_CONTAINS·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*,{WSC}*{VALUE})*){WSC}*\)' | 176 | PAT_PSEUDO_CONTAINS·=·fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*+,{WSC}*+{VALUE})*+){WSC}*+\)' |
| 171 | #·Regular·expressions | 177 | #·Regular·expressions |
| 172 | #·CSS·escape·pattern | 178 | #·CSS·escape·pattern |
| 173 | RE_CSS_ESC·=·re.compile(fr'(?:(\\[a-f0-9]{{1,6}}{WSC}?)|(\\[^\r\n\f])|(\\$))',·re.I) | 179 | RE_CSS_ESC·=·re.compile(fr'(?:(\\[a-f0-9]{{1,6}}+{WSC}?+)|(\\[^\r\n\f])|(\\$))',·re.I) |
| 174 | RE_CSS_STR_ESC·=·re.compile(fr'(?:(\\[a-f0-9]{{1,6}}{WS}?)|(\\[^\r\n\f])|(\\$)|(\\{NEWLINE}))',·re.I) | 180 | RE_CSS_STR_ESC·=·re.compile(fr'(?:(\\[a-f0-9]{{1,6}}+{WS}?+)|(\\[^\r\n\f])|(\\$)|(\\{NEWLINE}))',·re.I) |
| 175 | #·Pattern·to·break·up·`nth`·specifiers | 181 | #·Pattern·to·break·up·`nth`·specifiers |
| 176 | RE_NTH·=·re.compile(fr'(?P<s1>[-+])?(?P<a>[0-9]+n?|n)(?:(?<=n){WSC}*(?P<s2>[-+]){WSC}*(?P<b>[0-9]+))?',·re.I) | 182 | RE_NTH·=·re.compile(fr'(?P<s1>[-+])?+(?P<a>[0-9]++n?+|n)(?:(?<=n){WSC}*+(?P<s2>[-+]){WSC}*+(?P<b>[0-9]++))?+',·re.I) |
| 177 | #·Pattern·to·iterate·multiple·values. | 183 | #·Pattern·to·iterate·multiple·values. |
| 178 | RE_VALUES·=·re.compile(fr'(?:(?P<value>{VALUE})|(?P<split>{WSC}*,{WSC}*))',·re.X) | 184 | RE_VALUES·=·re.compile(fr'(?:(?P<value>{VALUE})|(?P<split>{WSC}*+,{WSC}*+))',·re.X) |
| 179 | #·Whitespace·checks | 185 | #·Whitespace·checks |
| 180 | RE_WS·=·re.compile(WS) | 186 | RE_WS·=·re.compile(WS) |
| 181 | RE_WS_BEGIN·=·re.compile(fr'^{WSC}*') | 187 | RE_WS_BEGIN·=·re.compile(fr'^{WSC}*+') |
| 182 | RE_WS_END·=·re.compile(fr'^(?:[·\t]|(? | 188 | RE_WS_END·=·re.compile(fr'^(?:[·\t]|(?>\n\r|[\n\f\r])|{COMMENTS})*+') |
| 183 | RE_CUSTOM·=·re.compile(fr'^{PAT_PSEUDO_CLASS_CUSTOM}$',·re.X) | 189 | RE_CUSTOM·=·re.compile(fr'^{PAT_PSEUDO_CLASS_CUSTOM}$',·re.X) |
| 184 | RE_PSEUDO_CLASS_SPECIAL·=·re.compile(PAT_PSEUDO_CLASS_SPECIAL,·re.I·|·re.X·|·re.U) | 190 | RE_PSEUDO_CLASS_SPECIAL·=·re.compile(PAT_PSEUDO_CLASS_SPECIAL,·re.I·|·re.X·|·re.U) |
| 191 | RE_PSEUDO_IGNORE·=·re.compile(PAT_PSEUDO_CLASS,·re.X·|·re.I·|·re.U) | ||
| 192 | QUOTED·=·("'",·'"') | ||
| 185 | #·Constants | 193 | #·Constants |
| 186 | #·List·split·token | 194 | #·List·split·token |
| 187 | COMMA_COMBINATOR·=·',' | 195 | COMMA_COMBINATOR·=·',' |
| 188 | #·Relation·token·for·descendant | 196 | #·Relation·token·for·descendant |
| 189 | WS_COMBINATOR·=·"·" | 197 | WS_COMBINATOR·=·"·" |
| Offset 211, 78 lines modified | Offset 220, 75 lines modified | ||
| 211 | @lru_cache(maxsize=_MAXCACHE) | 220 | @lru_cache(maxsize=_MAXCACHE) |
| 212 | def·_cached_css_compile( | 221 | def·_cached_css_compile( |
| 213 | ····pattern:·str, | 222 | ····pattern:·str, |
| 214 | ····namespaces:·ct.Namespaces·|·None, | 223 | ····namespaces:·ct.Namespaces·|·None, |
| Max diff block lines reached; 44370/51410 bytes (86.31%) of diff not shown. | |||
| Offset 1, 40 lines modified | Offset 1, 58 lines modified | ||
| 1 | """CSS·selector·structure·items.""" | 1 | """CSS·selector·structure·items.""" |
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | from·enum·import·Enum | ||
| 3 | import·copyreg | 4 | import·copyreg |
| 4 | from·.pretty·import·pretty | 5 | from·.pretty·import·pretty |
| 5 | from·typing·import·Any,·Iterator,· | 6 | from·typing·import·Any,·Iterator,·Pattern,·Iterable,·Mapping,·TypeVar,·overload |
| 6 | __all__·=·( | 7 | __all__·=·( |
| 7 | ····'Selector', | 8 | ····'Selector', |
| 8 | ····'SelectorNull', | 9 | ····'SelectorNull', |
| 9 | ····'SelectorTag', | 10 | ····'SelectorTag', |
| 10 | ····'SelectorAttribute', | 11 | ····'SelectorAttribute', |
| 11 | ····'SelectorContains', | 12 | ····'SelectorContains', |
| 12 | ····'SelectorNth', | 13 | ····'SelectorNth', |
| 13 | ····'SelectorLang', | 14 | ····'SelectorLang', |
| 14 | ····'SelectorList', | 15 | ····'SelectorList', |
| 15 | ····'Namespaces', | 16 | ····'Namespaces', |
| 16 | ····'CustomSelectors' | 17 | ····'CustomSelectors' |
| 17 | ) | 18 | ) |
| 18 | SEL_EMPTY·=·0x1 | 19 | SEL_EMPTY·=·0x1 |
| 19 | SEL_ROOT·=·0x2 | 20 | SEL_ROOT·=·0x2 |
| 20 | SEL_DEFAULT·=·0x4 | 21 | SEL_DEFAULT·=·0x4 |
| 21 | SEL_INDETERMINATE·=·0x8 | 22 | SEL_INDETERMINATE·=·0x8 |
| 22 | SEL_SCOPE·=·0x10 | 23 | SEL_SCOPE·=·0x10 |
| 23 | SEL_DIR_LTR·=·0x20 | 24 | SEL_DIR_LTR·=·0x20 |
| 24 | SEL_DIR_RTL·=·0x40 | 25 | SEL_DIR_RTL·=·0x40 |
| 25 | SEL_IN_RANGE·=·0x80 | 26 | SEL_IN_RANGE·=·0x80 |
| 26 | SEL_OUT_OF_RANGE·=·0x100 | 27 | SEL_OUT_OF_RANGE·=·0x100 |
| 27 | SEL_DEFINED·=·0x200 | 28 | SEL_DEFINED·=·0x200 |
| 28 | SEL_PLACEHOLDER_SHOWN·=·0x400 | 29 | SEL_PLACEHOLDER_SHOWN·=·0x400 |
| 30 | def·_repr_expand(value:·Any)·->·bool:··#·pragma:·no·cover | ||
| 31 | ····"""Check·if·the·value·is·an·immutable·object·that·uses·the·default·representation.""" | ||
| 32 | ····return·isinstance(value,·Immutable)·and·type(value).__repr__·is·Immutable.__repr__ | ||
| 33 | def·_repr_value(value:·Any)·->·Any:··#·pragma:·no·cover | ||
| 34 | ····""" | ||
| 35 | ····Return·the·representation·of·a·leaf·value,·or·the·value·itself·if·it·must·be·expanded. | ||
| 36 | ····Immutable·objects·using·the·default·representation·are·expanded,·as·are·tuples·containing·them. | ||
| 37 | ····""" | ||
| 38 | ····if·_repr_expand(value)·or·(value.__class__·is·tuple·and·any(_repr_expand(v)·for·v·in·value)): | ||
| 39 | ········return·value | ||
| 40 | ····return·repr(value) | ||
| 29 | class·Immutable: | 41 | class·Immutable: |
| 30 | ····"""Immutable.""" | 42 | ····"""Immutable.""" |
| 31 | ····__slots__:·tuple[str,·...]·=·('_hash',) | 43 | ····__slots__:·tuple[str,·...]·=·('_hash',) |
| 32 | ····_hash:·int | 44 | ····_hash:·int |
| Offset 51, 139 lines modified | Offset 69, 100 lines modified | ||
| 51 | ····@classmethod | 69 | ····@classmethod |
| 52 | ····def·__base__(cls)·->·type[Immutable]: | 70 | ····def·__base__(cls)·->·type[Immutable]: |
| 53 | ········"""Get·base·class.""" | 71 | ········"""Get·base·class.""" |
| 54 | ········return·cls | 72 | ········return·cls |
| 55 | ····def·__eq__(self,·other:·Any)·->·bool: | 73 | ····def·__eq__(self,·other:·Any)·->·bool: |
| 56 | ········""" | 74 | ········"""Check·equaling·in·a·non-recursive·manner.""" |
| 75 | ········stack:·list[tuple[Immutable,·Any]]·=·[(self,·other)] | ||
| 76 | ········while·stack: | ||
| 77 | ············a,·b·=·stack.pop() | ||
| 78 | ············if·a·is·b: | ||
| 79 | ················continue | ||
| 80 | ············#·The·hash·is·derived·from·the·content,·so·differing·hashes·cannot·be·equal. | ||
| 81 | ············if·not·isinstance(b,·a.__base__())·or·a._hash·!=·b._hash: | ||
| 82 | ················return·False | ||
| 83 | ············#·Compare·the·attributes·in·the·slot | ||
| 84 | ············for·key·in·a.__slots__[:-1]: | ||
| 85 | ················x·=·getattr(a,·key) | ||
| 86 | ················y·=·getattr(b,·key) | ||
| 87 | ················if·isinstance(x,·Immutable): | ||
| 88 | ····················stack.append((x,·y)) | ||
| 89 | ················elif·x.__class__·is·tuple·and·y.__class__·is·tuple: | ||
| 90 | ····················if·len(x)·!=·len(y):··#·pragma:·no·cover | ||
| 91 | ························return·False | ||
| 92 | ····················for·i,·j·in·zip(x,·y,·strict=True): | ||
| 93 | ························if·isinstance(i,·Immutable): | ||
| 94 | ····························stack.append((i,·j)) | ||
| 95 | ························elif·i·!=·j:··#·pragma:·no·cover | ||
| 96 | ····························return·False | ||
| 97 | ················elif·x·!=·y: | ||
| 98 | ····················return·False | ||
| 57 | ········return· | 99 | ········return·True |
| 58 | ············isinstance(other,·self.__base__())·and | ||
| 59 | ············all(getattr(other,·key)·==·getattr(self,·key)·for·key·in·self.__slots__·if·key·!=·'_hash') | ||
| 60 | ········) | ||
| 61 | ····def·__ne__(self,·other:·Any)·->·bool: | 100 | ····def·__ne__(self,·other:·Any)·->·bool: |
| 62 | ········""" | 101 | ········"""Not·equal.""" |
| 102 | ········return·not·self.__eq__(other) | ||
| 63 | ········return·( | ||
| 64 | ············not·isinstance(other,·self.__base__())·or | ||
| 65 | ············any(getattr(other,·key)·!=·getattr(self,·key)·for·key·in·self.__slots__·if·key·!=·'_hash') | ||
| 66 | ········) | ||
| 67 | ····def·__hash__(self)·->·int: | 103 | ····def·__hash__(self)·->·int: |
| 68 | ········"""Hash.""" | 104 | ········"""Hash.""" |
| 69 | ········return·self._hash | 105 | ········return·self._hash |
| 70 | ····def·__setattr__(self,·name:·str,·value:·Any)·->·None: | 106 | ····def·__setattr__(self,·name:·str,·value:·Any)·->·None: |
| 71 | ········"""Prevent·mutability.""" | 107 | ········"""Prevent·mutability.""" |
| 72 | ········raise·AttributeError(f"'{self.__class__.__name__}'·is·immutable") | 108 | ········raise·AttributeError(f"'{self.__class__.__name__}'·is·immutable") |
| 73 | ····def·__repr__(self)·->·str:··#·pragma:·no·cover | 109 | ····def·__repr__(self)·->·str:··#·pragma:·no·cover |
| 74 | ········""" | 110 | ········""" |
| 111 | ········Build·a·representation·without·using·recursion. | ||
| 75 | ········r·=·',·'.join([f"{k}={getattr(self,·k)!r}"·for·k·in·self.__slots__[:-1]]) | ||
| 76 | ········ | 112 | ········Selectors·can·be·nested·very·deeply,·so·build·the·representation·of·nested |
| 113 | ········immutable·objects·with·an·explicit·stack·instead·of·recursing·into·their·`__repr__`. | ||
| 114 | ········Strings·on·the·stack·are·output·as·is,·other·items·are·expanded·into·more·items. | ||
| Max diff block lines reached; 11400/16816 bytes (67.79%) of diff not shown. | |||
| Offset 2, 14 lines modified | Offset 2, 16 lines modified | ||
| 2 | from·__future__·import·annotations | 2 | from·__future__·import·annotations |
| 3 | from·functools·import·wraps,·lru_cache | 3 | from·functools·import·wraps,·lru_cache |
| 4 | import·warnings | 4 | import·warnings |
| 5 | import·re | 5 | import·re |
| 6 | from·typing·import·Callable,·Any | 6 | from·typing·import·Callable,·Any |
| 7 | DEBUG·=·0x00001 | 7 | DEBUG·=·0x00001 |
| 8 | NOCACHE·=·0x00002 | ||
| 9 | NOSTRICT·=·0x00004 | ||
| 8 | RE_PATTERN_LINE_SPLIT·=·re.compile(r'(?:\r\n|(?!\r\n)[\n\r])|$') | 10 | RE_PATTERN_LINE_SPLIT·=·re.compile(r'(?:\r\n|(?!\r\n)[\n\r])|$') |
| 9 | UC_A·=·ord('A') | 11 | UC_A·=·ord('A') |
| 10 | UC_Z·=·ord('Z') | 12 | UC_Z·=·ord('Z') |
| Offset 78, 17 lines modified | Offset 80, 17 lines modified | ||
| 78 | def·get_pattern_context(pattern:·str,·index:·int)·->·tuple[str,·int,·int]: | 80 | def·get_pattern_context(pattern:·str,·index:·int)·->·tuple[str,·int,·int]: |
| 79 | ····"""Get·the·pattern·context.""" | 81 | ····"""Get·the·pattern·context.""" |
| 80 | ····last·=·0 | 82 | ····last·=·0 |
| 81 | ····current_line·=·1 | 83 | ····current_line·=·1 |
| 82 | ····col·=·1 | 84 | ····col·=·1 |
| 83 | ····text | 85 | ····text:·list[str]·=·[] |
| 84 | ····line·=·1 | 86 | ····line·=·1 |
| 85 | ····offset | 87 | ····offset:·int·|·None·=·None |
| 86 | ····#·Split·pattern·by·newline·and·handle·the·text·before·the·newline | 88 | ····#·Split·pattern·by·newline·and·handle·the·text·before·the·newline |
| 87 | ····for·m·in·RE_PATTERN_LINE_SPLIT.finditer(pattern): | 89 | ····for·m·in·RE_PATTERN_LINE_SPLIT.finditer(pattern): |
| 88 | ········linetext·=·pattern[last:m.start(0)] | 90 | ········linetext·=·pattern[last:m.start(0)] |
| 89 | ········if·not·len(m.group(0))·and·not·len(text): | 91 | ········if·not·len(m.group(0))·and·not·len(text): |
| 90 | ············indent·=·'' | 92 | ············indent·=·'' |
| 91 | ············offset·=·-1 | 93 | ············offset·=·-1 |
| Offset 24, 15 lines modified | Offset 24, 19 lines modified | ||
| 24 | try: | 24 | try: |
| 25 | ····__version__·=·version("svglib") | 25 | ····__version__·=·version("svglib") |
| 26 | except·PackageNotFoundError: | 26 | except·PackageNotFoundError: |
| 27 | ····__version__·=·"unknown" | 27 | ····__version__·=·"unknown" |
| 28 | def·svg2pdf( | 28 | def·svg2pdf( |
| 29 | ····path:·str, | ||
| 30 | ····outputPat:·Optional[str]·=·None, | ||
| 31 | ····external_reference_root:·Optional[str]·=·None, | ||
| 32 | )·->·None: | ||
| 29 | ····"""Convert·an·SVG·file·to·PDF·format. | 33 | ····"""Convert·an·SVG·file·to·PDF·format. |
| 30 | ····High-level·function·that·loads·an·SVG·file,·converts·it·to·a·ReportLab·drawing, | 34 | ····High-level·function·that·loads·an·SVG·file,·converts·it·to·a·ReportLab·drawing, |
| 31 | ····and·saves·it·as·a·PDF·file.·Supports·both·.svg·and·.svgz·(compressed·SVG)·files. | 35 | ····and·saves·it·as·a·PDF·file.·Supports·both·.svg·and·.svgz·(compressed·SVG)·files. |
| 32 | ····Args: | 36 | ····Args: |
| 33 | ········path:·Path·to·the·input·SVG·file·(.svg·or·.svgz·extension). | 37 | ········path:·Path·to·the·input·SVG·file·(.svg·or·.svgz·extension). |
| Offset 40, 14 lines modified | Offset 44, 17 lines modified | ||
| 40 | ············-·%(dirname)s:·Directory·of·input·file | 44 | ············-·%(dirname)s:·Directory·of·input·file |
| 41 | ············-·%(basename)s:·Full·filename·with·extension | 45 | ············-·%(basename)s:·Full·filename·with·extension |
| 42 | ············-·%(base)s:·Filename·without·extension | 46 | ············-·%(base)s:·Filename·without·extension |
| 43 | ············-·%(ext)s:·File·extension | 47 | ············-·%(ext)s:·File·extension |
| 44 | ············-·%(now)s:·Current·datetime·object | 48 | ············-·%(now)s:·Current·datetime·object |
| 45 | ············-·%(format)s:·Output·format·(always·"pdf") | 49 | ············-·%(format)s:·Output·format·(always·"pdf") |
| 46 | ············Also·supports·{name}·format·strings. | 50 | ············Also·supports·{name}·format·strings. |
| 51 | ········external_reference_root:·Optional·directory·that·external·<image>/<use> | ||
| 52 | ············references·must·resolve·inside.·None·(the·default)·keeps·the | ||
| 53 | ············library's·behaviour·of·allowing·any·relative·reference. | ||
| 47 | ····Returns: | 54 | ····Returns: |
| 48 | ········None.·The·PDF·file·is·written·to·disk. | 55 | ········None.·The·PDF·file·is·written·to·disk. |
| 49 | ····Raises: | 56 | ····Raises: |
| 50 | ········FileNotFoundError:·If·the·input·SVG·file·does·not·exist. | 57 | ········FileNotFoundError:·If·the·input·SVG·file·does·not·exist. |
| 51 | ········Exception:·If·SVG·parsing·or·PDF·generation·fails. | 58 | ········Exception:·If·SVG·parsing·or·PDF·generation·fails. |
| Offset 85, 15 lines modified | Offset 92, 15 lines modified | ||
| 85 | ····#·allow·classic·%%(name)s·notation | 92 | ····#·allow·classic·%%(name)s·notation |
| 86 | ····out_path·=·out_pattern·%·file_info | 93 | ····out_path·=·out_pattern·%·file_info |
| 87 | ····#·allow·also·newer·{name}·notation | 94 | ····#·allow·also·newer·{name}·notation |
| 88 | ····out_path·=·out_path.format(**file_info) | 95 | ····out_path·=·out_path.format(**file_info) |
| 89 | ····#·generate·a·drawing·from·the·SVG·file | 96 | ····#·generate·a·drawing·from·the·SVG·file |
| 90 | ····try: | 97 | ····try: |
| 91 | ········drawing·=·svglib.svg2rlg(path) | 98 | ········drawing·=·svglib.svg2rlg(path,·external_reference_root=external_reference_root) |
| 92 | ····except: | 99 | ····except: |
| 93 | ········print("Rendering·failed.") | 100 | ········print("Rendering·failed.") |
| 94 | ········raise | 101 | ········raise |
| 95 | ····#·save·converted·file | 102 | ····#·save·converted·file |
| 96 | ····if·drawing: | 103 | ····if·drawing: |
| 97 | ········renderPDF.drawToFile(drawing,·out_path,·showBoundary=0) | 104 | ········renderPDF.drawToFile(drawing,·out_path,·showBoundary=0) |
| Offset 155, 14 lines modified | Offset 162, 24 lines modified | ||
| 155 | ········"--output", | 162 | ········"--output", |
| 156 | ········metavar="PATH_PAT", | 163 | ········metavar="PATH_PAT", |
| 157 | ········help="Set·output·path·(incl.·the·placeholders:·dirname,·basename," | 164 | ········help="Set·output·path·(incl.·the·placeholders:·dirname,·basename," |
| 158 | ········"base,·ext,·now)·in·both,·%%(name)s·and·{name}·notations.", | 165 | ········"base,·ext,·now)·in·both,·%%(name)s·and·{name}·notations.", |
| 159 | ····) | 166 | ····) |
| 160 | ····p.add_argument( | 167 | ····p.add_argument( |
| 168 | ········"-R", | ||
| 169 | ········"--external-root", | ||
| 170 | ········metavar="DIR", | ||
| 171 | ········help="Directory·that·external·image/use·references·must·stay·inside.·" | ||
| 172 | ········"Defaults·to·the·input·file's·own·directory,·so·a·converted·SVG·" | ||
| 173 | ········"cannot·read·files·elsewhere·on·disk.·Pass·a·parent·directory·to·" | ||
| 174 | ········"allow·shared·assets,·or·/·to·allow·any·relative·reference.", | ||
| 175 | ····) | ||
| 176 | ····p.add_argument( | ||
| 161 | ········"input", | 177 | ········"input", |
| 162 | ········metavar="PATH", | 178 | ········metavar="PATH", |
| 163 | ········nargs="*", | 179 | ········nargs="*", |
| 164 | ········help="Input·SVG·file·path·with·extension·.svg·or·.svgz.", | 180 | ········help="Input·SVG·file·path·with·extension·.svg·or·.svgz.", |
| 165 | ····) | 181 | ····) |
| 166 | ····args·=·p.parse_args() | 182 | ····args·=·p.parse_args() |
| Offset 173, 8 lines modified | Offset 190, 12 lines modified | ||
| 173 | ····if·not·args.input: | 190 | ····if·not·args.input: |
| 174 | ········p.print_usage() | 191 | ········p.print_usage() |
| 175 | ········sys.exit() | 192 | ········sys.exit() |
| 176 | ····paths·=·[a·for·a·in·args.input·if·exists(a)] | 193 | ····paths·=·[a·for·a·in·args.input·if·exists(a)] |
| 177 | ····for·path·in·paths: | 194 | ····for·path·in·paths: |
| 178 | ········ | 195 | ········#·Command-line·input·is·routinely·untrusted·(a·downloaded·or·uploaded |
| 196 | ········#·file),·so·confine·external·references·to·the·document's·own·directory | ||
| 197 | ········#·unless·the·caller·widens·the·root·explicitly. | ||
| 198 | ········root·=·args.external_root·or·dirname(path)·or·"." | ||
| 199 | ········svg2pdf(path,·outputPat=args.output,·external_reference_root=root) | ||
| Offset 11, 15 lines modified | Offset 11, 15 lines modified | ||
| 11 | -·Automatic·font·file·detection·and·registration | 11 | -·Automatic·font·file·detection·and·registration |
| 12 | """ | 12 | """ |
| 13 | import·os | 13 | import·os |
| 14 | import·shutil | 14 | import·shutil |
| 15 | import·subprocess | 15 | import·subprocess |
| 16 | import·sys | 16 | import·sys |
| 17 | from·typing·import· | 17 | from·typing·import·Optional,·Union |
| 18 | from·reportlab.pdfbase.pdfmetrics·import·registerFont | 18 | from·reportlab.pdfbase.pdfmetrics·import·registerFont |
| 19 | from·reportlab.pdfbase.ttfonts·import·TTFError,·TTFont | 19 | from·reportlab.pdfbase.ttfonts·import·TTFError,·TTFont |
| 20 | STANDARD_FONT_NAMES·=·( | 20 | STANDARD_FONT_NAMES·=·( |
| 21 | ····"Times-Roman", | 21 | ····"Times-Roman", |
| 22 | ····"Times-Italic", | 22 | ····"Times-Italic", |
| Offset 67, 16 lines modified | Offset 67, 16 lines modified | ||
| 67 | ················'rlgFont':·'reportlab_font_name', | 67 | ················'rlgFont':·'reportlab_font_name', |
| 68 | ················'exact':·True/False | 68 | ················'exact':·True/False |
| 69 | ············} | 69 | ············} |
| 70 | ········Internal·names·are·normalized·for·efficient·lookup·and·follow·the·pattern: | 70 | ········Internal·names·are·normalized·for·efficient·lookup·and·follow·the·pattern: |
| 71 | ········'Family-WeightStyle'·(e.g.,·'Arial-BoldItalic'). | 71 | ········'Family-WeightStyle'·(e.g.,·'Arial-BoldItalic'). |
| 72 | ········""" | 72 | ········""" |
| 73 | ········self._map:· | 73 | ········self._map:·dict[str,·dict[str,·Union[str,·bool,·int]]]·=·{} |
| 74 | ········self._family_index:· | 74 | ········self._family_index:·dict[str,·str]·=·{}··#·lowercase·family·→·canonical·family |
| 75 | ········self.register_default_fonts() | 75 | ········self.register_default_fonts() |
| 76 | ····@staticmethod | 76 | ····@staticmethod |
| 77 | ····def·build_internal_name( | 77 | ····def·build_internal_name( |
| 78 | ········family:·str,·weight:·str·=·"normal",·style:·str·=·"normal" | 78 | ········family:·str,·weight:·str·=·"normal",·style:·str·=·"normal" |
| 79 | ····)·->·str: | 79 | ····)·->·str: |
| Offset 150, 15 lines modified | Offset 150, 15 lines modified | ||
| 150 | ········elif·not·is_bold·and·is_italic: | 150 | ········elif·not·is_bold·and·is_italic: |
| 151 | ············prefix·=·"i" | 151 | ············prefix·=·"i" |
| 152 | ········filename·=·f"{basename}{prefix}.{extension}" | 152 | ········filename·=·f"{basename}{prefix}.{extension}" |
| 153 | ········return·filename | 153 | ········return·filename |
| 154 | ····def·use_fontconfig( | 154 | ····def·use_fontconfig( |
| 155 | ········self,·font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" | 155 | ········self,·font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" |
| 156 | ····)·->· | 156 | ····)·->·tuple[Optional[str],·bool]: |
| 157 | ········"""Find·and·register·a·font·using·system·fontconfig. | 157 | ········"""Find·and·register·a·font·using·system·fontconfig. |
| 158 | ········Uses·the·system's·fontconfig·utility·to·locate·and·register·fonts·that | 158 | ········Uses·the·system's·fontconfig·utility·to·locate·and·register·fonts·that |
| 159 | ········match·the·given·specifications.·This·provides·access·to·system-installed | 159 | ········match·the·given·specifications.·This·provides·access·to·system-installed |
| 160 | ········fonts·that·aren't·part·of·the·standard·PDF·font·set. | 160 | ········fonts·that·aren't·part·of·the·standard·PDF·font·set. |
| 161 | ········Args: | 161 | ········Args: |
| Offset 348, 15 lines modified | Offset 348, 15 lines modified | ||
| 348 | ····def·register_font( | 348 | ····def·register_font( |
| 349 | ········self, | 349 | ········self, |
| 350 | ········font_family:·str, | 350 | ········font_family:·str, |
| 351 | ········font_path:·Optional[str]·=·None, | 351 | ········font_path:·Optional[str]·=·None, |
| 352 | ········weight:·str·=·"normal", | 352 | ········weight:·str·=·"normal", |
| 353 | ········style:·str·=·"normal", | 353 | ········style:·str·=·"normal", |
| 354 | ········rlgFontName:·Optional[str]·=·None, | 354 | ········rlgFontName:·Optional[str]·=·None, |
| 355 | ····)·->· | 355 | ····)·->·tuple[Optional[str],·bool]: |
| 356 | ········"""Register·a·font·or·create·a·mapping·to·a·ReportLab·font·name. | 356 | ········"""Register·a·font·or·create·a·mapping·to·a·ReportLab·font·name. |
| 357 | ········This·method·handles·two·scenarios: | 357 | ········This·method·handles·two·scenarios: |
| 358 | ········1.·Registering·a·custom·TrueType·font·file·with·ReportLab | 358 | ········1.·Registering·a·custom·TrueType·font·file·with·ReportLab |
| 359 | ········2.·Creating·a·mapping·from·SVG·font·specifications·to·existing·ReportLab·fonts | 359 | ········2.·Creating·a·mapping·from·SVG·font·specifications·to·existing·ReportLab·fonts |
| 360 | ········For·standard·PDF·fonts,·only·the·mapping·is·created.·For·custom·fonts, | 360 | ········For·standard·PDF·fonts,·only·the·mapping·is·created.·For·custom·fonts, |
| Offset 422, 15 lines modified | Offset 422, 15 lines modified | ||
| 422 | ················return·NOT_FOUND | 422 | ················return·NOT_FOUND |
| 423 | ········#·If·we·reach·here,·no·registration·was·possible | 423 | ········#·If·we·reach·here,·no·registration·was·possible |
| 424 | ········return·NOT_FOUND | 424 | ········return·NOT_FOUND |
| 425 | ····def·find_font( | 425 | ····def·find_font( |
| 426 | ········self,·font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" | 426 | ········self,·font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" |
| 427 | ····)·->· | 427 | ····)·->·tuple[str,·bool]: |
| 428 | ········"""Find·the·best·matching·ReportLab·font·for·given·specifications. | 428 | ········"""Find·the·best·matching·ReportLab·font·for·given·specifications. |
| 429 | ········Searches·through·the·font·registry·to·find·the·most·appropriate·font·match. | 429 | ········Searches·through·the·font·registry·to·find·the·most·appropriate·font·match. |
| 430 | ········Uses·a·multi-step·fallback·strategy:·exact·match,·standard·fonts,·file-based | 430 | ········Uses·a·multi-step·fallback·strategy:·exact·match,·standard·fonts,·file-based |
| 431 | ········registration,·fontconfig·discovery,·and·finally·default·fallback. | 431 | ········registration,·fontconfig·discovery,·and·finally·default·fallback. |
| 432 | ········Args: | 432 | ········Args: |
| Offset 476, 15 lines modified | Offset 476, 15 lines modified | ||
| 476 | def·register_font( | 476 | def·register_font( |
| 477 | ····font_name:·str, | 477 | ····font_name:·str, |
| 478 | ····font_path:·Optional[str]·=·None, | 478 | ····font_path:·Optional[str]·=·None, |
| 479 | ····weight:·str·=·"normal", | 479 | ····weight:·str·=·"normal", |
| 480 | ····style:·str·=·"normal", | 480 | ····style:·str·=·"normal", |
| 481 | ····rlgFontName:·Optional[str]·=·None, | 481 | ····rlgFontName:·Optional[str]·=·None, |
| 482 | )·->· | 482 | )·->·tuple[Optional[str],·bool]: |
| 483 | ····"""Register·a·font·with·the·global·font·map. | 483 | ····"""Register·a·font·with·the·global·font·map. |
| 484 | ····Convenience·function·that·delegates·to·the·global·FontMap·instance. | 484 | ····Convenience·function·that·delegates·to·the·global·FontMap·instance. |
| 485 | ····Registers·a·custom·font·or·creates·a·mapping·to·an·existing·ReportLab·font. | 485 | ····Registers·a·custom·font·or·creates·a·mapping·to·an·existing·ReportLab·font. |
| 486 | ····Args: | 486 | ····Args: |
| 487 | ········font_name:·SVG·font·family·name·(e.g.,·"Arial",·"Times·New·Roman"). | 487 | ········font_name:·SVG·font·family·name·(e.g.,·"Arial",·"Times·New·Roman"). |
| Offset 501, 15 lines modified | Offset 501, 15 lines modified | ||
| 501 | ········FontMap.register_font:·The·underlying·implementation·method. | 501 | ········FontMap.register_font:·The·underlying·implementation·method. |
| 502 | ····""" | 502 | ····""" |
| 503 | ····return·_font_map.register_font(font_name,·font_path,·weight,·style,·rlgFontName) | 503 | ····return·_font_map.register_font(font_name,·font_path,·weight,·style,·rlgFontName) |
| 504 | def·find_font( | 504 | def·find_font( |
| 505 | ····font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" | 505 | ····font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" |
| 506 | )·->· | 506 | )·->·tuple[str,·bool]: |
| 507 | ····"""Find·the·best·matching·font·from·the·global·font·registry. | 507 | ····"""Find·the·best·matching·font·from·the·global·font·registry. |
| 508 | ····Convenience·function·that·delegates·to·the·global·FontMap·instance. | 508 | ····Convenience·function·that·delegates·to·the·global·FontMap·instance. |
| 509 | ····Searches·for·fonts·using·a·multi-step·fallback·strategy. | 509 | ····Searches·for·fonts·using·a·multi-step·fallback·strategy. |
| 510 | ····Args: | 510 | ····Args: |
| 511 | ········font_name:·SVG·font·family·name·to·search·for. | 511 | ········font_name:·SVG·font·family·name·to·search·for. |
| Offset 29, 20 lines modified | Offset 29, 16 lines modified | ||
| 29 | import·shlex | 29 | import·shlex |
| 30 | import·shutil | 30 | import·shutil |
| 31 | from·collections·import·defaultdict,·namedtuple | 31 | from·collections·import·defaultdict,·namedtuple |
| 32 | from·io·import·BytesIO | 32 | from·io·import·BytesIO |
| 33 | from·typing·import·( | 33 | from·typing·import·( |
| 34 | ····Any, | 34 | ····Any, |
| 35 | ····BinaryIO, | 35 | ····BinaryIO, |
| 36 | ····Dict, | ||
| 37 | ····List, | ||
| 38 | ····Optional, | 36 | ····Optional, |
| 39 | ····Set, | ||
| 40 | ····TextIO, | 37 | ····TextIO, |
| 41 | ····Tuple, | ||
| 42 | ····TypedDict, | 38 | ····TypedDict, |
| 43 | ····Union, | 39 | ····Union, |
| 44 | ····cast, | 40 | ····cast, |
| 45 | ) | 41 | ) |
| 46 | from·PIL·import·Image·as·PILImage | 42 | from·PIL·import·Image·as·PILImage |
| 47 | from·reportlab.graphics.renderSVG·import·SVGCanvas | 43 | from·reportlab.graphics.renderSVG·import·SVGCanvas |
| Offset 107, 24 lines modified | Offset 103, 24 lines modified | ||
| 107 | #·An·SVG·source·accepted·by·the·public·API:·a·path,·a·path-like·object,·or·an | 103 | #·An·SVG·source·accepted·by·the·public·API:·a·path,·a·path-like·object,·or·an |
| 108 | #·already-open·binary/text·file·object. | 104 | #·already-open·binary/text·file·object. |
| 109 | SVGSource·=·Union[str,·os.PathLike[str],·BinaryIO,·TextIO] | 105 | SVGSource·=·Union[str,·os.PathLike[str],·BinaryIO,·TextIO] |
| 110 | #·A·single·gradient·stop:·(offset,·ReportLab·color).·The·color·is·untyped | 106 | #·A·single·gradient·stop:·(offset,·ReportLab·color).·The·color·is·untyped |
| 111 | #·because·ReportLab·ships·no·stubs. | 107 | #·because·ReportLab·ships·no·stubs. |
| 112 | GradientStop·=· | 108 | GradientStop·=·tuple[float,·Any] |
| 113 | class·_GradientDefBase(TypedDict): | 109 | class·_GradientDefBase(TypedDict): |
| 114 | ····"""Keys·always·present·on·a·parsed·gradient·definition.""" | 110 | ····"""Keys·always·present·on·a·parsed·gradient·definition.""" |
| 115 | ····type:·str··#·"linear"·or·"radial" | 111 | ····type:·str··#·"linear"·or·"radial" |
| 116 | ····gradientUnits:·str | 112 | ····gradientUnits:·str |
| 117 | ····spreadMethod:·str | 113 | ····spreadMethod:·str |
| 118 | ····stops:· | 114 | ····stops:·list[GradientStop] |
| 119 | ····href:·Optional[str] | 115 | ····href:·Optional[str] |
| 120 | class·_GradientDef(_GradientDefBase,·total=False): | 116 | class·_GradientDef(_GradientDefBase,·total=False): |
| 121 | ····"""Geometry·keys·present·depending·on·``type``·(linear·vs·radial).""" | 117 | ····"""Geometry·keys·present·depending·on·``type``·(linear·vs·radial).""" |
| 122 | ····#·linearGradient | 118 | ····#·linearGradient |
| Offset 162, 15 lines modified | Offset 158, 15 lines modified | ||
| 162 | def·register_font( | 158 | def·register_font( |
| 163 | ····font_name:·str, | 159 | ····font_name:·str, |
| 164 | ····font_path:·Optional[str]·=·None, | 160 | ····font_path:·Optional[str]·=·None, |
| 165 | ····weight:·str·=·"normal", | 161 | ····weight:·str·=·"normal", |
| 166 | ····style:·str·=·"normal", | 162 | ····style:·str·=·"normal", |
| 167 | ····rlgFontName:·Optional[str]·=·None, | 163 | ····rlgFontName:·Optional[str]·=·None, |
| 168 | )·->· | 164 | )·->·tuple[Optional[str],·bool]: |
| 169 | ····"""Register·a·font·for·use·in·SVG·processing. | 165 | ····"""Register·a·font·for·use·in·SVG·processing. |
| 170 | ····This·function·serves·as·a·backward-compatible·wrapper·for·the·font | 166 | ····This·function·serves·as·a·backward-compatible·wrapper·for·the·font |
| 171 | ····registration·logic·defined·in·the·`svglib.fonts`·module. | 167 | ····registration·logic·defined·in·the·`svglib.fonts`·module. |
| 172 | ····Args: | 168 | ····Args: |
| 173 | ········font_name:·The·name·of·the·font·to·register. | 169 | ········font_name:·The·name·of·the·font·to·register. |
| Offset 184, 15 lines modified | Offset 180, 15 lines modified | ||
| 184 | ········if·the·registration·was·successful. | 180 | ········if·the·registration·was·successful. |
| 185 | ····""" | 181 | ····""" |
| 186 | ····return·_fonts_register_font(font_name,·font_path,·weight,·style,·rlgFontName) | 182 | ····return·_fonts_register_font(font_name,·font_path,·weight,·style,·rlgFontName) |
| 187 | def·find_font( | 183 | def·find_font( |
| 188 | ····font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" | 184 | ····font_name:·str,·weight:·str·=·"normal",·style:·str·=·"normal" |
| 189 | )·->· | 185 | )·->·tuple[str,·bool]: |
| 190 | ····"""Find·a·registered·font·by·its·properties. | 186 | ····"""Find·a·registered·font·by·its·properties. |
| 191 | ····This·function·serves·as·a·backward-compatible·wrapper·for·the·font | 187 | ····This·function·serves·as·a·backward-compatible·wrapper·for·the·font |
| 192 | ····finding·logic·defined·in·the·`svglib.fonts`·module. | 188 | ····finding·logic·defined·in·the·`svglib.fonts`·module. |
| 193 | ····Args: | 189 | ····Args: |
| 194 | ········font_name:·The·name·of·the·font·to·find. | 190 | ········font_name:·The·name·of·the·font·to·find. |
| Offset 284, 17 lines modified | Offset 280, 17 lines modified | ||
| 284 | ····def·__init__(self,·*args:·Any,·**kwargs:·Any)·->·None: | 280 | ····def·__init__(self,·*args:·Any,·**kwargs:·Any)·->·None: |
| 285 | ········"""Initialize·the·path,·optionally·copying·state·from·another·shape.""" | 281 | ········"""Initialize·the·path,·optionally·copying·state·from·another·shape.""" |
| 286 | ········copy_from·=·kwargs.pop("copy_from",·None) | 282 | ········copy_from·=·kwargs.pop("copy_from",·None) |
| 287 | ········super().__init__(*args,·**kwargs) | 283 | ········super().__init__(*args,·**kwargs) |
| 288 | ········if·copy_from: | 284 | ········if·copy_from: |
| 289 | ············self.__dict__.update(copy.deepcopy(copy_from.__dict__)) | 285 | ············self.__dict__.update(copy.deepcopy(copy_from.__dict__)) |
| 290 | ····def·getProperties(self,·*args:·Any,·**kwargs:·Any)·->· | 286 | ····def·getProperties(self,·*args:·Any,·**kwargs:·Any)·->·dict[str,·Any]: |
| 291 | ········"""Return·the·properties·of·the·path,·ensuring·no·stroke·is·applied.""" | 287 | ········"""Return·the·properties·of·the·path,·ensuring·no·stroke·is·applied.""" |
| 292 | ········props:· | 288 | ········props:·dict[str,·Any]·=·super().getProperties(*args,·**kwargs) |
| 293 | ········if·"strokeWidth"·in·props: | 289 | ········if·"strokeWidth"·in·props: |
| 294 | ············props["strokeWidth"]·=·0 | 290 | ············props["strokeWidth"]·=·0 |
| 295 | ········if·"strokeColor"·in·props: | 291 | ········if·"strokeColor"·in·props: |
| 296 | ············props["strokeColor"]·=·None | 292 | ············props["strokeColor"]·=·None |
| 297 | ········return·props | 293 | ········return·props |
| Offset 309, 17 lines modified | Offset 305, 17 lines modified | ||
| 309 | ········"""Initialize·the·clipping·path,·optionally·copying·state·from·another·shape.""" | 305 | ········"""Initialize·the·clipping·path,·optionally·copying·state·from·another·shape.""" |
| 310 | ········copy_from·=·kwargs.pop("copy_from",·None) | 306 | ········copy_from·=·kwargs.pop("copy_from",·None) |
| 311 | ········Path.__init__(self,·*args,·**kwargs) | 307 | ········Path.__init__(self,·*args,·**kwargs) |
| 312 | ········if·copy_from: | 308 | ········if·copy_from: |
| 313 | ············self.__dict__.update(copy.deepcopy(copy_from.__dict__)) | 309 | ············self.__dict__.update(copy.deepcopy(copy_from.__dict__)) |
| 314 | ········self.isClipPath·=·1 | 310 | ········self.isClipPath·=·1 |
| 315 | ····def·getProperties(self,·*args:·Any,·**kwargs:·Any)·->· | 311 | ····def·getProperties(self,·*args:·Any,·**kwargs:·Any)·->·dict[str,·Any]: |
| 316 | ········"""Return·the·properties·of·the·path,·ensuring·no·fill·or·stroke.""" | 312 | ········"""Return·the·properties·of·the·path,·ensuring·no·fill·or·stroke.""" |
| 317 | ········props:· | 313 | ········props:·dict[str,·Any]·=·Path.getProperties(self,·*args,·**kwargs) |
| 318 | ········if·"fillColor"·in·props: | 314 | ········if·"fillColor"·in·props: |
| 319 | ············props["fillColor"]·=·None | 315 | ············props["fillColor"]·=·None |
| 320 | ········if·"strokeColor"·in·props: | 316 | ········if·"strokeColor"·in·props: |
| 321 | ············props["strokeColor"]·=·None | 317 | ············props["strokeColor"]·=·None |
| 322 | ········return·props | 318 | ········return·props |
| Offset 368, 15 lines modified | Offset 364, 15 lines modified | ||
| 368 | ········"""Set·the·main·viewbox·for·resolving·percentage-based·units. | 364 | ········"""Set·the·main·viewbox·for·resolving·percentage-based·units. |
| 369 | ········Args: | 365 | ········Args: |
| 370 | ············main_box:·A·Box·tuple·representing·the·main·viewbox. | 366 | ············main_box:·A·Box·tuple·representing·the·main·viewbox. |
| 371 | ········""" | 367 | ········""" |
| 372 | ········self.main_box·=·main_box | 368 | ········self.main_box·=·main_box |
| 373 | ····def·parseMultiAttributes(self,·line:·str)·->· | 369 | ····def·parseMultiAttributes(self,·line:·str)·->·dict[str,·str]: |
| 374 | ········"""Parse·a·compound·attribute·string·into·a·dictionary. | 370 | ········"""Parse·a·compound·attribute·string·into·a·dictionary. |
| 375 | ········Args: | 371 | ········Args: |
| 376 | ············line:·A·string·of·semicolon-separated·style·attributes. | 372 | ············line:·A·string·of·semicolon-separated·style·attributes. |
| Max diff block lines reached; 31092/35661 bytes (87.19%) of diff not shown. | |||
| Offset 11, 20 lines modified | Offset 11, 20 lines modified | ||
| 11 | -·Elliptical·arc·processing·functions | 11 | -·Elliptical·arc·processing·functions |
| 12 | -·Vector·mathematics·helpers | 12 | -·Vector·mathematics·helpers |
| 13 | -·String·parsing·utilities·for·SVG·attributes | 13 | -·String·parsing·utilities·for·SVG·attributes |
| 14 | """ | 14 | """ |
| 15 | import·re | 15 | import·re |
| 16 | from·math·import·acos,·ceil,·copysign,·cos,·degrees,·fabs,·hypot,·radians,·sin,·sqrt | 16 | from·math·import·acos,·ceil,·copysign,·cos,·degrees,·fabs,·hypot,·radians,·sin,·sqrt |
| 17 | from·typing·import· | 17 | from·typing·import·Union,·cast |
| 18 | from·reportlab.graphics.shapes·import·mmult,·rotate,·transformPoint,·translate | 18 | from·reportlab.graphics.shapes·import·mmult,·rotate,·transformPoint,·translate |
| 19 | def·split_floats(op:·str,·min_num:·int,·value:·str)·->· | 19 | def·split_floats(op:·str,·min_num:·int,·value:·str)·->·list[Union[str,·list[float]]]: |
| 20 | ····"""Parse·SVG·coordinate·string·into·alternating·operators·and·coordinate·lists. | 20 | ····"""Parse·SVG·coordinate·string·into·alternating·operators·and·coordinate·lists. |
| 21 | ····Splits·a·string·of·numeric·values·into·groups·and·pairs·each·group·with·the | 21 | ····Splits·a·string·of·numeric·values·into·groups·and·pairs·each·group·with·the |
| 22 | ····appropriate·SVG·path·operation.·Automatically·converts·'M'·to·'L'·for·subsequent | 22 | ····appropriate·SVG·path·operation.·Automatically·converts·'M'·to·'L'·for·subsequent |
| 23 | ····coordinate·pairs·to·handle·move-to·followed·by·line-to·sequences. | 23 | ····coordinate·pairs·to·handle·move-to·followed·by·line-to·sequences. |
| 24 | ····Args: | 24 | ····Args: |
| Offset 48, 23 lines modified | Offset 48, 23 lines modified | ||
| 48 | ········whitespace·and·comma·separators·automatically. | 48 | ········whitespace·and·comma·separators·automatically. |
| 49 | ····""" | 49 | ····""" |
| 50 | ····floats·=·[ | 50 | ····floats·=·[ |
| 51 | ········float(seq) | 51 | ········float(seq) |
| 52 | ········for·seq·in·re.findall(r"(-?\d*\.?\d*(?:[eE][+-]?\d+)?)",·value) | 52 | ········for·seq·in·re.findall(r"(-?\d*\.?\d*(?:[eE][+-]?\d+)?)",·value) |
| 53 | ········if·seq | 53 | ········if·seq |
| 54 | ····] | 54 | ····] |
| 55 | ····res:· | 55 | ····res:·list[Union[str,·list[float]]]·=·[] |
| 56 | ····for·i·in·range(0,·len(floats),·min_num): | 56 | ····for·i·in·range(0,·len(floats),·min_num): |
| 57 | ········if·i·>·0·and·op·in·{"m",·"M"}: | 57 | ········if·i·>·0·and·op·in·{"m",·"M"}: |
| 58 | ············op·=·"l"·if·op·==·"m"·else·"L" | 58 | ············op·=·"l"·if·op·==·"m"·else·"L" |
| 59 | ········res.extend([op,·cast( | 59 | ········res.extend([op,·cast(list[float],·list(floats[i·:·i·+·min_num]))]) |
| 60 | ····return·res | 60 | ····return·res |
| 61 | def·split_arc_values(op:·str,·value:·str)·->· | 61 | def·split_arc_values(op:·str,·value:·str)·->·list[Union[str,·list[float]]]: |
| 62 | ····"""Parse·SVG·elliptical·arc·parameters·into·structured·format. | 62 | ····"""Parse·SVG·elliptical·arc·parameters·into·structured·format. |
| 63 | ····Parses·SVG·arc·command·parameters·which·consist·of:·rx,·ry,·x-axis-rotation, | 63 | ····Parses·SVG·arc·command·parameters·which·consist·of:·rx,·ry,·x-axis-rotation, |
| 64 | ····large-arc-flag,·sweep-flag,·x,·y.·Each·complete·parameter·set·is·paired·with | 64 | ····large-arc-flag,·sweep-flag,·x,·y.·Each·complete·parameter·set·is·paired·with |
| 65 | ····the·operation·character. | 65 | ····the·operation·character. |
| 66 | ····Args: | 66 | ····Args: |
| Offset 93, 21 lines modified | Offset 93, 21 lines modified | ||
| 93 | ····#·3·numb,·2·flags,·1·coord·pair | 93 | ····#·3·numb,·2·flags,·1·coord·pair |
| 94 | ····a_seq_re·=·( | 94 | ····a_seq_re·=·( |
| 95 | ········r"[\s,]*".join( | 95 | ········r"[\s,]*".join( |
| 96 | ············[float_re,·float_re,·float_re,·flag_re,·flag_re,·float_re,·float_re] | 96 | ············[float_re,·float_re,·float_re,·flag_re,·flag_re,·float_re,·float_re] |
| 97 | ········) | 97 | ········) |
| 98 | ········+·r"[\s,]*" | 98 | ········+·r"[\s,]*" |
| 99 | ····) | 99 | ····) |
| 100 | ····res:· | 100 | ····res:·list[Union[str,·list[float]]]·=·[] |
| 101 | ····for·seq·in·re.finditer(a_seq_re,·value.strip()): | 101 | ····for·seq·in·re.finditer(a_seq_re,·value.strip()): |
| 102 | ········res.extend([op,·cast( | 102 | ········res.extend([op,·cast(list[float],·list(float(num)·for·num·in·seq.groups()))]) |
| 103 | ····return·res | 103 | ····return·res |
| 104 | def·normalise_svg_path(attr:·str)·->· | 104 | def·normalise_svg_path(attr:·str)·->·list[Union[str,·list[float]]]: |
| 105 | ····"""Normalize·SVG·path·data·into·structured·format. | 105 | ····"""Normalize·SVG·path·data·into·structured·format. |
| 106 | ····Parses·raw·SVG·path·string·and·converts·it·into·a·standardized·list·format | 106 | ····Parses·raw·SVG·path·string·and·converts·it·into·a·standardized·list·format |
| 107 | ····where·each·path·command·is·paired·with·its·coordinate·parameters.·Automatically | 107 | ····where·each·path·command·is·paired·with·its·coordinate·parameters.·Automatically |
| 108 | ····handles·command·sequences·and·converts·implicit·line·commands·after·move·commands. | 108 | ····handles·command·sequences·and·converts·implicit·line·commands·after·move·commands. |
| 109 | ····Args: | 109 | ····Args: |
| Offset 154, 15 lines modified | Offset 154, 15 lines modified | ||
| 154 | ········"C":·6, | 154 | ········"C":·6, |
| 155 | ········"c":·6, | 155 | ········"c":·6, |
| 156 | ········"Z":·0, | 156 | ········"Z":·0, |
| 157 | ········"z":·0, | 157 | ········"z":·0, |
| 158 | ····} | 158 | ····} |
| 159 | ····op_keys·=·ops.keys() | 159 | ····op_keys·=·ops.keys() |
| 160 | ····result:· | 160 | ····result:·list[Union[str,·list[float]]]·=·[] |
| 161 | ····groups·=·re.split("([achlmqstvz])",·attr.strip(),·flags=re.I) | 161 | ····groups·=·re.split("([achlmqstvz])",·attr.strip(),·flags=re.I) |
| 162 | ····op·=·"" | 162 | ····op·=·"" |
| 163 | ····for·item·in·groups: | 163 | ····for·item·in·groups: |
| 164 | ········if·item.strip()·==·"": | 164 | ········if·item.strip()·==·"": |
| 165 | ············continue | 165 | ············continue |
| 166 | ········if·item·in·op_keys: | 166 | ········if·item·in·op_keys: |
| 167 | ············op·=·item | 167 | ············op·=·item |
| Offset 175, 17 lines modified | Offset 175, 17 lines modified | ||
| 175 | ················result.extend(split_floats(op,·ops[op],·item)) | 175 | ················result.extend(split_floats(op,·ops[op],·item)) |
| 176 | ············op·=·cast(str,·result[-2])··#·Remember·last·op | 176 | ············op·=·cast(str,·result[-2])··#·Remember·last·op |
| 177 | ····return·result | 177 | ····return·result |
| 178 | def·convert_quadratic_to_cubic_path( | 178 | def·convert_quadratic_to_cubic_path( |
| 179 | ····q0:· | 179 | ····q0:·tuple[float,·float],·q1:·tuple[float,·float],·q2:·tuple[float,·float] |
| 180 | )·->· | 180 | )·->·tuple[ |
| 181 | ···· | 181 | ····tuple[float,·float],·tuple[float,·float],·tuple[float,·float],·tuple[float,·float] |
| 182 | ]: | 182 | ]: |
| 183 | ····"""Convert·quadratic·Bezier·curve·to·cubic·Bezier·curve. | 183 | ····"""Convert·quadratic·Bezier·curve·to·cubic·Bezier·curve. |
| 184 | ····Converts·a·quadratic·Bezier·curve·defined·by·control·points·q0,·q1,·q2 | 184 | ····Converts·a·quadratic·Bezier·curve·defined·by·control·points·q0,·q1,·q2 |
| 185 | ····into·an·equivalent·cubic·Bezier·curve.·This·is·useful·for·SVG·processing | 185 | ····into·an·equivalent·cubic·Bezier·curve.·This·is·useful·for·SVG·processing |
| 186 | ····since·cubic·curves·are·more·commonly·supported·than·quadratic·curves. | 186 | ····since·cubic·curves·are·more·commonly·supported·than·quadratic·curves. |
| Offset 218, 15 lines modified | Offset 218, 15 lines modified | ||
| 218 | #·*********************************************** | 218 | #·*********************************************** |
| 219 | #·Helper·functions·for·elliptical·arc·conversion. | 219 | #·Helper·functions·for·elliptical·arc·conversion. |
| 220 | #·*********************************************** | 220 | #·*********************************************** |
| 221 | def·vector_angle(u:· | 221 | def·vector_angle(u:·tuple[float,·float],·v:·tuple[float,·float])·->·float: |
| 222 | ····"""Calculate·the·signed·angle·between·two·2D·vectors. | 222 | ····"""Calculate·the·signed·angle·between·two·2D·vectors. |
| 223 | ····Computes·the·angle·between·vectors·u·and·v·using·the·atan2·method·to | 223 | ····Computes·the·angle·between·vectors·u·and·v·using·the·atan2·method·to |
| 224 | ····determine·the·correct·quadrant·and·sign.·Returns·angle·in·degrees. | 224 | ····determine·the·correct·quadrant·and·sign.·Returns·angle·in·degrees. |
| 225 | ····Args: | 225 | ····Args: |
| 226 | ········u:·First·vector·as·(x,·y)·tuple. | 226 | ········u:·First·vector·as·(x,·y)·tuple. |
| Offset 271, 15 lines modified | Offset 271, 15 lines modified | ||
| 271 | ····x2:·float, | 271 | ····x2:·float, |
| 272 | ····y2:·float, | 272 | ····y2:·float, |
| 273 | ····fA:·int, | 273 | ····fA:·int, |
| 274 | ····fS:·int, | 274 | ····fS:·int, |
| 275 | ····rx:·float, | 275 | ····rx:·float, |
| 276 | ····ry:·float, | 276 | ····ry:·float, |
| 277 | ····phi:·float·=·0, | 277 | ····phi:·float·=·0, |
| 278 | )·->· | 278 | )·->·tuple[float,·float,·float,·float,·float,·float]: |
| 279 | ····"""Convert·SVG·arc·endpoint·parameters·to·center-based·representation. | 279 | ····"""Convert·SVG·arc·endpoint·parameters·to·center-based·representation. |
| Max diff block lines reached; 1432/6700 bytes (21.37%) of diff not shown. | |||
| Offset 1, 71 lines modified | Offset 1, 74 lines modified | ||
| 1 | #·coding:·utf-8 | ||
| 2 | """ | 1 | """ |
| 3 | ····webencodings | 2 | ····webencodings |
| 4 | ····~~~~~~~~~~~~ | 3 | ····~~~~~~~~~~~~ |
| 5 | ····This·is·a·Python·implementation·of·the·`WHATWG·Encoding·standard | 4 | ····This·is·a·Python·implementation·of·the·`WHATWG·Encoding·standard |
| 6 | ····<http://encoding.spec.whatwg.org/>`.·See·README·for·details. | 5 | ····<http://encoding.spec.whatwg.org/>`.·See·README·for·details. |
| 7 | ····:copyright:·Copyright·2012·by·Simon·Sapin | 6 | ····:copyright:·Copyright·2012·by·Simon·Sapin |
| 8 | ····:license:·BSD,·see·LICENSE·for·details. | 7 | ····:license:·BSD,·see·LICENSE·for·details. |
| 9 | """ | 8 | """ |
| 10 | from·__future__·import·unicode_literals | ||
| 11 | import·codecs | 9 | import·codecs |
| 10 | from·.custom·import·replacement_codec_info,·user_codec_info | ||
| 12 | from·.labels·import·LABELS | 11 | from·.labels·import·LABELS |
| 12 | VERSION·=·__version__·=·'0.6.1' | ||
| 13 | VERSION·=·'0.5.1' | ||
| 14 | #·Some·names·in·Encoding·are·not·valid·Python·aliases.·Remap·these. | ||
| 15 | PYTHON_NAMES·=·{ | 13 | PYTHON_NAMES·=·{ |
| 14 | ····#·Some·names·in·Encoding·are·not·valid·Python·aliases.·Remap·these: | ||
| 16 | ····'iso-8859-8-i':·'iso | 15 | ····'iso-8859-8-i':·'iso8859-8', |
| 17 | ····'x-mac-cyrillic':·'mac-cyrillic', | 16 | ····'x-mac-cyrillic':·'mac-cyrillic', |
| 18 | ····'macintosh':·'mac-roman', | 17 | ····'macintosh':·'mac-roman', |
| 19 | ····'windows-874':·'cp874' | 18 | ····'windows-874':·'cp874', |
| 19 | ····#·Some·WHATWG-defined·names·conflict·with·a·Python·alias·for·an | ||
| 20 | ····#·incompatible·codec.·These·should·be·remapped·to·the·correct·one: | ||
| 21 | ····'shift_jis':·'cp932', | ||
| 22 | ····'big5':·'big5hkscs', | ||
| 23 | ····'euc-kr':·'cp949', | ||
| 24 | } | ||
| 20 | CACHE·=·{} | 25 | CACHE·=·{} |
| 21 | def·ascii_lower(string): | 26 | def·ascii_lower(string): |
| 22 | ···· | 27 | ····"""Transform·(only)·ASCII·letters·to·lower·case:·A-Z·is·mapped·to·a-z. |
| 23 | ····:param·string:·An·Unicode·string. | 28 | ····:param·string:·An·Unicode·string. |
| 24 | ····:returns:·A·new·Unicode·string. | 29 | ····:returns:·A·new·Unicode·string. |
| 25 | ····This·is·used·for·`ASCII·case-insensitive | 30 | ····This·is·used·for·`ASCII·case-insensitive |
| 26 | ····<http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_ | 31 | ····<http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_ |
| 27 | ····matching·of·encoding·labels. | 32 | ····matching·of·encoding·labels. |
| 28 | ····The·same·matching·is·also·used,·among·other·things, | 33 | ····The·same·matching·is·also·used,·among·other·things, |
| 29 | ····for·`CSS·keywords·<http://dev.w3.org/csswg/css-values/#keywords>`_. | 34 | ····for·`CSS·keywords·<http://dev.w3.org/csswg/css-values/#keywords>`_. |
| 30 | ····This·is·different·from·the·:meth:` | 35 | ····This·is·different·from·the·:meth:`str.lower`·method·of·Unicode·strings |
| 31 | ····which·also·affect·non-ASCII·characters, | 36 | ····which·also·affect·non-ASCII·characters, |
| 32 | ····sometimes·mapping·them·into·the·ASCII·range: | 37 | ····sometimes·mapping·them·into·the·ASCII·range: |
| 33 | ········>>>·keyword·=· | 38 | ········>>>·keyword·=·'Bac\\N{KELVIN·SIGN}ground' |
| 34 | ········>>>·assert·keyword.lower()·==· | 39 | ········>>>·assert·keyword.lower()·==·'background' |
| 35 | ········>>>·assert·ascii_lower(keyword)·!=·keyword.lower() | 40 | ········>>>·assert·ascii_lower(keyword)·!=·keyword.lower() |
| 36 | ········>>>·assert·ascii_lower(keyword)·==· | 41 | ········>>>·assert·ascii_lower(keyword)·==·'bac\\N{KELVIN·SIGN}ground' |
| 37 | ····""" | 42 | ····""" |
| 38 | ····#·This·turns·out·to·be·faster·than·unicode.translate() | 43 | ····#·This·turns·out·to·be·faster·than·unicode.translate() |
| 39 | ····return·string.encode( | 44 | ····return·string.encode().lower().decode() |
| 40 | def·lookup(label): | 45 | def·lookup(label): |
| 41 | ····""" | ||
| 42 | ····Look·for·an·encoding·by·its·label. | 46 | ····"""Look·for·an·encoding·by·its·label. |
| 43 | ····This·is·the·spec | 47 | ····This·is·the·spec's·`get·an·encoding |
| 44 | ····<http://encoding.spec.whatwg.org/#concept-encoding-get>`_·algorithm. | 48 | ····<http://encoding.spec.whatwg.org/#concept-encoding-get>`_·algorithm. |
| 45 | ····Supported·labels·are·listed·there. | 49 | ····Supported·labels·are·listed·there. |
| 46 | ····:param·label:·A·string. | 50 | ····:param·label:·A·string. |
| 47 | ····:returns: | 51 | ····:returns: |
| 48 | ········An·:class:`Encoding`·object,·or·:obj:`None`·for·an·unknown·label. | 52 | ········An·:class:`Encoding`·object,·or·:obj:`None`·for·an·unknown·label. |
| Offset 74, 45 lines modified | Offset 77, 45 lines modified | ||
| 74 | ····label·=·ascii_lower(label.strip('\t\n\f\r·')) | 77 | ····label·=·ascii_lower(label.strip('\t\n\f\r·')) |
| 75 | ····name·=·LABELS.get(label) | 78 | ····name·=·LABELS.get(label) |
| 76 | ····if·name·is·None: | 79 | ····if·name·is·None: |
| 77 | ········return·None | 80 | ········return·None |
| 78 | ····encoding·=·CACHE.get(name) | 81 | ····encoding·=·CACHE.get(name) |
| 79 | ····if·encoding·is·None: | 82 | ····if·encoding·is·None: |
| 80 | ········if·name·==·'x-user-defined': | 83 | ········if·name·==·'x-user-defined': |
| 81 | ············ | 84 | ············codec_info·=·user_codec_info |
| 85 | ········elif·name·==·'replacement': | ||
| 86 | ············codec_info·=·replacement_codec_info | ||
| 82 | ········else: | 87 | ········else: |
| 83 | ············python_name·=·PYTHON_NAMES.get(name,·name) | 88 | ············python_name·=·PYTHON_NAMES.get(name,·name) |
| 84 | ············#·Any·python_name·value·that·gets·to·here·should·be·valid. | 89 | ············#·Any·python_name·value·that·gets·to·here·should·be·valid. |
| 85 | ············codec_info·=·codecs.lookup(python_name) | 90 | ············codec_info·=·codecs.lookup(python_name) |
| 86 | ········encoding·=·Encoding(name,·codec_info) | 91 | ········encoding·=·Encoding(name,·codec_info) |
| 87 | ········CACHE[name]·=·encoding | 92 | ········CACHE[name]·=·encoding |
| 88 | ····return·encoding | 93 | ····return·encoding |
| 89 | def·_get_encoding(encoding_or_label): | 94 | def·_get_encoding(encoding_or_label): |
| 90 | ····""" | ||
| 91 | ····Accept·either·an·encoding·object·or·label. | 95 | ····"""Accept·either·an·encoding·object·or·label. |
| 92 | ····:param·encoding:·An·:class:`Encoding`·object·or·a·label·string. | 96 | ····:param·encoding:·An·:class:`Encoding`·object·or·a·label·string. |
| 93 | ····:returns:·An·:class:`Encoding`·object. | 97 | ····:returns:·An·:class:`Encoding`·object. |
| 94 | ····:raises:·:exc:` | 98 | ····:raises:·:exc:`LookupError`·for·an·unknown·label. |
| 95 | ····""" | 99 | ····""" |
| 96 | ····if·hasattr(encoding_or_label,·'codec_info'): | 100 | ····if·hasattr(encoding_or_label,·'codec_info'): |
| 97 | ········return·encoding_or_label | 101 | ········return·encoding_or_label |
| 98 | ····encoding·=·lookup(encoding_or_label) | 102 | ····encoding·=·lookup(encoding_or_label) |
| 99 | ····if·encoding·is·None: | 103 | ····if·encoding·is·None: |
| 100 | ········raise·LookupError('Unknown·encoding·label: | 104 | ········raise·LookupError(f'Unknown·encoding·label:·{encoding_or_label!r}') |
| 101 | ····return·encoding | 105 | ····return·encoding |
| 102 | class·Encoding | 106 | class·Encoding: |
| 103 | ····"""Reresents·a·character·encoding·such·as·UTF-8, | ||
| 104 | ····that·can·be·used·for·decoding·or·encoding. | 107 | ····"""A·character·encoding·that·can·be·used·for·decoding·or·encoding. |
| 105 | ····..·attribute::·name | 108 | ····..·attribute::·name |
| 106 | ········Canonical·name·of·the·encoding | 109 | ········Canonical·name·of·the·encoding |
| Max diff block lines reached; 6493/11193 bytes (58.01%) of diff not shown. | |||
| Offset 1, 1 lines modified | Offset 1, 1 lines modified | ||
| 1 | u | 1 | us-ascii |
| Offset 11, 16 lines modified | Offset 11, 19 lines modified | ||
| 11 | """ | 11 | """ |
| 12 | #·XXX·Do·not·edit! | 12 | #·XXX·Do·not·edit! |
| 13 | #·This·file·is·automatically·generated·by·mklabels.py | 13 | #·This·file·is·automatically·generated·by·mklabels.py |
| 14 | LABELS·=·{ | 14 | LABELS·=·{ |
| 15 | ····'unicode-1-1-utf-8':···'utf-8', | 15 | ····'unicode-1-1-utf-8':···'utf-8', |
| 16 | ····'unicode11utf8':·······'utf-8', | ||
| 17 | ····'unicode20utf8':·······'utf-8', | ||
| 16 | ····'utf-8':···············'utf-8', | 18 | ····'utf-8':···············'utf-8', |
| 17 | ····'utf8':················'utf-8', | 19 | ····'utf8':················'utf-8', |
| 20 | ····'x-unicode20utf8':·····'utf-8', | ||
| 18 | ····'866':·················'ibm866', | 21 | ····'866':·················'ibm866', |
| 19 | ····'cp866':···············'ibm866', | 22 | ····'cp866':···············'ibm866', |
| 20 | ····'csibm866':············'ibm866', | 23 | ····'csibm866':············'ibm866', |
| 21 | ····'ibm866':··············'ibm866', | 24 | ····'ibm866':··············'ibm866', |
| 22 | ····'csisolatin2':·········'iso-8859-2', | 25 | ····'csisolatin2':·········'iso-8859-2', |
| 23 | ····'iso-8859-2':··········'iso-8859-2', | 26 | ····'iso-8859-2':··········'iso-8859-2', |
| 24 | ····'iso-ir-101':··········'iso-8859-2', | 27 | ····'iso-ir-101':··········'iso-8859-2', |
| Offset 117, 14 lines modified | Offset 120, 15 lines modified | ||
| 117 | ····'l9':··················'iso-8859-15', | 120 | ····'l9':··················'iso-8859-15', |
| 118 | ····'iso-8859-16':·········'iso-8859-16', | 121 | ····'iso-8859-16':·········'iso-8859-16', |
| 119 | ····'cskoi8r':·············'koi8-r', | 122 | ····'cskoi8r':·············'koi8-r', |
| 120 | ····'koi':·················'koi8-r', | 123 | ····'koi':·················'koi8-r', |
| 121 | ····'koi8':················'koi8-r', | 124 | ····'koi8':················'koi8-r', |
| 122 | ····'koi8-r':··············'koi8-r', | 125 | ····'koi8-r':··············'koi8-r', |
| 123 | ····'koi8_r':··············'koi8-r', | 126 | ····'koi8_r':··············'koi8-r', |
| 127 | ····'koi8-ru':·············'koi8-u', | ||
| 124 | ····'koi8-u':··············'koi8-u', | 128 | ····'koi8-u':··············'koi8-u', |
| 125 | ····'csmacintosh':·········'macintosh', | 129 | ····'csmacintosh':·········'macintosh', |
| 126 | ····'mac':·················'macintosh', | 130 | ····'mac':·················'macintosh', |
| 127 | ····'macintosh':···········'macintosh', | 131 | ····'macintosh':···········'macintosh', |
| 128 | ····'x-mac-roman':·········'macintosh', | 132 | ····'x-mac-roman':·········'macintosh', |
| 129 | ····'dos-874':·············'windows-874', | 133 | ····'dos-874':·············'windows-874', |
| 130 | ····'iso-8859-11':·········'windows-874', | 134 | ····'iso-8859-11':·········'windows-874', |
| Offset 190, 26 lines modified | Offset 194, 26 lines modified | ||
| 190 | ····'gb2312':··············'gbk', | 194 | ····'gb2312':··············'gbk', |
| 191 | ····'gb_2312':·············'gbk', | 195 | ····'gb_2312':·············'gbk', |
| 192 | ····'gb_2312-80':··········'gbk', | 196 | ····'gb_2312-80':··········'gbk', |
| 193 | ····'gbk':·················'gbk', | 197 | ····'gbk':·················'gbk', |
| 194 | ····'iso-ir-58':···········'gbk', | 198 | ····'iso-ir-58':···········'gbk', |
| 195 | ····'x-gbk':···············'gbk', | 199 | ····'x-gbk':···············'gbk', |
| 196 | ····'gb18030':·············'gb18030', | 200 | ····'gb18030':·············'gb18030', |
| 197 | ····'hz-gb-2312':··········'hz-gb-2312', | ||
| 198 | ····'big5':················'big5', | 201 | ····'big5':················'big5', |
| 199 | ····'big5-hkscs':··········'big5', | 202 | ····'big5-hkscs':··········'big5', |
| 200 | ····'cn-big5':·············'big5', | 203 | ····'cn-big5':·············'big5', |
| 201 | ····'csbig5':··············'big5', | 204 | ····'csbig5':··············'big5', |
| 202 | ····'x-x-big5':············'big5', | 205 | ····'x-x-big5':············'big5', |
| 203 | ····'cseucpkdfmtjapanese':·'euc-jp', | 206 | ····'cseucpkdfmtjapanese':·'euc-jp', |
| 204 | ····'euc-jp':··············'euc-jp', | 207 | ····'euc-jp':··············'euc-jp', |
| 205 | ····'x-euc-jp':············'euc-jp', | 208 | ····'x-euc-jp':············'euc-jp', |
| 206 | ····'csiso2022jp':·········'iso-2022-jp', | 209 | ····'csiso2022jp':·········'iso-2022-jp', |
| 207 | ····'iso-2022-jp':·········'iso-2022-jp', | 210 | ····'iso-2022-jp':·········'iso-2022-jp', |
| 208 | ····'csshiftjis':··········'shift_jis', | 211 | ····'csshiftjis':··········'shift_jis', |
| 212 | ····'ms932':···············'shift_jis', | ||
| 209 | ····'ms_kanji':············'shift_jis', | 213 | ····'ms_kanji':············'shift_jis', |
| 210 | ····'shift-jis':···········'shift_jis', | 214 | ····'shift-jis':···········'shift_jis', |
| 211 | ····'shift_jis':···········'shift_jis', | 215 | ····'shift_jis':···········'shift_jis', |
| 212 | ····'sjis':················'shift_jis', | 216 | ····'sjis':················'shift_jis', |
| 213 | ····'windows-31j':·········'shift_jis', | 217 | ····'windows-31j':·········'shift_jis', |
| 214 | ····'x-sjis':··············'shift_jis', | 218 | ····'x-sjis':··············'shift_jis', |
| 215 | ····'cseuckr':·············'euc-kr', | 219 | ····'cseuckr':·············'euc-kr', |
| Offset 218, 14 lines modified | Offset 222, 24 lines modified | ||
| 218 | ····'iso-ir-149':··········'euc-kr', | 222 | ····'iso-ir-149':··········'euc-kr', |
| 219 | ····'korean':··············'euc-kr', | 223 | ····'korean':··············'euc-kr', |
| 220 | ····'ks_c_5601-1987':······'euc-kr', | 224 | ····'ks_c_5601-1987':······'euc-kr', |
| 221 | ····'ks_c_5601-1989':······'euc-kr', | 225 | ····'ks_c_5601-1989':······'euc-kr', |
| 222 | ····'ksc5601':·············'euc-kr', | 226 | ····'ksc5601':·············'euc-kr', |
| 223 | ····'ksc_5601':············'euc-kr', | 227 | ····'ksc_5601':············'euc-kr', |
| 224 | ····'windows-949':·········'euc-kr', | 228 | ····'windows-949':·········'euc-kr', |
| 225 | ····'csiso2022kr':·········' | 229 | ····'csiso2022kr':·········'replacement', |
| 230 | ····'hz-gb-2312':··········'replacement', | ||
| 231 | ····'iso-2022-cn':·········'replacement', | ||
| 232 | ····'iso-2022-cn-ext':·····'replacement', | ||
| 226 | ····'iso-2022-kr':·········' | 233 | ····'iso-2022-kr':·········'replacement', |
| 234 | ····'replacement':·········'replacement', | ||
| 235 | ····'unicodefffe':·········'utf-16be', | ||
| 227 | ····'utf-16be':············'utf-16be', | 236 | ····'utf-16be':············'utf-16be', |
| 237 | ····'csunicode':···········'utf-16le', | ||
| 238 | ····'iso-10646-ucs-2':·····'utf-16le', | ||
| 239 | ····'ucs-2':···············'utf-16le', | ||
| 240 | ····'unicode':·············'utf-16le', | ||
| 241 | ····'unicodefeff':·········'utf-16le', | ||
| 228 | ····'utf-16':··············'utf-16le', | 242 | ····'utf-16':··············'utf-16le', |
| 229 | ····'utf-16le':············'utf-16le', | 243 | ····'utf-16le':············'utf-16le', |
| 230 | ····'x-user-defined':······'x-user-defined', | 244 | ····'x-user-defined':······'x-user-defined', |
| 231 | } | 245 | } |
| Offset 1, 10 lines modified | Offset 1, 10 lines modified | ||
| 1 | Metadata-Version:·2.4 | 1 | Metadata-Version:·2.4 |
| 2 | Name:·charset-normalizer | 2 | Name:·charset-normalizer |
| 3 | Version:·3. | 3 | Version:·3.5.2 |
| 4 | Summary:·The·Real·First·Universal·Charset·Detector.·Open,·modern·and·actively·maintained·alternative·to·Chardet. | 4 | Summary:·The·Real·First·Universal·Charset·Detector.·Open,·modern·and·actively·maintained·alternative·to·Chardet. |
| 5 | Author-email:·"Ahmed·R.·TAHRI"·<tahri.ahmed@proton.me> | 5 | Author-email:·"Ahmed·R.·TAHRI"·<tahri.ahmed@proton.me> |
| 6 | Maintainer-email:·"Ahmed·R.·TAHRI"·<tahri.ahmed@proton.me> | 6 | Maintainer-email:·"Ahmed·R.·TAHRI"·<tahri.ahmed@proton.me> |
| 7 | License:·MIT | 7 | License:·MIT |
| 8 | Project-URL:·Changelog,·https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md | 8 | Project-URL:·Changelog,·https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md |
| 9 | Project-URL:·Documentation,·https://charset-normalizer.readthedocs.io/ | 9 | Project-URL:·Documentation,·https://charset-normalizer.readthedocs.io/ |
| 10 | Project-URL:·Code,·https://github.com/jawah/charset_normalizer | 10 | Project-URL:·Code,·https://github.com/jawah/charset_normalizer |
| Offset 19, 18 lines modified | Offset 19, 21 lines modified | ||
| 19 | Classifier:·Programming·Language·::·Python·::·3.8 | 19 | Classifier:·Programming·Language·::·Python·::·3.8 |
| 20 | Classifier:·Programming·Language·::·Python·::·3.9 | 20 | Classifier:·Programming·Language·::·Python·::·3.9 |
| 21 | Classifier:·Programming·Language·::·Python·::·3.10 | 21 | Classifier:·Programming·Language·::·Python·::·3.10 |
| 22 | Classifier:·Programming·Language·::·Python·::·3.11 | 22 | Classifier:·Programming·Language·::·Python·::·3.11 |
| 23 | Classifier:·Programming·Language·::·Python·::·3.12 | 23 | Classifier:·Programming·Language·::·Python·::·3.12 |
| 24 | Classifier:·Programming·Language·::·Python·::·3.13 | 24 | Classifier:·Programming·Language·::·Python·::·3.13 |
| 25 | Classifier:·Programming·Language·::·Python·::·3.14 | 25 | Classifier:·Programming·Language·::·Python·::·3.14 |
| 26 | Classifier:·Programming·Language·::·Python·::·3.15 | ||
| 26 | Classifier:·Programming·Language·::·Python·::·3·::·Only | 27 | Classifier:·Programming·Language·::·Python·::·3·::·Only |
| 27 | Classifier:·Programming·Language·::·Python·::·Implementation·::·CPython | 28 | Classifier:·Programming·Language·::·Python·::·Implementation·::·CPython |
| 28 | Classifier:·Programming·Language·::·Python·::·Implementation·::·PyPy | 29 | Classifier:·Programming·Language·::·Python·::·Implementation·::·PyPy |
| 29 | Classifier:·Programming·Language·::·Python·::·Free·Threading·::·4·-·Resilient | 30 | Classifier:·Programming·Language·::·Python·::·Free·Threading·::·4·-·Resilient |
| 31 | Classifier:·Environment·::·WebAssembly | ||
| 32 | Classifier:·Environment·::·WebAssembly·::·Emscripten | ||
| 30 | Classifier:·Topic·::·Text·Processing·::·Linguistic | 33 | Classifier:·Topic·::·Text·Processing·::·Linguistic |
| 31 | Classifier:·Topic·::·Utilities | 34 | Classifier:·Topic·::·Utilities |
| 32 | Classifier:·Typing·::·Typed | 35 | Classifier:·Typing·::·Typed |
| 33 | Requires-Python:·>=3.7 | 36 | Requires-Python:·>=3.7 |
| 34 | Description-Content-Type:·text/markdown | 37 | Description-Content-Type:·text/markdown |
| 35 | License-File:·LICENSE | 38 | License-File:·LICENSE |
| 36 | Provides-Extra:·unicode-backport | 39 | Provides-Extra:·unicode-backport |
| Offset 72, 56 lines modified | Offset 75, 67 lines modified | ||
| 72 | >·You·can·also·register·your·own·set·of·codecs,·and·yes,·it·would·work·as-is. | 75 | >·You·can·also·register·your·own·set·of·codecs,·and·yes,·it·would·work·as-is. |
| 73 | This·project·offers·you·an·alternative·to·**Universal·Charset·Encoding·Detector**,·also·known·as·**Chardet**. | 76 | This·project·offers·you·an·alternative·to·**Universal·Charset·Encoding·Detector**,·also·known·as·**Chardet**. |
| 74 | |·Feature··········································|·[Chardet](https://github.com/chardet/chardet)·|·······································Charset·Normalizer········································|·[cChardet](https://github.com/PyYoshi/cChardet)·| | 77 | |·Feature··········································|·[Chardet](https://github.com/chardet/chardet)·|·······································Charset·Normalizer········································|·[cChardet](https://github.com/PyYoshi/cChardet)·| |
| 75 | |--------------------------------------------------|:---------------------------------------------:|:-----------------------------------------------------------------------------------------------:|:-----------------------------------------------:| | 78 | |--------------------------------------------------|:---------------------------------------------:|:-----------------------------------------------------------------------------------------------:|:-----------------------------------------------:| |
| 76 | |·`Fast`···········································|·······················✅·······················|················································✅················································|························✅························| | 79 | |·`Fast`···········································|·······················✅·······················|················································✅················································|························✅························| |
| 80 | |·`Fast·on·large·content·(uncapped)`···············|·······················❌·······················|················································✅················································|························❌························| | ||
| 77 | |·`Universal`[^1]··································|·······················❌·······················|················································✅················································|························❌························| | 81 | |·`Universal`[^1]··································|·······················❌·······················|················································✅················································|························❌························| |
| 78 | |·`Reliable`·**without**·distinguishable·standards·|·······················✅·······················|················································✅················································|························✅························| | 82 | |·`Reliable`·**without**·distinguishable·standards·|·······················✅·······················|················································✅················································|························✅························| |
| 79 | |·`Reliable`·**with**·distinguishable·standards····|·······················✅·······················|················································✅················································|························✅························| | 83 | |·`Reliable`·**with**·distinguishable·standards····|·······················✅·······················|················································✅················································|························✅························| |
| 80 | |·`License`········································|········ | 84 | |·`License`········································|···········_0BSD_[^2]<br>_disputed_············|···············································MIT···············································|············MPL-1.1<br>_restrictive_·············| |
| 81 | |·`Native·Python`··································|·······················✅·······················|················································✅················································|························❌························| | 85 | |·`Native·Python`··································|·······················✅·······················|················································✅················································|························❌························| |
| 82 | |·`Detect·spoken·language`·························|·······················✅·······················|················································✅················································|·······················N/A·······················| | 86 | |·`Detect·spoken·language`·························|·······················✅·······················|················································✅················································|·······················N/A·······················| |
| 83 | |·`UnicodeDecodeError·Safety`······················|·······················✅·······················|················································✅················································|························❌························| | ||
| 84 | |·` | 87 | |·`UnicodeDecodeError·Safety`······················|·······················❌·······················|················································✅················································|························❌························| |
| 88 | |·`Whl·Size`·······································|···················~1200·kB····················|·············································~250·kB·············································|·····················~200·kB·····················| | ||
| 85 | |·`Supported·Encoding`·····························|······················99·······················|·[99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings)·|·······················40························| | 89 | |·`Supported·Encoding`·····························|······················99·······················|·[99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings)·|·······················40························| |
| 86 | |·`Can·register·custom·encoding`···················|·······················❌·······················|················································✅················································|························❌························| | 90 | |·`Can·register·custom·encoding`···················|·······················❌·······················|················································✅················································|························❌························| |
| 87 | <p·align="center"> | 91 | <p·align="center"> |
| 88 | <img·src="https://i.imgflip.com/373iay.gif"·alt="Reading·Normalized·Text"·width="226"/><img·src="https://media.tenor.com/images/c0180f70732a18b4965448d33adba3d0/tenor.gif"·alt="Cat·Reading·Text"·width="200"/> | 92 | <img·src="https://i.imgflip.com/373iay.gif"·alt="Reading·Normalized·Text"·width="226"/><img·src="https://media.tenor.com/images/c0180f70732a18b4965448d33adba3d0/tenor.gif"·alt="Cat·Reading·Text"·width="200"/> |
| 89 | </p> | 93 | </p> |
| 90 | [^1]:·They·are·clearly·using·specific·code·for·a·specific·encoding·even·if·covering·most·of· | 94 | [^1]:·They·are·clearly·using·specific·code·for·a·specific·encoding·even·if·covering·most·of·them. |
| 91 | [^2]:·Chardet·7 | 95 | [^2]:·Chardet·7·replaced·the·historical·LGPL-licensed·implementation·with·an·AI-assisted·rewrite,·initially·distributed·under·MIT·and·later·under·0BSD.·The·original·author·[contests](https://github.com/chardet/chardet/issues/327)·that·the·rewrite·was·sufficiently·indepen[·...·truncated·by·diffoscope;·len:·2096,·SHA:·da0513e912930efa168e79bcaaee28017613ad64cc9734c52ca36133c8808e4e·...·]. |
| 92 | ##·⚡·Performance | 96 | ##·⚡·Performance |
| 93 | This·package·offer· | 97 | This·package·offer·similar·performances·in·general·against·Chardet.·Expect·10X·faster·with·large·contents·when·you·uncap·Chardet·max_bytes·default·assumption. |
| 94 | |·Package···········································|·Accuracy·|·Mean·per·file·(ms)·|·File·per·sec·(est)·| | ||
| 95 | |---------------------------------------------------|:--------:|:------------------:|:------------------:| | ||
| 96 | |·[chardet·7.4](https://github.com/chardet/chardet)·|···89·%···|········3·ms········|····333·file/sec····| | ||
| 97 | |· | 98 | |·Package············|·Accuracy·|··Mean·per·file·(ms)···| |
| 99 | |--------------------|:--------:|:---------------------:| | ||
| 100 | |·Chardet············|···99·%···|·0.4·ms[^4]·0.6·ms[^5]·| | ||
| 101 | |·charset-normalizer·|···98·%···|········0.4·ms·········| | ||
| 102 | |·cchardet[^3]·······|···94·%···|········0.6·ms·········| | ||
| 103 | _Well,·sub-ms·detectors·made·them·extremely·discrete·in·the·overall·runtime. | ||
| 104 | Competitors·can·still·win·individual·measurements,·especially·capped·Chardet·on | ||
| 105 | small-file·median·latency.·But·when·performance,·accuracy,·binary·handling,·validation | ||
| 106 | strength,·portability,·and·maintainability·are·considered·together,·charset-normalizer | ||
| 107 | is·the·stronger·package._ | ||
| 108 | |·Package············|···99th·percentile····|·95th·percentile·|·50th·percentile·| | ||
| 109 | |--------------------|:--------------------:|:---------------:|:---------------:| | ||
| 110 | |·Chardet············|·2.5·ms[^4]·4.2ms[^5]·|······1·ms·······|·····0.2·ms······| | ||
| 111 | |·charset-normalizer·|········2.7·ms········|·····1.5·ms······|·····0.2·ms······| | ||
| 112 | |·cchardet···········|········2.7·ms········|······2·ms·······|·····0.3·ms······| | ||
| 113 | _updated·as·of·August·2026·using·CPython·3.12,·Charset-Normalizer·3.5.1,·and·Chardet·7.5·inside·a·(libc·Debian)·container.·The·host·CPU·is·a·13th·gen·Intel·mobile·CPU.·We'll·no·longer·update·regularly·those·since·the·sub-ms·changes·aren't·meaningful·to·anyone·anymore._ | ||
| 98 | |·Package···········································|·99th·percentile·|·95th·percentile·|·50th·percentile·| | ||
| 99 | |---------------------------------------------------|:---------------:|:---------------:|:---------------:| | ||
| 100 | |·[chardet·7.4](https://github.com/chardet/chardet)·|······28·ms······|······16·ms······|·····<·1·ms······| | ||
| 101 | |·charset-normalizer································|······8·ms·······|······5·ms·······|······1·ms·······| | ||
| 102 | _updated·as·of·July·2026·using·CPython·3.12,·Charset-Normalizer·3.4.8,·and·Chardet·7.4.3_ | ||
| 103 | ~Chardet's·performance·on·larger·file·(1MB+)·are·very·poor.·Expect·huge·difference·on·large·payload.~·No·longer·the·case·since·Chardet·7.0+ | ||
| 104 | >·Stats·are·generated·using·4 | 114 | >·Stats·are·generated·using·477·files·using·default·parameters.·More·details·on·used·files,·see·GHA·workflows. |
| 105 | >·And·yes,·these·results·might·change·at·any·time.·The·dataset·can·be·updated·to·include·more·files. | 115 | >·And·yes,·these·results·might·change·at·any·time.·The·dataset·can·be·updated·to·include·more·files. |
| 106 | >·The·actual·delays·heavily·depends·on·your·CPU·capabilities.·The·factors·should·remain·the·same. | 116 | >·The·actual·delays·heavily·depends·on·your·CPU·capabilities.·The·factors·should·remain·the·same. |
| 107 | >·Chardet·claims·on·his·documentation·to·have·a·greater·accuracy·than·us·based·on·the·dataset·they·trained·Chardet·on(...) | 117 | >·Chardet·claims·on·his·documentation·to·have·a·greater·accuracy·than·us·based·on·the·dataset·they·trained·Chardet·on(...) |
| 108 | >·Well,·it's·normal,·the·opposite·would·have·been·worrying.·Whereas·charset-normalizer·don't·train·on·anything,·our·solution | ||
| 109 | >· | 118 | >·Whereas·charset-normalizer·don't·train·on·anything,·our·solution·is·based·on·a·completely·different·algorithm,·still·heuristic |
| 119 | >·through,·it·does·not·need·weights·across·every·encoding·tables. | ||
| 120 | [^3]:·cchardet·main·repository/package·was·discontinued.·we're·relying·on·a·known·fork·namely·faust-cchardet.·the·idea·remained·the·same:·uchardet·bindings. | ||
| 121 | [^4]:·Chardet·does·not·feed·the·complete·body·but·rather·a·limited·part·of·it,·because·the·algorithm·doesn't·scale·properly·with·larger·samples.·Feeding·the·whole·content·slow·things·to·0.8·ms·(from·the·0.5ms·avg).·While·we·do·not·skip·content·in·order·for·us·to·guarantee·a·usable·result·each·and·every·time.·We·attempted·to·feed·a·272·MiB·UTF-8·(Reddit·archive·on·comments/posts)·file·in·Chardet·uncapped·and·waited·3.4s·while·Charset-Normalizer·took·0.3s,·this·is·a·10-fold·speedup. | ||
| 122 | [^5]:·Uncapped·max_bytes·(no·truncating·of·content) | ||
| 110 | ##·✨·Installation | 123 | ##·✨·Installation |
| 111 | Using·pip: | 124 | Using·pip: |
| 112 | ```sh | 125 | ```sh |
| 113 | pip·install·charset-normalizer·-U | 126 | pip·install·charset-normalizer·-U |
| Offset 296, 14 lines modified | Offset 310, 65 lines modified | ||
| 296 | [](https://www.bestpractices.dev/projects/7297) | 310 | [](https://www.bestpractices.dev/projects/7297) |
| 297 | #·Changelog | 311 | #·Changelog |
| 298 | All·notable·changes·to·charset-normalizer·will·be·documented·in·this·file.·This·project·adheres·to·[Semantic·Versioning](https://semver.org/spec/v2.0.0.html). | 312 | All·notable·changes·to·charset-normalizer·will·be·documented·in·this·file.·This·project·adheres·to·[Semantic·Versioning](https://semver.org/spec/v2.0.0.html). |
| 299 | The·format·is·based·on·[Keep·a·Changelog](https://keepachangelog.com/en/1.0.0/). | 313 | The·format·is·based·on·[Keep·a·Changelog](https://keepachangelog.com/en/1.0.0/). |
| 314 | ##·[3.5.2](https://github.com/Ousret/charset_normalizer/compare/3.5.1...3.5.2)·(2026-09-29) | ||
| 315 | ###·Changed | ||
| 316 | -·Raised·the·Cython·upper·bound·to·`<3.4`·for·native·builds.·The·bound·remains·`<3.3`·for | ||
| 317 | ··`abi3`·builds·to·preserve·compatibility·with·the·Python·3.7·Limited·API. | ||
| Max diff block lines reached; 224/17760 bytes (1.26%) of diff not shown. | |||
| Offset 1, 8 lines modified | Offset 1, 8 lines modified | ||
| 1 | Metadata-Version:·2.4·Name:·charset-normalizer·Version:·3. | 1 | Metadata-Version:·2.4·Name:·charset-normalizer·Version:·3.5.2·Summary:·The·Real |
| 2 | First·Universal·Charset·Detector.·Open,·modern·and·actively·maintained | 2 | First·Universal·Charset·Detector.·Open,·modern·and·actively·maintained |
| 3 | alternative·to·Chardet.·Author-email:·"Ahmed·R.·TAHRI" | 3 | alternative·to·Chardet.·Author-email:·"Ahmed·R.·TAHRI" |
| 4 | proton.me>·Maintainer-email:·"Ahmed·R.·TAHRI" | 4 | proton.me>·Maintainer-email:·"Ahmed·R.·TAHRI" |
| 5 | proton.me>·License:·MIT·Project-URL:·Changelog,·https://github.com/jawah/ | 5 | proton.me>·License:·MIT·Project-URL:·Changelog,·https://github.com/jawah/ |
| 6 | charset_normalizer/blob/master/CHANGELOG.md·Project-URL:·Documentation,·https:/ | 6 | charset_normalizer/blob/master/CHANGELOG.md·Project-URL:·Documentation,·https:/ |
| 7 | /charset-normalizer.readthedocs.io/·Project-URL:·Code,·https://github.com/ | 7 | /charset-normalizer.readthedocs.io/·Project-URL:·Code,·https://github.com/ |
| 8 | jawah/charset_normalizer·Project-URL:·Issue·tracker,·https://github.com/jawah/ | 8 | jawah/charset_normalizer·Project-URL:·Issue·tracker,·https://github.com/jawah/ |
| Offset 12, 22 lines modified | Offset 12, 23 lines modified | ||
| 12 | Classifier:·Operating·System·::·OS·Independent·Classifier:·Programming·Language | 12 | Classifier:·Operating·System·::·OS·Independent·Classifier:·Programming·Language |
| 13 | ::·Python·Classifier:·Programming·Language·::·Python·::·3·Classifier: | 13 | ::·Python·Classifier:·Programming·Language·::·Python·::·3·Classifier: |
| 14 | Programming·Language·::·Python·::·3.7·Classifier:·Programming·Language·:: | 14 | Programming·Language·::·Python·::·3.7·Classifier:·Programming·Language·:: |
| 15 | Python·::·3.8·Classifier:·Programming·Language·::·Python·::·3.9·Classifier: | 15 | Python·::·3.8·Classifier:·Programming·Language·::·Python·::·3.9·Classifier: |
| 16 | Programming·Language·::·Python·::·3.10·Classifier:·Programming·Language·:: | 16 | Programming·Language·::·Python·::·3.10·Classifier:·Programming·Language·:: |
| 17 | Python·::·3.11·Classifier:·Programming·Language·::·Python·::·3.12·Classifier: | 17 | Python·::·3.11·Classifier:·Programming·Language·::·Python·::·3.12·Classifier: |
| 18 | Programming·Language·::·Python·::·3.13·Classifier:·Programming·Language·:: | 18 | Programming·Language·::·Python·::·3.13·Classifier:·Programming·Language·:: |
| 19 | Python·::·3.14·Classifier:·Programming·Language·::·Python·::·3· | 19 | Python·::·3.14·Classifier:·Programming·Language·::·Python·::·3.15·Classifier: |
| 20 | Classifier:·Programming·Language·::·Python·::·Implementation·::·CPython | ||
| 21 | Classifier:·Programming·Language·::·Python·::·Implementation·::·PyPy | ||
| 22 | Classifier:·Programming·Language·::·Python·::·Free·Threading·::·4·-·Resilient | ||
| 23 | Classifier:·Topic·::·Text·Processing·::·Linguistic·Classifier:·Topic·:: | ||
| 24 | Utilities·Classifier:·Typing·::·Typed·Requires-Python:·>=3.7·Description- | ||
| 25 | Content-Type:·text/markdown·License-File:·LICENSE·Provides-Extra:·unicode- | ||
| 26 | 20 | Programming·Language·::·Python·::·3·::·Only·Classifier:·Programming·Language·:: | |
| 21 | Python·::·Implementation·::·CPython·Classifier:·Programming·Language·::·Python | ||
| 22 | ::·Implementation·::·PyPy·Classifier:·Programming·Language·::·Python·::·Free | ||
| 23 | Threading·::·4·-·Resilient·Classifier:·Environment·::·WebAssembly·Classifier: | ||
| 24 | Environment·::·WebAssembly·::·Emscripten·Classifier:·Topic·::·Text·Processing | ||
| 25 | ::·Linguistic·Classifier:·Topic·::·Utilities·Classifier:·Typing·::·Typed | ||
| 26 | Requires-Python:·>=3.7·Description-Content-Type:·text/markdown·License-File: | ||
| 27 | LICENSE·Provides-Extra:·unicode-backport·Dynamic:·license-file | ||
| 27 | ··············*\x8**\x8**\x8**\x8**\x8**\x8*·C\x8Ch\x8ha\x8ar\x8rs\x8se\x8et\x8t·D\x8De\x8et\x8te\x8ec\x8ct\x8ti\x8io\x8on\x8n,\x8,·f\x8fo\x8or\x8r·E\x8Ev\x8ve\x8er\x8ry\x8yo\x8on\x8ne\x8e·?\x8ð?\x8?\x8?\x8·*\x8**\x8**\x8**\x8**\x8**\x8* | 28 | ··············*\x8**\x8**\x8**\x8**\x8**\x8*·C\x8Ch\x8ha\x8ar\x8rs\x8se\x8et\x8t·D\x8De\x8et\x8te\x8ec\x8ct\x8ti\x8io\x8on\x8n,\x8,·f\x8fo\x8or\x8r·E\x8Ev\x8ve\x8er\x8ry\x8yo\x8on\x8ne\x8e·?\x8ð?\x8?\x8?\x8·*\x8**\x8**\x8**\x8**\x8**\x8* |
| 28 | ···················The·Real·First·Universal·Charset·Detector | 29 | ···················The·Real·First·Universal·Charset·Detector |
| 29 | ··_\x8[_\x8h_\x8t_\x8t_\x8p_\x8s_\x8:_\x8/_\x8/_\x8i_\x8m_\x8g_\x8._\x8s_\x8h_\x8i_\x8e_\x8l_\x8d_\x8s_\x8._\x8i_\x8o_\x8/_\x8p_\x8y_\x8p_\x8i_\x8/_\x8p_\x8y_\x8v_\x8e_\x8r_\x8s_\x8i_\x8o_\x8n_\x8s_\x8/_\x8c_\x8h_\x8a_\x8r_\x8s_\x8e_\x8t_\x8__\x8n_\x8o_\x8r_\x8m_\x8a_\x8l_\x8i_\x8z_\x8e_\x8r_\x8._\x8s_\x8v_\x8g_\x8?_\x8o_\x8r_\x8a_\x8n_\x8g_\x8e_\x8=_\x8b_\x8l_\x8u_\x8e_\x8] | 30 | ··_\x8[_\x8h_\x8t_\x8t_\x8p_\x8s_\x8:_\x8/_\x8/_\x8i_\x8m_\x8g_\x8._\x8s_\x8h_\x8i_\x8e_\x8l_\x8d_\x8s_\x8._\x8i_\x8o_\x8/_\x8p_\x8y_\x8p_\x8i_\x8/_\x8p_\x8y_\x8v_\x8e_\x8r_\x8s_\x8i_\x8o_\x8n_\x8s_\x8/_\x8c_\x8h_\x8a_\x8r_\x8s_\x8e_\x8t_\x8__\x8n_\x8o_\x8r_\x8m_\x8a_\x8l_\x8i_\x8z_\x8e_\x8r_\x8._\x8s_\x8v_\x8g_\x8?_\x8o_\x8r_\x8a_\x8n_\x8g_\x8e_\x8=_\x8b_\x8l_\x8u_\x8e_\x8] |
| 30 | ·_\x8[_\x8D_\x8o_\x8w_\x8n_\x8l_\x8o_\x8a_\x8d_\x8·_\x8C_\x8o_\x8u_\x8n_\x8t_\x8·_\x8T_\x8o_\x8t_\x8a_\x8l_\x8]_\x8[_\x8h_\x8t_\x8t_\x8p_\x8s_\x8:_\x8/_\x8/_\x8b_\x8e_\x8s_\x8t_\x8p_\x8r_\x8a_\x8c_\x8t_\x8i_\x8c_\x8e_\x8s_\x8._\x8c_\x8o_\x8r_\x8e_\x8i_\x8n_\x8f_\x8r_\x8a_\x8s_\x8t_\x8r_\x8u_\x8c_\x8t_\x8u_\x8r_\x8e_\x8._\x8o_\x8r_\x8g_\x8/_\x8p_\x8r_\x8o_\x8j_\x8e_\x8c_\x8t_\x8s_\x8/ | 31 | ·_\x8[_\x8D_\x8o_\x8w_\x8n_\x8l_\x8o_\x8a_\x8d_\x8·_\x8C_\x8o_\x8u_\x8n_\x8t_\x8·_\x8T_\x8o_\x8t_\x8a_\x8l_\x8]_\x8[_\x8h_\x8t_\x8t_\x8p_\x8s_\x8:_\x8/_\x8/_\x8b_\x8e_\x8s_\x8t_\x8p_\x8r_\x8a_\x8c_\x8t_\x8i_\x8c_\x8e_\x8s_\x8._\x8c_\x8o_\x8r_\x8e_\x8i_\x8n_\x8f_\x8r_\x8a_\x8s_\x8t_\x8r_\x8u_\x8c_\x8t_\x8u_\x8r_\x8e_\x8._\x8o_\x8r_\x8g_\x8/_\x8p_\x8r_\x8o_\x8j_\x8e_\x8c_\x8t_\x8s_\x8/ |
| 31 | ··································_\x87_\x82_\x89_\x87_\x8/_\x8b_\x8a_\x8d_\x8g_\x8e_\x8] | 32 | ··································_\x87_\x82_\x89_\x87_\x8/_\x8b_\x8a_\x8d_\x8g_\x8e_\x8] |
| 32 | ·······························Featured·Packages | 33 | ·······························Featured·Packages |
| 33 | ·························_\x8[_\x8S_\x8t_\x8a_\x8t_\x8i_\x8c_\x8·_\x8B_\x8a_\x8d_\x8g_\x8e_\x8]_\x8[_\x8S_\x8t_\x8a_\x8t_\x8i_\x8c_\x8·_\x8B_\x8a_\x8d_\x8g_\x8e_\x8] | 34 | ·························_\x8[_\x8S_\x8t_\x8a_\x8t_\x8i_\x8c_\x8·_\x8B_\x8a_\x8d_\x8g_\x8e_\x8]_\x8[_\x8S_\x8t_\x8a_\x8t_\x8i_\x8c_\x8·_\x8B_\x8a_\x8d_\x8g_\x8e_\x8] |
| Offset 40, 126 lines modified | Offset 41, 154 lines modified | ||
| 40 | and·yes,·it·would·work·as-is.·This·project·offers·you·an·alternative·to | 41 | and·yes,·it·would·work·as-is.·This·project·offers·you·an·alternative·to |
| 41 | **Universal·Charset·Encoding·Detector**,·also·known·as·**Chardet**.·|·Feature·| | 42 | **Universal·Charset·Encoding·Detector**,·also·known·as·**Chardet**.·|·Feature·| |
| 42 | [Chardet](https://github.com/chardet/chardet)·|·Charset·Normalizer·|·[cChardet] | 43 | [Chardet](https://github.com/chardet/chardet)·|·Charset·Normalizer·|·[cChardet] |
| 43 | (https://github.com/PyYoshi/cChardet)·|·|-------------------------------------- | 44 | (https://github.com/PyYoshi/cChardet)·|·|-------------------------------------- |
| 44 | ------------|:---------------------------------------------:|:----------------- | 45 | ------------|:---------------------------------------------:|:----------------- |
| 45 | ------------------------------------------------------------------------------: | 46 | ------------------------------------------------------------------------------: |
| 46 | |:-----------------------------------------------:|·|·`Fast`·|·â ·|·â ·|·â | 47 | |:-----------------------------------------------:|·|·`Fast`·|·â ·|·â ·|·â |
| 47 | |·|·`Universal`[^1]·|·â·|·â ·|·â·|·|·`Reliable`·**without** | ||
| 48 | distinguishable·standards·|·â ·|·â ·|·â ·|·|·`Reliable`·**with** | ||
| 49 | distinguishable·standards·|·â ·|·â ·|·â ·|·|·`License`·|·_Disputed_[^2] | ||
| 50 | 48 | |·|·`Fast·on·large·content·(uncapped)`·|·â·|·â ·|·â·|·|·`Universal`[^1]·| | |
| 49 | â·|·â ·|·â·|·|·`Reliable`·**without**·distinguishable·standards·|·â ·| | ||
| 50 | â ·|·â ·|·|·`Reliable`·**with**·distinguishable·standards·|·â ·|·â ·|·â ·| | ||
| 51 | |·`License`·|·_0BSD_[^2] | ||
| 52 | _disputed_·|·MIT·|·MPL-1.1 | ||
| 51 | _restrictive_·|·|·`Native·Python`·|·â ·|·â ·|·â·|·|·`Detect·spoken | 53 | _restrictive_·|·|·`Native·Python`·|·â ·|·â ·|·â·|·|·`Detect·spoken |
| 52 | language`·|·â
·|·â
·|·N/A·|·|·`UnicodeDecodeError·Safety`·|·â | 54 | language`·|·â ·|·â ·|·N/A·|·|·`UnicodeDecodeError·Safety`·|·â·|·â ·|·â·| |
| 53 | |·`Whl·Size | 55 | |·`Whl·Size`·|·~1200·kB·|·~250·kB·|·~200·kB·|·|·`Supported·Encoding`·|·99·| |
| 54 | [99](https://charset-normalizer.readthedocs.io/en/latest/user/ | 56 | [99](https://charset-normalizer.readthedocs.io/en/latest/user/ |
| 55 | support.html#supported-encodings)·|·40·|·|·`Can·register·custom·encoding`·|·â | 57 | support.html#supported-encodings)·|·40·|·|·`Can·register·custom·encoding`·|·â |
| 56 | |·â ·|·â·| | 58 | |·â ·|·â·| |
| 57 | ··················[Reading·Normalized·Text][Cat·Reading·Text] | 59 | ··················[Reading·Normalized·Text][Cat·Reading·Text] |
| 58 | [^1]:·They·are·clearly·using·specific·code·for·a·specific·encoding·even·if | 60 | [^1]:·They·are·clearly·using·specific·code·for·a·specific·encoding·even·if |
| 59 | covering·most·of·used·one.·[^2]:·Chardet·7.0+·was·relicensed·from·LGPL-2.1·to | ||
| 60 | MIT·following·an·AI-assisted·rewrite.·This·relicensing·is·disputed·on·two | ||
| 61 | independent·grounds:·**(a)**·the·original·author·[contests](https://github.com/ | ||
| 62 | chardet/chardet/issues/327)·that·the·maintainer·had·the·right·to·relicense, | ||
| 63 | arguing·the·rewrite·is·a·derivative·work·of·the·LGPL-licensed·codebase·since·it | ||
| 64 | was·not·a·clean·room·implementation;·**(b)**·the·copyright·claim·itself·is | ||
| 65 | [questionable](https://github.com/chardet/chardet/issues/334)·given·the·code | ||
| 66 | was·primarily·generated·by·an·LLM,·and·AI-generated·output·may·not·be | ||
| 67 | copyrightable·under·most·jurisdictions.·Either·issue·alone·could·undermine·the | ||
| 68 | MIT·license.·Beyond·licensing,·the·rewrite·raises·questions·about·responsible | ||
| 69 | use·of·AI·in·open·source:·key·architectural·ideas·pioneered·by·charset- | ||
| 70 | normalizer·-·notably·decode-first·validity·filtering·(our·foundational·approach | ||
| 71 | since·v1)·and·encoding·pairwise·similarity·with·the·same·algorithm·and | ||
| 72 | threshold·â·surfaced·in·chardet·7·without·acknowledgment.·The·project·also | ||
| 73 | imported·test·files·from·charset-normalizer·to·train·and·benchmark·against·it, | ||
| 74 | then·claimed·superior·accuracy·on·those·very·files.·Charset-normalizer·has | ||
| 75 | always·been·MIT-licensed,·encoding-agnostic·by·design,·and·built·on·a | ||
| 76 | verifiable·human-authored·history.·##·â¡·Performance·This·package·offer·better | ||
| 77 | performances·against·Chardet.·Here·are·some·numbers.·|·Package·|·Accuracy·| | ||
| 78 | Mean·per·file·(ms)·|·File·per·sec·(est)·|·|------------------------------------ | ||
| 79 | ---------------|:--------:|:------------------:|:------------------:|·| | ||
| 80 | [chardet·7.4](https://github.com/chardet/chardet)·|·89·%·|·3·ms·|·333·file/sec | ||
| 81 | 61 | covering·most·of·them.·[^2]:·Chardet·7·replaced·the·historical·LGPL-licensed | |
| 62 | implementation·with·an·AI-assisted·rewrite,·initially·distributed·under·MIT·and | ||
| 63 | later·under·0BSD.·The·original·author·[contests](https://github.com/chardet/ | ||
| 64 | chardet/issues/327)·that·the·rewrite·was·sufficiently·independent·to·permit | ||
| 65 | relicensing,·while·Chardet's·maintainer·maintains·that·it·is·a·new,·non- | ||
| 66 | derivative·implementation.·A·separate·[discussion](https://github.com/chardet/ | ||
| 67 | chardet/issues/334)·raises·questions·about·copyright·ownership·and·licensing·of | ||
| 68 | substantially·AI-generated·code.·Neither·unresolved·question·is·presented·here | ||
| 69 | as·settled·law.·The·concern·is·broader·than·whether·ideas,·APIs,·or·observable | ||
| 70 | behavior·are·copyrightable.·Independent·implementations·are·essential·to·open- | ||
| 71 | source·competition.·The·ethical·question·is·whether·a·maintainer·with·extensive | ||
| 72 | access·to·a·reciprocal·project's·source,·architecture,·tests,·behavior, | ||
| 73 | community,·and·reputation·can·use·an·LLM·to·recreate·the·same·product·under·the | ||
| 74 | same·package·identity,·then·treat·the·generated·implementation·as·a·provenance | ||
| 75 | reset·that·extinguishes·the·project's·reciprocal·licensing·obligations·and | ||
| 76 | contributor·expectations.·Responsible·AI·use·in·open·source·requires·more·than | ||
| 77 | producing·text·that·differs·from·the·historical·source:·it·requires·transparent | ||
| 78 | provenance,·respect·for·project·lineage,·meaningful·attribution,·accountable | ||
| 79 | human·review,·and·consideration·for·the·social·agreement·under·which·earlier | ||
| 80 | contributors·participated.·If·automated·rewriting·becomes·an·accepted·way·to | ||
| 81 | retain·a·project's·name,·users,·and·accumulated·reputation·while·discarding·its | ||
| 82 | reciprocal·license,·it·risks·weakening·the·trust·and·incentives·on·which·FOSS | ||
| 83 | depends.·Early·Chardet·7.x·development·and·evaluation·also·incorporated·files | ||
| 84 | originating·from·charset-normalizer's·test·corpus.·Results·measured·on·data | ||
| 85 | that·influenced·implementation·or·model·development·are·not·independent | ||
| 86 | validation.·Charset-normalizer·has·been·MIT-licensed·since·inception·and | ||
| 87 | originates·from·a·continuous·human-designed,·encoding-agnostic·project·history. | ||
| 88 | AI·assistance·may·be·used,·but·every·proposed·change·remains·subject·to | ||
| 89 | maintainer·review,·adjustment,·testing,·and·accountability;·AI·is·an | ||
| 90 | engineering·aid,·not·a·mechanism·for·erasing·provenance·or·project·lineage.·An | ||
| 91 | attentive·eye·will·see·that·some·aspects·lead·by·us·are·magically·found·in | ||
| 92 | Chardet.·##·â¡·Performance·This·package·offer·similar·performances·in·general | ||
| 93 | against·Chardet.·Expect·10X·faster·with·large·contents·when·you·uncap·Chardet | ||
| 94 | max_bytes·default·assumption.·|·Package·|·Accuracy·|·Mean·per·file·(ms)·|·|---- | ||
| 95 | ----------------|:--------:|:---------------------:|·|·Chardet·|·99·%·|·0.4·ms | ||
| 96 | [^4]·0.6·ms[^5]·|·|·charset-normalizer·|·98·%·|·0.4·ms·|·|·cchardet[^3]·|·94·% | ||
| 97 | |·0.6·ms·|·_Well,·sub-ms·detectors·made·them·extremely·discrete·in·the·overall | ||
| 98 | runtime.·Competitors·can·still·win·individual·measurements,·especially·capped | ||
| 99 | Chardet·on·small-file·median·latency.·But·when·performance,·accuracy,·binary | ||
| 100 | handling,·validation·strength,·portability,·and·maintainability·are·considered | ||
| 101 | together,·charset-normalizer·is·the·stronger·package._·|·Package·|·99th | ||
| 82 | percentile·|·95th·percentile·|·50th·percentile·|·|-------------------- | 102 | percentile·|·95th·percentile·|·50th·percentile·|·|--------------------|:------- |
| 83 | ----------------------|:---------------:|:---------------:|:---------------:|·| | ||
| Max diff block lines reached; 4446/27253 bytes (16.31%) of diff not shown. | |||
| Offset 1, 10 lines modified | Offset 1, 10 lines modified | ||
| 1 | Metadata-Version:·2. | 1 | Metadata-Version:·2.5 |
| 2 | Name:·cssselect2 | 2 | Name:·cssselect2 |
| 3 | Version:·0. | 3 | Version:·0.10.1 |
| 4 | Summary:·CSS·selectors·for·Python·ElementTree | 4 | Summary:·CSS·selectors·for·Python·ElementTree |
| 5 | Keywords:·css,elementtree | 5 | Keywords:·css,elementtree |
| 6 | Author-email:·Simon·Sapin·<simon.sapin@exyr.org> | 6 | Author-email:·Simon·Sapin·<simon.sapin@exyr.org> |
| 7 | Maintainer-email:·CourtBouillon·<contact@courtbouillon.org> | 7 | Maintainer-email:·CourtBouillon·<contact@courtbouillon.org> |
| 8 | Requires-Python:·>=3.10 | 8 | Requires-Python:·>=3.10 |
| 9 | Description-Content-Type:·text/x-rst | 9 | Description-Content-Type:·text/x-rst |
| 10 | Classifier:·Development·Status·::·5·-·Production/Stable | 10 | Classifier:·Development·Status·::·5·-·Production/Stable |
| Offset 33, 14 lines modified | Offset 33, 15 lines modified | ||
| 33 | Project-URL:·Code,·https://github.com/Kozea/cssselect2/ | 33 | Project-URL:·Code,·https://github.com/Kozea/cssselect2/ |
| 34 | Project-URL:·Documentation,·https://doc.courtbouillon.org/cssselect2/ | 34 | Project-URL:·Documentation,·https://doc.courtbouillon.org/cssselect2/ |
| 35 | Project-URL:·Donation,·https://opencollective.com/courtbouillon | 35 | Project-URL:·Donation,·https://opencollective.com/courtbouillon |
| 36 | Project-URL:·Homepage,·https://doc.courtbouillon.org/cssselect2/ | 36 | Project-URL:·Homepage,·https://doc.courtbouillon.org/cssselect2/ |
| 37 | Project-URL:·Issues,·https://github.com/Kozea/cssselect2/issues | 37 | Project-URL:·Issues,·https://github.com/Kozea/cssselect2/issues |
| 38 | Provides-Extra:·doc | 38 | Provides-Extra:·doc |
| 39 | Provides-Extra:·test | 39 | Provides-Extra:·test |
| 40 | Import-Name:·cssselect2 | ||
| 40 | cssselect2·is·a·straightforward·implementation·of·CSS4·Selectors·for·markup | 41 | cssselect2·is·a·straightforward·implementation·of·CSS4·Selectors·for·markup |
| 41 | documents·(HTML,·XML,·etc.)·that·can·be·read·by·ElementTree-like·parsers | 42 | documents·(HTML,·XML,·etc.)·that·can·be·read·by·ElementTree-like·parsers |
| 42 | (including·cElementTree,·lxml,·html5lib,·etc.) | 43 | (including·cElementTree,·lxml,·html5lib,·etc.) |
| 43 | *·Free·software:·BSD·license | 44 | *·Free·software:·BSD·license |
| 44 | *·For·Python·3.10+,·tested·on·CPython·and·PyPy | 45 | *·For·Python·3.10+,·tested·on·CPython·and·PyPy |
| Offset 1, 10 lines modified | Offset 1, 10 lines modified | ||
| 1 | Metadata-Version:·2. | 1 | Metadata-Version:·2.5 |
| 2 | Name:·filelock | 2 | Name:·filelock |
| 3 | Version:· | 3 | Version:·4.2.4 |
| 4 | Summary:·A·platform·independent·file·lock. | 4 | Summary:·A·platform·independent·file·lock. |
| 5 | Project-URL:·Documentation,·https://py-filelock.readthedocs.io | 5 | Project-URL:·Documentation,·https://py-filelock.readthedocs.io |
| 6 | Project-URL:·Homepage,·https://github.com/tox-dev/py-filelock | 6 | Project-URL:·Homepage,·https://github.com/tox-dev/py-filelock |
| 7 | Project-URL:·Source,·https://github.com/tox-dev/py-filelock | 7 | Project-URL:·Source,·https://github.com/tox-dev/py-filelock |
| 8 | Project-URL:·Tracker,·https://github.com/tox-dev/py-filelock/issues | 8 | Project-URL:·Tracker,·https://github.com/tox-dev/py-filelock/issues |
| 9 | Maintainer-email:·Bernát·Gábor·<gaborjbernat@gmail.com> | 9 | Maintainer-email:·Bernát·Gábor·<gaborjbernat@gmail.com> |
| 10 | License-Expression:·MIT | 10 | License-Expression:·MIT |
| Offset 12, 24 lines modified | Offset 12, 23 lines modified | ||
| 12 | Keywords:·application,cache,directory,log,user | 12 | Keywords:·application,cache,directory,log,user |
| 13 | Classifier:·Development·Status·::·5·-·Production/Stable | 13 | Classifier:·Development·Status·::·5·-·Production/Stable |
| 14 | Classifier:·Intended·Audience·::·Developers | 14 | Classifier:·Intended·Audience·::·Developers |
| 15 | Classifier:·License·::·OSI·Approved·::·MIT·License | 15 | Classifier:·License·::·OSI·Approved·::·MIT·License |
| 16 | Classifier:·Operating·System·::·OS·Independent | 16 | Classifier:·Operating·System·::·OS·Independent |
| 17 | Classifier:·Programming·Language·::·Python | 17 | Classifier:·Programming·Language·::·Python |
| 18 | Classifier:·Programming·Language·::·Python·::·3·::·Only | 18 | Classifier:·Programming·Language·::·Python·::·3·::·Only |
| 19 | Classifier:·Programming·Language·::·Python·::·3.10 | ||
| 20 | Classifier:·Programming·Language·::·Python·::·3.11 | 19 | Classifier:·Programming·Language·::·Python·::·3.11 |
| 21 | Classifier:·Programming·Language·::·Python·::·3.12 | 20 | Classifier:·Programming·Language·::·Python·::·3.12 |
| 22 | Classifier:·Programming·Language·::·Python·::·3.13 | 21 | Classifier:·Programming·Language·::·Python·::·3.13 |
| 23 | Classifier:·Programming·Language·::·Python·::·3.14 | 22 | Classifier:·Programming·Language·::·Python·::·3.14 |
| 24 | Classifier:·Programming·Language·::·Python·::·3.15 | 23 | Classifier:·Programming·Language·::·Python·::·3.15 |
| 25 | Classifier:·Topic·::·Internet | 24 | Classifier:·Topic·::·Internet |
| 26 | Classifier:·Topic·::·Software·Development·::·Libraries | 25 | Classifier:·Topic·::·Software·Development·::·Libraries |
| 27 | Classifier:·Topic·::·System | 26 | Classifier:·Topic·::·System |
| 28 | Requires-Python:·>=3.1 | 27 | Requires-Python:·>=3.11 |
| 29 | Description-Content-Type:·text/markdown | 28 | Description-Content-Type:·text/markdown |
| 30 | #·filelock | 29 | #·filelock |
| 31 | [](https://pypi.org/project/filelock/) | 30 | [](https://pypi.org/project/filelock/) |
| 32 | [](https://pypi.org/project/filelock/) | 31 | [](https://pypi.org/project/filelock/) |
| 33 | [](https://py-filelock.readthedocs.io/en/latest/?badge=latest) | 32 | [](https://py-filelock.readthedocs.io/en/latest/?badge=latest) |
| Offset 1, 10 lines modified | Offset 1, 10 lines modified | ||
| 1 | Metadata-Version:·2.4 | 1 | Metadata-Version:·2.4 |
| 2 | Name:·reportlab | 2 | Name:·reportlab |
| 3 | Version:·5.0. | 3 | Version:·5.0.1 |
| 4 | Summary:·The·Reportlab·Toolkit | 4 | Summary:·The·Reportlab·Toolkit |
| 5 | Home-page:·https://www.reportlab.com/ | 5 | Home-page:·https://www.reportlab.com/ |
| 6 | Author:·Andy·Robinson,·Robin·Becker,·the·ReportLab·team·and·the·community | 6 | Author:·Andy·Robinson,·Robin·Becker,·the·ReportLab·team·and·the·community |
| 7 | Author-email:·reportlab-users@lists2.reportlab.com | 7 | Author-email:·reportlab-users@lists2.reportlab.com |
| 8 | License:·BSD·license·(see·license.txt·for·details),·Copyright·(c)·2000-2025,·ReportLab·Inc. | 8 | License:·BSD·license·(see·license.txt·for·details),·Copyright·(c)·2000-2025,·ReportLab·Inc. |
| 9 | Classifier:·Development·Status·::·5·-·Production/Stable | 9 | Classifier:·Development·Status·::·5·-·Production/Stable |
| 10 | Classifier:·Intended·Audience·::·Developers | 10 | Classifier:·Intended·Audience·::·Developers |
| Offset 1, 35 lines modified | Offset 1, 34 lines modified | ||
| 1 | Metadata-Version:·2. | 1 | Metadata-Version:·2.5 |
| 2 | Name:·soupsieve | 2 | Name:·soupsieve |
| 3 | Version:· | 3 | Version:·3.0.3 |
| 4 | Summary:·A·modern·CSS·selector·implementation·for·Beautiful·Soup. | 4 | Summary:·A·modern·CSS·selector·implementation·for·Beautiful·Soup. |
| 5 | Project-URL:·Homepage,·https://github.com/facelessuser/soupsieve | 5 | Project-URL:·Homepage,·https://github.com/facelessuser/soupsieve |
| 6 | Author-email:·Isaac·Muse·<Isaac.Muse@gmail.com> | 6 | Author-email:·Isaac·Muse·<Isaac.Muse@gmail.com> |
| 7 | License-Expression:·MIT | 7 | License-Expression:·MIT |
| 8 | License-File:·LICENSE.md | 8 | License-File:·LICENSE.md |
| 9 | Keywords:·CSS,HTML,XML,filter,query,selector,soup | 9 | Keywords:·CSS,HTML,XML,filter,query,selector,soup |
| 10 | Classifier:·Development·Status·::·5·-·Production/Stable | 10 | Classifier:·Development·Status·::·5·-·Production/Stable |
| 11 | Classifier:·Environment·::·Console | 11 | Classifier:·Environment·::·Console |
| 12 | Classifier:·Intended·Audience·::·Developers | 12 | Classifier:·Intended·Audience·::·Developers |
| 13 | Classifier:·License·::·OSI·Approved·::·MIT·License | 13 | Classifier:·License·::·OSI·Approved·::·MIT·License |
| 14 | Classifier:·Operating·System·::·OS·Independent | 14 | Classifier:·Operating·System·::·OS·Independent |
| 15 | Classifier:·Programming·Language·::·Python·::·3 | 15 | Classifier:·Programming·Language·::·Python·::·3 |
| 16 | Classifier:·Programming·Language·::·Python·::·3.10 | ||
| 17 | Classifier:·Programming·Language·::·Python·::·3.11 | 16 | Classifier:·Programming·Language·::·Python·::·3.11 |
| 18 | Classifier:·Programming·Language·::·Python·::·3.12 | 17 | Classifier:·Programming·Language·::·Python·::·3.12 |
| 19 | Classifier:·Programming·Language·::·Python·::·3.13 | 18 | Classifier:·Programming·Language·::·Python·::·3.13 |
| 20 | Classifier:·Programming·Language·::·Python·::·3.14 | 19 | Classifier:·Programming·Language·::·Python·::·3.14 |
| 20 | Classifier:·Programming·Language·::·Python·::·3.15 | ||
| 21 | Classifier:·Topic·::·Internet·::·WWW/HTTP·::·Dynamic·Content | 21 | Classifier:·Topic·::·Internet·::·WWW/HTTP·::·Dynamic·Content |
| 22 | Classifier:·Topic·::·Software·Development·::·Libraries·::·Python·Modules | 22 | Classifier:·Topic·::·Software·Development·::·Libraries·::·Python·Modules |
| 23 | Classifier:·Typing·::·Typed | 23 | Classifier:·Typing·::·Typed |
| 24 | Requires-Python:·>=3.1 | 24 | Requires-Python:·>=3.11.5 |
| 25 | Description-Content-Type:·text/markdown | 25 | Description-Content-Type:·text/markdown |
| 26 | [![Donate·via·PayPal][donate-image]][donate-link] | 26 | [![Donate·via·PayPal][donate-image]][donate-link] |
| 27 | [![Build][github-ci-image]][github-ci-link] | ||
| 28 | [![Coverage·Status][codecov-image]][codecov-link] | 27 | [![Coverage·Status][codecov-image]][codecov-link] |
| 29 | [![PyPI·Version][pypi-image]][pypi-link] | 28 | [![PyPI·Version][pypi-image]][pypi-link] |
| 30 | [![PyPI·Downloads][pypi-down]][pypi-link] | 29 | [![PyPI·Downloads][pypi-down]][pypi-link] |
| 31 | [![PyPI·-·Python·Version][python-image]][pypi-link] | 30 | [![PyPI·-·Python·Version][python-image]][pypi-link] |
| 32 | [![License][license-image-mit]][license-link] | 31 | [![License][license-image-mit]][license-link] |
| 33 | #·Soup·Sieve | 32 | #·Soup·Sieve |
| Offset 61, 51 lines modified | Offset 60, 48 lines modified | ||
| 61 | -·and·[many·more](https://facelessuser.github.io/soupsieve/selectors/) | 60 | -·and·[many·more](https://facelessuser.github.io/soupsieve/selectors/) |
| 62 | ##·Installation | 61 | ##·Installation |
| 63 | You·must·have·Beautiful·Soup·already·installed: | 62 | You·must·have·Beautiful·Soup·already·installed: |
| 64 | ``` | 63 | ```console |
| 65 | pip·install·beautifulsoup4 | 64 | $·pip·install·beautifulsoup4 |
| 66 | ``` | 65 | ``` |
| 67 | In·most·cases,·assuming·you've·installed·version·4.7.0,·that·should·be·all·you·need·to·do,·but·if·you've·installed·via | 66 | In·most·cases,·assuming·you've·installed·version·4.7.0,·that·should·be·all·you·need·to·do,·but·if·you've·installed·via |
| 68 | some·alternative·method,·and·Soup·Sieve·is·not·automatically·installed,·you·can·install·it·directly: | 67 | some·alternative·method,·and·Soup·Sieve·is·not·automatically·installed,·you·can·install·it·directly: |
| 69 | ``` | 68 | ```console |
| 70 | pip·install·soupsieve | 69 | $·pip·install·soupsieve |
| 71 | ``` | 70 | ``` |
| 72 | If·you·want·to·manually·install·it·from·source,·first·ensure·that·[`build`](https://pypi.org/project/build/)·is | 71 | If·you·want·to·manually·install·it·from·source,·first·ensure·that·[`build`](https://pypi.org/project/build/)·is |
| 73 | installed: | 72 | installed: |
| 74 | ``` | 73 | ```console |
| 75 | pip·install·build | 74 | $·pip·install·build |
| 76 | ``` | 75 | ``` |
| 77 | Then·navigate·to·the·root·of·the·project·and·build·the·wheel·and·install·(replacing·`<ver>`·with·the·current·version): | 76 | Then·navigate·to·the·root·of·the·project·and·build·the·wheel·and·install·(replacing·`<ver>`·with·the·current·version): |
| 78 | ``` | 77 | ```console |
| 79 | python·-m·build·-w | 78 | $·python·-m·build·-w |
| 80 | pip·install·dist/soupsieve-<ver>-py3-none-any.whl | 79 | $·pip·install·dist/soupsieve-<ver>-py3-none-any.whl |
| 81 | ``` | 80 | ``` |
| 82 | ##·Documentation | 81 | ##·Documentation |
| 83 | Documentation·is·found·here:·https://facelessuser.github.io/soupsieve/. | 82 | Documentation·is·found·here:·https://facelessuser.github.io/soupsieve/. |
| 84 | ##·License | 83 | ##·License |
| 85 | MIT | 84 | MIT |
| 86 | [bs4]:·https://beautiful-soup-4.readthedocs.io/en/latest/# | 85 | [bs4]:·https://beautiful-soup-4.readthedocs.io/en/latest/# |
| 87 | [github-ci-image]:·https://github.com/facelessuser/soupsieve/workflows/build/badge.svg | ||
| 88 | [github-ci-link]:·https://github.com/facelessuser/soupsieve/actions?query=workflow%3Abuild+branch%3Amain | ||
| 89 | [codecov-image]:·https://img.shields.io/codecov/c/github/facelessuser/soupsieve/master.svg?logo=codecov&logoColor=aaaaaa&labelColor=333333 | 86 | [codecov-image]:·https://img.shields.io/codecov/c/github/facelessuser/soupsieve/master.svg?logo=codecov&logoColor=aaaaaa&labelColor=333333 |
| 90 | [codecov-link]:·https://codecov.io/github/facelessuser/soupsieve | 87 | [codecov-link]:·https://codecov.io/github/facelessuser/soupsieve |
| 91 | [pypi-image]:·https://img.shields.io/pypi/v/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 | 88 | [pypi-image]:·https://img.shields.io/pypi/v/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 |
| 92 | [pypi-down]:·https://img.shields.io/pypi/dm/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 | 89 | [pypi-down]:·https://img.shields.io/pypi/dm/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 |
| 93 | [pypi-link]:·https://pypi.python.org/pypi/soupsieve | 90 | [pypi-link]:·https://pypi.python.org/pypi/soupsieve |
| 94 | [python-image]:·https://img.shields.io/pypi/pyversions/soupsieve?logo=python&logoColor=aaaaaa&labelColor=333333 | 91 | [python-image]:·https://img.shields.io/pypi/pyversions/soupsieve?logo=python&logoColor=aaaaaa&labelColor=333333 |
| 95 | [license-image-mit]:·https://img.shields.io/badge/license-MIT-blue.svg?labelColor=333333 | 92 | [license-image-mit]:·https://img.shields.io/badge/license-MIT-blue.svg?labelColor=333333 |
| Offset 1, 10 lines modified | Offset 1, 10 lines modified | ||
| 1 | Metadata-Version:·2. | 1 | Metadata-Version:·2.5 |
| 2 | Name:·svglib | 2 | Name:·svglib |
| 3 | Version:·2. | 3 | Version:·2.3.0 |
| 4 | Summary:·A·pure-Python·library·for·reading·and·converting·SVG | 4 | Summary:·A·pure-Python·library·for·reading·and·converting·SVG |
| 5 | Project-URL:·Homepage,·https://github.com/deeplook/svglib | 5 | Project-URL:·Homepage,·https://github.com/deeplook/svglib |
| 6 | Author:·Dinu·Gherman | 6 | Author:·Dinu·Gherman |
| 7 | License-Expression:·LGPL-3.0-or-later | 7 | License-Expression:·LGPL-3.0-or-later |
| 8 | License-File:·LICENSE.txt | 8 | License-File:·LICENSE.txt |
| 9 | Keywords:·PDF,SVG,conversion,graphics,reportlab | 9 | Keywords:·PDF,SVG,conversion,graphics,reportlab |
| 10 | Classifier:·Development·Status·::·5·-·Production/Stable | 10 | Classifier:·Development·Status·::·5·-·Production/Stable |
| Offset 37, 15 lines modified | Offset 37, 15 lines modified | ||
| 37 | ········"bootstrap-native/x86_64/math.so":·"b5514fd77493532a51329d69d45b17d386dce4ec", | 37 | ········"bootstrap-native/x86_64/math.so":·"b5514fd77493532a51329d69d45b17d386dce4ec", |
| 38 | ········"bootstrap-native/x86_64/mmap.so":·"59d5bdc3daf49510b555e4b5ccfc3182646a8a4d", | 38 | ········"bootstrap-native/x86_64/mmap.so":·"59d5bdc3daf49510b555e4b5ccfc3182646a8a4d", |
| 39 | ········"bootstrap-native/x86_64/zlib.so":·"53c15fa2d19cdace60b2828b8e2af1f32e33c5bc", | 39 | ········"bootstrap-native/x86_64/zlib.so":·"53c15fa2d19cdace60b2828b8e2af1f32e33c5bc", |
| 40 | ········"bootstrap.imy":·"41a0b4122ce32432b247645932cfb831357a7724", | 40 | ········"bootstrap.imy":·"41a0b4122ce32432b247645932cfb831357a7724", |
| 41 | ········"cacert.pem":·"2c68212e96605210eddf740291862bdf59398aef", | 41 | ········"cacert.pem":·"2c68212e96605210eddf740291862bdf59398aef", |
| 42 | ········"requirements-arm64-v8a.imy":·"d1c15a21c79bbfb2a21969983a5c3aa363e3572a", | 42 | ········"requirements-arm64-v8a.imy":·"d1c15a21c79bbfb2a21969983a5c3aa363e3572a", |
| 43 | ········"requirements-armeabi-v7a.imy":·"d6dc32d2d5d01480de10ad32b4f4b3084ad2e5e6", | 43 | ········"requirements-armeabi-v7a.imy":·"d6dc32d2d5d01480de10ad32b4f4b3084ad2e5e6", |
| 44 | ········"requirements-common.imy":·" | 44 | ········"requirements-common.imy":·"246acc8cd3abe0efee954a99a486485b0bceeabb", |
| 45 | ········"requirements-x86_64.imy":·"117873e944235279c1b5cdf8a23cb1ae7bf6cc47", | 45 | ········"requirements-x86_64.imy":·"117873e944235279c1b5cdf8a23cb1ae7bf6cc47", |
| 46 | ········"stdlib-arm64-v8a.imy":·"612b92fdeb357374b9d1742707428de8814a2470", | 46 | ········"stdlib-arm64-v8a.imy":·"612b92fdeb357374b9d1742707428de8814a2470", |
| 47 | ········"stdlib-armeabi-v7a.imy":·"cd04ebaad8bba14a5bcdc665671090da5631b967", | 47 | ········"stdlib-armeabi-v7a.imy":·"cd04ebaad8bba14a5bcdc665671090da5631b967", |
| 48 | ········"stdlib-common.imy":·"e17aea5e7f5d5ef8c9cc260620409eaf7b4bb33b", | 48 | ········"stdlib-common.imy":·"e17aea5e7f5d5ef8c9cc260620409eaf7b4bb33b", |
| 49 | ········"stdlib-x86_64.imy":·"43e3c83dba14e01cd82f0167a4152d3c1dbdcc25" | 49 | ········"stdlib-x86_64.imy":·"43e3c83dba14e01cd82f0167a4152d3c1dbdcc25" |
| 50 | ····}, | 50 | ····}, |
| 51 | ····"extract_packages":·[ | 51 | ····"extract_packages":·[ |