rdworks 0.25.7__py3-none-any.whl → 0.35.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rdworks/__init__.py +19 -20
- rdworks/conf.py +308 -117
- rdworks/display.py +244 -83
- rdworks/mol.py +621 -493
- rdworks/mollibr.py +336 -182
- rdworks/readin.py +2 -4
- rdworks/scaffold.py +1 -1
- rdworks/std.py +64 -24
- rdworks/torsion.py +477 -0
- rdworks/units.py +7 -58
- rdworks/utils.py +141 -258
- rdworks/xtb/__init__.py +0 -0
- rdworks/xtb/wrapper.py +304 -0
- {rdworks-0.25.7.dist-info → rdworks-0.35.1.dist-info}/METADATA +7 -10
- {rdworks-0.25.7.dist-info → rdworks-0.35.1.dist-info}/RECORD +18 -15
- {rdworks-0.25.7.dist-info → rdworks-0.35.1.dist-info}/WHEEL +1 -1
- {rdworks-0.25.7.dist-info → rdworks-0.35.1.dist-info}/licenses/LICENSE +0 -0
- {rdworks-0.25.7.dist-info → rdworks-0.35.1.dist-info}/top_level.txt +0 -0
rdworks/xtb/wrapper.py
ADDED
@@ -0,0 +1,304 @@
|
|
1
|
+
import os
|
2
|
+
import resource
|
3
|
+
import subprocess
|
4
|
+
import json
|
5
|
+
import tempfile
|
6
|
+
import logging
|
7
|
+
|
8
|
+
from pathlib import Path
|
9
|
+
from types import SimpleNamespace
|
10
|
+
|
11
|
+
from rdkit import Chem
|
12
|
+
from rdkit.Geometry import Point3D
|
13
|
+
|
14
|
+
|
15
|
+
main_logger = logging.getLogger()
|
16
|
+
|
17
|
+
# In ASE, the default energy unit is eV (electron volt).
|
18
|
+
# It will be converted to kcal/mol
|
19
|
+
# CODATA 2018 energy conversion factor
|
20
|
+
hartree2ev = 27.211386245988
|
21
|
+
hartree2kcalpermol = 627.50947337481
|
22
|
+
ev2kcalpermol = 23.060547830619026
|
23
|
+
|
24
|
+
|
25
|
+
class GFN2xTB:
|
26
|
+
def __init__(self, molecule: Chem.Mol | None = None, ncores: int = 4):
|
27
|
+
if isinstance(molecule, Chem.Mol):
|
28
|
+
assert molecule.GetConformer().Is3D(), "requires 3D coordinates"
|
29
|
+
self.rdmol = molecule
|
30
|
+
self.natoms = molecule.GetNumAtoms()
|
31
|
+
self.symbols = [ atom.GetSymbol() for atom in molecule.GetAtoms() ]
|
32
|
+
self.positions = molecule.GetConformer().GetPositions().tolist()
|
33
|
+
|
34
|
+
# Parallelisation
|
35
|
+
os.environ['OMP_STACKSIZE'] = '4G'
|
36
|
+
os.environ['OMP_NUM_THREADS'] = f'{ncores},1'
|
37
|
+
os.environ['OMP_MAX_ACTIVE_LEVELS'] = '1'
|
38
|
+
os.environ['MKL_NUM_THREADS'] = f'{ncores}'
|
39
|
+
|
40
|
+
# unlimit the system stack
|
41
|
+
resource.setrlimit(resource.RLIMIT_STACK, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
|
42
|
+
|
43
|
+
|
44
|
+
def version(self) -> str | None:
|
45
|
+
"""Check xtb version.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
str | None: version statement.
|
49
|
+
"""
|
50
|
+
cmd = ['xtb', '--version']
|
51
|
+
proc = subprocess.run(cmd, capture_output=True, text=True)
|
52
|
+
assert proc.returncode == 0, "GFN2xTB() Error: xtb not available"
|
53
|
+
for line in proc.stdout.split('\n'):
|
54
|
+
line = line.strip()
|
55
|
+
if 'version' in line:
|
56
|
+
return line
|
57
|
+
|
58
|
+
return None
|
59
|
+
|
60
|
+
|
61
|
+
def to_xyz(self) -> str:
|
62
|
+
"""Export to XYZ formatted string.
|
63
|
+
|
64
|
+
Returns:
|
65
|
+
str: XYZ formatted string
|
66
|
+
"""
|
67
|
+
lines = [f'{self.natoms}', ' ']
|
68
|
+
for e, (x, y, z) in zip(self.symbols, self.positions):
|
69
|
+
lines.append(f'{e:5} {x:23.14f} {y:23.14f} {z:23.14f}')
|
70
|
+
|
71
|
+
return '\n'.join(lines)
|
72
|
+
|
73
|
+
|
74
|
+
def load_xyz(self, geometry_path: Path) -> Chem.Mol:
|
75
|
+
"""Load geometry.
|
76
|
+
|
77
|
+
Args:
|
78
|
+
geometry_path (Path): pathlib.Path to the xyz
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
Chem.Mol: rdkit Chem.Mol object.
|
82
|
+
"""
|
83
|
+
rdmol_opt = Chem.Mol(self.rdmol)
|
84
|
+
with open(geometry_path, 'r') as f:
|
85
|
+
for lineno, line in enumerate(f):
|
86
|
+
if lineno == 0:
|
87
|
+
assert int(line.strip()) == self.natoms
|
88
|
+
continue
|
89
|
+
elif lineno == 1: # comment or title
|
90
|
+
continue
|
91
|
+
(symbol, x, y, z) = line.strip().split()
|
92
|
+
x, y, z = float(x), float(y), float(z)
|
93
|
+
atom = rdmol_opt.GetAtomWithIdx(lineno-2)
|
94
|
+
assert symbol == atom.GetSymbol()
|
95
|
+
rdmol_opt.GetConformer().SetAtomPosition(atom.GetIdx(), Point3D(x, y, z))
|
96
|
+
|
97
|
+
return rdmol_opt
|
98
|
+
|
99
|
+
|
100
|
+
def load_wbo(self, wbo_path: Path) -> dict[tuple[int, int], float]:
|
101
|
+
"""Load Wiberg bond order.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
wbo_path (Path): path to the wbo file.
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
dict(tuple[int, int], float): { (i, j) : wbo, ... } where i and j are atom indices for a bond.
|
108
|
+
"""
|
109
|
+
|
110
|
+
with open(wbo_path, 'r') as f:
|
111
|
+
# Wiberg bond order (WBO)
|
112
|
+
Wiberg_bond_orders = {}
|
113
|
+
for line in f:
|
114
|
+
line = line.strip()
|
115
|
+
if line:
|
116
|
+
# wbo output has 1-based indices
|
117
|
+
(i, j, wbo) = line.split()
|
118
|
+
# changes to 0-based indices
|
119
|
+
i = int(i) - 1
|
120
|
+
j = int(j) - 1
|
121
|
+
# wbo ouput indices are ascending order
|
122
|
+
ij = (i, j) if i < j else (j, i)
|
123
|
+
Wiberg_bond_orders[ij] = float(wbo)
|
124
|
+
|
125
|
+
return Wiberg_bond_orders
|
126
|
+
|
127
|
+
|
128
|
+
def singlepoint(self, water: str | None = None, verbose: bool = False) -> SimpleNamespace:
|
129
|
+
"""Calculate single point energy.
|
130
|
+
|
131
|
+
Total energy from xtb output in atomic units (Eh, hartree) is converted to kcal/mol.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
water (str, optional) : water solvation model (choose 'gbsa' or 'alpb')
|
135
|
+
alpb: ALPB solvation model (Analytical Linearized Poisson-Boltzmann).
|
136
|
+
gbsa: generalized Born (GB) model with Surface Area contributions.
|
137
|
+
|
138
|
+
Returns:
|
139
|
+
SimpleNamespace(PE(total energy in kcal/mol), charges, wbo)
|
140
|
+
"""
|
141
|
+
|
142
|
+
with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
|
143
|
+
workdir = Path(temp_dir)
|
144
|
+
if verbose:
|
145
|
+
main_logger.info(f'xtb.singlepoint workdir= {temp_dir}')
|
146
|
+
|
147
|
+
geometry_path = workdir / 'geometry.xyz'
|
148
|
+
xtbout_path = workdir / 'xtbout.json'
|
149
|
+
wbo_path = workdir / 'wbo'
|
150
|
+
|
151
|
+
with open(geometry_path, 'w') as geometry:
|
152
|
+
geometry.write(self.to_xyz())
|
153
|
+
|
154
|
+
cmd = ['xtb', geometry_path.as_posix()]
|
155
|
+
|
156
|
+
options = ['--gfn', '2', '--json']
|
157
|
+
|
158
|
+
if water is not None and isinstance(water, str):
|
159
|
+
if water == 'gbsa':
|
160
|
+
options += ['--gbsa', 'H2O']
|
161
|
+
elif water == 'alpb':
|
162
|
+
options += ['--alpb', 'water']
|
163
|
+
|
164
|
+
# 'xtbout.json', 'xtbrestart', 'xtbtopo.mol', 'charges', and 'wbo' files will be
|
165
|
+
# created in the current working directory.
|
166
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
167
|
+
|
168
|
+
# if proc.returncode == 0:
|
169
|
+
# print("Standard Output:")
|
170
|
+
# print(proc.stdout)
|
171
|
+
# else:
|
172
|
+
# print("Error:")
|
173
|
+
# print(proc.stderr)
|
174
|
+
|
175
|
+
if proc.returncode == 0 and xtbout_path.is_file():
|
176
|
+
with open(xtbout_path, 'r') as f:
|
177
|
+
datadict = json.load(f) # takes the file object as input
|
178
|
+
|
179
|
+
Wiberg_bond_orders = self.load_wbo(wbo_path)
|
180
|
+
|
181
|
+
return SimpleNamespace(
|
182
|
+
PE = datadict['total energy'] * hartree2kcalpermol,
|
183
|
+
charges = datadict['partial charges'],
|
184
|
+
wbo = Wiberg_bond_orders,
|
185
|
+
)
|
186
|
+
|
187
|
+
# something went wrong if it reaches here
|
188
|
+
return SimpleNamespace()
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
def optimize(self, water: str | None = None, verbose: bool = False) -> SimpleNamespace:
|
193
|
+
"""Optimize geometry.
|
194
|
+
|
195
|
+
Fortran runtime errror:
|
196
|
+
At line 852 of file ../src/optimizer.f90 (unit = 6, file = 'stdout')
|
197
|
+
Fortran runtime error: Missing comma between descriptors
|
198
|
+
(1x,"("f7.2"%)")
|
199
|
+
^
|
200
|
+
Error termination.
|
201
|
+
|
202
|
+
Args:
|
203
|
+
water (str, optional) : water solvation model (choose 'gbsa' or 'alpb')
|
204
|
+
alpb: ALPB solvation model (Analytical Linearized Poisson-Boltzmann).
|
205
|
+
gbsa: generalized Born (GB) model with Surface Area contributions.
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
(total energy in kcal/mol, optimized geometry)
|
209
|
+
"""
|
210
|
+
with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
|
211
|
+
workdir = Path(temp_dir)
|
212
|
+
if verbose:
|
213
|
+
main_logger.info(f'xtb.optimize workdir= {temp_dir}')
|
214
|
+
|
215
|
+
geometry_path = workdir / 'geometry.xyz'
|
216
|
+
xtbout_path = workdir / 'xtbout.json'
|
217
|
+
xtbopt_path = workdir / 'xtbopt.xyz'
|
218
|
+
wbo_path = workdir / 'wbo'
|
219
|
+
|
220
|
+
with open(geometry_path, 'w') as geometry:
|
221
|
+
geometry.write(self.to_xyz())
|
222
|
+
|
223
|
+
cmd = ['xtb', geometry_path.as_posix()]
|
224
|
+
|
225
|
+
options = ['--opt', '--gfn', '2', '--json']
|
226
|
+
|
227
|
+
if water is not None and isinstance(water, str):
|
228
|
+
if water == 'gbsa':
|
229
|
+
options += ['--gbsa', 'H2O']
|
230
|
+
elif water == 'alpb':
|
231
|
+
options += ['--alpb', 'water']
|
232
|
+
|
233
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
234
|
+
|
235
|
+
if proc.returncode == 0 and xtbout_path.is_file():
|
236
|
+
with open(xtbout_path, 'r') as f:
|
237
|
+
datadict = json.load(f) # takes the file object as input
|
238
|
+
|
239
|
+
Wiberg_bond_orders = self.load_wbo(wbo_path)
|
240
|
+
rdmol_opt = self.load_xyz(xtbopt_path)
|
241
|
+
|
242
|
+
return SimpleNamespace(
|
243
|
+
PE = datadict['total energy'] * hartree2kcalpermol,
|
244
|
+
charges = datadict['partial charges'],
|
245
|
+
wbo = Wiberg_bond_orders,
|
246
|
+
geometry = rdmol_opt,
|
247
|
+
)
|
248
|
+
|
249
|
+
# something went wrong if it reaches here
|
250
|
+
return SimpleNamespace()
|
251
|
+
|
252
|
+
|
253
|
+
def esp(self, water: str | None = None, verbose: bool = False) -> None:
|
254
|
+
"""Calculate electrostatic potential
|
255
|
+
|
256
|
+
Example:
|
257
|
+
v = py3Dmol.view()
|
258
|
+
v.addVolumetricData(dt,
|
259
|
+
"cube.gz", {
|
260
|
+
'isoval': 0.005,
|
261
|
+
'smoothness': 2,
|
262
|
+
'opacity':.9,
|
263
|
+
'voldata': esp,
|
264
|
+
'volformat': 'cube.gz',
|
265
|
+
'volscheme': {
|
266
|
+
'gradient':'rwb',
|
267
|
+
'min':-.1,
|
268
|
+
'max':.1,
|
269
|
+
}
|
270
|
+
});
|
271
|
+
v.addModel(dt,'cube')
|
272
|
+
v.setStyle({'stick':{}})
|
273
|
+
v.zoomTo()
|
274
|
+
v.show()
|
275
|
+
"""
|
276
|
+
with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
|
277
|
+
workdir = Path(temp_dir)
|
278
|
+
if verbose:
|
279
|
+
main_logger.info(f'xtb.optimize workdir= {temp_dir}')
|
280
|
+
|
281
|
+
geometry_path = workdir / 'geometry.xyz'
|
282
|
+
xtb_esp_dat = workdir / 'xtb_esp_dat'
|
283
|
+
|
284
|
+
with open(geometry_path, 'w') as geometry:
|
285
|
+
geometry.write(self.to_xyz())
|
286
|
+
|
287
|
+
cmd = ['xtb', geometry_path.as_posix()]
|
288
|
+
|
289
|
+
options = ['--esp', '--gfn', '2']
|
290
|
+
|
291
|
+
if water is not None and isinstance(water, str):
|
292
|
+
if water == 'gbsa':
|
293
|
+
options += ['--gbsa', 'H2O']
|
294
|
+
elif water == 'alpb':
|
295
|
+
options += ['--alpb', 'water']
|
296
|
+
|
297
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
298
|
+
# output files: xtb_esp.cosmo, xtb_esp.dat, xtb_esp_profile.dat
|
299
|
+
|
300
|
+
if proc.returncode == 0 and xtb_esp_dat.is_file():
|
301
|
+
with open(xtb_esp_dat, 'r') as f:
|
302
|
+
pass
|
303
|
+
|
304
|
+
return None
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: rdworks
|
3
|
-
Version: 0.
|
4
|
-
Summary:
|
3
|
+
Version: 0.35.1
|
4
|
+
Summary: Frequently used tasks built on RDKit and other tools
|
5
5
|
Author-email: Sung-Hun Bae <sunghun.bae@gmail.com>
|
6
6
|
Maintainer-email: Sung-Hun Bae <sunghun.bae@gmail.com>
|
7
7
|
License-Expression: MIT
|
@@ -10,7 +10,7 @@ Project-URL: Repository, https://github.com/sunghunbae/rdworks.git
|
|
10
10
|
Project-URL: Issues, https://github.com/sunghunbae/rdworks/issues
|
11
11
|
Project-URL: Changelog, https://github.com/sunghunbae/rdworks/blob/master/CHANGELOG.md
|
12
12
|
Project-URL: Documentation, https://sunghunbae.github.io/rdworks/
|
13
|
-
Keywords:
|
13
|
+
Keywords: cheminformatics,rdkit
|
14
14
|
Classifier: Development Status :: 3 - Alpha
|
15
15
|
Classifier: Intended Audience :: Developers
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
@@ -18,18 +18,15 @@ Classifier: Operating System :: OS Independent
|
|
18
18
|
Requires-Python: >=3.11
|
19
19
|
Description-Content-Type: text/markdown
|
20
20
|
License-File: LICENSE
|
21
|
-
Requires-Dist:
|
22
|
-
Requires-Dist:
|
23
|
-
Requires-Dist: scikit-learn
|
21
|
+
Requires-Dist: rdkit>=2024
|
22
|
+
Requires-Dist: cdpkit
|
24
23
|
Requires-Dist: pandas
|
25
24
|
Requires-Dist: seaborn
|
26
|
-
Requires-Dist: networkx
|
27
25
|
Requires-Dist: tqdm
|
28
|
-
Requires-Dist: psutil
|
29
26
|
Requires-Dist: ase
|
30
|
-
Requires-Dist:
|
27
|
+
Requires-Dist: mendeleev
|
28
|
+
Requires-Dist: scour
|
31
29
|
Requires-Dist: bitarray
|
32
|
-
Requires-Dist: cdpkit
|
33
30
|
Requires-Dist: pytest
|
34
31
|
Dynamic: license-file
|
35
32
|
|
@@ -1,20 +1,21 @@
|
|
1
|
-
rdworks/__init__.py,sha256=
|
2
|
-
rdworks/conf.py,sha256=
|
1
|
+
rdworks/__init__.py,sha256=UPZKHw1RajTvab15-wzdsP4UjD27yQT0n6Q5waUaJQE,1368
|
2
|
+
rdworks/conf.py,sha256=BPp_uZAXXOU53tKzjZz8SsUdAvi7aK1s_zCeHfiRATk,21744
|
3
3
|
rdworks/descriptor.py,sha256=34T_dQ6g8v3u-ym8TLKbQtxIIV5TEo-d3pdedq3o-cg,2106
|
4
|
-
rdworks/display.py,sha256=
|
4
|
+
rdworks/display.py,sha256=JR0gR26UpH-JCxVOaqXZCUj2MiGZSrx9Me87FncspVI,13469
|
5
5
|
rdworks/ionized.py,sha256=5oIjMRpkX792RIpEEE2Ir96icfFaN_h21mSihhfQPAw,6713
|
6
6
|
rdworks/matchedseries.py,sha256=A3ON4CUpQV159mu9VqgNiJ8uoQ9ePOry9d3ra4NCAgc,10377
|
7
|
-
rdworks/mol.py,sha256=
|
8
|
-
rdworks/mollibr.py,sha256=
|
7
|
+
rdworks/mol.py,sha256=5ZaBIpCnKIqxbIZM0IAJ2uG5fEIlZotw1Lb2QT_IXe0,71145
|
8
|
+
rdworks/mollibr.py,sha256=X4UBO6Ga-QmNS7RwUiaDYAx0Q5hnWs71yTkEpH02Qb4,37696
|
9
9
|
rdworks/pka.py,sha256=NVJVfpcNEMlX5QRyLBgUM7GIT7VMjO-llAR4LWc8J2c,1656
|
10
|
-
rdworks/readin.py,sha256=
|
10
|
+
rdworks/readin.py,sha256=0bnVcZcAmSLqc6zu1mYcv0LdBv2agQfOpKGwpSRL9VE,11742
|
11
11
|
rdworks/rgroup.py,sha256=ivF2gzmRtt339rxEnkv2KfnCs0CUdBbnSje7Y54rtFI,57996
|
12
|
-
rdworks/scaffold.py,sha256=
|
13
|
-
rdworks/std.py,sha256=
|
12
|
+
rdworks/scaffold.py,sha256=60T5YacyxZsEpDo_J5Qxulm2YNQO4EQR8PcNUwjn1QU,22026
|
13
|
+
rdworks/std.py,sha256=p-Ha8uJla_6bDLkf-zvdsCeXqrV8jJTLYiV6IkSW9FE,7147
|
14
14
|
rdworks/stereoisomers.py,sha256=g8hhPI-mbYX-MzbF1uAqo5fDZOCNiKYjxI-kLBGdGgg,4980
|
15
15
|
rdworks/tautomers.py,sha256=gtZHZJ-aJbryhBdljHbfjx7xhVW3u_OzdYPtwPail54,610
|
16
|
-
rdworks/
|
17
|
-
rdworks/
|
16
|
+
rdworks/torsion.py,sha256=Y0QOi5JEc7-0YpJ7b0rzA1UuuJxymzjm9Ap-9u8udfg,18429
|
17
|
+
rdworks/units.py,sha256=nljKPHcr6IWoAp0CkL7y1gSNDd6a07NeVfxXwSMuHQM,365
|
18
|
+
rdworks/utils.py,sha256=IxgFniUvjXlJuNJ1Sx9hsJknNNSglP6qzFyz8vdgDcw,13406
|
18
19
|
rdworks/xml.py,sha256=aaMhwVRGvt1VzasaKDnkYnZ4kp2cIgvGb1CsmMgwQ_c,10704
|
19
20
|
rdworks/autograph/__init__.py,sha256=0Qfjwo0h4Q0n08zsqHRbuNOZms6MuNXnWErnQpQ6Px0,140
|
20
21
|
rdworks/autograph/autograph.py,sha256=frjsUaCTOD-Z1lYPzOxRoTtqMMiYroWAy6tSwKn3CUA,8769
|
@@ -62,8 +63,10 @@ rdworks/predefined/misc/makexml.py,sha256=T9c6ssKYdDzMkkcaCjEUe59nVPJfwJEoHm6Rhk
|
|
62
63
|
rdworks/predefined/misc/reactive-part-2.xml,sha256=0vNTMwWrrQmxBpbgbyRHx8sVs83cqn7xsfr5qqrelRA,3676
|
63
64
|
rdworks/predefined/misc/reactive-part-3.xml,sha256=LgWHSEbRTVmgBoIO45xbTo1xQJs0Xu51j3JnIapRYo4,3094
|
64
65
|
rdworks/predefined/misc/reactive.xml,sha256=syedoQ6VYUfRLnxy99ObuDniJ_a_WhrWAJbTKFfJ6VY,11248
|
65
|
-
rdworks
|
66
|
-
rdworks
|
67
|
-
rdworks-0.
|
68
|
-
rdworks-0.
|
69
|
-
rdworks-0.
|
66
|
+
rdworks/xtb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67
|
+
rdworks/xtb/wrapper.py,sha256=I0nW89vlJZ5Za5pCjIpjsEOFbTm7HpeNGiPgssheWn8,11350
|
68
|
+
rdworks-0.35.1.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
|
69
|
+
rdworks-0.35.1.dist-info/METADATA,sha256=cmN6_DkuVc8s0zE1LClwGTv2RGbwP6lrVxPOt2hST5k,1183
|
70
|
+
rdworks-0.35.1.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
71
|
+
rdworks-0.35.1.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
|
72
|
+
rdworks-0.35.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|