⊟
3.66 MB
/home/fdroid/fdroiddata/tmp/com.econverter.app_9.apk vs.
/home/fdroid/fdroiddata/unsigned/com.econverter.app_9.apk
⊟
8.2 KB
APK Signing Block
    
Offset 1, 121 lines modifiedOffset 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 
⊟
3.02 KB
zipinfo {}
    
Offset 1, 8 lines modifiedOffset 1, 8 lines modified
1 Zip·file·size:·63382292·bytes,·number·of·entries:·2191 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.properties2 -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.textproto3 -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.prof4 -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.profm5 -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.dex6 -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.dex7 -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.so8 -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 modifiedOffset 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.so70 -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.so71 -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.imy72 -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.json73 -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.pem74 -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.imy75 -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.imy76 -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··3739830·b-·stor·81-Jan-01·01:01·assets/chaquopy/requirements-common.imy77 -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.imy78 -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.imy79 -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.imy80 -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.imy81 -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.imy82 -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.bin83 -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.version84 -rw----·····2.4·fat········6·b-·stor·81-Jan-01·01:01·META-INF/androidx.activity_activity-compose.version
Offset 211, 11 lines modifiedOffset 211, 8 lines modified
211 -rw----·····0.0·fat······225·b-·stor·81-Jan-01·01:01·res/wN.9.png211 -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.xml212 -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.png213 -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.png214 -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.png215 -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.png216 -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.arsc217 -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 219·files,·74764908·bytes·uncompressed,·62854572·bytes·compressed:··15.9%218 216·files,·74789342·bytes·uncompressed,·62907998·bytes·compressed:··15.9%
⊟
3.64 MB
assets/chaquopy/requirements-common.imy
⊟
25.9 KB
zipinfo {}
    
Offset 1, 8 lines modifiedOffset 1, 8 lines modified
1 Zip·file·size:·3739830·bytes,·number·of·entries:·7731 Zip·file·size:·3810937·bytes,·number·of·entries:·772
2 -rw----·····2.0·fat····34703·b-·defN·80-Feb-01·00:00·six.py2 -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.py3 -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.py5 -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.py6 -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.py7 -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.py8 -rw----·····2.0·fat·····1753·b-·defN·80-Feb-01·00:00·PIL/BufrStubImagePlugin.py
Offset 142, 35 lines modifiedOffset 142, 35 lines modified
142 -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·chaquopy_libxml2-2.9.8.dist-info/INSTALLER142 -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/METADATA143 -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/COPYING145 -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/INSTALLER146 -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/METADATA147 -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·····1590·b-·defN·80-Feb-01·00:00·charset_normalizer/__init__.py149 -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__.py150 -rw----·····2.0·fat······109·b-·defN·80-Feb-01·00:00·charset_normalizer/__main__.py
151 -rw----·····2.0·fat····42325·b-·defN·80-Feb-01·00:00·charset_normalizer/api.py151 -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.py152 -rw----·····2.0·fat····15980·b-·defN·80-Feb-01·00:00·charset_normalizer/cd.py
153 -rw----·····2.0·fat····44624·b-·defN·80-Feb-01·00:00·charset_normalizer/constant.py153 -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.py154 -rw----·····2.0·fat·····2651·b-·defN·80-Feb-01·00:00·charset_normalizer/legacy.py
155 -rw----·····2.0·fat····32641·b-·defN·80-Feb-01·00:00·charset_normalizer/md.py155 -rw----·····2.0·fat····35274·b-·defN·80-Feb-01·00:00·charset_normalizer/md.py
156 -rw----·····2.0·fat····12830·b-·defN·80-Feb-01·00:00·charset_normalizer/models.py156 -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.typed157 -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·charset_normalizer/py.typed
158 -rw----·····2.0·fat····13537·b-·defN·80-Feb-01·00:00·charset_normalizer/utils.py158 -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.py159 -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__.py161 -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__.py162 -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.4.9.dist-info/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.4.9.dist-info/INSTALLER164 -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····41678·b-·defN·80-Feb-01·00:00·charset_normalizer-3.4.9.dist-info/METADATA165 -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.4.9.dist-info/entry_points.txt166 -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.4.9.dist-info/top_level.txt167 -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.4.9.dist-info/licenses/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.4.9.dist-info/licenses/LICENSE169 -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__.py171 -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.py172 -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.py173 -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.py174 -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.py175 -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.py176 -rw----·····2.0·fat·····4059·b-·defN·80-Feb-01·00:00·css_parser/errorhandler.py
Offset 226, 23 lines modifiedOffset 226, 23 lines modified
226 -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·css_parser-1.1.1.dist-info/INSTALLER226 -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/METADATA227 -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.txt228 -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/COPYING230 -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.LESSER231 -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·····4289·b-·defN·80-Feb-01·00:00·cssselect2/__init__.py233 -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.py234 -rw----·····2.0·fat····18907·b-·defN·80-Feb-01·00:00·cssselect2/compiler.py
235 -rw----·····2.0·fat····16285·b-·defN·80-Feb-01·00:00·cssselect2/parser.py235 -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.py236 -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.9.0.dist-info/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.9.0.dist-info/INSTALLER238 -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·cssselect2-0.10.1.dist-info/INSTALLER
239 -rw----·····2.0·fat·····2916·b-·defN·80-Feb-01·00:00·cssselect2-0.9.0.dist-info/METADATA239 -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.9.0.dist-info/licenses/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.9.0.dist-info/licenses/LICENSE241 -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__.py243 -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.py244 -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.py245 -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.py246 -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.py247 -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.py248 -rw----·····2.0·fat····66557·b-·defN·80-Feb-01·00:00·dateutil/rrule.py
Offset 276, 42 lines modifiedOffset 276, 44 lines modified
276 -rw----·····2.0·fat·····5364·b-·defN·80-Feb-01·00:00·defusedxml/xmlrpc.py276 -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/INSTALLER278 -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/LICENSE279 -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/METADATA280 -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.txt281 -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·····3469·b-·defN·80-Feb-01·00:00·filelock/__init__.py283 -rw----·····2.0·fat·····5693·b-·defN·80-Feb-01·00:00·filelock/__init__.py
284 -rw----·····2.0·fat····82263·b-·defN·80-Feb-01·00:00·filelock/_api.py284 -rw----·····2.0·fat···106170·b-·defN·80-Feb-01·00:00·filelock/_api.py
285 -rw----·····2.0·fat·····6111·b-·defN·80-Feb-01·00:00·filelock/_async.py285 -rw----·····2.0·fat····20487·b-·defN·80-Feb-01·00:00·filelock/_async.py
286 -rw----·····2.0·fat····13325·b-·defN·80-Feb-01·00:00·filelock/_async_read_write.py286 -rw----·····2.0·fat····17947·b-·defN·80-Feb-01·00:00·filelock/_async_read_write.py
287 -rw----·····2.0·fat·····2981·b-·defN·80-Feb-01·00:00·filelock/_descriptor.py287 -rw----·····2.0·fat·····3277·b-·defN·80-Feb-01·00:00·filelock/_descriptor.py
288 -rw----·····2.0·fat·····2699·b-·defN·80-Feb-01·00:00·filelock/_error.py288 -rw----·····2.0·fat·····3235·b-·defN·80-Feb-01·00:00·filelock/_error.py
289 -rw----·····2.0·fat·····8415·b-·defN·80-Feb-01·00:00·filelock/_identity.py289 -rw----·····2.0·fat····17183·b-·defN·80-Feb-01·00:00·filelock/_identity.py
290 -rw----·····2.0·fat····15152·b-·defN·80-Feb-01·00:00·filelock/_lease.py290 -rw----·····2.0·fat····19173·b-·defN·80-Feb-01·00:00·filelock/_lease.py
291 -rw----·····2.0·fat·····6026·b-·defN·80-Feb-01·00:00·filelock/_marker.py291 -rw----·····2.0·fat·····7896·b-·defN·80-Feb-01·00:00·filelock/_marker.py
292 -rw----·····2.0·fat····32895·b-·defN·80-Feb-01·00:00·filelock/_read_write.py292 -rw----·····2.0·fat····68071·b-·defN·80-Feb-01·00:00·filelock/_read_write.py
293 -rw----·····2.0·fat····13014·b-·defN·80-Feb-01·00:00·filelock/_soft.py293 -rw----·····2.0·fat····33064·b-·defN·80-Feb-01·00:00·filelock/_soft.py
294 -rw----·····2.0·fat······187·b-·defN·80-Feb-01·00:00·filelock/_soft_protocol.py294 -rw----·····2.0·fat······218·b-·defN·80-Feb-01·00:00·filelock/_soft_protocol.py
295 -rw----·····2.0·fat····38823·b-·defN·80-Feb-01·00:00·filelock/_strict.py295 -rw----·····2.0·fat····58570·b-·defN·80-Feb-01·00:00·filelock/_strict.py
296 -rw----·····2.0·fat·····8722·b-·defN·80-Feb-01·00:00·filelock/_unix.py296 -rw----·····2.0·fat····10985·b-·defN·80-Feb-01·00:00·filelock/_unix.py
297 -rw----·····2.0·fat·····6356·b-·defN·80-Feb-01·00:00·filelock/_util.py297 -rw----·····2.0·fat····19280·b-·defN·80-Feb-01·00:00·filelock/_util.py
298 -rw----·····2.0·fat····15988·b-·defN·80-Feb-01·00:00·filelock/_windows.py298 -rw----·····2.0·fat····38880·b-·defN·80-Feb-01·00:00·filelock/_windows.py
299 -rw----·····2.0·fat····34599·b-·defN·80-Feb-01·00:00·filelock/asyncio.py299 -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.typed300 -rw----·····2.0·fat········0·b-·defN·80-Feb-01·00:00·filelock/py.typed
301 -rw----·····2.0·fat······522·b-·defN·80-Feb-01·00:00·filelock/version.py301 -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······370·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/__init__.py303 -rw----·····2.0·fat······452·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/__init__.py
304 -rw----·····2.0·fat····11492·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_async.py304 -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····43201·b-·defN·80-Feb-01·00:00·filelock/_soft_rw/_sync.py307 -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-3.32.2.dist-info/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-3.32.2.dist-info/INSTALLER309 -rw----·····2.0·fat········4·b-·defN·80-Feb-01·00:00·filelock-4.2.4.dist-info/INSTALLER
308 -rw----·····2.0·fat·····2028·b-·defN·80-Feb-01·00:00·filelock-3.32.2.dist-info/METADATA310 -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-3.32.2.dist-info/licenses/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-3.32.2.dist-info/licenses/LICENSE312 -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__.py314 -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__.py315 -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.py316 -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.py317 -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.py318 -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.py319 -rw----·····2.0·fat·····4052·b-·defN·80-Feb-01·00:00·html2text/config.py
Offset 509, 15 lines modifiedOffset 511, 15 lines modified
509 -rw----·····2.0·fat·····3284·b-·defN·80-Feb-01·00:00·reportlab/fonts/hb-test.ttf511 -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______.pfb512 -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______.pfb513 -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______.pfb514 -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______.pfb515 -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__.py517 -rw----·····2.0·fat······274·b-·defN·80-Feb-01·00:00·reportlab/graphics/__init__.py
516 -rw----·····2.0·fat····15285·b-·defN·80-Feb-01·00:00·reportlab/graphics/renderPDF.py518 -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.py519 -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.py520 -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.py521 -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.py522 -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.py523 -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.
⊟
6.14 KB
zipnote «TEMP»/diffoscope_ck0yund1_unsigned/tmp1hex3_fp_.zip
    
Offset 477, 33 lines modifiedOffset 477, 33 lines modified
  
477 Filename:·charset_normalizer/cli/__init__.py477 Filename:·charset_normalizer/cli/__init__.py
478 Comment:·478 Comment:·
  
479 Filename:·charset_normalizer/cli/__main__.py479 Filename:·charset_normalizer/cli/__main__.py
480 Comment:·480 Comment:·
  
481 Filename:·charset_normalizer-3.4.9.dist-info/481 Filename:·charset_normalizer-3.5.2.dist-info/
482 Comment:·482 Comment:·
  
483 Filename:·charset_normalizer-3.4.9.dist-info/INSTALLER483 Filename:·charset_normalizer-3.5.2.dist-info/INSTALLER
484 Comment:·484 Comment:·
  
485 Filename:·charset_normalizer-3.4.9.dist-info/METADATA485 Filename:·charset_normalizer-3.5.2.dist-info/METADATA
486 Comment:·486 Comment:·
  
487 Filename:·charset_normalizer-3.4.9.dist-info/entry_points.txt487 Filename:·charset_normalizer-3.5.2.dist-info/entry_points.txt
488 Comment:·488 Comment:·
  
489 Filename:·charset_normalizer-3.4.9.dist-info/top_level.txt489 Filename:·charset_normalizer-3.5.2.dist-info/top_level.txt
490 Comment:·490 Comment:·
  
491 Filename:·charset_normalizer-3.4.9.dist-info/licenses/491 Filename:·charset_normalizer-3.5.2.dist-info/licenses/
492 Comment:·492 Comment:·
  
493 Filename:·charset_normalizer-3.4.9.dist-info/licenses/LICENSE493 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__.py497 Filename:·css_parser/__init__.py
498 Comment:·498 Comment:·
Offset 699, 27 lines modifiedOffset 699, 27 lines modified
  
699 Filename:·cssselect2/parser.py699 Filename:·cssselect2/parser.py
700 Comment:·700 Comment:·
  
701 Filename:·cssselect2/tree.py701 Filename:·cssselect2/tree.py
702 Comment:·702 Comment:·
  
703 Filename:·cssselect2-0.9.0.dist-info/703 Filename:·cssselect2-0.10.1.dist-info/
704 Comment:·704 Comment:·
  
705 Filename:·cssselect2-0.9.0.dist-info/INSTALLER705 Filename:·cssselect2-0.10.1.dist-info/INSTALLER
706 Comment:·706 Comment:·
  
707 Filename:·cssselect2-0.9.0.dist-info/METADATA707 Filename:·cssselect2-0.10.1.dist-info/METADATA
708 Comment:·708 Comment:·
  
709 Filename:·cssselect2-0.9.0.dist-info/licenses/709 Filename:·cssselect2-0.10.1.dist-info/licenses/
710 Comment:·710 Comment:·
  
711 Filename:·cssselect2-0.9.0.dist-info/licenses/LICENSE711 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__.py715 Filename:·dateutil/__init__.py
716 Comment:·716 Comment:·
Offset 903, 30 lines modifiedOffset 903, 36 lines modified
  
903 Filename:·filelock/_soft_rw/__init__.py903 Filename:·filelock/_soft_rw/__init__.py
904 Comment:·904 Comment:·
  
905 Filename:·filelock/_soft_rw/_async.py905 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.py911 Filename:·filelock/_soft_rw/_sync.py
908 Comment:·912 Comment:·
  
909 Filename:·filelock-3.32.2.dist-info/913 Filename:·filelock-4.2.4.dist-info/
910 Comment:·914 Comment:·
  
911 Filename:·filelock-3.32.2.dist-info/INSTALLER915 Filename:·filelock-4.2.4.dist-info/INSTALLER
912 Comment:·916 Comment:·
  
913 Filename:·filelock-3.32.2.dist-info/METADATA917 Filename:·filelock-4.2.4.dist-info/METADATA
914 Comment:·918 Comment:·
  
915 Filename:·filelock-3.32.2.dist-info/licenses/919 Filename:·filelock-4.2.4.dist-info/licenses/
916 Comment:·920 Comment:·
  
917 Filename:·filelock-3.32.2.dist-info/licenses/LICENSE921 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__.py925 Filename:·html2text/__init__.py
922 Comment:·926 Comment:·
Offset 2025, 30 lines modifiedOffset 2031, 30 lines modified
  
2025 Filename:·reportlab/platypus/tables.py2031 Filename:·reportlab/platypus/tables.py
2026 Comment:·2032 Comment:·
  
2027 Filename:·reportlab/platypus/xpreformatted.py2033 Filename:·reportlab/platypus/xpreformatted.py
2028 Comment:·2034 Comment:·
  
2029 Filename:·reportlab-5.0.0.dist-info/2035 Filename:·reportlab-5.0.1.dist-info/
2030 Comment:·2036 Comment:·
  
2031 Filename:·reportlab-5.0.0.dist-info/INSTALLER2037 Filename:·reportlab-5.0.1.dist-info/INSTALLER
2032 Comment:·2038 Comment:·
  
2033 Filename:·reportlab-5.0.0.dist-info/METADATA2039 Filename:·reportlab-5.0.1.dist-info/METADATA
2034 Comment:·2040 Comment:·
  
2035 Filename:·reportlab-5.0.0.dist-info/top_level.txt2041 Filename:·reportlab-5.0.1.dist-info/top_level.txt
2036 Comment:·2042 Comment:·
  
2037 Filename:·reportlab-5.0.0.dist-info/licenses/2043 Filename:·reportlab-5.0.1.dist-info/licenses/
2038 Comment:·2044 Comment:·
  
2039 Filename:·reportlab-5.0.0.dist-info/licenses/LICENSE2045 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.
⊟
2.76 MB
zipdetails --redact --walk --utc {}
    
Offset 3532, 35923 lines modifiedOffset 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···················84EED9B3·(2230245811)3539 077477·CRC···················36D9FA28·(920255016)
3540 07747B·Compressed·Size·······00000324·(804)3540 07747B·Compressed·Size·······0000031C·(796)
3541 07747F·Uncompressed·Size·····00000636·(1590)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·filename3547 #··········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···0000000000000636·(1590)3551 0774A9···Uncompressed·Size···000000000000062E·(1582)
3552 0774B1···Compressed·Size·····0000000000000324·(804)3552 0774B1···Compressed·Size·····000000000000031C·(796)
3553 0774B9·PAYLOAD3553 0774B9·PAYLOAD
Diff chunk too large, falling back to line-by-line diff (2567 lines added, 2567 lines removed)
  
3554 0777DD·LOCAL·HEADER·#149·····04034B50·(67324752)3554 0777D5·LOCAL·HEADER·#149·····04034B50·(67324752)
3555 0777E1·Extract·Zip·Spec······14·(20)·'2.0'3555 0777D9·Extract·Zip·Spec······14·(20)·'2.0'
3556 0777E2·Extract·OS············00·(0)·'MS-DOS'3556 0777DA·Extract·OS············00·(0)·'MS-DOS'
3557 0777E3·General·Purpose·Flag··0800·(2048)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 0777E5·Compression·Method····0008·(8)·'Deflated'3560 0777DD·Compression·Method····0008·(8)·'Deflated'
3561 0777E7·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'3561 0777DF·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'
3562 0777EB·CRC···················35633DF4·(895696372)3562 0777E3·CRC···················35633DF4·(895696372)
3563 0777EF·Compressed·Size·······00000055·(85)3563 0777E7·Compressed·Size·······00000055·(85)
3564 0777F3·Uncompressed·Size·····0000006D·(109)3564 0777EB·Uncompressed·Size·····0000006D·(109)
3565 0777F7·Filename·Length·······001E·(30)3565 0777EF·Filename·Length·······001E·(30)
3566 0777F9·Extra·Length··········0014·(20)3566 0777F1·Extra·Length··········0014·(20)
3567 0777FB·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'3567 0777F3·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
3568 #3568 #
3569 #·WARNING:·Offset·0x777FB:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'3569 #·WARNING:·Offset·0x777F3:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
3570 #··········Zero·length·filename3570 #··········Zero·length·filename
3571 #3571 #
3572 077819·Extra·ID·#1···········0001·(1)·'ZIP64'3572 077811·Extra·ID·#1···········0001·(1)·'ZIP64'
3573 07781B···Length··············0010·(16)3573 077813···Length··············0010·(16)
3574 07781D···Uncompressed·Size···000000000000006D·(109)3574 077815···Uncompressed·Size···000000000000006D·(109)
3575 077825···Compressed·Size·····0000000000000055·(85)3575 07781D···Compressed·Size·····0000000000000055·(85)
3576 07782D·PAYLOAD···············XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3576 077825·PAYLOAD···············XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  
3577 077882·LOCAL·HEADER·#150·····04034B50·(67324752)3577 07787A·LOCAL·HEADER·#150·····04034B50·(67324752)
3578 077886·Extract·Zip·Spec······14·(20)·'2.0'3578 07787E·Extract·Zip·Spec······14·(20)·'2.0'
3579 077887·Extract·OS············00·(0)·'MS-DOS'3579 07787F·Extract·OS············00·(0)·'MS-DOS'
3580 077888·General·Purpose·Flag··0800·(2048)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 07788A·Compression·Method····0008·(8)·'Deflated'3583 077882·Compression·Method····0008·(8)·'Deflated'
3584 07788C·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'3584 077884·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'
3585 077890·CRC···················FABFCC0E·(4206873614)3585 077888·CRC···················155BD86E·(358340718)
3586 077894·Compressed·Size·······00002504·(9476)3586 07788C·Compressed·Size·······000020BB·(8379)
3587 077898·Uncompressed·Size·····0000A555·(42325)3587 077890·Uncompressed·Size·····00008BBE·(35774)
3588 07789C·Filename·Length·······0019·(25)3588 077894·Filename·Length·······0019·(25)
3589 07789E·Extra·Length··········0014·(20)3589 077896·Extra·Length··········0014·(20)
3590 0778A0·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXX'3590 077898·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXX'
3591 #3591 #
3592 #·WARNING:·Offset·0x778A0:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXX'3592 #·WARNING:·Offset·0x77898:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXX'
3593 #··········Zero·length·filename3593 #··········Zero·length·filename
3594 #3594 #
3595 0778B9·Extra·ID·#1···········0001·(1)·'ZIP64'3595 0778B1·Extra·ID·#1···········0001·(1)·'ZIP64'
3596 0778BB···Length··············0010·(16)3596 0778B3···Length··············0010·(16)
3597 0778BD···Uncompressed·Size···000000000000A555·(42325)3597 0778B5···Uncompressed·Size···0000000000008BBE·(35774)
3598 0778C5···Compressed·Size·····0000000000002504·(9476)3598 0778BD···Compressed·Size·····00000000000020BB·(8379)
3599 0778CD·PAYLOAD3599 0778C5·PAYLOAD
  
3600 079DD1·LOCAL·HEADER·#151·····04034B50·(67324752)3600 079980·LOCAL·HEADER·#151·····04034B50·(67324752)
3601 079DD5·Extract·Zip·Spec······14·(20)·'2.0'3601 079984·Extract·Zip·Spec······14·(20)·'2.0'
3602 079DD6·Extract·OS············00·(0)·'MS-DOS'3602 079985·Extract·OS············00·(0)·'MS-DOS'
3603 079DD7·General·Purpose·Flag··0800·(2048)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 079DD9·Compression·Method····0008·(8)·'Deflated'3606 079988·Compression·Method····0008·(8)·'Deflated'
3607 079DDB·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'3607 07998A·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'
3608 079DDF·CRC···················16049338·(369398584)3608 07998E·CRC···················16049338·(369398584)
3609 079DE3·Compressed·Size·······000010D3·(4307)3609 079992·Compressed·Size·······000010D3·(4307)
3610 079DE7·Uncompressed·Size·····00003E6C·(15980)3610 079996·Uncompressed·Size·····00003E6C·(15980)
3611 079DEB·Filename·Length·······0018·(24)3611 07999A·Filename·Length·······0018·(24)
3612 079DED·Extra·Length··········0014·(20)3612 07999C·Extra·Length··········0014·(20)
3613 079DEF·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXX'3613 07999E·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXX'
3614 #3614 #
3615 #·WARNING:·Offset·0x79DEF:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXX'3615 #·WARNING:·Offset·0x7999E:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXX'
3616 #··········Zero·length·filename3616 #··········Zero·length·filename
3617 #3617 #
3618 079E07·Extra·ID·#1···········0001·(1)·'ZIP64'3618 0799B6·Extra·ID·#1···········0001·(1)·'ZIP64'
3619 079E09···Length··············0010·(16)3619 0799B8···Length··············0010·(16)
3620 079E0B···Uncompressed·Size···0000000000003E6C·(15980)3620 0799BA···Uncompressed·Size···0000000000003E6C·(15980)
3621 079E13···Compressed·Size·····00000000000010D3·(4307)3621 0799C2···Compressed·Size·····00000000000010D3·(4307)
3622 079E1B·PAYLOAD3622 0799CA·PAYLOAD
  
3623 07AEEE·LOCAL·HEADER·#152·····04034B50·(67324752)3623 07AA9D·LOCAL·HEADER·#152·····04034B50·(67324752)
3624 07AEF2·Extract·Zip·Spec······14·(20)·'2.0'3624 07AAA1·Extract·Zip·Spec······14·(20)·'2.0'
3625 07AEF3·Extract·OS············00·(0)·'MS-DOS'3625 07AAA2·Extract·OS············00·(0)·'MS-DOS'
3626 07AEF4·General·Purpose·Flag··0800·(2048)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 07AEF6·Compression·Method····0008·(8)·'Deflated'3629 07AAA5·Compression·Method····0008·(8)·'Deflated'
3630 07AEF8·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'3630 07AAA7·Modification·Time·····00410000·(4259840)·'Fri·Feb··1·00:00:00·1980'
3631 07AEFC·CRC···················57A86875·(1470654581)3631 07AAAB·CRC···················FA97DBAA·(4204256170)
3632 07AF00·Compressed·Size·······00003253·(12883)3632 07AAAF·Compressed·Size·······00003DB4·(15796)
3633 07AF04·Uncompressed·Size·····0000AE50·(44624)3633 07AAB3·Uncompressed·Size·····0000ED8C·(60812)
3634 07AF08·Filename·Length·······001E·(30)3634 07AAB7·Filename·Length·······001E·(30)
3635 07AF0A·Extra·Length··········0014·(20)3635 07AAB9·Extra·Length··········0014·(20)
3636 07AF0C·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'3636 07AABB·Filename··············'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
3637 #3637 #
3638 #·WARNING:·Offset·0x7AF0C:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'3638 #·WARNING:·Offset·0x7AABB:·Filename·'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
3639 #··········Zero·length·filename3639 #··········Zero·length·filename
3640 #3640 #
3641 07AF2A·Extra·ID·#1···········0001·(1)·'ZIP64'3641 07AAD9·Extra·ID·#1···········0001·(1)·'ZIP64'
3642 07AF2C···Length··············0010·(16)3642 07AADB···Length··············0010·(16)
3643 07AF2E···Uncompressed·Size···000000000000AE50·(44624)3643 07AADD···Uncompressed·Size···000000000000ED8C·(60812)
3644 07AF36···Compressed·Size·····0000000000003253·(12883)3644 07AAE5···Compressed·Size·····0000000000003DB4·(15796)
3645 07AF3E·PAYLOAD3645 07AAED·PAYLOAD
  
3646 07E191·LOCAL·HEADER·#153·····04034B50·(67324752)3646 07E8A1·LOCAL·HEADER·#153·····04034B50·(67324752)
3647 07E195·Extract·Zip·Spec······14·(20)·'2.0'3647 07E8A5·Extract·Zip·Spec······14·(20)·'2.0'
3648 07E196·Extract·OS············00·(0)·'MS-DOS'3648 07E8A6·Extract·OS············00·(0)·'MS-DOS'
3649 07E197·General·Purpose·Flag··0800·(2048)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 07E199·Compression·Method····0008·(8)·'Deflated'3652 07E8A9·Compression·Method····0008·(8)·'Deflated'
Max diff block lines reached; 2670775/2891748 bytes (92.36%) of diff not shown.
⊟
599 B
charset_normalizer/__init__.py
    
Offset 11, 15 lines modifiedOffset 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·documentation15 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)·2021·by·Ahmed·TAHRI17 :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·annotations20 from·__future__·import·annotations
  
21 import·logging21 import·logging
  
⊟
14.6 KB
charset_normalizer/api.py
    
Offset 136, 24 lines modifiedOffset 136, 22 lines modified
  
136 ····is_too_small_sequence:·bool·=·len(sequences)·<·TOO_SMALL_SEQUENCE136 ····is_too_small_sequence:·bool·=·len(sequences)·<·TOO_SMALL_SEQUENCE
137 ····is_too_large_sequence:·bool·=·len(sequences)·>=·TOO_BIG_SEQUENCE137 ····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·({})·byte(s).".format(141 ············"Trying·to·detect·encoding·from·a·tiny·portion·of·(%i)·byte(s).",
142 ················length142 ············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,·({})·byte(s).".format(147 ············"Using·lazy·str·decoding·because·the·payload·is·quite·large,·(%i)·byte(s).",
149 ················length148 ············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·None152 ········any_specified_encoding(sequences)·if·preemptive_behaviour·else·None
155 ····)153 ····)
Offset 166, 20 lines modifiedOffset 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·for171 ····#·this·cache·is·mostly·interesting·for
179 ····#·local·usage.·Garbage·collected·at·the172 ····#·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 modifiedOffset 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.append(sig_encoding)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 modifiedOffset 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 ············continue271 ············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 modifiedOffset 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_up467 ············early_stop_count·=·max_chunk_gave_up
485 ············lazy_str_hard_failure·=·True468 ············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·content470 ········#·We·might·want·to·check·the·sequence·again·with·the·whole·content,
487 ········#·Only·if·initial·MD·tests·passes471 ········#·but·only·if·initial·MD·tests·passed.
488 ········if·(472 ········if·(
489 ············not·lazy_str_hard_failure473 ············not·lazy_str_hard_failure
490 ············and·is_too_large_sequence474 ············and·is_too_large_sequence
491 ············and·not·is_multi_byte_decoder475 ············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 ················continue489 ················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.
⊟
17.3 KB
charset_normalizer/constant.py
    
Offset 371, 14 lines modifiedOffset 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.
⊟
30.8 KB
charset_normalizer/md.py
    
Offset 1, 37 lines modifiedOffset 1, 34 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
2 import·sys 
3 from·functools·import·lru_cache2 from·functools·import·lru_cache
4 from·logging·import·getLogger3 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 ····UNICODE_SECONDARY_RANGE_KEYWORD,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 modifiedOffset 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·|·_THAI40 _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 modifiedOffset 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:·str77 ····character:·str
76 ····printable:·bool78 ····printable:·bool
77 ····alpha:·bool79 ····alpha:·bool
78 ····upper:·bool80 ····upper:·bool
79 ····lower:·bool81 ····lower:·bool
Offset 82, 37 lines modifiedOffset 84, 52 lines modified
82 ····digit:·bool84 ····digit:·bool
83 ····is_ascii:·bool85 ····is_ascii:·bool
84 ····case_variable:·bool86 ····case_variable:·bool
85 ····flags:·int87 ····flags:·int
86 ····accentuated:·bool88 ····accentuated:·bool
87 ····latin:·bool89 ····latin:·bool
88 ····is_cjk:·bool90 ····is_cjk:·bool
 91 ····is_katakana:·bool
 92 ····is_halfwidth_katakana:·bool
89 ····is_arabic:·bool93 ····is_arabic:·bool
 94 ····is_ligature:·bool
 95 ····is_superscript:·bool
 96 ····is_sentence_open_punctuation:·bool
90 ····is_glyph:·bool97 ····is_glyph:·bool
91 ····punct:·bool98 ····punct:·bool
92 ····sym:·bool99 ····sym:·bool
93 ····range:·str·|·None100 ····range:·str·|·None
94 ····sep:·bool101 ····sep:·bool
95 ····emoticon:·bool102 ····emoticon:·bool
96 ····safe:·bool103 ····safe:·bool
97 ····common_cjk:·bool104 ····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·=·character109 ········self.character·=·character
  
102 ········#·ASCII·fast-path:·for·characters·with·ord·<·128,·we·can·skip110 ········#·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·=·True114 ············self.is_ascii·=·True
107 ············self.accentuated·=·False115 ············self.accentuated·=·False
 116 ············self.unaccented·=·character
Max diff block lines reached; 28287/31487 bytes (89.84%) of diff not shown.
⊟
3.95 KB
charset_normalizer/models.py
    
Offset 36, 15 lines modifiedOffset 36, 19 lines modified
36 ········self._string:·str·|·None·=·decoded_payload36 ········self._string:·str·|·None·=·decoded_payload
  
37 ········self._preemptive_declaration:·str·|·None·=·preemptive_declaration37 ········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.encoding45 ················return·iana_name(other,·False)·==·self.encoding
42 ············return·False46 ············return·False
43 ········return·self.encoding·==·other.encoding·and·self.fingerprint·==·other.fingerprint47 ········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 modifiedOffset 68, 19 lines modified
64 ················return·self.chaos·<·other.chaos68 ················return·self.chaos·<·other.chaos
65 ············return·self.multi_byte_usage·>·other.multi_byte_usage69 ············return·self.multi_byte_usage·>·other.multi_byte_usage
  
66 ········return·self.chaos·<·other.chaos70 ········return·self.chaos·<·other.chaos
  
67 ····@property71 ····@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))·/·len(self.raw))77 ········return·1.0·-·(len(str(self))·/·raw_len)
  
70 ····def·__str__(self)·->·str:78 ····def·__str__(self)·->·str:
71 ········#·Lazy·Str·Loading79 ········#·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·boundary82 ············#·UTF-7·BOM·is·encoded·in·modified·Base64·whose·byte·boundary
75 ············#·can·overlap·with·the·next·character,·so·raw-byte·stripping83 ············#·can·overlap·with·the·next·character,·so·raw-byte·stripping
Offset 254, 24 lines modifiedOffset 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._results275 ········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·result288 ····················return·result
274 ········raise·KeyError289 ········raise·KeyError
Offset 296, 22 lines modifiedOffset 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 ····················return317 ····················return
302 ········self._results.append(item)318 ········self._results.append(item)
303 ········self._results·=·sorted(self._results)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·None325 ············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()
⊟
11.4 KB
charset_normalizer/utils.py
    
Offset 1, 37 lines modifiedOffset 1, 42 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
2 import·importlib2 import·importlib
3 import·logging3 import·logging
4 import·unicodedata4 import·unicodedata
5 from·bisect·import·bisect_right5 from·bisect·import·bisect_right
6 from·codecs·import·IncrementalDecoder6 from·codecs·import·IncrementalDecoder
7 from·encodings.aliases·import·aliases 
8 from·functools·import·lru_cache7 from·functools·import·lru_cache
9 from·re·import·findall 
10 from·typing·import·Generator8 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 modifiedOffset 49, 43 lines modified
44 ········flags·|=·_LATIN49 ········flags·|=·_LATIN
45 ····if·"CJK"·in·desc:50 ····if·"CJK"·in·desc:
46 ········flags·|=·_CJK51 ········flags·|=·_CJK
47 ····if·"HANGUL"·in·desc:52 ····if·"HANGUL"·in·desc:
48 ········flags·|=·_HANGUL53 ········flags·|=·_HANGUL
49 ····if·"KATAKANA"·in·desc:54 ····if·"KATAKANA"·in·desc:
50 ········flags·|=·_KATAKANA55 ········flags·|=·_KATAKANA
 56 ········if·"HALFWIDTH"·in·desc:
 57 ············flags·|=·_HALFWIDTH_KATAKANA
51 ····if·"HIRAGANA"·in·desc:58 ····if·"HIRAGANA"·in·desc:
52 ········flags·|=·_HIRAGANA59 ········flags·|=·_HIRAGANA
53 ····if·"THAI"·in·desc:60 ····if·"THAI"·in·desc:
54 ········flags·|=·_THAI61 ········flags·|=·_THAI
55 ····if·"ARABIC"·in·desc:62 ····if·"ARABIC"·in·desc:
56 ········flags·|=·_ARABIC63 ········flags·|=·_ARABIC
57 ········if·"ISOLATED·FORM"·in·desc:64 ········if·"ISOLATED·FORM"·in·desc:
58 ············flags·|=·_ARABIC_ISOLATED_FORM65 ············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·|=·_ACCENTUATED74 ············flags·|=·_ACCENTUATED
62 ············break75 ············break
  
63 ····return·flags76 ····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·character82 ········return·character
  
71 ····codes:·list[str]·=·decomposed.split("·")83 ····codes:·list[str]·=·decomposed.split("·")
  
Offset 91, 14 lines modifiedOffset 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_ord112 ····#·Binary·search:·find·the·rightmost·range·whose·start·<=·character_ord
97 ····idx·=·bisect_right(_UNICODE_RANGE_STARTS,·character_ord)·-·1113 ····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·name117 ············return·name
  
Offset 151, 64 lines modifiedOffset 168, 54 lines modified
151 ········return·True168 ········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.
⊟
220 B
charset_normalizer/version.py
    
Offset 1, 8 lines modifiedOffset 1, 8 lines modified
1 """1 """
2 Expose·version2 Expose·version
3 """3 """
  
4 from·__future__·import·annotations4 from·__future__·import·annotations
  
5 __version__·=·"3.4.9"5 __version__·=·"3.5.2"
6 VERSION·=·__version__.split(".")6 VERSION·=·__version__.split(".")
⊟
569 B
cssselect2/__init__.py
    
Offset 9, 15 lines modifiedOffset 9, 15 lines modified
9 from·webencodings·import·ascii_lower9 from·webencodings·import·ascii_lower
  
10 #·Classes·are·imported·here·to·expose·them·at·the·top·level·of·the·module10 #·Classes·are·imported·here·to·expose·them·at·the·top·level·of·the·module
11 from·.compiler·import·compile_selector_list··#·noqa11 from·.compiler·import·compile_selector_list··#·noqa
12 from·.parser·import·SelectorError··#·noqa12 from·.parser·import·SelectorError··#·noqa
13 from·.tree·import·ElementWrapper··#·noqa13 from·.tree·import·ElementWrapper··#·noqa
  
14 VERSION·=·__version__·=·'0.9.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·=·{}
⊟
711 B
cssselect2/parser.py
    
Offset 5, 14 lines modifiedOffset 5, 16 lines modified
5 SUPPORTED_PSEUDO_ELEMENTS·=·{5 SUPPORTED_PSEUDO_ELEMENTS·=·{
6 ····#·As·per·CSS·Pseudo-Elements·Module·Level·46 ····#·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·Module10 ····#·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·114 ····#·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``.
⊟
7.29 KB
filelock/__init__.py
    
Offset 1, 81 lines modifiedOffset 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·annotations8 from·__future__·import·annotations
  
 9 __lazy_modules__·=·["filelock._descriptor",·"filelock._error",·"importlib"]
  
7 import·sys10 import·sys
8 import·warnings11 import·warnings
 12 from·importlib·import·import_module
9 from·typing·import·TYPE_CHECKING,·Final13 from·typing·import·TYPE_CHECKING,·Final
  
10 from·._api·import·AcquireReturnProxy,·BaseFileLock,·CloseErrorPolicy,·ContextErrorPolicy,·LockOptions14 from·filelock._api·import·AcquireReturnProxy,·BaseFileLock,·CloseErrorPolicy,·ContextErrorPolicy,·LockOptions
11 from·._descriptor·import·lock_descriptor,·unlock_descriptor15 from·filelock._descriptor·import·lock_descriptor,·unlock_descriptor
12 from·._error·import·LeaseSettingsMismatch,·SoftFileLockLifetimeWarning,·SoftFileLockProtocolError,·Timeout16 from·filelock._error·import·LeaseSettingsMismatch,·SoftFileLockLifetimeWarning,·SoftFileLockProtocolError,·Timeout
13 from·._lease·import·LeaseCompromise,·SoftFileLease 
14 from·._marker·import·MarkerSoftFileLock,·OwnerRecord17 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·._async_read_write·import·(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 ········AsyncAcquireReadWriteReturnProxy,32 ········AsyncAcquireReturnProxy,
 33 ········AsyncSoftFileLease,
18 ········AsyncReadWriteLock,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·string40 #:·version·of·the·project·as·a·string
45 __version__:·Final[str]·=·version41 __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·cover47 if·sys.platform·==·"win32":··#·pragma:·win32·cover
47 ····_FileLock:·type[BaseFileLock]·=·WindowsFileLock48 ····_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·pragma49 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]·=·UnixFileLock51 ········_FileLock:·type[BaseFileLock]·=·UnixFileLock
52 ········_AsyncFileLock:·type[BaseAsyncFileLock]·=·AsyncUnixFileLock 
53 ····else:52 ····else:
 53 ········from·filelock._soft·import·SoftFileLock
  
54 ········_FileLock·=·SoftFileLock54 ········_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·=·SoftFileLock57 ····FileLock·=·SoftFileLock
59 ····AsyncFileLock·=·AsyncSoftFileLock58 ····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·=·_FileLock61 ····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.
⊟
96.2 KB
filelock/_api.py
    
Offset 1, 52 lines modifiedOffset 1, 77 lines modified
1 from·__future__·import·annotations1 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·contextlib15 import·contextlib
3 import·inspect16 import·inspect
4 import·logging17 import·logging
5 import·math18 import·math
6 import·os19 import·os
7 import·secrets20 import·secrets
 21 import·stat
8 import·sys22 import·sys
9 import·time23 import·time
 24 import·types
10 import·warnings25 import·warnings
11 from·abc·import·ABCMeta,·abstractmethod26 from·abc·import·ABCMeta,·abstractmethod
12 from·collections.abc·import·Callable,·Hashable27 from·collections.abc·import·Callable,·Hashable
13 from·contextlib·import·contextmanager28 from·contextlib·import·contextmanager
14 from·dataclasses·import·dataclass29 from·dataclasses·import·dataclass,·fields
 30 from·decimal·import·Decimal
 31 from·functools·import·cache,·partial
15 from·itertools·import·count,·starmap32 from·itertools·import·count,·starmap
 33 from·numbers·import·Real
16 from·threading·import·Condition,·RLock,·get_ident,·local34 from·threading·import·TIMEOUT_MAX,·Condition,·RLock,·Thread,·current_thread,·get_ident,·local
17 from·typing·import·TYPE_CHECKING,·Final,·Literal,·NoReturn,·TypedDict,·TypeVar,·cast35 from·typing·import·TYPE_CHECKING,·Final,·Generic,·Literal,·NoReturn,·TypedDict,·TypeVar,·cast
18 from·weakref·import·WeakKeyDictionary,·WeakValueDictionary36 from·weakref·import·WeakKeyDictionary,·WeakValueDictionary,·ref
  
19 from·._error·import·SoftFileLockLifetimeWarning,·Timeout37 from·filelock._error·import·SoftFileLockLifetimeWarning,·Timeout
20 from·._util·import·break_lock_file38 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·pick39 #:·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]·=·-141 _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]·=·2044 _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·Generator52 ····from·collections.abc·import·Generator,·Mapping
 53 ····from·threading·import·Lock
34 ····from·types·import·TracebackType54 ····from·types·import·FrameType,·TracebackType
35 ····from·typing·import·Protocol55 ····from·typing·import·Protocol
  
 56 ····from·_typeshed·import·Unused
  
 57 ····from·filelock._lease·import·_LeaseClaim
36 ····from·._read_write·import·ReadWriteLock58 ····from·filelock._read_write·import·ReadWriteLock
37 ····from·._soft_rw·import·SoftReadWriteLock59 ····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 modifiedOffset 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 ········from·typing·import·Self91 ····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·None94 _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 modifiedOffset 114, 28 lines modified
92 ····context_error_policy:·ContextErrorPolicy114 ····context_error_policy:·ContextErrorPolicy
93 ····close_error_policy:·CloseErrorPolicy115 ····close_error_policy:·CloseErrorPolicy
94 ····fallback_to_soft:·bool116 ····fallback_to_soft:·bool
95 ····preserve_lock_file:·bool117 ····preserve_lock_file:·bool
96 ····on_acquired:·Callable[[int],·None]·|·None118 ····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.
⊟
21.1 KB
filelock/_async.py
    
Offset 1, 117 lines modifiedOffset 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·annotations2 from·__future__·import·annotations
  
 3 __lazy_modules__·=·["asyncio",·"collections",·"concurrent.futures",·"filelock._error"]
  
3 import·asyncio4 import·asyncio
4 import·contextlib5 import·contextlib
5 import·time6 import·time
 7 from·collections·import·deque
6 from·concurrent.futures·import·Future·as·ConcurrentFuture8 from·concurrent.futures·import·Future·as·ConcurrentFuture
7 from·dataclasses·import·dataclass9 from·dataclasses·import·dataclass
8 from·threading·import·Lock10 from·threading·import·Lock
9 from·typing·import·TYPE_CHECKING,·Final,·Generic,·NoReturn,·TypeVar,·cast11 from·typing·import·TYPE_CHECKING,·Final,·Generic,·Literal,·NoReturn,·TypeVar,·cast
 12 from·weakref·import·WeakKeyDictionary
  
10 from·._api·import·_append_exception_context,·_raise_chained_errors13 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·AsyncIterator,·Awaitable,·Callable21 ····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 ····pass30 ····pass
  
  
16 @dataclass(frozen=True)31 @dataclass(frozen=True)
17 class·_BackendOutcome(Generic[_T]):32 class·_BackendOutcome(Generic[_T]):
18 ····value:·_T·|·None·=·None33 ····value:·_T·|·None·=·None
19 ····error:·BaseException·|·None·=·None34 ····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._tail_lock:·Final[Lock]·=·Lock()42 ········self._queue_lock:·Final[Lock]·=·Lock()
23 ········self._tail:·ConcurrentFuture[None]·|·None·=·None43 ········self._queue:·Final[deque[ConcurrentFuture[None]]]·=·deque()
  
24 ····@contextlib.asynccontextmanager44 ····@contextlib.asynccontextmanager
25 ····async·def·hold(self)·->·AsyncIterator[None]: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 ············yield51 ············yield
38 ········finally:52 ········finally:
39 ············self._leave(ticket)53 ············self._leave(ticket)
  
40 ····@contextlib.asynccontextmanager54 ····@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 ····)·->·AsyncIterator[None]: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 ············try:64 ········try:
 65 ············self._join(ticket)
 66 ············if·not·ticket.done():
55 ················await·self._wait_for_predecessor(67 ················await·self._wait_for_turn(
56 ····················predecessor,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 ············yield74 ············yield
67 ········finally:75 ········finally:
68 ············self._leave(ticket)76 ············self._leave(ticket)
  
69 ····@staticmethod 
70 ····async·def·_wait_for_predecessor(77 ····async·def·_wait_for_turn(
 78 ········self,
71 ········predecessor:·ConcurrentFuture[None],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·_AsyncTransitionUnavailableError87 ············raise·_AsyncTransitionUnavailableError
80 ········waiter·=·asyncio.wrap_future(predecessor)88 ········waiter·=·asyncio.wrap_future(ticket)
81 ········while·not·predecessor.done():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.
⊟
18.8 KB
filelock/_async_read_write.py
    
Offset 1, 56 lines modifiedOffset 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·annotations2 from·__future__·import·annotations
  
 3 __lazy_modules__·=·["asyncio",·"concurrent.futures",·"filelock._async",·"filelock._error",·"functools",·"threading"]
  
3 import·asyncio4 import·asyncio
4 import·functools5 import·functools
5 import·os6 import·os
6 import·sqlite37 import·sqlite3
 8 import·threading
7 from·concurrent.futures·import·ThreadPoolExecutor9 from·concurrent.futures·import·ThreadPoolExecutor
 10 from·concurrent.futures·import·thread·as·executor_threads
8 from·contextlib·import·asynccontextmanager11 from·contextlib·import·asynccontextmanager
9 from·typing·import·TYPE_CHECKING,·ParamSpec,·TypeVar12 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·ReadWriteLock30 from·filelock._read_write·import·ReadWriteLock
  
25 if·TYPE_CHECKING:31 if·TYPE_CHECKING:
26 ····from·collections.abc·import·AsyncGenerator,·Callable32 ····from·collections.abc·import·AsyncGenerator,·Callable,·MutableMapping
27 ····from·concurrent·import·futures33 ····from·concurrent·import·futures
28 ····from·types·import·TracebackType34 ····from·types·import·TracebackType
  
29 ····from·._api·import·AcquireReturnProxy35 ····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()``·because41 ····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 ····behavior·to·the·underlying·:class:`ReadWriteLock`.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·lock46 ····:param·lock_file:·path·to·the·SQLite·database·file·used·as·the·lock
39 ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``·means·block·indefinitely47 ····: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·unavailable48 ····: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·path49 ····: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·loop50 ····: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·dedicated51 ····: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·it52 ········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·passing53 ········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 modifiedOffset 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_pid83 ········self._creator_pid·=·creator_pid
74 ········self._fork_invalidated·=·False84 ········self._fork_invalidated·=·False
75 ········self._closed·=·False85 ········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·=·loop93 ············self._loop·=·loop
80 ············self._owns_executor·=·executor·is·None94 ············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·child96 ············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 modifiedOffset 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·default130 ········: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·default131 ········: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·=·None134 ········body_error:·BaseException·|·None·=·None
125 ········try:135 ········try:
126 ············yield136 ············yield
127 ········except·BaseException·as·error:137 ········except·BaseException·as·error:
128 ············body_error·=·error138 ············body_error·=·error
129 ············raise139 ············raise
Offset 140, 18 lines modifiedOffset 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·default151 ········: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·default152 ········: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·=·None155 ········body_error:·BaseException·|·None·=·None
150 ········try:156 ········try:
151 ············yield157 ············yield
152 ········except·BaseException·as·error:158 ········except·BaseException·as·error:
153 ············body_error·=·error159 ············body_error·=·error
154 ············raise160 ············raise
Max diff block lines reached; 13240/19148 bytes (69.15%) of diff not shown.
⊟
3.02 KB
filelock/_descriptor.py
    
Offset 1, 20 lines modifiedOffset 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·annotations2 from·__future__·import·annotations
  
 3 __lazy_modules__·=·["filelock._unix",·"threading",·"typing"]
  
3 import·sys4 import·sys
4 import·time5 import·time
5 from·math·import·isfinite6 from·threading·import·TIMEOUT_MAX
6 from·typing·import·Final7 from·typing·import·Final
  
 8 from·filelock._api·import·_seconds
  
7 if·sys.platform·==·"win32":··#·pragma:·win32·cover9 if·sys.platform·==·"win32":··#·pragma:·win32·cover
8 ····from·._windows·import·_lock_fd_nonblocking,·_unlock_fd10 ····from·filelock._windows·import·_lock_fd_nonblocking,·_unlock_fd
9 else:··#·pragma:·win32·no·cover11 else:··#·pragma:·win32·no·cover
10 ····from·._unix·import·_lock_fd_nonblocking,·_unlock_fd12 ····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·same16 ····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 modifiedOffset 28, 31 lines modified
  
24 ····For·timeout,·reentrancy,·singleton,·lifetime,·or·stale-break·behavior,·use·:class:`FileLock`.·There·is·no·async28 ····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·it31 ····: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 ········``False``.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·the36 ····: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·non-finite·or·non-positive·*poll_interval*.38 ····:raises·ValueError:·if·a·blocking·call·receives·a·*poll_interval*·outside·that·range,·including·``nan``.
  
35 ····..·versionadded::·3.30.039 ····..·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 ····if·not·isfinite(poll_interval)·or·poll_interval·<=·0: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·finite·and·greater·than·0,·got·{poll_interval}"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·True49 ····return·True
  
  
45 def·unlock_descriptor(fd:·int)·->·None:50 def·unlock_descriptor(fd:·int)·->·None:
⊟
3.25 KB
filelock/_error.py
    
Offset 1, 35 lines modifiedOffset 1, 49 lines modified
1 from·__future__·import·annotations1 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·API4 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_file8 ········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 ········#·__init__·needs·lock_file,·so·pickle·must·restore·it·as·a·constructor·arg11 ········#·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-link13 ····def·__str__(self)·->·str:··#·pragma:·needs·hard-link
11 ········return·f"The·file·lock·'{self._lock_file}'·could·not·be·acquired."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 ····@property20 ····@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_file23 ········return·self._lock_file
  
  
18 class·SoftFileLockLifetimeWarning(DeprecationWarning):24 class·SoftFileLockLifetimeWarning(FutureWarning):
 25 ····"""
19 ····"""The·configured·soft-lock·lifetime·permits·overlapping·live·holders·after·expiry."""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·API30 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 modifiedOffset 53, 18 lines modified
39 ········self._lock_file·=·lock_file53 ········self._lock_file·=·lock_file
40 ········self._claim_name·=·claim_name54 ········self._claim_name·=·claim_name
41 ········self._reason·=·reason55 ········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[type[SoftFileLockProtocolError],·tuple[str,·str·|·None,·str]]:··#·pragma:·needs·hard-link59 ····)·->·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 ····@property66 ····@property
51 ····def·lock_file(self)·->·str:··#·pragma:·needs·hard-link67 ····def·lock_file(self)·->·str:··#·pragma:·needs·hard-link
⊟
13.8 KB
filelock/_identity.py
    
Offset 1, 40 lines modifiedOffset 1, 111 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["hashlib",·"pathlib",·"socket",·"typing"]
  
 3 import·hashlib
2 import·os4 import·os
3 import·socket5 import·socket
4 import·sys6 import·sys
5 from·errno·import·EPERM,·ESRCH7 from·errno·import·EPERM,·ESRCH
6 from·pathlib·import·Path8 from·pathlib·import·Path
7 from·typing·import·Final9 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 ····"""The·hostname·recorded·alongside·an·owner,·so·a·marker·written·on·another·machine·is·never·probed·here."""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·from57 ····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·the58 ····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·that59 ····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·death60 ····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·False64 ········return·False
22 ····if·not·process_alive(pid):65 ····if·process_alive(pid)·and·(
23 ········return·True 
24 ····if·start_token·is·None:66 ········start_token·is·None·or·(current·:=·process_start_token(pid))·is·None·or·_same_start(current,·start_token)
 67 ····):
25 ········return·False68 ········return·False
26 ····current·=·process_start_token(pid) 
27 ····return·current·is·not·None·and·current·!=·start_token69 ····#·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·cover87 if·sys.platform·==·"win32":··#·pragma:·win32·cover
29 ····import·ctypes88 ····import·ctypes
30 ····from·ctypes·import·wintypes89 ····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 modifiedOffset 174, 112 lines modified
103 ········#·comm·(field·2)·is·wrapped·in·parentheses·and·may·itself·contain·spaces·or·a·')',·so·the·fixed·fields·start174 ········#·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]·=·19176 ········_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·the178 ············#·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·Windows179 ············#·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·the180 ············#·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.
⊟
24.7 KB
filelock/_lease.py
    
Offset 1, 47 lines modifiedOffset 1, 61 lines modified
1 from·__future__·import·annotations1 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·os13 import·os
3 import·secrets14 import·secrets
 15 import·sys
4 import·time16 import·time
5 from·contextlib·import·suppress17 from·contextlib·import·suppress
6 from·dataclasses·import·dataclass18 from·dataclasses·import·dataclass
 19 from·math·import·isfinite
7 from·threading·import·Event,·Thread,·current_thread,·local20 from·threading·import·Event,·Thread,·current_thread
8 from·typing·import·TYPE_CHECKING,·Literal21 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·LeaseSettingsMismatch24 from·filelock._error·import·LeaseSettingsMismatch
10 from·._identity·import·owner_is_stale25 from·filelock._identity·import·owner_is_stale
11 from·._marker·import·MarkerSoftFileLock,·OwnerMode,·OwnerRecord,·parse_marker26 from·filelock._marker·import·MarkerSoftFileLock,·OwnerMode,·OwnerRecord,·parse_marker
12 from·._soft·import·_read_lock_file27 from·filelock._soft·import·_read_lock_file
13 from·._util·import·break_lock_file,·touch28 from·filelock._util·import·pin_inode,·touch
  
14 if·TYPE_CHECKING:29 if·TYPE_CHECKING:
15 ····import·sys 
16 ····from·collections.abc·import·Callable30 ····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",·"lost",·"transient"]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:·str41 ····lock_file:·str
28 ····token:·str42 ····token:·str
29 ····reason:·CompromiseReason43 ····reason:·CompromiseReason
30 ····error:·OSError·|·None·=·None44 ····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:·Thread48 ····thread:·Thread
Offset 53, 36 lines modifiedOffset 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·=·None68 ····token:·str·|·None·=·None
55 ····compromise:·LeaseCompromise·|·None·=·None69 ····compromise:·LeaseCompromise·|·None·=·None
56 ····heartbeat:·_Heartbeat·|·None·=·None70 ····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·every74 ····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·is·``lease_duration``·seconds·stale.·Nothing75 ····``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 ····stops·the·expired·holder:·it·keeps·running,·and·it·keeps·using·whatever·the·lock·protects.·Treat·the·lease·as·a·hint77 ····expired·holder:·it·keeps·running,·and·it·keeps·using·whatever·the·lock·protects.·Treat·the·lease·as·a·hint·about
71 ····about·who·*should*·be·working,·not·as·a·guarantee·that·only·one·worker·is.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·a79 ····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·a82 ····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·own83 ····different·duration·raises·:class:`LeaseSettingsMismatch·<filelock.LeaseSettingsMismatch>`·rather·than·apply·its·own
Offset 108, 54 lines modifiedOffset 109, 80 lines modified
108 ····_lifetime_supported:·bool·=·False109 ····_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·=·30.0,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·of·marker·staleness·after·which·a·contender·may·take·the·claim.·Every·contender122 ········: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·room124 ········: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.
⊟
9.3 KB
filelock/_marker.py
    
Offset 1, 46 lines modifiedOffset 1, 41 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["contextlib",·"filelock._identity",·"filelock._util",·"math"]
  
2 import·math3 import·math
3 import·os4 import·os
 5 import·re
4 from·contextlib·import·suppress6 from·contextlib·import·suppress
5 from·typing·import·Final,·Literal,·NamedTuple7 from·typing·import·Final,·Literal,·NamedTuple
  
6 from·._identity·import·host_name,·process_start_token8 from·filelock._identity·import·host_name,·owner_is_current_process,·owner_is_stale,·process_start_token
7 from·._soft·import·SoftFileLock,·_read_lock_file9 from·filelock._soft·import·SoftFileLock,·_read_lock_file,·parse_decimal
8 from·._util·import·write_all10 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·malformed12 #:·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·-·115 _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 OwnerMode·=·Literal["lease",·"unknown"]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 ····#:·Filled·in·by·each·mode·so·the·published·record·states·the·contract·its·holder·acquired·under.23 ····#:·Age-based·expiry·requires·a·lease·contract;·an·exclusive·holder·grants·none.
28 ····_owner_mode:·OwnerMode24 ····_owner_mode:·OwnerMode·=·"exclusive"
  
29 ····@property25 ····@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·129 ········:returns:·the·published·record,·or·``None``·when·no·marker·exists·or·its·record·is·malformed·or·protocol·1
Offset 59, 61 lines modifiedOffset 54, 99 lines modified
59 ········return·None·if·(owner·:=·self._read_owner())·is·None·else·owner.pid54 ········return·None·if·(owner·:=·self._read_owner())·is·None·else·owner.pid
  
60 ····@property55 ····@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's·PID·and·hostname·match·this·process59 ········: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.pid·==·os.getpid()·and·owner.hostname·==·host_name()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·lock66 ········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_file)[0])95 ············return·parse_marker(_read_lock_file(self._lock_path)[0])
78 ········return·None96 ········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.
⊟
67.1 KB
filelock/_read_write.py
    
Offset 1, 52 lines modifiedOffset 1, 99 lines modified
1 from·__future__·import·annotations1 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·logging13 import·logging
3 import·os14 import·os
4 import·pathlib15 import·pathlib
 16 import·secrets
5 import·sqlite317 import·sqlite3
 18 import·stat
6 import·sys19 import·sys
 20 import·tempfile
7 import·threading21 import·threading
8 import·time22 import·time
 23 from·collections·import·deque
9 from·contextlib·import·contextmanager,·suppress24 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,·cast27 from·typing·import·TYPE_CHECKING,·ClassVar,·Final,·Literal,·NamedTuple,·TypeAlias,·cast
11 from·weakref·import·WeakValueDictionary28 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·Timeout45 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,·Generator57 ····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.getpid61 _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]·|·None67 ····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·-·171 _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]·=·7074 _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·=·086 ····depth:·int·=·0
  
  
42 _SQLITE_TRANSITION_CONTEXT:·Final·=·_SQLiteTransitionContext()87 _SQLITE_TRANSITION_CONTEXT:·Final·=·_SQLiteTransitionContext()
Offset 130, 54 lines modifiedOffset 177, 203 lines modified
130 ········except·OSError:177 ········except·OSError:
131 ············return·None178 ············return·None
132 ········return·stat_result.st_dev,·stat_result.st_ino179 ········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.
⊟
36.1 KB
filelock/_soft.py
    
Offset 1, 27 lines modifiedOffset 1, 63 lines modified
1 from·__future__·import·annotations1 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·os13 import·os
 14 import·re
 15 import·secrets
3 import·stat16 import·stat
4 import·sys17 import·sys
 18 import·threading
5 import·time19 import·time
6 from·contextlib·import·suppress20 from·contextlib·import·suppress
7 from·errno·import·EACCES,·EEXIST,·EPERM21 from·errno·import·EACCES,·EEXIST,·EPERM
 22 from·itertools·import·islice
8 from·pathlib·import·Path23 from·pathlib·import·Path
9 from·typing·import·Final24 from·typing·import·Final
  
10 from·._api·import·BaseFileLock,·_raise_grouped_errors25 from·filelock._api·import·BaseFileLock,·_raise_grouped_errors
11 from·._identity·import·host_name,·owner_is_stale,·process_start_token26 from·filelock._identity·import·host_name,·owner_is_current_process,·owner_is_stale,·process_start_token
12 from·._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD27 from·filelock._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD
13 from·._util·import·break_lock_file,·ensure_directory_exists,·raise_on_not_writable_file,·write_all28 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 _MALFORMED_LOCK_AGE_THRESHOLD:·Final[float]·=·2.042 MALFORMED_LOCK_AGE_THRESHOLD:·Final[float]·=·2.0
15 _MAX_LOCK_FILE_SIZE:·Final[int]·=·102443 _MAX_LOCK_FILE_SIZE:·Final[int]·=·1024
16 _UNLINK_MAX_RETRIES:·Final[int]·=·1044 _UNLINK_MAX_RETRIES:·Final[int]·=·10
17 _MARKER_WITH_START_TOKEN_LINE_COUNT:·Final[int]·=·345 _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>`,·this55 ····Unlike·:class:`UnixFileLock·<filelock.UnixFileLock>`·and·:class:`WindowsFileLock·<filelock.WindowsFileLock>`,·this
Offset 44, 68 lines modifiedOffset 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·=·False81 ····_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·=·False83 ····_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_file)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·open93 ········#·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_TRUNC95 ········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-nofollow96 ········if·(o_nofollow·:=·getattr(os,·"O_NOFOLLOW",·None))·is·not·None:··#·pragma:·needs·o-nofollow
55 ············flags·|=·o_nofollow97 ············flags·|=·o_nofollow
56 ········try:98 ········try:
57 ············fd·=·os.open(self.lock_file,·flags,·self._open_mode())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·cover103 ············):··#·pragma:·win32·no·cover
62 ················raise104 ················raise
63 ············self._try_break_stale_lock()105 ············self._try_break_stale_lock()
64 ············return106 ············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·fully·on·disk.·On·any·failure,·including·cancellation,·close·the107 ········#·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 ········#·successor's·marker·that·replaced·ours·at·the·same·path·after·our·lease·expired.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·=·None111 ········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 ············os.close(fd)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 ····················Path(self.lock_file).unlink()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.
⊟
298 B
filelock/_soft_protocol.py
    
Offset 1, 9 lines modifiedOffset 1, 11 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["typing"]
  
2 from·typing·import·Final3 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 ]
⊟
56.8 KB
filelock/_strict.py
    
Offset 1, 32 lines modifiedOffset 1, 52 lines modified
1 from·__future__·import·annotations1 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·contextlib14 import·contextlib
3 import·errno15 import·errno
 16 import·functools
4 import·os17 import·os
5 import·secrets18 import·secrets
6 import·stat19 import·stat
7 import·sys20 import·sys
8 import·tempfile21 import·tempfile
9 import·time22 import·time
10 from·dataclasses·import·dataclass23 from·dataclasses·import·dataclass
11 from·errno·import·EACCES,·EEXIST,·ENOENT,·ENOSYS,·EPERM,·ESTALE,·EXDEV24 from·errno·import·EACCES,·EEXIST,·ENOENT,·ENOSYS,·EPERM,·ESTALE,·EXDEV
12 from·pathlib·import·Path25 from·pathlib·import·Path
13 from·typing·import·TYPE_CHECKING,·Final,·Literal,·cast26 from·typing·import·TYPE_CHECKING,·Final,·Literal,·cast
  
14 from·._api·import·BaseFileLock,·_canonical,·_raise_cleanup_errors27 from·filelock._api·import·BaseFileLock,·ThreadLocalFileContext,·_canonical,·_raise_cleanup_errors
15 from·._error·import·SoftFileLockProtocolError28 from·filelock._error·import·SoftFileLockProtocolError
16 from·._identity·import·host_name,·process_start_token29 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_RECORD32 from·filelock._soft_protocol·import·STRICT_SOFT_SENTINEL_RECORD
18 from·._util·import·ensure_directory_exists,·write_all33 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·Iterator37 ····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]·=·102444 _CLAIM_RECORD_LIMIT:·Final[int]·=·1024
27 _CLAIM_NAME_PART_COUNT:·Final[int]·=·345 _CLAIM_NAME_PART_COUNT:·Final[int]·=·3
Offset 35, 14 lines modifiedOffset 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]·=·3256 _PRIVATE_RECORD_RANDOM_HEX_LENGTH:·Final[int]·=·32
37 _PRIVATE_RECORD_GRACE:·Final[float]·=·2.057 _PRIVATE_RECORD_GRACE:·Final[float]·=·2.0
38 _UNLINK_MAX_RETRIES:·Final[int]·=·1058 _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.560 _CLAIM_READ_GRACE:·Final[float]·=·0.5
41 _CLAIM_READ_RETRY:·Final[float]·=·0.00261 _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-link70 #·Termux/Android·CPython·ships·without·os.link·(bionic·long·had·only·linkat),·so·the·strict·backend's·whole·hard-link
Offset 52, 14 lines modifiedOffset 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·moment75 #·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_fd77 _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_fd78 _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_fd79 _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_fd80 _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·answer85 ····#·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·only86 ····#·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·surfaces87 ····#·hardens·a·source·this·process·created·with·O_EXCL,·so·skipping·it·is·safe,·and·a·real·environment·fault·surfaces
Offset 97, 166 lines modifiedOffset 122, 230 lines modified
  
97 ····_preserve_lock_file_supported:·bool·=·True122 ····_preserve_lock_file_supported:·bool·=·True
98 ····_on_acquired_supported:·bool·=·False123 ····_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·rule124 ····#:·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·=·False126 ····_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·back·their·retries·off·across·a·jittered·window128 ····#:·Contending·processes·each·publish·and·rescan·several·files,·so·jitter·their·retries.·Seconds.·Only·a
106 ····#:·rather·than·let·them·collide·on·every·poll.·Seconds;·keeps·a·waiter·responsive·once·it·wins.129 ····#:·poll_interval·below·this·cap·jitters;·the·default·equals·it·and·keeps·a·fixed·cadence.
107 ····_poll_backoff_cap:·float·=·0.05130 ····_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(claim_root)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_NAME139 ········claim_directory·=·coordination_directory·/·_CLAIM_DIRECTORY_NAME
116 ········ensure_directory_exists(os.fspath(lock_path))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_protocol_directory(self.lock_file,·claim_directory)144 ········_ensure_claim_directory(self.lock_file,·claim_directory,·directory_mode)
119 ········if·(sentinel_fd·:=·_open_or_create_sentinel(self.lock_file,·lock_path,·self._open_mode()))·is·None: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 ············return150 ············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.
⊟
13.6 KB
filelock/_unix.py
    
Offset 1, 19 lines modifiedOffset 1, 21 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["contextlib",·"filelock._util",·"pathlib",·"typing",·"warnings"]
  
2 import·os3 import·os
3 import·sys4 import·sys
4 import·warnings5 import·warnings
5 from·contextlib·import·suppress6 from·contextlib·import·suppress
6 from·errno·import·EACCES,·EAGAIN,·ENOSYS,·EWOULDBLOCK7 from·errno·import·EACCES,·EAGAIN,·ENOSYS,·EWOULDBLOCK
7 from·pathlib·import·Path8 from·pathlib·import·Path
8 from·typing·import·Final,·cast9 from·typing·import·Final,·cast
  
9 from·._api·import·BaseFileLock10 from·filelock._api·import·BaseFileLock
10 from·._util·import·ensure_directory_exists11 from·filelock._util·import·remove_own_file
  
11 has_fcntl·=·False12 has_fcntl·=·False
12 if·sys.platform·==·"win32":··#·pragma:·win32·cover13 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 modifiedOffset 55, 154 lines modified
53 ····················return·False55 ····················return·False
54 ················raise56 ················raise
55 ············return·True57 ············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·splits69 ········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·the70 ········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 ················self._switch_to_soft_lock(*missing_flock)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 ············#·truncates·and·normalizes·mode·once·it·owns·the·lock·(#591).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_RDWR114 ············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_nofollow116 ················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 ················fd·=·os.open(self.lock_file,·open_flags,·open_mode)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 ················if·self.lock_file·and·Path(self.lock_file).parent.exists():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·None127 ····················return·None
87 ················raise128 ················raise
88 ············except·PermissionError:129 ············except·PermissionError:
89 ················#·Sticky-bit·dirs·(e.g.·/tmp):·O_CREAT·fails·if·the·file·is·owned·by·another·user·(#317).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_file).exists():131 ················if·not·Path(self._lock_path).exists():
92 ····················raise132 ····················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.
⊟
21.8 KB
filelock/_util.py
    
Offset 1, 25 lines modifiedOffset 1, 36 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["pathlib",·"platform",·"secrets"]
  
 3 import·errno
2 import·os4 import·os
 5 import·platform
3 import·secrets6 import·secrets
4 import·stat7 import·stat
5 import·sys8 import·sys
 9 from·contextlib·import·contextmanager,·suppress
6 from·errno·import·EACCES,·EIO,·EISDIR10 from·errno·import·EACCES,·EINVAL,·EIO,·EISDIR,·ENOSYS,·EXDEV
 11 from·functools·import·cache
7 from·pathlib·import·Path12 from·pathlib·import·Path
8 from·typing·import·Final13 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·``os.write``·is·allowed·to·make.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 ····kernel·view.·No·``fsync``:·filelock·needs·a·complete·record,·not·crash-durable·storage.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 modifiedOffset 57, 343 lines modified
46 ········#·make·stat·inspect·the·link·target,·letting·an·attacker·turn·a·contended·acquire·into·a·misleading57 ········#·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·and58 ········#·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·on62 ········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·cover64 ········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·cover66 ········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.
⊟
37.7 KB
filelock/_windows.py
    
Offset 1, 61 lines modifiedOffset 1, 102 lines modified
1 from·__future__·import·annotations1 from·__future__·import·annotations
  
 2 __lazy_modules__·=·["filelock._util",·"msvcrt",·"struct"]
  
2 import·os3 import·os
 4 import·struct
3 import·sys5 import·sys
 6 import·time
4 from·contextlib·import·suppress7 from·contextlib·import·contextmanager,·suppress
5 from·pathlib·import·Path8 from·errno·import·ENOENT,·ENOTDIR,·EWOULDBLOCK
 9 from·functools·import·cache
6 from·typing·import·Final,·cast10 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 from·._util·import·ensure_directory_exists,·raise_on_not_writable_file13 if·TYPE_CHECKING:
 14 ····from·collections.abc·import·Generator
  
9 if·sys.platform·==·"win32":··#·pragma:·win32·cover15 if·sys.platform·==·"win32":··#·pragma:·win32·cover
10 ····import·ctypes16 ····import·ctypes
11 ····import·msvcrt17 ····import·msvcrt
12 ····from·ctypes·import·wintypes18 ····from·ctypes·import·wintypes
  
13 ····_GENERIC_READ:·Final[int]·=·0x8000000019 ····_GENERIC_READ:·Final[int]·=·0x80000000
14 ····_GENERIC_WRITE:·Final[int]·=·0x4000000020 ····_GENERIC_WRITE:·Final[int]·=·0x40000000
15 ····_SYNCHRONIZE:·Final[int]·=·0x0010000021 ····_SYNCHRONIZE:·Final[int]·=·0x00100000
 22 ····_DELETE:·Final[int]·=·0x00010000
16 ····_DESIRED_ACCESS:·Final[int]·=·_GENERIC_READ·|·_GENERIC_WRITE·|·_SYNCHRONIZE23 ····_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·|·0x0000000225 ········0x00000001·|·0x00000002
19 ····)··#·read·|·write;·matches·os.open·(_SH_DENYNO),·no·delete26 ····)··#·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_ALWAYS28 ····_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]·=·0x0000000132 ····_FILE_ATTRIBUTE_READONLY:·Final[int]·=·0x00000001
22 ····_FILE_ATTRIBUTE_NORMAL:·Final[int]·=·0x0000008033 ····_FILE_ATTRIBUTE_NORMAL:·Final[int]·=·0x00000080
23 ····_FILE_ATTRIBUTE_REPARSE_POINT:·Final[int]·=·0x0000040034 ····_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 ····#·refuse·a·directory,·and·open·a·reparse·point·rather·than·following·it·so·the·check·below·acts·on·the·link·itself.37 ····#·reparse·point·rather·than·following·it·so·the·check·below·acts·on·the·link·itself.
26 ····_FILE_SYNCHRONOUS_IO_NONALERT:·Final[int]·=·0x0000002038 ····_FILE_SYNCHRONOUS_IO_NONALERT:·Final[int]·=·0x00000020
27 ····_FILE_NON_DIRECTORY_FILE:·Final[int]·=·0x0000004039 ····_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]·=·0x0020000042 ····_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 ····_CREATE_OPTIONS:·Final[int]·=·_FILE_SYNCHRONOUS_IO_NONALERT·|·_FILE_NON_DIRECTORY_FILE·|·_FILE_OPEN_REPARSE_POINT50 ····_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-insensitive51 ····_OBJ_CASE_INSENSITIVE:·Final[int]·=·0x00000040··#·Win32·name·lookups·are·case-insensitive
31 ····_OWNER_WRITE:·Final[int]·=·0o20052 ····_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·shift60 ····#·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's61 ····#·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]·=·0x0000000163 ····_LOCKFILE_FAIL_IMMEDIATELY:·Final[int]·=·0x00000001
37 ····_LOCKFILE_EXCLUSIVE_LOCK:·Final[int]·=·0x0000000264 ····_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·range66 ····_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·one68 ····#·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·is69 ····#·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]·=·0x0000000071 ····_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]·=·0xC000002274 ····_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]·=·0xC000004377 ····_STATUS_SHARING_VIOLATION:·Final[int]·=·0xC0000043
45 ····_STATUS_DELETE_PENDING:·Final[int]·=·0xC000005678 ····_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·name87 ····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·count89 ············("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 modifiedOffset 113, 21 lines modified
  
72 ····class·_IO_STATUS_BLOCK(ctypes.Structure):··#·ruff:ignore[invalid-class-name]··#·mirrors·the·Win32·struct·name113 ····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-sized115 ············("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·name124 ····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·Offset126 ············("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·offset128 ············("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 modifiedOffset 190, 65 lines modified
142 ········wintypes.HANDLE,190 ········wintypes.HANDLE,
Max diff block lines reached; 31085/38526 bytes (80.69%) of diff not shown.
⊟
28.7 KB
filelock/asyncio.py
    
Offset 1, 75 lines modifiedOffset 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·annotations2 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·asyncio14 import·asyncio
4 import·contextlib15 import·contextlib
 16 import·functools
5 import·logging17 import·logging
6 import·os18 import·os
 19 import·sys
7 import·time20 import·time
 21 from·concurrent·import·futures
8 from·dataclasses·import·dataclass22 from·dataclasses·import·dataclass,·field,·fields
9 from·inspect·import·iscoroutinefunction23 from·inspect·import·iscoroutinefunction
10 from·threading·import·local24 from·threading·import·RLock
11 from·typing·import·TYPE_CHECKING,·Final,·NoReturn,·TypeVar,·cast25 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·Timeout60 from·filelock._error·import·Timeout
41 from·._lease·import·SoftFileLease61 from·filelock._lease·import·SoftFileLease
42 from·._soft·import·SoftFileLock62 from·filelock._soft·import·SoftFileLock
43 from·._strict·import·StrictSoftFileLock63 from·filelock._strict·import·StrictSoftFileLock
44 from·._unix·import·UnixFileLock64 from·filelock._unix·import·UnixFileLock
 65 from·filelock._util·import·ensure_directory_exists
45 from·._windows·import·WindowsFileLock66 from·filelock._windows·import·WindowsFileLock
  
46 if·TYPE_CHECKING:67 if·TYPE_CHECKING:
47 ····import·sys 
48 ····from·collections.abc·import·Awaitable,·Callable,·Coroutine,·Hashable68 ····from·collections.abc·import·Awaitable,·Callable,·Coroutine,·Hashable,·Mapping
49 ····from·concurrent·import·futures 
50 ····from·types·import·TracebackType69 ····from·types·import·TracebackType
  
51 ····if·sys.version_info·>=·(3,·11):··#·pragma:·no·cover·(py311+) 
52 ········from·typing·import·Self70 ····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·parameters80 ····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·constructed81 ········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 modifiedOffset 177, 20 lines modified
159 ········:param·lock_file:·path·to·the·file177 ········: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·the178 ········: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·a179 ············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·and181 ········: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·to183 ········: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``·(the·default),·**all·fields·of·the184 ············``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·change186 ············``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·supplied187 ············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 ············with·``thread_local=False``.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·not190 ········: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·lock191 ········: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·the192 ············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·value194 ········: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·delete196 ········:param·lifetime:·for·:class:`AsyncSoftFileLock`,·the·age·in·seconds·after·which·a·waiting·process·may·delete
Offset 193, 66 lines modifiedOffset 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·lock213 ········: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·before214 ············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·the215 ············: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.
⊟
420 B
filelock/version.py
    
Offset 14, 11 lines modifiedOffset 14, 11 lines modified
14 version:·str14 version:·str
15 __version__:·str15 __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·|·None18 commit_id:·str·|·None
19 __commit_id__:·str·|·None19 __commit_id__:·str·|·None
  
20 __version__·=·version·=·'3.32.2'20 __version__·=·version·=·'4.2.4'
21 __version_tuple__·=·version_tuple·=·(3,·32,·2)21 __version_tuple__·=·version_tuple·=·(4,·2,·4)
  
22 __commit_id__·=·commit_id·=·None22 __commit_id__·=·commit_id·=·None
⊟
764 B
filelock/_soft_rw/__init__.py
    
Offset 1, 12 lines modifiedOffset 1, 14 lines modified
1 """Cross-process·and·cross-host·reader/writer·lock·on·:class:`~filelock.SoftFileLock`·primitives."""1 """Cross-process·and·cross-host·reader/writer·lock·over·a·generation·log·of·immutable·snapshots."""
  
2 from·__future__·import·annotations2 from·__future__·import·annotations
  
 3 __lazy_modules__·=·["filelock._soft_rw._async"]
  
3 from·._async·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock4 from·filelock._soft_rw._async·import·AsyncAcquireSoftReadWriteReturnProxy,·AsyncSoftReadWriteLock
4 from·._sync·import·SoftReadWriteLock5 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 ]
⊟
19.0 KB
filelock/_soft_rw/_async.py
    
Offset 1, 54 lines modifiedOffset 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·annotations2 from·__future__·import·annotations
  
 3 __lazy_modules__·=·["asyncio",·"filelock._async",·"filelock._error",·"functools",·"threading"]
  
3 import·asyncio4 import·asyncio
4 import·functools5 import·functools
5 import·os6 import·os
 7 import·threading
6 from·contextlib·import·asynccontextmanager8 from·contextlib·import·asynccontextmanager
7 from·typing·import·TYPE_CHECKING,·ParamSpec,·TypeVar9 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·._sync·import·SoftReadWriteLock20 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,·Callable23 ····from·collections.abc·import·AsyncGenerator,·Callable
19 ····from·concurrent·import·futures24 ····from·concurrent·import·futures
20 ····from·types·import·TracebackType25 ····from·types·import·TracebackType
  
21 ····from·filelock._api·import·AcquireReturnProxy26 ····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()``.·The33 ····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 ····TTL·stale·detection,·and·singleton·behavior.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;·sidecar·state/write/readers·live·next·to·it38 ····: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·indefinitely39 ····:param·timeout:·maximum·wait·time·in·seconds;·``-1``·means·block·indefinitely
32 ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·on·contention40 ····:param·blocking:·if·``False``,·raise·:class:`~filelock.Timeout`·immediately·on·contention
33 ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`SoftReadWriteLock`·instances·per·resolved·path41 ····:param·is_singleton:·if·``True``,·reuse·existing·:class:`SoftReadWriteLock`·instances·per·resolved·path
34 ····:param·heartbeat_interval:·seconds·between·heartbeat·refreshes;·default·30·s42 ····:param·heartbeat_interval:·seconds·between·heartbeat·refreshes;·default·30·s
35 ····:param·stale_threshold:·seconds·of·mtime·inactivity·before·a·marker·is·stale;·defaults·to·``3·*·heartbeat_interval``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·s45 ····: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·loop48 ····: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·executor49 ····:param·executor:·executor·for·``run_in_executor``;·``None``·uses·the·default·executor
  
39 ····..·versionadded::·3.27.050 ····..·versionadded::·3.27.0
  
40 ····"""51 ····"""
  
Offset 58, 27 lines modifiedOffset 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·=·loop96 ········self._loop·=·loop
79 ········self._executor·=·executor97 ········self._executor·=·executor
  
80 ····@property98 ····@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_file101 ········return·self._lock.lock_file
Offset 90, 14 lines modifiedOffset 108, 24 lines modified
  
90 ····@property108 ····@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.blocking111 ········return·self._lock.blocking
  
94 ····@property112 ····@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._loop123 ········return·self._loop
  
98 ····@property124 ····@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.
⊟
65.7 KB
filelock/_soft_rw/_sync.py
    
Offset 1, 241 lines modifiedOffset 1, 294 lines modified
1 """Cross-process·and·cross-host·reader/writer·lock·built·on·:class:`SoftFileLock`·primitives."""1 """Cross-process·and·cross-host·reader/writer·lock·over·a·generation·log·of·immutable·snapshots."""
  
2 from·__future__·import·annotations2 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·atexit10 import·atexit
4 import·hmac 
5 import·os11 import·os
6 import·re 
7 import·secrets 
8 import·socket 
9 import·stat 
10 import·sys 
11 import·threading12 import·threading
12 import·time13 import·time
13 import·uuid 
14 from·contextlib·import·closing,·contextmanager,·suppress14 from·contextlib·import·contextmanager,·suppress
15 from·dataclasses·import·dataclass15 from·dataclasses·import·dataclass
16 from·pathlib·import·Path16 from·math·import·isfinite
17 from·typing·import·TYPE_CHECKING,·Final,·Literal17 from·typing·import·TYPE_CHECKING,·ClassVar,·Final
18 from·weakref·import·WeakValueDictionary18 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 ····_unregister_owned_descriptor,27 ····_resolve_read_write_timeout,
 28 ····_seconds,
 29 ····_timeout_behavior,
28 )30 )
29 from·filelock._error·import·Timeout31 from·filelock._error·import·Timeout
30 from·filelock._soft·import·SoftFileLock 
31 from·filelock._util·import·ensure_directory_exists,·touch,·write_all32 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,·Generator36 ····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[Path,·SoftReadWriteLock]41 ····_instances:·WeakValueDictionary[str,·SoftReadWriteLock]
47 ····_instances_lock:·threading.RLock42 ····_instances_lock:·threading.RLock
 43 ····_instances_under_construction:·set[str]
  
48 ····def·__call__(··#·ruff:ignore[too-many-arguments]··#·forwards·the·public·constructor's·documented·parameters44 ····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·=·Path(lock_file).resolve()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·_SINGLETONS_UNDER_CONSTRUCTION:··#·pragma:·needs·fork76 ················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 ················_SINGLETONS_UNDER_CONSTRUCTION.add(normalized)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 ····················_SINGLETONS_UNDER_CONSTRUCTION.discard(normalized)94 ····················construction_registry.discard(normalized)
91 ················if·os.getpid()·!=·construction_pid:··#·pragma:·needs·fork95 ················if·os.getpid()·!=·construction_pid:··#·pragma:·needs·fork
Max diff block lines reached; 61623/67182 bytes (91.73%) of diff not shown.
⊟
561 B
reportlab/__init__.py
    
Offset 1, 13 lines modifiedOffset 1, 13 lines modified
1 #Copyright·ReportLab·Europe·Ltd.·2000-20261 #Copyright·ReportLab·Europe·Ltd.·2000-2026
2 #see·license.txt·for·license·details2 #see·license.txt·for·license·details
3 __doc__="""The·Reportlab·PDF·generation·library."""3 __doc__="""The·Reportlab·PDF·generation·library."""
4 Version·=·"5.0.0"4 Version·=·"5.0.1"
5 __version__=Version5 __version__=Version
6 __date__='20260618'6 __date__='20260820'
  
7 import·sys,·os7 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__
⊟
646 B
reportlab/graphics/renderPDF.py
    
Offset 291, 15 lines modifiedOffset 291, 15 lines modified
291 ····an·A4·page·with·a·title·above·it·-·possibly·overflowing291 ····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'+x295 ········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))
⊟
3.3 KB
reportlab/lib/rl_safe_eval.py
    
Offset 5, 14 lines modifiedOffset 5, 19 lines modified
5 #hopefully·we·are·standing·on·giants'·shoulders5 #hopefully·we·are·standing·on·giants'·shoulders
6 import·sys,·os,·ast,·re,·weakref,·time,·copy,·math,·types6 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·textwrap15 import·textwrap
  
12 class·BadCode(ValueError):16 class·BadCode(ValueError):
13 »       pass17 »       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 modifiedOffset 920, 26 lines modified
915 »       »       #these·are·used·in·the·tree·visitor920 »       »       #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·builtins936 »       »       #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 modifiedOffset 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.start1092 »       »       »       »       start·=·a.start
1082 »       »       »       »       stop·=·a.stop1093 »       »       »       »       stop·=·a.stop
1083 »       »       »       »       if·start·is·None:1094 »       »       »       »       if·start·is·None:
Offset 1090, 14 lines modifiedOffset 1102, 25 lines modified
1090 »       »       »       »       »       v·=·obj[start:stop]1102 »       »       »       »       »       v·=·obj[start:stop]
1091 »       »       »       return·v1103 »       »       »       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__·=·51118 »       __rl_tmax__·=·5
1097 »       __rl_max_len__·=·1000001119 »       __rl_max_len__·=·100000
1098 »       __rl_max_pow_digits__·=·1001120 »       __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__):
⊟
6.54 KB
reportlab/lib/utils.py
    
Offset 467, 21 lines modifiedOffset 467, 16 lines modified
467 ········#the·dirname(reportlab.__file__)·or·is·relative467 ········#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,·urlparse472 from·urllib.parse·import·unquote,·urlparse
473 from·urllib.request·import·urlopen,·Request473 _tHaS·=·{}··#cache·for·(trustedHosts,trustedSchemes)
474 def·rlUrlRead(name,·headers=None):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·because476 ····#copied·here·from·urllib.URLopener.open_data·because
481 ····#·1)·they·want·to·remove·it477 ····#·1)·they·want·to·remove·it
482 ····#·2)·the·existing·one·is·borken478 ····#·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·data481 ········#·ignore·POSTed·data
Offset 505, 49 lines modifiedOffset 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·data506 ········return·data
512 ····from·reportlab.rl_config·import·trustedHosts,·trustedSchemes 
513 ····if·trustedHosts:507 ····import·socket
 508 ····from·urllib.request·import·OpenerDirector,·build_opener,·Request
514 ········import·re,·fnmatch509 ····import·re,·fnmatch
515 ········def·xre(s):510 ····def·xre(s):
516 ············s·=·fnmatch.translate(s)511 ········s·=·fnmatch.translate(s)
517 ············return·s[4:-3]·if·s.startswith('(?s:')·else·s[:-7]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 ········trustedHosts·=·re.compile(''.join(('^(?:',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 ································')\\Z')))543 ································))
  
521 ····def·open_for_read(name,mode='b'): 
522 ········'''attempt·to·open·a·file·or·URL·for·reading''' 
523 ········if·hasattr(name,'read'):·return·name544 ················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 ············return·open_for_read_by_name(name,mode)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 ················raise·IOError(f'Cannot·open·resource·{name!r}')558 ············raise·IOError(f'Cannot·open·resource·{url!r}')
544 ····globals()['open_for_read']·=·open_for_read559 ····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 modifiedOffset 675, 18 lines modified
652 ········else:675 ········else:
653 ············try:676 ············try:
654 ················from·reportlab.rl_config·import·imageReaderFlags677 ················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.
⊟
777 B
reportlab/pdfgen/canvas.py
    
Offset 1304, 15 lines modifiedOffset 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('utf-8')1311 ············s·=·s.encode('latin1')··#this·is·what·pdfdoc.py·uses;·could·not·detect·need·in·tests
1312 ········return·s1312 ········return·s
  
1313 ····def·setPageSize(self,·size):1313 ····def·setPageSize(self,·size):
1314 ········"""accepts·a·2-tuple·in·points·for·paper·size·for·this1314 ········"""accepts·a·2-tuple·in·points·for·paper·size·for·this
1315 ········and·subsequent·pages"""1315 ········and·subsequent·pages"""
1316 ········self._pagesize·=·size1316 ········self._pagesize·=·size
1317 ········self._make_preamble()1317 ········self._make_preamble()
⊟
6.37 KB
soupsieve/__init__.py
    
Offset 26, 33 lines modifiedOffset 26, 35 lines modified
26 SOFTWARE.26 SOFTWARE.
27 """27 """
28 from·__future__·import·annotations28 from·__future__·import·annotations
29 from·.__meta__·import·__version__,·__version_info__··#·noqa:·F40129 from·.__meta__·import·__version__,·__version_info__··#·noqa:·F401
30 from·.·import·css_parser·as·cp30 from·.·import·css_parser·as·cp
31 from·.·import·css_match·as·cm31 from·.·import·css_match·as·cm
32 from·.·import·css_types·as·ct32 from·.·import·css_types·as·ct
33 from·.util·import·DEBUG,·SelectorSyntaxError··#·noqa:·F40133 from·.util·import·DEBUG,·NOCACHE,·NOSTRICT,·SelectorSyntaxError··#·noqa:·F401
34 import·bs434 import·bs4
35 from·typing·import·Any,·Iterator,·Iterable35 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.SoupSieve40 SoupSieve·=·cm.SoupSieve
 41 CustomSelectors·=·ct.CustomSelectors
  
  
42 def·compile(··#·noqa:·A00142 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:·dict[str,·str]·|·None·=·None,47 ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None,
 48 ····ignore:·Iterable[str]·|·None·=·None,
 49 ····max_selectors:·int·=·cp.SELECTOR_LIMIT,
48 ····**kwargs:·Any50 ····**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 modifiedOffset 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·pattern65 ········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(custom)·if·custom·is·not·None·else·custom,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 ········flags73 ········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 modifiedOffset 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:·dict[str,·str]·|·None·=·None,90 ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None,
 91 ····ignore:·Iterable[str]·|·None·=·None,
 92 ····max_selectors:·int·=·cp.SELECTOR_LIMIT,
85 ····**kwargs:·Any93 ····**kwargs:·Any
86 )·->·bs4.Tag·|·None:94 )·->·bs4.Tag·|·None:
87 ····"""Match·closest·ancestor."""95 ····"""Match·closest·ancestor."""
  
88 ····return·compile(select,·namespaces,·flags,·**kwargs).closest(tag)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:·dict[str,·str]·|·None·=·None,111 ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None,
 112 ····ignore:·Iterable[str]·|·None·=·None,
 113 ····max_selectors:·int·=·cp.SELECTOR_LIMIT,
96 ····**kwargs:·Any114 ····**kwargs:·Any
97 )·->·bool:115 )·->·bool:
98 ····"""Match·node."""116 ····"""Match·node."""
  
99 ····return·compile(select,·namespaces,·flags,·**kwargs).match(tag)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:·A001126 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:·dict[str,·str]·|·None·=·None,132 ····custom:·Mapping[str,·str·|·ct.SelectorList]·|·None·=·None,
 133 ····ignore:·Iterable[str]·|·None·=·None,
 134 ····max_selectors:·int·=·cp.SELECTOR_LIMIT,
107 ····**kwargs:·Any135 ····**kwargs:·Any
108 )·->·list[bs4.Tag]:136 )·->·list[bs4.Tag]:
109 ····"""Filter·list·of·nodes."""137 ····"""Filter·list·of·nodes."""
  
110 ····return·compile(select,·namespaces,·flags,·**kwargs).filter(iterable)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.
⊟
355 B
soupsieve/__meta__.py
    
Offset 189, 9 lines modifiedOffset 189, 9 lines modified
  
189 ····#·Handle·post189 ····#·Handle·post
190 ····post·=·int(m.group('post'))·if·m.group('post')·else·0190 ····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(2,·9,·1,·"final")192 __version_info__·=·Version(3,·0,·3,·"final")
193 __version__·=·__version_info__._get_canonical()193 __version__·=·__version_info__._get_canonical()
⊟
48.5 KB
soupsieve/css_match.py
    
Offset 1, 16 lines modifiedOffset 1, 28 lines modified
1 """CSS·matcher."""1 """CSS·matcher."""
2 from·__future__·import·annotations2 from·__future__·import·annotations
3 from·datetime·import·datetime3 from·datetime·import·datetime
 4 from·collections.abc·import·Hashable
4 from·.·import·util5 from·.·import·util
5 import·re6 import·re
6 from·.·import·css_types·as·ct7 from·.·import·css_types·as·ct
7 import·unicodedata8 import·unicodedata
8 import·bs49 import·bs4
9 from·typing·import·Iterator,·Iterable,·Any,·Callable,·Sequence,·Any,·cast··#·noqa:·F401,·F81110 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 #·Relationships25 #·Relationships
Offset 21, 14 lines modifiedOffset 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_RTL45 DIR_FLAGS·=·ct.SEL_DIR_LTR·|·ct.SEL_DIR_RTL
29 RANGES·=·ct.SEL_IN_RANGE·|·ct.SEL_OUT_OF_RANGE46 RANGES·=·ct.SEL_IN_RANGE·|·ct.SEL_OUT_OF_RANGE
  
30 DIR_MAP·=·{47 DIR_MAP·=·{
Offset 52, 32 lines modifiedOffset 70, 19 lines modified
52 SHORT_MONTH·=·3070 SHORT_MONTH·=·30
53 LONG_MONTH·=·3171 LONG_MONTH·=·31
54 FEB_MONTH·=·2872 FEB_MONTH·=·28
55 FEB_LEAP_MONTH·=·2973 FEB_LEAP_MONTH·=·29
56 DAYS_IN_WEEK·=·774 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 ········return·len(self.contents)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 ····@classmethod81 ····@classmethod
73 ····def·assert_valid_input(cls,·tag:·Any)·->·None:82 ····def·assert_valid_input(cls,·tag:·Any)·->·None:
Offset 125, 20 lines modifiedOffset 130, 14 lines modified
125 ····@classmethod130 ····@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 ····@staticmethod134 ····@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 modifiedOffset 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·=·False179 ········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)··#·type:·ignore[return-value]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.
⊟
50.2 KB
soupsieve/css_parser.py
    
Offset 3, 19 lines modifiedOffset 3, 21 lines modified
3 import·re3 import·re
4 from·functools·import·lru_cache4 from·functools·import·lru_cache
5 from·.·import·util5 from·.·import·util
6 from·.·import·css_match·as·cm6 from·.·import·css_match·as·cm
7 from·.·import·css_types·as·ct7 from·.·import·css_types·as·ct
8 from·.util·import·SelectorSyntaxError8 from·.util·import·SelectorSyntaxError
9 import·warnings9 import·warnings
10 from·typing·import·Match,·Any,·Iterator,·cast10 from·typing·import·Match,·Any,·Callable,·Iterator,·Iterable,·Mapping,·cast
11 from·dataclasses·import·dataclass11 from·dataclasses·import·dataclass
12 from·collections·import·UserDict12 from·collections·import·UserDict
13 import·threading13 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·=·0xFFFD17 UNICODE_REPLACEMENT_CHAR·=·0xFFFD
  
17 SELECTOR_LIMIT·=·819218 SELECTOR_LIMIT·=·8192
  
Offset 105, 91 lines modifiedOffset 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_SPECIAL109 PSEUDO_SUPPORTED·=·PSEUDO_SIMPLE·|·PSEUDO_SIMPLE_NO_MATCH·|·PSEUDO_COMPLEX·|·PSEUDO_COMPLEX_NO_MATCH·|·PSEUDO_SPECIAL
  
108 #·Sub-patterns·parts110 #·Sub-patterns·parts
109 #·Whitespace111 #·Whitespace
110 NEWLINE·=·r'(?:\r\n|(?!\r\n)[\n\f\r])'112 NEWLINE·=·r'(?>\r\n|[\n\f\r])'
111 WS·=·fr'(?:[·\t]|{NEWLINE})'113 WS·=·fr'(?:[·\t]|{NEWLINE})'
112 #·Comments114 #·Comments
113 COMMENTS·=·r'(?:/\*(?:[^*]|\*(?!/))*\*/)'115 COMMENTS·=·r'(?:/\*(?:[^*]|\*(?!/))*+\*/)'
114 #·Whitespace·with·comments·included116 #·Whitespace·with·comments·included
115 WSC·=·fr'(?:{WS}|{COMMENTS})'117 WSC·=·fr'(?:{WS}|{COMMENTS})'
116 #·CSS·escapes118 #·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}?|[^\r\n\f]|$|{NEWLINE}))'120 CSS_STRING_ESCAPES·=·fr'(?:\\(?:[a-f0-9]{{1,6}}+{WS}?+|{NEWLINE}|[^\r\n\f]|$))'
119 #·CSS·Identifier121 #·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`·content126 #·`nth`·content
125 NTH·=·fr'(?:[-+])?(?:[0-9]+n?|n)(?:(?<=n){WSC}*(?:[-+]){WSC}*(?:[0-9]+))?'127 NTH·=·fr'[-+]?+(?:[0-9]++n?+|n)(?:(?<=n){WSC}*+[-+]{WSC}*+[0-9]++)?+'
126 #·Value:·quoted·string·or·identifier128 #·Value:·quoted·string·or·identifier
127 VALUE·=·fr'''(?:"(?:\\(?:.|{NEWLINE})|[^\\"\r\n\f])*?"|'(?:\\(?:.|{NEWLINE})|[^\\'\r\n\f])*?'|{IDENTIFIER})'''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]))?)?{WSC}*'135 ATTR·=·fr'(?:{WSC}*+(?P<cmp>[!~^|*$]?+=){WSC}*+(?P<value>{VALUE})(?:{WSC}*+(?P<case>[is]))?+)?+'
  
130 #·Selector·patterns136 #·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'{WSC}*?(?P<relation>[,+>~]|{WS}(?![,+>~])){WSC}*'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·expressions177 #·Regular·expressions
172 #·CSS·escape·pattern178 #·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`·specifiers181 #·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·checks185 #·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]|(?:\n\r|(?!\n\r)[\n\f\r])|{COMMENTS})*')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 #·Constants193 #·Constants
186 #·List·split·token194 #·List·split·token
187 COMMA_COMBINATOR·=·','195 COMMA_COMBINATOR·=·','
188 #·Relation·token·for·descendant196 #·Relation·token·for·descendant
189 WS_COMBINATOR·=·"·"197 WS_COMBINATOR·=·"·"
  
Offset 211, 78 lines modifiedOffset 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.
⊟
16.5 KB
soupsieve/css_types.py
    
Offset 1, 40 lines modifiedOffset 1, 58 lines modified
1 """CSS·selector·structure·items."""1 """CSS·selector·structure·items."""
2 from·__future__·import·annotations2 from·__future__·import·annotations
 3 from·enum·import·Enum
3 import·copyreg4 import·copyreg
4 from·.pretty·import·pretty5 from·.pretty·import·pretty
5 from·typing·import·Any,·Iterator,·Hashable,·Pattern,·Iterable,·Mapping6 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·=·0x119 SEL_EMPTY·=·0x1
19 SEL_ROOT·=·0x220 SEL_ROOT·=·0x2
20 SEL_DEFAULT·=·0x421 SEL_DEFAULT·=·0x4
21 SEL_INDETERMINATE·=·0x822 SEL_INDETERMINATE·=·0x8
22 SEL_SCOPE·=·0x1023 SEL_SCOPE·=·0x10
23 SEL_DIR_LTR·=·0x2024 SEL_DIR_LTR·=·0x20
24 SEL_DIR_RTL·=·0x4025 SEL_DIR_RTL·=·0x40
25 SEL_IN_RANGE·=·0x8026 SEL_IN_RANGE·=·0x80
26 SEL_OUT_OF_RANGE·=·0x10027 SEL_OUT_OF_RANGE·=·0x100
27 SEL_DEFINED·=·0x20028 SEL_DEFINED·=·0x200
28 SEL_PLACEHOLDER_SHOWN·=·0x40029 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:·int44 ····_hash:·int
  
Offset 51, 139 lines modifiedOffset 69, 100 lines modified
51 ····@classmethod69 ····@classmethod
52 ····def·__base__(cls)·->·type[Immutable]:70 ····def·__base__(cls)·->·type[Immutable]:
53 ········"""Get·base·class."""71 ········"""Get·base·class."""
  
54 ········return·cls72 ········return·cls
  
55 ····def·__eq__(self,·other:·Any)·->·bool:73 ····def·__eq__(self,·other:·Any)·->·bool:
56 ········"""Equal."""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 ········"""Equal."""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._hash105 ········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·cover109 ····def·__repr__(self)·->·str:··#·pragma:·no·cover
74 ········"""Representation."""110 ········"""
 111 ········Build·a·representation·without·using·recursion.
  
75 ········r·=·',·'.join([f"{k}={getattr(self,·k)!r}"·for·k·in·self.__slots__[:-1]]) 
76 ········return·f"{self.__class__.__name__}({r})"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.
⊟
959 B
soupsieve/util.py
    
Offset 2, 14 lines modifiedOffset 2, 16 lines modified
2 from·__future__·import·annotations2 from·__future__·import·annotations
3 from·functools·import·wraps,·lru_cache3 from·functools·import·wraps,·lru_cache
4 import·warnings4 import·warnings
5 import·re5 import·re
6 from·typing·import·Callable,·Any6 from·typing·import·Callable,·Any
  
7 DEBUG·=·0x000017 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 modifiedOffset 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·=·082 ····last·=·0
81 ····current_line·=·183 ····current_line·=·1
82 ····col·=·184 ····col·=·1
83 ····text·=·[]··#·type:·list[str]85 ····text:·list[str]·=·[]
84 ····line·=·186 ····line·=·1
85 ····offset·=·None··#·type:·int·|·None87 ····offset:·int·|·None·=·None
  
86 ····#·Split·pattern·by·newline·and·handle·the·text·before·the·newline88 ····#·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·=·-193 ············offset·=·-1
⊟
3.31 KB
svglib/__init__.py
    
Offset 24, 15 lines modifiedOffset 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(path:·str,·outputPat:·Optional[str]·=·None)·->·None: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 modifiedOffset 44, 17 lines modified
40 ············-·%(dirname)s:·Directory·of·input·file44 ············-·%(dirname)s:·Directory·of·input·file
41 ············-·%(basename)s:·Full·filename·with·extension45 ············-·%(basename)s:·Full·filename·with·extension
42 ············-·%(base)s:·Filename·without·extension46 ············-·%(base)s:·Filename·without·extension
43 ············-·%(ext)s:·File·extension47 ············-·%(ext)s:·File·extension
44 ············-·%(now)s:·Current·datetime·object48 ············-·%(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 modifiedOffset 92, 15 lines modified
85 ····#·allow·classic·%%(name)s·notation92 ····#·allow·classic·%%(name)s·notation
86 ····out_path·=·out_pattern·%·file_info93 ····out_path·=·out_pattern·%·file_info
87 ····#·allow·also·newer·{name}·notation94 ····#·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·file96 ····#·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 ········raise101 ········raise
  
95 ····#·save·converted·file102 ····#·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 modifiedOffset 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 modifiedOffset 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 ········svg2pdf(path,·outputPat=args.output)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)
⊟
4.22 KB
svglib/fonts.py
    
Offset 11, 15 lines modifiedOffset 11, 15 lines modified
11 -·Automatic·font·file·detection·and·registration11 -·Automatic·font·file·detection·and·registration
12 """12 """
  
13 import·os13 import·os
14 import·shutil14 import·shutil
15 import·subprocess15 import·subprocess
16 import·sys16 import·sys
17 from·typing·import·Dict,·Optional,·Tuple,·Union17 from·typing·import·Optional,·Union
  
18 from·reportlab.pdfbase.pdfmetrics·import·registerFont18 from·reportlab.pdfbase.pdfmetrics·import·registerFont
19 from·reportlab.pdfbase.ttfonts·import·TTFError,·TTFont19 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 modifiedOffset 67, 16 lines modified
67 ················'rlgFont':·'reportlab_font_name',67 ················'rlgFont':·'reportlab_font_name',
68 ················'exact':·True/False68 ················'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:·Dict[str,·Dict[str,·Union[str,·bool,·int]]]·=·{}73 ········self._map:·dict[str,·dict[str,·Union[str,·bool,·int]]]·=·{}
74 ········self._family_index:·Dict[str,·str]·=·{}··#·lowercase·family·→·canonical·family74 ········self._family_index:·dict[str,·str]·=·{}··#·lowercase·family·→·canonical·family
  
75 ········self.register_default_fonts()75 ········self.register_default_fonts()
  
76 ····@staticmethod76 ····@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 modifiedOffset 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·filename153 ········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 ····)·->·Tuple[Optional[str],·bool]: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·that158 ········Uses·the·system's·fontconfig·utility·to·locate·and·register·fonts·that
159 ········match·the·given·specifications.·This·provides·access·to·system-installed159 ········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 modifiedOffset 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 ····)·->·Tuple[Optional[str],·bool]: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·ReportLab358 ········1.·Registering·a·custom·TrueType·font·file·with·ReportLab
359 ········2.·Creating·a·mapping·from·SVG·font·specifications·to·existing·ReportLab·fonts359 ········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 modifiedOffset 422, 15 lines modified
422 ················return·NOT_FOUND422 ················return·NOT_FOUND
  
423 ········#·If·we·reach·here,·no·registration·was·possible423 ········#·If·we·reach·here,·no·registration·was·possible
424 ········return·NOT_FOUND424 ········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 ····)·->·Tuple[str,·bool]: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-based430 ········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 modifiedOffset 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 )·->·Tuple[Optional[str],·bool]: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 modifiedOffset 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 )·->·Tuple[str,·bool]: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.
⊟
34.9 KB
svglib/svglib.py
    
Offset 29, 20 lines modifiedOffset 29, 16 lines modified
29 import·shlex29 import·shlex
30 import·shutil30 import·shutil
31 from·collections·import·defaultdict,·namedtuple31 from·collections·import·defaultdict,·namedtuple
32 from·io·import·BytesIO32 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·PILImage42 from·PIL·import·Image·as·PILImage
47 from·reportlab.graphics.renderSVG·import·SVGCanvas43 from·reportlab.graphics.renderSVG·import·SVGCanvas
Offset 107, 24 lines modifiedOffset 103, 24 lines modified
  
107 #·An·SVG·source·accepted·by·the·public·API:·a·path,·a·path-like·object,·or·an103 #·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·untyped106 #·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·=·Tuple[float,·Any]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:·str112 ····gradientUnits:·str
117 ····spreadMethod:·str113 ····spreadMethod:·str
118 ····stops:·List[GradientStop]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 ····#·linearGradient118 ····#·linearGradient
Offset 162, 15 lines modifiedOffset 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 )·->·Tuple[Optional[str],·bool]: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·font166 ····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 modifiedOffset 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 )·->·Tuple[str,·bool]: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·font187 ····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 modifiedOffset 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)·->·Dict[str,·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:·Dict[str,·Any]·=·super().getProperties(*args,·**kwargs)288 ········props:·dict[str,·Any]·=·super().getProperties(*args,·**kwargs)
293 ········if·"strokeWidth"·in·props:289 ········if·"strokeWidth"·in·props:
294 ············props["strokeWidth"]·=·0290 ············props["strokeWidth"]·=·0
295 ········if·"strokeColor"·in·props:291 ········if·"strokeColor"·in·props:
296 ············props["strokeColor"]·=·None292 ············props["strokeColor"]·=·None
297 ········return·props293 ········return·props
  
  
Offset 309, 17 lines modifiedOffset 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·=·1310 ········self.isClipPath·=·1
  
315 ····def·getProperties(self,·*args:·Any,·**kwargs:·Any)·->·Dict[str,·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:·Dict[str,·Any]·=·Path.getProperties(self,·*args,·**kwargs)313 ········props:·dict[str,·Any]·=·Path.getProperties(self,·*args,·**kwargs)
318 ········if·"fillColor"·in·props:314 ········if·"fillColor"·in·props:
319 ············props["fillColor"]·=·None315 ············props["fillColor"]·=·None
320 ········if·"strokeColor"·in·props:316 ········if·"strokeColor"·in·props:
321 ············props["strokeColor"]·=·None317 ············props["strokeColor"]·=·None
322 ········return·props318 ········return·props
  
  
Offset 368, 15 lines modifiedOffset 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_box368 ········self.main_box·=·main_box
  
373 ····def·parseMultiAttributes(self,·line:·str)·->·Dict[str,·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.
⊟
6.57 KB
svglib/utils.py
    
Offset 11, 20 lines modifiedOffset 11, 20 lines modified
11 -·Elliptical·arc·processing·functions11 -·Elliptical·arc·processing·functions
12 -·Vector·mathematics·helpers12 -·Vector·mathematics·helpers
13 -·String·parsing·utilities·for·SVG·attributes13 -·String·parsing·utilities·for·SVG·attributes
14 """14 """
  
15 import·re15 import·re
16 from·math·import·acos,·ceil,·copysign,·cos,·degrees,·fabs,·hypot,·radians,·sin,·sqrt16 from·math·import·acos,·ceil,·copysign,·cos,·degrees,·fabs,·hypot,·radians,·sin,·sqrt
17 from·typing·import·List,·Tuple,·Union,·cast17 from·typing·import·Union,·cast
  
18 from·reportlab.graphics.shapes·import·mmult,·rotate,·transformPoint,·translate18 from·reportlab.graphics.shapes·import·mmult,·rotate,·transformPoint,·translate
  
  
19 def·split_floats(op:·str,·min_num:·int,·value:·str)·->·List[Union[str,·List[float]]]: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·the21 ····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·subsequent22 ····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 modifiedOffset 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·seq53 ········if·seq
54 ····]54 ····]
55 ····res:·List[Union[str,·List[float]]]·=·[]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(List[float],·list(floats[i·:·i·+·min_num]))])59 ········res.extend([op,·cast(list[float],·list(floats[i·:·i·+·min_num]))])
60 ····return·res60 ····return·res
  
  
61 def·split_arc_values(op:·str,·value:·str)·->·List[Union[str,·List[float]]]: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·with64 ····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 modifiedOffset 93, 21 lines modified
93 ····#·3·numb,·2·flags,·1·coord·pair93 ····#·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:·List[Union[str,·List[float]]]·=·[]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(List[float],·list(float(num)·for·num·in·seq.groups()))])102 ········res.extend([op,·cast(list[float],·list(float(num)·for·num·in·seq.groups()))])
103 ····return·res103 ····return·res
  
  
104 def·normalise_svg_path(attr:·str)·->·List[Union[str,·List[float]]]: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·format106 ····Parses·raw·SVG·path·string·and·converts·it·into·a·standardized·list·format
107 ····where·each·path·command·is·paired·with·its·coordinate·parameters.·Automatically107 ····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 modifiedOffset 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:·List[Union[str,·List[float]]]·=·[]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 ············continue165 ············continue
166 ········if·item·in·op_keys:166 ········if·item·in·op_keys:
167 ············op·=·item167 ············op·=·item
Offset 175, 17 lines modifiedOffset 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·op176 ············op·=·cast(str,·result[-2])··#·Remember·last·op
  
177 ····return·result177 ····return·result
  
  
178 def·convert_quadratic_to_cubic_path(178 def·convert_quadratic_to_cubic_path(
179 ····q0:·Tuple[float,·float],·q1:·Tuple[float,·float],·q2:·Tuple[float,·float]179 ····q0:·tuple[float,·float],·q1:·tuple[float,·float],·q2:·tuple[float,·float]
180 )·->·Tuple[180 )·->·tuple[
181 ····Tuple[float,·float],·Tuple[float,·float],·Tuple[float,·float],·Tuple[float,·float]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,·q2184 ····Converts·a·quadratic·Bezier·curve·defined·by·control·points·q0,·q1,·q2
185 ····into·an·equivalent·cubic·Bezier·curve.·This·is·useful·for·SVG·processing185 ····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 modifiedOffset 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:·Tuple[float,·float],·v:·Tuple[float,·float])·->·float: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·to223 ····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 modifiedOffset 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 )·->·Tuple[float,·float,·float,·float,·float,·float]: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.
⊟
11.0 KB
webencodings/__init__.py
    
Offset 1, 71 lines modifiedOffset 1, 74 lines modified
1 #·coding:·utf-8 
2 """1 """
  
3 ····webencodings2 ····webencodings
4 ····~~~~~~~~~~~~3 ····~~~~~~~~~~~~
  
5 ····This·is·a·Python·implementation·of·the·`WHATWG·Encoding·standard4 ····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·Sapin6 ····: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·codecs9 import·codecs
  
 10 from·.custom·import·replacement_codec_info,·user_codec_info
12 from·.labels·import·LABELS11 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-8859-8',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 ····r"""Transform·(only)·ASCII·letters·to·lower·case:·A-Z·is·mapped·to·a-z.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-insensitive30 ····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:`~py:str.lower`·method·of·Unicode·strings35 ····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·=·u'Bac\N{KELVIN·SIGN}ground'38 ········>>>·keyword·=·'Bac\\N{KELVIN·SIGN}ground'
34 ········>>>·assert·keyword.lower()·==·u'background'39 ········>>>·assert·keyword.lower()·==·'background'
35 ········>>>·assert·ascii_lower(keyword)·!=·keyword.lower()40 ········>>>·assert·ascii_lower(keyword)·!=·keyword.lower()
36 ········>>>·assert·ascii_lower(keyword)·==·u'bac\N{KELVIN·SIGN}ground'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('utf8').lower().decode('utf8')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’s·`get·an·encoding47 ····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 modifiedOffset 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·None80 ········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 ············from·.x_user_defined·import·codec_info84 ············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]·=·encoding92 ········CACHE[name]·=·encoding
88 ····return·encoding93 ····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:`~exceptions.LookupError`·for·an·unknown·label.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_label101 ········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:·%r'·%·encoding_or_label)104 ········raise·LookupError(f'Unknown·encoding·label:·{encoding_or_label!r}')
101 ····return·encoding105 ····return·encoding
  
  
102 class·Encoding(object):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::·name108 ····..·attribute::·name
  
106 ········Canonical·name·of·the·encoding109 ········Canonical·name·of·the·encoding
  
Max diff block lines reached; 6493/11193 bytes (58.01%) of diff not shown.
⊟
45.0 B
encoding
    
Offset 1, 1 lines modifiedOffset 1, 1 lines modified
1 utf-81 us-ascii
⊟
3.3 KB
webencodings/labels.py
    
Offset 11, 16 lines modifiedOffset 11, 19 lines modified
11 """11 """
  
12 #·XXX·Do·not·edit!12 #·XXX·Do·not·edit!
13 #·This·file·is·automatically·generated·by·mklabels.py13 #·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 modifiedOffset 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 modifiedOffset 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 modifiedOffset 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':·········'iso-2022-kr',229 ····'csiso2022kr':·········'replacement',
 230 ····'hz-gb-2312':··········'replacement',
 231 ····'iso-2022-cn':·········'replacement',
 232 ····'iso-2022-cn-ext':·····'replacement',
226 ····'iso-2022-kr':·········'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 }
⊟
44.1 KB
charset_normalizer-3.4.9.dist-info/METADATA vs.
charset_normalizer-3.5.2.dist-info/METADATA
Files 92% similar despite different names
    
Offset 1, 10 lines modifiedOffset 1, 10 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.4
2 Name:·charset-normalizer2 Name:·charset-normalizer
3 Version:·3.4.93 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:·MIT7 License:·MIT
8 Project-URL:·Changelog,·https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md8 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_normalizer10 Project-URL:·Code,·https://github.com/jawah/charset_normalizer
Offset 19, 18 lines modifiedOffset 19, 21 lines modified
19 Classifier:·Programming·Language·::·Python·::·3.819 Classifier:·Programming·Language·::·Python·::·3.8
20 Classifier:·Programming·Language·::·Python·::·3.920 Classifier:·Programming·Language·::·Python·::·3.9
21 Classifier:·Programming·Language·::·Python·::·3.1021 Classifier:·Programming·Language·::·Python·::·3.10
22 Classifier:·Programming·Language·::·Python·::·3.1122 Classifier:·Programming·Language·::·Python·::·3.11
23 Classifier:·Programming·Language·::·Python·::·3.1223 Classifier:·Programming·Language·::·Python·::·3.12
24 Classifier:·Programming·Language·::·Python·::·3.1324 Classifier:·Programming·Language·::·Python·::·3.13
25 Classifier:·Programming·Language·::·Python·::·3.1425 Classifier:·Programming·Language·::·Python·::·3.14
 26 Classifier:·Programming·Language·::·Python·::·3.15
26 Classifier:·Programming·Language·::·Python·::·3·::·Only27 Classifier:·Programming·Language·::·Python·::·3·::·Only
27 Classifier:·Programming·Language·::·Python·::·Implementation·::·CPython28 Classifier:·Programming·Language·::·Python·::·Implementation·::·CPython
28 Classifier:·Programming·Language·::·Python·::·Implementation·::·PyPy29 Classifier:·Programming·Language·::·Python·::·Implementation·::·PyPy
29 Classifier:·Programming·Language·::·Python·::·Free·Threading·::·4·-·Resilient30 Classifier:·Programming·Language·::·Python·::·Free·Threading·::·4·-·Resilient
 31 Classifier:·Environment·::·WebAssembly
 32 Classifier:·Environment·::·WebAssembly·::·Emscripten
30 Classifier:·Topic·::·Text·Processing·::·Linguistic33 Classifier:·Topic·::·Text·Processing·::·Linguistic
31 Classifier:·Topic·::·Utilities34 Classifier:·Topic·::·Utilities
32 Classifier:·Typing·::·Typed35 Classifier:·Typing·::·Typed
33 Requires-Python:·>=3.736 Requires-Python:·>=3.7
34 Description-Content-Type:·text/markdown37 Description-Content-Type:·text/markdown
35 License-File:·LICENSE38 License-File:·LICENSE
36 Provides-Extra:·unicode-backport39 Provides-Extra:·unicode-backport
Offset 72, 56 lines modifiedOffset 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`········································|········_Disputed_[^2]<br>_restrictive_········|···············································MIT···············································|············MPL-1.1<br>_restrictive_·············|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 |·`Whl·Size·(min)`·································|····················500·kB·····················|·············································150·kB··············································|·····················~200·kB·····················|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·used·one.94 [^1]:·They·are·clearly·using·specific·code·for·a·specific·encoding·even·if·covering·most·of·them.
91 [^2]:·Chardet·7.0+·was·relicensed·from·LGPL-2.1·to·MIT·following·an·AI-assisted·rewrite.·This·relicensing·is·disputed·on·two·independent·grounds:·**(a)**·the·original·author·[contests](https://github.com/chardet/chardet/issues/327)·that·the·maintainer·had·the·right·to·re[·...·truncated·by·diffoscope;·len:·1022,·SHA:·bd8f50206097e27a8557d398b8d7fd66053cb41ebeeabd24186dc25151673471·...·].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 ##·⚡·Performance96 ##·⚡·Performance
  
93 This·package·offer·better·performances·against·Chardet.·Here·are·some·numbers.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 |·charset-normalizer································|·**97·%**·|········1·ms········|···1000·file/sec····|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·400+·files·using·default·parameters.·More·details·on·used·files,·see·GHA·workflows.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 >·is·based·on·a·completely·different·algorithm,·still·heuristic·through,·it·does·not·need·weights·across·every·encoding·tables.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 ##·✨·Installation123 ##·✨·Installation
  
111 Using·pip:124 Using·pip:
  
112 ```sh125 ```sh
113 pip·install·charset-normalizer·-U126 pip·install·charset-normalizer·-U
Offset 296, 14 lines modifiedOffset 310, 65 lines modified
  
296 [![OpenSSF·Best·Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297)310 [![OpenSSF·Best·Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297)
  
297 #·Changelog311 #·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.
⊟
26.6 KB
html2text {}
    
Offset 1, 8 lines modifiedOffset 1, 8 lines modified
1 Metadata-Version:·2.4·Name:·charset-normalizer·Version:·3.4.9·Summary:·The·Real1 Metadata-Version:·2.4·Name:·charset-normalizer·Version:·3.5.2·Summary:·The·Real
2 First·Universal·Charset·Detector.·Open,·modern·and·actively·maintained2 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 modifiedOffset 12, 23 lines modified
12 Classifier:·Operating·System·::·OS·Independent·Classifier:·Programming·Language12 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·::·Only19 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 backport·Dynamic:·license-file20 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·Detector29 ···················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·Packages33 ·······························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 modifiedOffset 41, 154 lines modified
40 and·yes,·it·would·work·as-is.·This·project·offers·you·an·alternative·to41 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 _restrictive_·|·MIT·|·MPL-1.148 |·|·`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·spoken53 _restrictive_·|·|·`Native·Python`·|·âœ…·|·âœ…·|·âŒ·|·|·`Detect·spoken
52 language`·|·âœ…·|·âœ…·|·N/A·|·|·`UnicodeDecodeError·Safety`·|·âœ…·|·âœ…·|·âŒ·|54 language`·|·âœ…·|·âœ…·|·N/A·|·|·`UnicodeDecodeError·Safety`·|·âŒ·|·âœ…·|·âŒ·|
53 |·`Whl·Size·(min)`·|·500·kB·|·150·kB·|·~200·kB·|·|·`Supported·Encoding`·|·99·|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·if60 [^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 |·|·charset-normalizer·|·**97·%**·|·1·ms·|·1000·file/sec·|·|·Package·|·99th61 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.
⊟
141 B
charset_normalizer-3.4.9.dist-info/licenses/LICENSE vs.
charset_normalizer-3.5.2.dist-info/licenses/LICENSE
Files identical despite different names
⊟
1.2 KB
cssselect2-0.9.0.dist-info/METADATA vs.
cssselect2-0.10.1.dist-info/METADATA
Files 98% similar despite different names
    
Offset 1, 10 lines modifiedOffset 1, 10 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.5
2 Name:·cssselect22 Name:·cssselect2
3 Version:·0.9.03 Version:·0.10.1
4 Summary:·CSS·selectors·for·Python·ElementTree4 Summary:·CSS·selectors·for·Python·ElementTree
5 Keywords:·css,elementtree5 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.108 Requires-Python:·>=3.10
9 Description-Content-Type:·text/x-rst9 Description-Content-Type:·text/x-rst
10 Classifier:·Development·Status·::·5·-·Production/Stable10 Classifier:·Development·Status·::·5·-·Production/Stable
Offset 33, 14 lines modifiedOffset 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/courtbouillon35 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/issues37 Project-URL:·Issues,·https://github.com/Kozea/cssselect2/issues
38 Provides-Extra:·doc38 Provides-Extra:·doc
39 Provides-Extra:·test39 Provides-Extra:·test
 40 Import-Name:·cssselect2
  
40 cssselect2·is·a·straightforward·implementation·of·CSS4·Selectors·for·markup41 cssselect2·is·a·straightforward·implementation·of·CSS4·Selectors·for·markup
41 documents·(HTML,·XML,·etc.)·that·can·be·read·by·ElementTree-like·parsers42 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·license44 *·Free·software:·BSD·license
44 *·For·Python·3.10+,·tested·on·CPython·and·PyPy45 *·For·Python·3.10+,·tested·on·CPython·and·PyPy
⊟
126 B
cssselect2-0.9.0.dist-info/licenses/LICENSE vs.
cssselect2-0.10.1.dist-info/licenses/LICENSE
Files identical despite different names
⊟
1.83 KB
filelock-3.32.2.dist-info/METADATA vs.
filelock-4.2.4.dist-info/METADATA
Files 96% similar despite different names
    
Offset 1, 10 lines modifiedOffset 1, 10 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.5
2 Name:·filelock2 Name:·filelock
3 Version:·3.32.23 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.io5 Project-URL:·Documentation,·https://py-filelock.readthedocs.io
6 Project-URL:·Homepage,·https://github.com/tox-dev/py-filelock6 Project-URL:·Homepage,·https://github.com/tox-dev/py-filelock
7 Project-URL:·Source,·https://github.com/tox-dev/py-filelock7 Project-URL:·Source,·https://github.com/tox-dev/py-filelock
8 Project-URL:·Tracker,·https://github.com/tox-dev/py-filelock/issues8 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:·MIT10 License-Expression:·MIT
Offset 12, 24 lines modifiedOffset 12, 23 lines modified
12 Keywords:·application,cache,directory,log,user12 Keywords:·application,cache,directory,log,user
13 Classifier:·Development·Status·::·5·-·Production/Stable13 Classifier:·Development·Status·::·5·-·Production/Stable
14 Classifier:·Intended·Audience·::·Developers14 Classifier:·Intended·Audience·::·Developers
15 Classifier:·License·::·OSI·Approved·::·MIT·License15 Classifier:·License·::·OSI·Approved·::·MIT·License
16 Classifier:·Operating·System·::·OS·Independent16 Classifier:·Operating·System·::·OS·Independent
17 Classifier:·Programming·Language·::·Python17 Classifier:·Programming·Language·::·Python
18 Classifier:·Programming·Language·::·Python·::·3·::·Only18 Classifier:·Programming·Language·::·Python·::·3·::·Only
19 Classifier:·Programming·Language·::·Python·::·3.10 
20 Classifier:·Programming·Language·::·Python·::·3.1119 Classifier:·Programming·Language·::·Python·::·3.11
21 Classifier:·Programming·Language·::·Python·::·3.1220 Classifier:·Programming·Language·::·Python·::·3.12
22 Classifier:·Programming·Language·::·Python·::·3.1321 Classifier:·Programming·Language·::·Python·::·3.13
23 Classifier:·Programming·Language·::·Python·::·3.1422 Classifier:·Programming·Language·::·Python·::·3.14
24 Classifier:·Programming·Language·::·Python·::·3.1523 Classifier:·Programming·Language·::·Python·::·3.15
25 Classifier:·Topic·::·Internet24 Classifier:·Topic·::·Internet
26 Classifier:·Topic·::·Software·Development·::·Libraries25 Classifier:·Topic·::·Software·Development·::·Libraries
27 Classifier:·Topic·::·System26 Classifier:·Topic·::·System
28 Requires-Python:·>=3.1027 Requires-Python:·>=3.11
29 Description-Content-Type:·text/markdown28 Description-Content-Type:·text/markdown
  
30 #·filelock29 #·filelock
  
31 [![PyPI](https://img.shields.io/pypi/v/filelock)](https://pypi.org/project/filelock/)30 [![PyPI](https://img.shields.io/pypi/v/filelock)](https://pypi.org/project/filelock/)
32 [![Supported·Python·versions](https://img.shields.io/pypi/pyversions/filelock.svg)](https://pypi.org/project/filelock/)31 [![Supported·Python·versions](https://img.shields.io/pypi/pyversions/filelock.svg)](https://pypi.org/project/filelock/)
33 [![Documentation·status](https://readthedocs.org/projects/py-filelock/badge/?version=latest)](https://py-filelock.readthedocs.io/en/latest/?badge=latest)32 [![Documentation·status](https://readthedocs.org/projects/py-filelock/badge/?version=latest)](https://py-filelock.readthedocs.io/en/latest/?badge=latest)
⊟
122 B
filelock-3.32.2.dist-info/licenses/LICENSE vs.
filelock-4.2.4.dist-info/licenses/LICENSE
Files identical despite different names
⊟
592 B
reportlab-5.0.0.dist-info/METADATA vs.
reportlab-5.0.1.dist-info/METADATA
Files 92% similar despite different names
    
Offset 1, 10 lines modifiedOffset 1, 10 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.4
2 Name:·reportlab2 Name:·reportlab
3 Version:·5.0.03 Version:·5.0.1
4 Summary:·The·Reportlab·Toolkit4 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·community6 Author:·Andy·Robinson,·Robin·Becker,·the·ReportLab·team·and·the·community
7 Author-email:·reportlab-users@lists2.reportlab.com7 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/Stable9 Classifier:·Development·Status·::·5·-·Production/Stable
10 Classifier:·Intended·Audience·::·Developers10 Classifier:·Intended·Audience·::·Developers
⊟
123 B
reportlab-5.0.0.dist-info/licenses/LICENSE vs.
reportlab-5.0.1.dist-info/licenses/LICENSE
Files identical despite different names
⊟
3.69 KB
soupsieve-2.9.1.dist-info/METADATA vs.
soupsieve-3.0.3.dist-info/METADATA
Files 84% similar despite different names
    
Offset 1, 35 lines modifiedOffset 1, 34 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.5
2 Name:·soupsieve2 Name:·soupsieve
3 Version:·2.9.13 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/soupsieve5 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:·MIT7 License-Expression:·MIT
8 License-File:·LICENSE.md8 License-File:·LICENSE.md
9 Keywords:·CSS,HTML,XML,filter,query,selector,soup9 Keywords:·CSS,HTML,XML,filter,query,selector,soup
10 Classifier:·Development·Status·::·5·-·Production/Stable10 Classifier:·Development·Status·::·5·-·Production/Stable
11 Classifier:·Environment·::·Console11 Classifier:·Environment·::·Console
12 Classifier:·Intended·Audience·::·Developers12 Classifier:·Intended·Audience·::·Developers
13 Classifier:·License·::·OSI·Approved·::·MIT·License13 Classifier:·License·::·OSI·Approved·::·MIT·License
14 Classifier:·Operating·System·::·OS·Independent14 Classifier:·Operating·System·::·OS·Independent
15 Classifier:·Programming·Language·::·Python·::·315 Classifier:·Programming·Language·::·Python·::·3
16 Classifier:·Programming·Language·::·Python·::·3.10 
17 Classifier:·Programming·Language·::·Python·::·3.1116 Classifier:·Programming·Language·::·Python·::·3.11
18 Classifier:·Programming·Language·::·Python·::·3.1217 Classifier:·Programming·Language·::·Python·::·3.12
19 Classifier:·Programming·Language·::·Python·::·3.1318 Classifier:·Programming·Language·::·Python·::·3.13
20 Classifier:·Programming·Language·::·Python·::·3.1419 Classifier:·Programming·Language·::·Python·::·3.14
 20 Classifier:·Programming·Language·::·Python·::·3.15
21 Classifier:·Topic·::·Internet·::·WWW/HTTP·::·Dynamic·Content21 Classifier:·Topic·::·Internet·::·WWW/HTTP·::·Dynamic·Content
22 Classifier:·Topic·::·Software·Development·::·Libraries·::·Python·Modules22 Classifier:·Topic·::·Software·Development·::·Libraries·::·Python·Modules
23 Classifier:·Typing·::·Typed23 Classifier:·Typing·::·Typed
24 Requires-Python:·>=3.1024 Requires-Python:·>=3.11.5
25 Description-Content-Type:·text/markdown25 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·Sieve32 #·Soup·Sieve
Offset 61, 51 lines modifiedOffset 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 ##·Installation61 ##·Installation
  
63 You·must·have·Beautiful·Soup·already·installed:62 You·must·have·Beautiful·Soup·already·installed:
  
64 ```63 ```console
65 pip·install·beautifulsoup464 $·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·via66 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·soupsieve69 $·pip·install·soupsieve
71 ```70 ```
  
72 If·you·want·to·manually·install·it·from·source,·first·ensure·that·[`build`](https://pypi.org/project/build/)·is71 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·build74 $·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·-w78 $·python·-m·build·-w
80 pip·install·dist/soupsieve-<ver>-py3-none-any.whl79 $·pip·install·dist/soupsieve-<ver>-py3-none-any.whl
81 ```80 ```
  
82 ##·Documentation81 ##·Documentation
  
83 Documentation·is·found·here:·https://facelessuser.github.io/soupsieve/.82 Documentation·is·found·here:·https://facelessuser.github.io/soupsieve/.
  
84 ##·License83 ##·License
  
85 MIT84 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=33333386 [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/soupsieve87 [codecov-link]:·https://codecov.io/github/facelessuser/soupsieve
91 [pypi-image]:·https://img.shields.io/pypi/v/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=33333388 [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=33333389 [pypi-down]:·https://img.shields.io/pypi/dm/soupsieve.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333
93 [pypi-link]:·https://pypi.python.org/pypi/soupsieve90 [pypi-link]:·https://pypi.python.org/pypi/soupsieve
94 [python-image]:·https://img.shields.io/pypi/pyversions/soupsieve?logo=python&logoColor=aaaaaa&labelColor=33333391 [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=33333392 [license-image-mit]:·https://img.shields.io/badge/license-MIT-blue.svg?labelColor=333333
⊟
129 B
soupsieve-2.9.1.dist-info/licenses/LICENSE.md vs.
soupsieve-3.0.3.dist-info/licenses/LICENSE.md
Files identical despite different names
⊟
529 B
svglib-2.1.0.dist-info/METADATA vs.
svglib-2.3.0.dist-info/METADATA
Files 99% similar despite different names
    
Offset 1, 10 lines modifiedOffset 1, 10 lines modified
1 Metadata-Version:·2.41 Metadata-Version:·2.5
2 Name:·svglib2 Name:·svglib
3 Version:·2.1.03 Version:·2.3.0
4 Summary:·A·pure-Python·library·for·reading·and·converting·SVG4 Summary:·A·pure-Python·library·for·reading·and·converting·SVG
5 Project-URL:·Homepage,·https://github.com/deeplook/svglib5 Project-URL:·Homepage,·https://github.com/deeplook/svglib
6 Author:·Dinu·Gherman6 Author:·Dinu·Gherman
7 License-Expression:·LGPL-3.0-or-later7 License-Expression:·LGPL-3.0-or-later
8 License-File:·LICENSE.txt8 License-File:·LICENSE.txt
9 Keywords:·PDF,SVG,conversion,graphics,reportlab9 Keywords:·PDF,SVG,conversion,graphics,reportlab
10 Classifier:·Development·Status·::·5·-·Production/Stable10 Classifier:·Development·Status·::·5·-·Production/Stable
⊟
125 B
svglib-2.1.0.dist-info/licenses/LICENSE.txt vs.
svglib-2.3.0.dist-info/licenses/LICENSE.txt
Files identical despite different names
⊟
1.34 KB
assets/chaquopy/build.json
⊟
1.29 KB
Pretty-printed
Similarity: 0.99822695035461% Differences: {"'assets'": "{'requirements-common.imy': '246acc8cd3abe0efee954a99a486485b0bceeabb'}"}
    
Offset 37, 15 lines modifiedOffset 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":·"3c00596fad605594a284c59421ca4c7d9cb34201",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":·[