Switch over to using pytest to run the python tests (#5916)

* misc adaptations/modernizations
plus a few changes to allow pytest discovery

* get the recap unittests running

* pytest config updates

* all tests pass

* integrate the pytest stuff into ctest

* integrate Projects dir
better cmake integration

* ci build env updates

* ignore more files

* remove six.py

* cleanup UnitTestPandasTools

* cleanup pytest

* remove obsolete use of rdkit.six from doctests

* update release notes

* mysterious CI fix

* add conftest to remove some tests

* remove the old python-based testing infrastructure

---------

Co-authored-by: Ric <ricrogz@gmail.com>
This commit is contained in:
Greg Landrum
2023-11-03 14:39:24 +01:00
committed by GitHub
parent 908e47cc03
commit ab152a4ed1
77 changed files with 824 additions and 2526 deletions

View File

@@ -12,7 +12,7 @@ steps:
numpy pillow eigen pandas matplotlib-base \
qt=5.9.7 cairo
conda activate rdkit_build
conda install -c conda-forge nbval ipykernel>=6.0
conda install -c conda-forge pytest nbval ipykernel>=6.0
displayName: Setup build environment
- bash: |
source ${CONDA}/etc/profile.d/conda.sh

View File

@@ -10,7 +10,7 @@ steps:
boost-cpp=$(boost_version) \
py-boost=$(boost_version) \
numpy pillow eigen pandas \
qt
qt pytest
conda activate rdkit_build
conda install -c rdkit nox cairo=1.14.6
displayName: Setup build environment

View File

@@ -25,7 +25,7 @@ steps:
jupyter
conda activate rdkit_build
conda install -c conda-forge sphinx myst-parser
conda install -c conda-forge nbval
conda install -c conda-forge pytest nbval
displayName: Setup build environment
- bash: |
source ${CONDA}/etc/profile.d/conda.sh

View File

@@ -11,7 +11,8 @@ steps:
py-boost=$(boost_version) libboost=$(boost_version) ^
numpy matplotlib cairo pillow eigen pandas jupyter
call activate rdkit_build
conda install -c conda-forge cmake nbval
conda install -c conda-forge sphinx myst-parser jupyter pytest nbval
conda install -c conda-forge cmake
displayName: Install dependencies
- script: |
set Boost_ROOT=

View File

@@ -11,7 +11,7 @@ steps:
libboost=$(boost_version) ^
cairo eigen
call activate rdkit_build
conda install -c conda-forge cmake
conda install -c conda-forge cmake pytest nbval
displayName: Install dependencies
- script: |
set Boost_ROOT=

View File

@@ -223,6 +223,16 @@ function(add_jupytertest testname workingdir notebook)
endif()
endfunction(add_jupytertest)
function(add_pythonpytest testname workingdir)
if(RDK_BUILD_PYTHON_WRAPPERS)
add_test(NAME ${testname} COMMAND ${PYTHON_EXECUTABLE} -m pytest
WORKING_DIRECTORY ${workingdir} )
SET(RDKIT_PYTHONTEST_CACHE "${testname};${RDKIT_PYTHONTEST_CACHE}" CACHE INTERNAL "Global list of pytest tests")
endif()
endfunction(add_pythonpytest)
function(computeMD5 target md5chksum)
execute_process(COMMAND ${CMAKE_COMMAND} -E md5sum ${target} OUTPUT_VARIABLE md5list)
string(REGEX REPLACE "([a-z0-9]+)" "\\1;" md5list "${md5list}")

View File

@@ -1,12 +0,0 @@
tests = [
("python", "testConformerParser.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("testExecs/testConformerParser.exe", "", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "test_rfrag.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -402,7 +402,7 @@ An SDWriter can also be initialized using a file-like object:
.. doctest::
>>> from rdkit.six import StringIO
>>> from io import StringIO
>>> sio = StringIO()
>>> with Chem.SDWriter(sio) as w:
... for m in mols:

View File

@@ -1,11 +0,0 @@
tests = [
("python", "testAvalonTools.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,14 +0,0 @@
tests = [
("testExecs/test1.exe", "", {}),
("python", "test_list.py", {
"dir": "Wrap"
}),
]
longTests = []
if __name__ == '__main__':
import sys
import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,3 +1,2 @@
add_pytest(pythonTestDbCLI
${CMAKE_CURRENT_SOURCE_DIR}/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR} )
add_pythonpytest(pythonProjectTests ${CMAKE_CURRENT_SOURCE_DIR} )

View File

@@ -11,9 +11,15 @@ import unittest
from rdkit import RDConfig
from rdkit.Dbase.DbConnection import DbConnect
import sys
import pytest
class TestCase(unittest.TestCase):
# pytest fixture to make sure we're working in the source dir
@pytest.fixture(autouse=True)
def change_test_dir(self, request, monkeypatch):
monkeypatch.chdir(request.fspath.dirname)
def test1Create(self):
p = subprocess.Popen((sys.executable, 'CreateDb.py', '--dbDir=testData/bzr',

View File

@@ -1,12 +0,0 @@
tests = [
("python", "TestDbCLI.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

4
Projects/pytest.ini Normal file
View File

@@ -0,0 +1,4 @@
[pytest]
python_files = UnitTest*.py
doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
addopts = --doctest-modules --ignore-glob='**/test_list.py'

View File

@@ -1,14 +0,0 @@
tests = [
("python", "TestDbCLI.py", {
'dir': 'DbCLI'
}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -18,7 +18,9 @@ GitHub)
## Code removed in this release:
- The python implementations of MolStandardize has been removed.
Please use the implementation in `rdkit.Chem.MolStandardize.rdMolStandardize` instead.
Please use the implementation in `rdkit.Chem.MolStandardize.rdMolStandardize` instead.
- The rdkit.six module, a leftover from the days when we supported both python 2
and python 3, has been removed
## Deprecated code (to be removed in a future release):

View File

@@ -13,19 +13,6 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/RDPaths.py
DESTINATION ${RDKit_PythonDir}
COMPONENT python)
add_pytest(pythonTestDirRoot
${CMAKE_CURRENT_SOURCE_DIR}/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR} )
add_pytest(pythonTestDirML
${CMAKE_CURRENT_SOURCE_DIR}/ML/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/ML )
add_pytest(pythonTestDirDataStructs
${CMAKE_CURRENT_SOURCE_DIR}/DataStructs/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/DataStructs )
add_pytest(pythonTestDirDbase
${CMAKE_CURRENT_SOURCE_DIR}/Dbase/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/Dbase )
add_pytest(pythonTestDirSimDivFilters
${CMAKE_CURRENT_SOURCE_DIR}/SimDivFilters/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/SimDivFilters )
add_pytest(pythonTestDirVLib
${CMAKE_CURRENT_SOURCE_DIR}/VLib/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/VLib )
add_pytest(pythonTestSping
${CMAKE_CURRENT_SOURCE_DIR}/Chem/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR}/sping )
add_pythonpytest(pythonSourceTests ${CMAKE_CURRENT_SOURCE_DIR} )
add_subdirectory(Chem)

View File

@@ -1,16 +0,0 @@
import sys
from rdkit import TestRunner
tests = [
("python", "Utils.py", {}),
("python", "Torsions.py", {}),
("python", "Pairs.py", {}),
("python", "UnitTestDescriptors.py", {}),
]
longTests = []
if __name__ == '__main__':
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,4 +1 @@
add_pytest(pythonTestDirChem
${CMAKE_CURRENT_SOURCE_DIR}/test_list.py --testDir ${CMAKE_CURRENT_SOURCE_DIR} --buildType ${CMAKE_BUILD_TYPE})
add_jupytertest(github4823 ${CMAKE_CURRENT_SOURCE_DIR}/nbtests github4823.ipynb)
add_jupytertest(github4823 ${CMAKE_CURRENT_SOURCE_DIR}/nbtests github4823.ipynb)

View File

@@ -1,15 +0,0 @@
tests = [
("python", "UnitTestSDFToCSV.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
doLong = 0
if '-l' in sys.argv:
doLong = 1
failed, tests = TestRunner.RunScript('test_list.py', doLong, 1)
sys.exit(len(failed))

View File

@@ -1,14 +0,0 @@
tests = [
("python", "UnitTestDraw.py", {}),
("python", "UnitTestSimilarityMaps.py", {}),
("python", "UnitTestIPython.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,15 +0,0 @@
tests = [
("python", "UnitTestEState.py", {}),
("python", "UnitTestFingerprints.py", {}),
("python", "UnitTestTypes.py", {}),
("python", "UnitTestVSA.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,16 +0,0 @@
tests = [
("python", "FeatMapPoint.py", {}),
("python", "UnitTestFeatMap.py", {}),
("python", "UnitTestFeatMapPoint.py", {}),
("python", "UnitTestFeatMapParser.py", {}),
("python", "UnitTestFeatMapUtils.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,9 +0,0 @@
tests = [("python", "UnitTestFeatDirUtilsRD.py", {})]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestFingerprints.py", {}),
("python", "UnitTestSimScreener.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestFraggle.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -395,7 +395,7 @@ def GetKeyForCTAB(ctab, stereo_info=None, stereo_comment=None, logger=None):
try:
err, inchi, fixed_mol = GetInchiForCTAB(ctab)
except BadMoleculeException:
logger.warn(u'Corrupt molecule substituting no-struct: --->\n{0}\n<----'.format(ctab))
logger.warning(u'Corrupt molecule substituting no-struct: --->\n{0}\n<----'.format(ctab))
err = NULL_MOL
key = _identify(err, '', '', None, None)
return MolKeyResult(key, err, '', '', None, None)
@@ -411,7 +411,7 @@ def GetKeyForCTAB(ctab, stereo_info=None, stereo_comment=None, logger=None):
if not stereo_comment and len(info_flds) > 1:
extra_structure_desc = info_flds[1].strip()
else:
logger.warn(f'stereo code {code_fld} not recognized. Using default value for ctab.')
logger.warning(f'stereo code {code_fld} not recognized. Using default value for ctab.')
if not (err & BAD_SET):
n_stereo, n_undef_stereo, is_meso, dummy = InchiInfo.InchiInfo(

View File

@@ -11,7 +11,8 @@ import unittest
from rdkit.Chem import inchi
from rdkit.TestRunner import redirect_stderr
import os
import io
if inchi.INCHI_AVAILABLE:
from rdkit.Chem.MolKey.InchiInfo import InchiInfo
@@ -38,7 +39,8 @@ class TestMolKey(unittest.TestCase):
res = MolKey.GetKeyForCTAB('IncorrectCTAB')
self.assertNotEqual(res.error, 0)
s = f.getvalue()
self.assertIn('WARNING:', s)
if "PYTEST_CURRENT_TEST" not in os.environ:
self.assertIn('WARNING:', s)
def test_CheckCTAB(self):
self.assertRaises(MolKey.BadMoleculeException, MolKey.CheckCTAB, None)

View File

@@ -1,15 +0,0 @@
try:
tests = [
("python", "UnitTestMolKey.py", {}),
]
except ImportError:
pass
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,10 +0,0 @@
tests = [("python", "UnitTestMolStandardize.py", {})]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -33,8 +33,9 @@ Importing pandasTools enables several features that allow for using RDKit molecu
Pandas dataframe.
If the dataframe is containing a molecule format in a column (e.g. smiles), like in this example:
>>> from rdkit.Chem import PandasTools
>>> import pandas as pd
>>> from rdkit.Chem import PandasTools
>>> PandasTools.InstallPandasTools() # <- only necessary during testing, you don't need to do this
>>> import os
>>> from rdkit import RDConfig
>>> antibiotics = pd.DataFrame(columns=['Name','Smiles'])
@@ -66,7 +67,7 @@ because the ">=" operator has been modified to work as a substructure check.
Such the antibiotics containing the beta-lactam ring "C1C(=O)NC1" can be obtained by
>>> beta_lactam = Chem.MolFromSmiles('C1C(=O)NC1')
>>> beta_lactam_antibiotics = antibiotics[antibiotics['Molecule'] >= beta_lactam]
>>> beta_lactam_antibiotics = antibiotics[antibiotics['Molecule'] >= beta_lactam]
>>> print(beta_lactam_antibiotics[['Name','Smiles']])
Name Smiles
0 Penicilline G CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)O)C
@@ -112,7 +113,7 @@ The standard ForwardSDMolSupplier keywords are also available:
Conversion to html is quite easy:
>>> htm = frame.to_html() # doctest:
>>> htm = frame.to_html()
...
>>> str(htm[:36])
'<table border="1" class="dataframe">'
@@ -543,7 +544,8 @@ def SaveXlsxFromFrame(frame, outFile, molCol='ROMol', size=(300, 300), formats=N
if col_idx in molCol_indices:
image_data = BytesIO()
m = row[col]
img = Draw.MolToImage(m if isinstance(m, Chem.Mol) else Chem.Mol(), size=size, options=drawOptions)
img = Draw.MolToImage(m if isinstance(m, Chem.Mol) else Chem.Mol(), size=size,
options=drawOptions)
img.save(image_data, format='PNG')
worksheet.insert_image(row_idx_actual, col_idx, "f", {'image_data': image_data})
worksheet.set_column(col_idx, col_idx,
@@ -648,12 +650,32 @@ def _runDoctests(verbose=None): # pragma: nocover
InstallPandasTools()
try:
import xlsxwriter
except ImportError:
xlsxwriter = None
import unittest
class TestCase(unittest.TestCase):
@unittest.skipIf(xlsxwriter is None or pd is None, 'pandas/xlsxwriter not installed')
def testGithub1507(self):
import os
from rdkit import RDConfig
sdfFile = os.path.join(RDConfig.RDDataDir, 'NCI/first_200.props.sdf')
frame = LoadSDF(sdfFile)
SaveXlsxFromFrame(frame, 'foo.xlsx', formats={'write_string': {'text_wrap': True}})
@unittest.skipIf(pd is None, 'pandas not installed')
def testGithub3701(self):
' problem with update to pandas v1.2.0 '
df = pd.DataFrame({"name": ["ethanol", "furan"], "smiles": ["CCO", "c1ccoc1"]})
AddMoleculeColumnToFrame(df, 'smiles', 'molecule')
self.assertEqual(len(df.molecule), 2)
if __name__ == '__main__': # pragma: nocover
import unittest
try:
import xlsxwriter
except ImportError:
xlsxwriter = None
try:
import pandas as pd

View File

@@ -1,17 +0,0 @@
tests = [
("python", "UnitTestMatcher.py", {}),
("python", "UnitTestSignature.py", {}),
# ("python","UnitTestLazyGenerator.py",{}),
("python", "UnitTestGenerate.py", {}),
("python", "UnitTestUtils.py", {}),
("python", "UnitTestGobbi.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,14 +0,0 @@
tests = [
("python", "UnitTestEmbed.py", {}),
("python", "UnitTestExcludedVolume.py", {}),
("python", "UnitTestPharmacophore.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -215,394 +215,395 @@ def RecapDecompose(mol, allNodes=None, minFragmentSize=0, onlyUseReactions=None)
# ------- ------- ------- ------- ------- ------- ------- -------
# Begin testing code
import unittest
class TestCase(unittest.TestCase):
def test1(self):
m = Chem.MolFromSmiles('C1CC1Oc1ccccc1-c1ncc(OC)cc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 4)
self.assertTrue(len(res.GetAllChildren().keys()) == 5)
self.assertTrue(len(res.GetLeaves().keys()) == 3)
def test2(self):
m = Chem.MolFromSmiles('CCCOCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(res.children == {})
def test3(self):
allNodes = {}
m = Chem.MolFromSmiles('c1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 2)
self.assertTrue(len(allNodes.keys()) == 3)
m = Chem.MolFromSmiles('COc1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 2)
# we get two more nodes from that:
self.assertTrue(len(allNodes.keys()) == 5)
self.assertTrue('*c1ccccc1OC' in allNodes)
self.assertTrue('*c1ccccc1' in allNodes)
m = Chem.MolFromSmiles('C1CC1Oc1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 4)
self.assertTrue(len(allNodes.keys()) == 10)
def testSFNetIssue1801871(self):
m = Chem.MolFromSmiles('c1ccccc1OC(Oc1ccccc1)Oc1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertFalse('*C(*)*' in ks)
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C(*)Oc1ccccc1' in ks)
def testSFNetIssue1804418(self):
m = Chem.MolFromSmiles('C1CCCCN1CCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCCCC1' in ks)
self.assertTrue('*CCCC' in ks)
def testMinFragmentSize(self):
m = Chem.MolFromSmiles('CCCOCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(res.children == {})
res = RecapDecompose(m, minFragmentSize=3)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 1)
ks = res.GetLeaves().keys()
self.assertTrue('*CCC' in ks)
m = Chem.MolFromSmiles('CCCOCC')
res = RecapDecompose(m, minFragmentSize=3)
self.assertTrue(res)
self.assertTrue(res.children == {})
m = Chem.MolFromSmiles('CCCOCCOC')
res = RecapDecompose(m, minFragmentSize=2)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*CCC' in ks)
ks = res.GetLeaves().keys()
self.assertTrue('*CCOC' in ks)
def testAmideRxn(self):
m = Chem.MolFromSmiles('C1CC1C(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)N(C)C1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*N(C)C1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)n1cccc1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*n1cccc1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)CC1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CCC(=O)NC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('CC(=O)NC')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
m = Chem.MolFromSmiles('CC(=O)N')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C(=O)NCCNC(=O)CC')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.children) == 4)
self.assertTrue(len(res.GetLeaves()) == 3)
def testEsterRxn(self):
m = Chem.MolFromSmiles('C1CC1C(=O)OC1OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*OC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)CC1OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CCC(=O)OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testUreaRxn(self):
m = Chem.MolFromSmiles('C1CC1NC(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NC1CC1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1NC(=O)N(C)C1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NC1CC1' in ks)
self.assertTrue('*N(C)C1CO1' in ks)
m = Chem.MolFromSmiles('C1CCNC(=O)NC1C')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('c1cccn1C(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('c1cccn1C(=O)n1c(C)ccc1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1C' in ks)
def testAmineRxn(self):
m = Chem.MolFromSmiles('C1CC1N(C1NC1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*C1CC1' in ks)
self.assertTrue('*C1CO1' in ks)
self.assertTrue('*C1CN1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(C1NC1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C1CO1' in ks)
self.assertTrue('*C1CN1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(c1ncccc1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(c1ncccc1)c1ccco1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
self.assertTrue('*c1ccco1' in ks)
m = Chem.MolFromSmiles('C1CCCCN1C1CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCCCC1' in ks)
self.assertTrue('*C1CC1' in ks)
m = Chem.MolFromSmiles('C1CCC2N1CC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testEtherRxn(self):
m = Chem.MolFromSmiles('C1CC1OC1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C1CC1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('C1CCCCO1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('c1ccccc1OC1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('c1ccccc1Oc1ncccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
def testOlefinRxn(self):
m = Chem.MolFromSmiles('ClC=CBr')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*CCl' in ks)
self.assertTrue('*CBr' in ks)
m = Chem.MolFromSmiles('C1CC=CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromNAliphCRxn(self):
m = Chem.MolFromSmiles('c1cccn1CCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*CCCC' in ks)
m = Chem.MolFromSmiles('c1ccc2n1CCCC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testLactamNAliphCRxn(self):
m = Chem.MolFromSmiles('C1CC(=O)N1CCCC')
res = RecapDecompose(m, onlyUseReactions=[8])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCC1=O' in ks)
self.assertTrue('*CCCC' in ks)
m = Chem.MolFromSmiles('O=C1CC2N1CCCC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromCAromCRxn(self):
m = Chem.MolFromSmiles('c1ccccc1c1ncccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
m = Chem.MolFromSmiles('c1ccccc1C1CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromNAromCRxn(self):
m = Chem.MolFromSmiles('c1cccn1c1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*c1ccccc1' in ks)
def testSulfonamideRxn(self):
m = Chem.MolFromSmiles('CCCNS(=O)(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NCCC' in ks)
self.assertTrue('*S(=O)(=O)CC' in ks)
m = Chem.MolFromSmiles('c1cccn1S(=O)(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*S(=O)(=O)CC' in ks)
m = Chem.MolFromSmiles('C1CNS(=O)(=O)CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testSFNetIssue1881803(self):
m = Chem.MolFromSmiles('c1ccccc1n1cccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('c1ccccc1[n+]1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CC1NC(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('C1CC1[NH+]C(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CC1NC(=O)NC1CCC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('C1CC1[NH+]C(=O)[NH+]C1CCC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
if __name__ == '__main__':
import unittest
class TestCase(unittest.TestCase):
def test1(self):
m = Chem.MolFromSmiles('C1CC1Oc1ccccc1-c1ncc(OC)cc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 4)
self.assertTrue(len(res.GetAllChildren().keys()) == 5)
self.assertTrue(len(res.GetLeaves().keys()) == 3)
def test2(self):
m = Chem.MolFromSmiles('CCCOCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(res.children == {})
def test3(self):
allNodes = {}
m = Chem.MolFromSmiles('c1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 2)
self.assertTrue(len(allNodes.keys()) == 3)
m = Chem.MolFromSmiles('COc1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 2)
# we get two more nodes from that:
self.assertTrue(len(allNodes.keys()) == 5)
self.assertTrue('*c1ccccc1OC' in allNodes)
self.assertTrue('*c1ccccc1' in allNodes)
m = Chem.MolFromSmiles('C1CC1Oc1ccccc1-c1ncccc1')
res = RecapDecompose(m, allNodes=allNodes)
self.assertTrue(res)
self.assertTrue(len(res.children.keys()) == 4)
self.assertTrue(len(allNodes.keys()) == 10)
def testSFNetIssue1801871(self):
m = Chem.MolFromSmiles('c1ccccc1OC(Oc1ccccc1)Oc1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertFalse('*C(*)*' in ks)
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C(*)Oc1ccccc1' in ks)
def testSFNetIssue1804418(self):
m = Chem.MolFromSmiles('C1CCCCN1CCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCCCC1' in ks)
self.assertTrue('*CCCC' in ks)
def testMinFragmentSize(self):
m = Chem.MolFromSmiles('CCCOCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(res.children == {})
res = RecapDecompose(m, minFragmentSize=3)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 1)
ks = res.GetLeaves().keys()
self.assertTrue('*CCC' in ks)
m = Chem.MolFromSmiles('CCCOCC')
res = RecapDecompose(m, minFragmentSize=3)
self.assertTrue(res)
self.assertTrue(res.children == {})
m = Chem.MolFromSmiles('CCCOCCOC')
res = RecapDecompose(m, minFragmentSize=2)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*CCC' in ks)
ks = res.GetLeaves().keys()
self.assertTrue('*CCOC' in ks)
def testAmideRxn(self):
m = Chem.MolFromSmiles('C1CC1C(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)N(C)C1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*N(C)C1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)n1cccc1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*n1cccc1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)CC1OC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CCC(=O)NC1')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('CC(=O)NC')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
m = Chem.MolFromSmiles('CC(=O)N')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C(=O)NCCNC(=O)CC')
res = RecapDecompose(m, onlyUseReactions=[1])
self.assertTrue(res)
self.assertTrue(len(res.children) == 4)
self.assertTrue(len(res.GetLeaves()) == 3)
def testEsterRxn(self):
m = Chem.MolFromSmiles('C1CC1C(=O)OC1OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C(=O)C1CC1' in ks)
self.assertTrue('*OC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1C(=O)CC1OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CCC(=O)OC1')
res = RecapDecompose(m, onlyUseReactions=[2])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testUreaRxn(self):
m = Chem.MolFromSmiles('C1CC1NC(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NC1CC1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('C1CC1NC(=O)N(C)C1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NC1CC1' in ks)
self.assertTrue('*N(C)C1CO1' in ks)
m = Chem.MolFromSmiles('C1CCNC(=O)NC1C')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('c1cccn1C(=O)NC1OC1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*NC1CO1' in ks)
m = Chem.MolFromSmiles('c1cccn1C(=O)n1c(C)ccc1')
res = RecapDecompose(m, onlyUseReactions=[0])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1C' in ks)
def testAmineRxn(self):
m = Chem.MolFromSmiles('C1CC1N(C1NC1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*C1CC1' in ks)
self.assertTrue('*C1CO1' in ks)
self.assertTrue('*C1CN1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(C1NC1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C1CO1' in ks)
self.assertTrue('*C1CN1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(c1ncccc1)C1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('c1ccccc1N(c1ncccc1)c1ccco1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 3)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
self.assertTrue('*c1ccco1' in ks)
m = Chem.MolFromSmiles('C1CCCCN1C1CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCCCC1' in ks)
self.assertTrue('*C1CC1' in ks)
m = Chem.MolFromSmiles('C1CCC2N1CC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testEtherRxn(self):
m = Chem.MolFromSmiles('C1CC1OC1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*C1CC1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('C1CCCCO1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('c1ccccc1OC1OC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*C1CO1' in ks)
m = Chem.MolFromSmiles('c1ccccc1Oc1ncccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
def testOlefinRxn(self):
m = Chem.MolFromSmiles('ClC=CBr')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*CCl' in ks)
self.assertTrue('*CBr' in ks)
m = Chem.MolFromSmiles('C1CC=CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromNAliphCRxn(self):
m = Chem.MolFromSmiles('c1cccn1CCCC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*CCCC' in ks)
m = Chem.MolFromSmiles('c1ccc2n1CCCC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testLactamNAliphCRxn(self):
m = Chem.MolFromSmiles('C1CC(=O)N1CCCC')
res = RecapDecompose(m, onlyUseReactions=[8])
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*N1CCC1=O' in ks)
self.assertTrue('*CCCC' in ks)
m = Chem.MolFromSmiles('O=C1CC2N1CCCC2')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromCAromCRxn(self):
m = Chem.MolFromSmiles('c1ccccc1c1ncccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*c1ccccc1' in ks)
self.assertTrue('*c1ccccn1' in ks)
m = Chem.MolFromSmiles('c1ccccc1C1CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testAromNAromCRxn(self):
m = Chem.MolFromSmiles('c1cccn1c1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*c1ccccc1' in ks)
def testSulfonamideRxn(self):
m = Chem.MolFromSmiles('CCCNS(=O)(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*NCCC' in ks)
self.assertTrue('*S(=O)(=O)CC' in ks)
m = Chem.MolFromSmiles('c1cccn1S(=O)(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
ks = res.GetLeaves().keys()
self.assertTrue('*n1cccc1' in ks)
self.assertTrue('*S(=O)(=O)CC' in ks)
m = Chem.MolFromSmiles('C1CNS(=O)(=O)CC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
def testSFNetIssue1881803(self):
m = Chem.MolFromSmiles('c1ccccc1n1cccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('c1ccccc1[n+]1ccccc1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CC1NC(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('C1CC1[NH+]C(=O)CC')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
m = Chem.MolFromSmiles('C1CC1NC(=O)NC1CCC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 2)
m = Chem.MolFromSmiles('C1CC1[NH+]C(=O)[NH+]C1CCC1')
res = RecapDecompose(m)
self.assertTrue(res)
self.assertTrue(len(res.GetLeaves()) == 0)
unittest.main()

View File

@@ -13,7 +13,7 @@ from rdkit.Chem.Scaffolds.MurckoScaffold import (
GetScaffoldForMol, MakeScaffoldGeneric, MurckoScaffoldSmiles,
MurckoScaffoldSmilesFromSmiles, _pyGetScaffoldForMol)
TestMolecule = namedtuple('TestMolecule', 'smiles,scaffold')
_TestMolecule = namedtuple('_TestMolecule', 'smiles,scaffold')
def load_tests(loader, tests, ignore):
@@ -73,491 +73,491 @@ class TestCase(unittest.TestCase):
self.assertEqual(testSmiles('C1[C@](Cl)(F)O1'), 'CC1(C)CC1')
testMolecules = [
TestMolecule('CC1CCC1', 'C1CCC1'),
TestMolecule('NCNCC2CC2C1CC1O', 'C1CC1C1CC1'),
_TestMolecule('CC1CCC1', 'C1CCC1'),
_TestMolecule('NCNCC2CC2C1CC1O', 'C1CC1C1CC1'),
# Spiro
TestMolecule('OC2C(C)C21C(N)C1C', 'C2CC12CC1'),
_TestMolecule('OC2C(C)C21C(N)C1C', 'C2CC12CC1'),
# Carbonyl outside scaffold
TestMolecule('C1CC1C(=O)OC', 'C1CC1'),
_TestMolecule('C1CC1C(=O)OC', 'C1CC1'),
# Double bond outside scaffold
TestMolecule('C1CC1C=C', 'C1CC1'),
_TestMolecule('C1CC1C=C', 'C1CC1'),
# Double bond in scaffold
TestMolecule('C1CC1C=CC1CC1C=CNNCO', 'C1CC1C=CC1CC1'),
TestMolecule('CC1CC1C(N)C1C(N)C1', 'C1CC1CC1CC1'),
_TestMolecule('C1CC1C=CC1CC1C=CNNCO', 'C1CC1C=CC1CC1'),
_TestMolecule('CC1CC1C(N)C1C(N)C1', 'C1CC1CC1CC1'),
# Double bond in linker
TestMolecule('C1CC1C(C(C)C)=NC1CC1', 'C1CC1C=NC1CC1'),
_TestMolecule('C1CC1C(C(C)C)=NC1CC1', 'C1CC1C=NC1CC1'),
# S=O group in scaffold
TestMolecule('C1CC1S(=O)C1CC1C=CNNCO', 'C1CC1S(=O)C1CC1'),
_TestMolecule('C1CC1S(=O)C1CC1C=CNNCO', 'C1CC1S(=O)C1CC1'),
# S=O group outside scaffold
TestMolecule('O=SCNC1CC1S(=O)C1CC1C=CNNCO', 'C1CC1S(=O)C1CC1'),
_TestMolecule('O=SCNC1CC1S(=O)C1CC1C=CNNCO', 'C1CC1S(=O)C1CC1'),
# SO2 group in scaffold
TestMolecule('C1CC1S(=O)(=O)C1CC1C=CNNCO', 'C1CC1S(=O)(=O)C1CC1'),
_TestMolecule('C1CC1S(=O)(=O)C1CC1C=CNNCO', 'C1CC1S(=O)(=O)C1CC1'),
# SO2 group outside scaffold
TestMolecule('O=S(CNCNC)(=O)CNC1CC1S(=O)(=O)C1CC1C=CNNCO', 'C1CC1S(=O)(=O)C1CC1'),
_TestMolecule('O=S(CNCNC)(=O)CNC1CC1S(=O)(=O)C1CC1C=CNNCO', 'C1CC1S(=O)(=O)C1CC1'),
# Hydroxamide
TestMolecule('C1CC1C=NO', 'C1CC1'),
_TestMolecule('C1CC1C=NO', 'C1CC1'),
# Cyano group
TestMolecule('C1CC1C#N', 'C1CC1'),
_TestMolecule('C1CC1C#N', 'C1CC1'),
# Acetylene group
TestMolecule('C1CC1C#CNC', 'C1CC1'),
TestMolecule('O=C1N(C)C(=O)N1C#CNC', 'O=C1NC(=O)N1'),
TestMolecule('[O-][N+](=O)c1cc(ccc1Cl)NS(=O)(=O)Cc2ccccc2', 'c1ccccc1NS(=O)(=O)Cc2ccccc2'),
_TestMolecule('C1CC1C#CNC', 'C1CC1'),
_TestMolecule('O=C1N(C)C(=O)N1C#CNC', 'O=C1NC(=O)N1'),
_TestMolecule('[O-][N+](=O)c1cc(ccc1Cl)NS(=O)(=O)Cc2ccccc2', 'c1ccccc1NS(=O)(=O)Cc2ccccc2'),
# N-Substituted pyrrol
TestMolecule('Cn1cccc1', 'c1ccc[nH]1'),
_TestMolecule('Cn1cccc1', 'c1ccc[nH]1'),
# Explicit hydrogens are removed
TestMolecule('C1CC1[CH](C)C1CC1', 'C1CC1CC1CC1'),
_TestMolecule('C1CC1[CH](C)C1CC1', 'C1CC1CC1CC1'),
]
testMolecules2 = [
TestMolecule('CCOc1ccccc1N(S(C)(=O)=O)CC(NC1CCCCC1)=O', 'O=C(NC1CCCCC1)CNc1ccccc1'),
TestMolecule('c1ccc(-c2c(C)n(-c3c(C(O)=O)cccc3)c(C)nc2=O)cc1',
_TestMolecule('CCOc1ccccc1N(S(C)(=O)=O)CC(NC1CCCCC1)=O', 'O=C(NC1CCCCC1)CNc1ccccc1'),
_TestMolecule('c1ccc(-c2c(C)n(-c3c(C(O)=O)cccc3)c(C)nc2=O)cc1',
'O=c1c(cn(cn1)-c1ccccc1)-c1ccccc1'),
TestMolecule('Cc1ccc(Cl)c2c1NC(=O)C2=C1NC(=S)NC1=O', 'c1cc2c(cc1)C(=C1C(NC(N1)=S)=O)C(=O)N2'),
TestMolecule('CNC(=O)CCc1[nH]c2c(c1Sc1ccccc1)cccc2', 'c1cc(Sc2c3c([nH]c2)cccc3)ccc1'),
TestMolecule('CC(=O)OCC(=O)C1(O)CCC2C1(C)CC(=O)C1C3(C)CCC(=O)C=C3CCC21',
_TestMolecule('Cc1ccc(Cl)c2c1NC(=O)C2=C1NC(=S)NC1=O', 'c1cc2c(cc1)C(=C1C(NC(N1)=S)=O)C(=O)N2'),
_TestMolecule('CNC(=O)CCc1[nH]c2c(c1Sc1ccccc1)cccc2', 'c1cc(Sc2c3c([nH]c2)cccc3)ccc1'),
_TestMolecule('CC(=O)OCC(=O)C1(O)CCC2C1(C)CC(=O)C1C3(C)CCC(=O)C=C3CCC21',
'O=C1C=C2CCC3C4CCCC4CC(=O)C3C2CC1'),
TestMolecule('CC(C)CC(Nc1nc(Cl)ccc1[N+]([O-])=O)C(O)=O', 'c1ccncc1'),
TestMolecule('COc1ccc(C(Nc2ccc(S(N3C(C)CCCC3)(=O)=O)cc2)=O)c(OC)c1OC',
_TestMolecule('CC(C)CC(Nc1nc(Cl)ccc1[N+]([O-])=O)C(O)=O', 'c1ccncc1'),
_TestMolecule('COc1ccc(C(Nc2ccc(S(N3C(C)CCCC3)(=O)=O)cc2)=O)c(OC)c1OC',
'O=C(Nc1ccc(S(=O)(=O)N2CCCCC2)cc1)c1ccccc1'),
TestMolecule('CC(C)CCNc1nc(N)c([N+](=O)[O-])c(NCCO)n1', 'c1cncnc1'),
TestMolecule('c1ccc(Oc2c(NC(COC(c3c(C)noc3C)=O)=O)cccc2)cc1',
_TestMolecule('CC(C)CCNc1nc(N)c([N+](=O)[O-])c(NCCO)n1', 'c1cncnc1'),
_TestMolecule('c1ccc(Oc2c(NC(COC(c3c(C)noc3C)=O)=O)cccc2)cc1',
'O=C(COC(=O)c1cnoc1)Nc1ccccc1Oc1ccccc1'),
TestMolecule('COC(CCCCC1SCC(NC(OC)=O)C1NC(OC)=O)=O', 'C1CCCS1'),
TestMolecule('CSc1ccc(-c2c(C#N)c(N)nc3n(-c4ccccc4)nc(C)c32)cc1',
_TestMolecule('COC(CCCCC1SCC(NC(OC)=O)C1NC(OC)=O)=O', 'C1CCCS1'),
_TestMolecule('CSc1ccc(-c2c(C#N)c(N)nc3n(-c4ccccc4)nc(C)c32)cc1',
'c1ccc(cc1)-c1c2c(n(nc2)-c2ccccc2)ncc1'),
TestMolecule('O=C1Cc2ccccc2Sc2c1cc(Cl)cc2', 'O=C1Cc2ccccc2Sc2ccccc21'),
TestMolecule('COC(c1n(CC(N(C)c2ccccc2)=O)c2ccsc2c1)=O', 'O=C(Cn1c2ccsc2cc1)Nc1ccccc1'),
TestMolecule('N=C1C(=Cc2coc3ccccc3c2=O)C(=O)N=C2SC(c3ccncc3)=NN12',
_TestMolecule('O=C1Cc2ccccc2Sc2c1cc(Cl)cc2', 'O=C1Cc2ccccc2Sc2ccccc21'),
_TestMolecule('COC(c1n(CC(N(C)c2ccccc2)=O)c2ccsc2c1)=O', 'O=C(Cn1c2ccsc2cc1)Nc1ccccc1'),
_TestMolecule('N=C1C(=Cc2coc3ccccc3c2=O)C(=O)N=C2SC(c3ccncc3)=NN12',
'N=C1C(=Cc2coc3ccccc3c2=O)C(=O)N=C2SC(c3ccncc3)=NN12'),
TestMolecule('CCOC(c1ccc(NC(CCc2c(C)nc3ncnn3c2C)=O)cc1)=O', 'O=C(Nc1ccccc1)CCc1cnc2n(ncn2)c1'),
TestMolecule('COC(=O)C1=C(C)NC(C)=C(C(OC)=O)C1c1oc(-c2c(Cl)c(Cl)ccc2)cc1',
_TestMolecule('CCOC(c1ccc(NC(CCc2c(C)nc3ncnn3c2C)=O)cc1)=O', 'O=C(Nc1ccccc1)CCc1cnc2n(ncn2)c1'),
_TestMolecule('COC(=O)C1=C(C)NC(C)=C(C(OC)=O)C1c1oc(-c2c(Cl)c(Cl)ccc2)cc1',
'c1ccc(-c2oc(C3C=CNC=C3)cc2)cc1'),
TestMolecule('CCN(S(c1cc(NC(COC(CCc2nc3ccccc3s2)=O)=O)ccc1)(=O)=O)CC',
_TestMolecule('CCN(S(c1cc(NC(COC(CCc2nc3ccccc3s2)=O)=O)ccc1)(=O)=O)CC',
'c1cc(NC(COC(=O)CCc2nc3c(s2)cccc3)=O)ccc1'),
TestMolecule('CCOC(c1cc(OC(c2ccccc2)=O)n(-c2ccccc2)n1)=O', 'O=C(Oc1n(ncc1)-c1ccccc1)c1ccccc1'),
TestMolecule('CCOC(=O)c1nc2c(c(NCc3ccccc3F)n1)cccc2', 'c1ccc(CNc2ncnc3c2cccc3)cc1'),
TestMolecule('Cc1nc(C)n(CC(N2CCCC(C(c3c(C)cc(Cl)cc3)=O)C2)=O)n1',
_TestMolecule('CCOC(c1cc(OC(c2ccccc2)=O)n(-c2ccccc2)n1)=O', 'O=C(Oc1n(ncc1)-c1ccccc1)c1ccccc1'),
_TestMolecule('CCOC(=O)c1nc2c(c(NCc3ccccc3F)n1)cccc2', 'c1ccc(CNc2ncnc3c2cccc3)cc1'),
_TestMolecule('Cc1nc(C)n(CC(N2CCCC(C(c3c(C)cc(Cl)cc3)=O)C2)=O)n1',
'c1ccc(cc1)C(=O)C1CCCN(C(=O)Cn2cncn2)C1'),
TestMolecule('COc1cc(NC(=O)c2nnn(CCc3ccccc3)c2N)c(OC)cc1', 'O=C(c1nnn(c1)CCc1ccccc1)Nc1ccccc1'),
TestMolecule('Cc1cc(C(=O)CN2C(=O)c3ccccc3C2=O)c(C)n1Cc1cccs1',
_TestMolecule('COc1cc(NC(=O)c2nnn(CCc3ccccc3)c2N)c(OC)cc1', 'O=C(c1nnn(c1)CCc1ccccc1)Nc1ccccc1'),
_TestMolecule('Cc1cc(C(=O)CN2C(=O)c3ccccc3C2=O)c(C)n1Cc1cccs1',
'O=C(CN1C(c2c(cccc2)C1=O)=O)c1cn(Cc2cccs2)cc1'),
TestMolecule('c1cnc2c(c1)cccc2S(N1CCC(C(=O)N2CCN(c3ccc(Cl)cc3)CC2)CC1)(=O)=O',
_TestMolecule('c1cnc2c(c1)cccc2S(N1CCC(C(=O)N2CCN(c3ccc(Cl)cc3)CC2)CC1)(=O)=O',
'c1ccc(cc1)N1CCN(C(=O)C2CCN(S(=O)(=O)c3c4ncccc4ccc3)CC2)CC1'),
TestMolecule('CCOC(c1c(C)[nH]c(C(NNC(c2ccc(C(C)(C)C)cc2)=O)=O)c1C)=O',
_TestMolecule('CCOC(c1c(C)[nH]c(C(NNC(c2ccc(C(C)(C)C)cc2)=O)=O)c1C)=O',
'c1ccc(cc1)C(NNC(c1ccc[nH]1)=O)=O'),
TestMolecule('CCOC(c1cc(C(C)C)sc1NC(=O)COC(CCS(c1ccccc1)(=O)=O)=O)=O',
_TestMolecule('CCOC(c1cc(C(C)C)sc1NC(=O)COC(CCS(c1ccccc1)(=O)=O)=O)=O',
'c1ccc(S(CCC(=O)OCC(Nc2cccs2)=O)(=O)=O)cc1'),
TestMolecule('CCC1CCCCN1CCCNC(=O)Cn1nc(-c2ccccc2)ccc1=O',
_TestMolecule('CCC1CCCCN1CCCNC(=O)Cn1nc(-c2ccccc2)ccc1=O',
'O=C(NCCCN1CCCCC1)Cn1nc(ccc1=O)-c1ccccc1'),
TestMolecule('CCc1cc(OCCn2nc(C(O)=O)c3ccccc3c2=O)ccc1', 'O=c1n(CCOc2ccccc2)ncc2ccccc21'),
TestMolecule('Fc1ccc(CN2CCN3C(CCC3)C2C2CCCCC2)cc1F', 'c1ccc(cc1)CN1CCN2CCCC2C1C1CCCCC1'),
TestMolecule('O=[N+]([O-])c1cc(-c2nnc(N3CCOCC3)c3ccccc23)ccc1N1CCOCC1',
_TestMolecule('CCc1cc(OCCn2nc(C(O)=O)c3ccccc3c2=O)ccc1', 'O=c1n(CCOc2ccccc2)ncc2ccccc21'),
_TestMolecule('Fc1ccc(CN2CCN3C(CCC3)C2C2CCCCC2)cc1F', 'c1ccc(cc1)CN1CCN2CCCC2C1C1CCCCC1'),
_TestMolecule('O=[N+]([O-])c1cc(-c2nnc(N3CCOCC3)c3ccccc23)ccc1N1CCOCC1',
'c1cc2c(nnc(c2cc1)N1CCOCC1)-c1ccc(cc1)N1CCOCC1'),
TestMolecule('Cc1ccnc(NC(=O)COc2ccc3oc4c(c3c2)CCCC4)c1',
_TestMolecule('Cc1ccnc(NC(=O)COc2ccc3oc4c(c3c2)CCCC4)c1',
'O=C(COc1ccc2oc3c(c2c1)CCCC3)Nc1ccccn1'),
TestMolecule('Cc1cc(=O)oc(C)c1C(=O)NCCCN1CCN(c2ccc(F)cc2)CC1',
_TestMolecule('Cc1cc(=O)oc(C)c1C(=O)NCCCN1CCN(c2ccc(F)cc2)CC1',
'c1ccc(N2CCN(CCCNC(c3ccc(oc3)=O)=O)CC2)cc1'),
TestMolecule('Cc1cc(C(=O)CSc2nc(=O)cc(N)[nH]2)c(C)n1-c1cccc(F)c1',
_TestMolecule('Cc1cc(C(=O)CSc2nc(=O)cc(N)[nH]2)c(C)n1-c1cccc(F)c1',
'O=C(CSc1nc(cc[nH]1)=O)c1cn(cc1)-c1ccccc1'),
TestMolecule('CCN(S(c1cccc(C(=O)N2CCCCC2)c1)(=O)=O)CC', 'O=C(N1CCCCC1)c1ccccc1'),
TestMolecule('CNC(=S)N1CCC(NC(=O)C23CC4CC(C2)CC(C3)C4)CC1',
_TestMolecule('CCN(S(c1cccc(C(=O)N2CCCCC2)c1)(=O)=O)CC', 'O=C(N1CCCCC1)c1ccccc1'),
_TestMolecule('CNC(=S)N1CCC(NC(=O)C23CC4CC(C2)CC(C3)C4)CC1',
'O=C(NC1CCNCC1)C12CC3CC(C1)CC(C3)C2'),
TestMolecule('Cc1cc2c(cc1)N=C(C)C(N=O)=C(C)N2', 'c1cc2NC=CC=Nc2cc1'),
TestMolecule('COc1ccc(Sc2cc(C(F)(F)F)nc(-c3ncccc3)n2)cc1', 'c1ccc(cc1)Sc1nc(ncc1)-c1ncccc1'),
TestMolecule('c1coc(CNC(Cn2cc(C(c3ccccc3)=O)c3c2cccc3)=O)c1',
_TestMolecule('Cc1cc2c(cc1)N=C(C)C(N=O)=C(C)N2', 'c1cc2NC=CC=Nc2cc1'),
_TestMolecule('COc1ccc(Sc2cc(C(F)(F)F)nc(-c3ncccc3)n2)cc1', 'c1ccc(cc1)Sc1nc(ncc1)-c1ncccc1'),
_TestMolecule('c1coc(CNC(Cn2cc(C(c3ccccc3)=O)c3c2cccc3)=O)c1',
'c1coc(CNC(Cn2cc(C(c3ccccc3)=O)c3c2cccc3)=O)c1'),
TestMolecule('O=C(NCc1ccc(Cl)cc1)c1noc(-c2ccco2)c1', 'O=C(c1noc(c1)-c1ccco1)NCc1ccccc1'),
TestMolecule('CN(C)c1ccc(C(c2n(CCOC(=O)Nc3ccc(Cl)cc3)nnn2)N2CCOCC2)cc1',
_TestMolecule('O=C(NCc1ccc(Cl)cc1)c1noc(-c2ccco2)c1', 'O=C(c1noc(c1)-c1ccco1)NCc1ccccc1'),
_TestMolecule('CN(C)c1ccc(C(c2n(CCOC(=O)Nc3ccc(Cl)cc3)nnn2)N2CCOCC2)cc1',
'O=C(Nc1ccccc1)OCCn1nnnc1C(c1ccccc1)N1CCOCC1'),
TestMolecule('NC(=NOC(=O)c1cc(Cn2cc(C(F)(F)F)ccc2=O)ccc1)c1ccccc1',
_TestMolecule('NC(=NOC(=O)c1cc(Cn2cc(C(F)(F)F)ccc2=O)ccc1)c1ccccc1',
'c1ccc(C=NOC(c2cc(Cn3ccccc3=O)ccc2)=O)cc1'),
TestMolecule('CCc1nnc(NC(=O)Cc2c(-c3ccc(C)cc3)nc(C)s2)s1', 'O=C(Cc1c(-c2ccccc2)ncs1)Nc1nncs1'),
TestMolecule('COCCCNC(=O)CN1C(=O)N(Cc2ccccc2Cl)CC1', 'O=C1NCCN1Cc1ccccc1'),
TestMolecule('Cc1cc([N+]([O-])=O)nn1CC(=O)NCCCn1ccnc1', 'O=C(Cn1nccc1)NCCCn1ccnc1'),
TestMolecule('c1cc(F)c(N2CCN(C(=O)c3ccc(S(NCC4OCCC4)(=O)=O)cc3)CC2)cc1',
_TestMolecule('CCc1nnc(NC(=O)Cc2c(-c3ccc(C)cc3)nc(C)s2)s1', 'O=C(Cc1c(-c2ccccc2)ncs1)Nc1nncs1'),
_TestMolecule('COCCCNC(=O)CN1C(=O)N(Cc2ccccc2Cl)CC1', 'O=C1NCCN1Cc1ccccc1'),
_TestMolecule('Cc1cc([N+]([O-])=O)nn1CC(=O)NCCCn1ccnc1', 'O=C(Cn1nccc1)NCCCn1ccnc1'),
_TestMolecule('c1cc(F)c(N2CCN(C(=O)c3ccc(S(NCC4OCCC4)(=O)=O)cc3)CC2)cc1',
'c1ccc(cc1)N1CCN(C(c2ccc(cc2)S(=O)(=O)NCC2OCCC2)=O)CC1'),
TestMolecule('CC(NCc1cccnc1)=C1C(=O)NC(=O)N(c2ccc(C)cc2)C1=O',
_TestMolecule('CC(NCc1cccnc1)=C1C(=O)NC(=O)N(c2ccc(C)cc2)C1=O',
'c1cc(ccc1)N1C(=O)NC(C(=CNCc2cccnc2)C1=O)=O'),
TestMolecule('Cc1ccn(C)c(=N)c1', 'N=c1[nH]cccc1'),
TestMolecule('Cc1cc(C)nc(N2CCC(CNC(=O)CCc3ccccc3)CC2)n1',
_TestMolecule('Cc1ccn(C)c(=N)c1', 'N=c1[nH]cccc1'),
_TestMolecule('Cc1cc(C)nc(N2CCC(CNC(=O)CCc3ccccc3)CC2)n1',
'O=C(CCc1ccccc1)NCC1CCN(c2ncccn2)CC1'),
TestMolecule('CCOC1=CC(=CNNC(CCCC(NC2CCCCC2)=O)=O)C=CC1=O',
_TestMolecule('CCOC1=CC(=CNNC(CCCC(NC2CCCCC2)=O)=O)C=CC1=O',
'C1=CC(C=CC1=O)=CNNC(=O)CCCC(=O)NC1CCCCC1'),
TestMolecule('CC(=O)N1CCN(c2ccc([N+]([O-])=O)cc2)CC1', 'c1ccc(cc1)N1CCNCC1'),
TestMolecule('CS(N(CC(=O)N1CCCCC1)Cc1ccc(Cl)cc1)(=O)=O', 'O=C(N1CCCCC1)CNCc1ccccc1'),
TestMolecule('c1coc(C(=O)N2CCN(C(COc3cc(C(NCc4ccccc4)=O)ccc3)=O)CC2)c1',
_TestMolecule('CC(=O)N1CCN(c2ccc([N+]([O-])=O)cc2)CC1', 'c1ccc(cc1)N1CCNCC1'),
_TestMolecule('CS(N(CC(=O)N1CCCCC1)Cc1ccc(Cl)cc1)(=O)=O', 'O=C(N1CCCCC1)CNCc1ccccc1'),
_TestMolecule('c1coc(C(=O)N2CCN(C(COc3cc(C(NCc4ccccc4)=O)ccc3)=O)CC2)c1',
'c1coc(C(=O)N2CCN(C(COc3cc(C(NCc4ccccc4)=O)ccc3)=O)CC2)c1'),
TestMolecule('Cc1cccc2sc(NNC(=O)C3=COCCO3)nc12', 'O=C(NNc1nc2ccccc2s1)C1=COCCO1'),
TestMolecule('c1ccc2c(c1)N(C)C1(C=Nc3c(cc(N4CCOCC4)c4ccccc34)O1)C2(C)C',
_TestMolecule('Cc1cccc2sc(NNC(=O)C3=COCCO3)nc12', 'O=C(NNc1nc2ccccc2s1)C1=COCCO1'),
_TestMolecule('c1ccc2c(c1)N(C)C1(C=Nc3c(cc(N4CCOCC4)c4ccccc34)O1)C2(C)C',
'C1=Nc2c(cc(c3ccccc23)N2CCOCC2)OC11Nc2ccccc2C1'),
TestMolecule('COc1cccc(C2N(CCN3CCOCC3)C(=O)C(O)=C2C(=O)c2sc(C)nc2C)c1',
_TestMolecule('COc1cccc(C2N(CCN3CCOCC3)C(=O)C(O)=C2C(=O)c2sc(C)nc2C)c1',
'O=C(C1=CC(=O)N(C1c1ccccc1)CCN1CCOCC1)c1scnc1'),
TestMolecule('COc1cc(OC)c(NC(CSc2nc3c(c(=O)n2-c2ccc(F)cc2)SCC3)=O)cc1',
_TestMolecule('COc1cc(OC)c(NC(CSc2nc3c(c(=O)n2-c2ccc(F)cc2)SCC3)=O)cc1',
'c1ccc(cc1)NC(=O)CSc1n(c(=O)c2c(n1)CCS2)-c1ccccc1'),
TestMolecule('Cc1ccccc1CN1c2ccccc2C2(C1=O)OCCCO2', 'O=C1C2(OCCCO2)c2c(N1Cc1ccccc1)cccc2'),
TestMolecule('O=C(N1C2(OCC1)CCN(c1ncc(C(F)(F)F)cc1Cl)CC2)c1ccccc1',
_TestMolecule('Cc1ccccc1CN1c2ccccc2C2(C1=O)OCCCO2', 'O=C1C2(OCCCO2)c2c(N1Cc1ccccc1)cccc2'),
_TestMolecule('O=C(N1C2(OCC1)CCN(c1ncc(C(F)(F)F)cc1Cl)CC2)c1ccccc1',
'O=C(c1ccccc1)N1C2(OCC1)CCN(c1ccccn1)CC2'),
TestMolecule('CC=CC=CC(=O)Nc1nccs1', 'c1ncsc1'),
TestMolecule('CC(C)(C)c1ccc(C(c2c[nH]c(C(NCc3cccnc3)=O)c2)=O)cc1',
_TestMolecule('CC=CC=CC(=O)Nc1nccs1', 'c1ncsc1'),
_TestMolecule('CC(C)(C)c1ccc(C(c2c[nH]c(C(NCc3cccnc3)=O)c2)=O)cc1',
'c1ccc(cc1)C(=O)c1c[nH]c(c1)C(=O)NCc1cccnc1'),
TestMolecule('CCC(=O)Nc1c(C)nn(-c2cc(C)c(C)cc2)c1C', 'c1ccc(cc1)-n1nccc1'),
TestMolecule('Cc1ccc(SCCC(=O)NCCSCc2c(C)cccc2)cc1', 'O=C(NCCSCc1ccccc1)CCSc1ccccc1'),
TestMolecule('CC1=NN(Cc2ccccc2)C(=O)C1=Cc1ccc(N(C)C)cc1', 'O=C1C(C=NN1Cc1ccccc1)=Cc1ccccc1'),
TestMolecule('COCC(=O)Nc1ccc(S(NCCc2ccccc2)(=O)=O)cc1', 'c1ccc(CCNS(=O)(=O)c2ccccc2)cc1'),
TestMolecule('CCOC(=O)N(C)c1ccc(C(O)(C(F)(F)F)C(F)(F)F)cc1', 'c1ccccc1'),
TestMolecule('Fc1ccc(COC2=C(C(O)=O)CCNC2=O)cc1F', 'O=C1NCCC=C1OCc1ccccc1'),
TestMolecule('O=C1N2C(Nc3ccccc31)CCCCC2', 'O=C1N2C(Nc3ccccc31)CCCCC2'),
TestMolecule('Cl.COc1ccc(-c2nc3n(ccc4ccccc43)c2CN2CCOCC2)cc1OC',
_TestMolecule('CCC(=O)Nc1c(C)nn(-c2cc(C)c(C)cc2)c1C', 'c1ccc(cc1)-n1nccc1'),
_TestMolecule('Cc1ccc(SCCC(=O)NCCSCc2c(C)cccc2)cc1', 'O=C(NCCSCc1ccccc1)CCSc1ccccc1'),
_TestMolecule('CC1=NN(Cc2ccccc2)C(=O)C1=Cc1ccc(N(C)C)cc1', 'O=C1C(C=NN1Cc1ccccc1)=Cc1ccccc1'),
_TestMolecule('COCC(=O)Nc1ccc(S(NCCc2ccccc2)(=O)=O)cc1', 'c1ccc(CCNS(=O)(=O)c2ccccc2)cc1'),
_TestMolecule('CCOC(=O)N(C)c1ccc(C(O)(C(F)(F)F)C(F)(F)F)cc1', 'c1ccccc1'),
_TestMolecule('Fc1ccc(COC2=C(C(O)=O)CCNC2=O)cc1F', 'O=C1NCCC=C1OCc1ccccc1'),
_TestMolecule('O=C1N2C(Nc3ccccc31)CCCCC2', 'O=C1N2C(Nc3ccccc31)CCCCC2'),
_TestMolecule('Cl.COc1ccc(-c2nc3n(ccc4ccccc43)c2CN2CCOCC2)cc1OC',
'c1cccc(c1)-c1nc2c3c(ccn2c1CN1CCOCC1)cccc3'),
TestMolecule('ClCc1oc(-c2ccccc2)nn1', 'c1oc(nn1)-c1ccccc1'),
TestMolecule('Cl.Cc1ccc(OCC(O)Cn2c(=N)n(CCN3CCCCC3)c3ccccc32)cc1',
_TestMolecule('ClCc1oc(-c2ccccc2)nn1', 'c1oc(nn1)-c1ccccc1'),
_TestMolecule('Cl.Cc1ccc(OCC(O)Cn2c(=N)n(CCN3CCCCC3)c3ccccc32)cc1',
'N=c1n(CCCOc2ccccc2)c2ccccc2n1CCN1CCCCC1'),
TestMolecule('COc1ccc(C(=O)C=C(C)Nc2ccc3c(c2)OCO3)cc1', 'O=C(C=CNc1ccc2c(c1)OCO2)c1ccccc1'),
TestMolecule('c1csc(CN(C(c2ccc(F)cc2)C(NC2CCCCC2)=O)C(=O)CN2S(=O)(=O)c3ccccc3C2=O)c1',
_TestMolecule('COc1ccc(C(=O)C=C(C)Nc2ccc3c(c2)OCO3)cc1', 'O=C(C=CNc1ccc2c(c1)OCO2)c1ccccc1'),
_TestMolecule('c1csc(CN(C(c2ccc(F)cc2)C(NC2CCCCC2)=O)C(=O)CN2S(=O)(=O)c3ccccc3C2=O)c1',
'c1cc(CN(C(=O)CN2S(=O)(c3ccccc3C2=O)=O)C(C(=O)NC2CCCCC2)c2ccccc2)sc1'),
TestMolecule('c1csc(S(NCCSc2n(-c3ccccc3)nnn2)(=O)=O)c1',
_TestMolecule('c1csc(S(NCCSc2n(-c3ccccc3)nnn2)(=O)=O)c1',
'c1csc(S(NCCSc2n(-c3ccccc3)nnn2)(=O)=O)c1'),
TestMolecule('Cc1cccc(C=NNC(=O)Cn2c(N)nnn2)n1', 'O=C(Cn1cnnn1)NN=Cc1ccccn1'),
TestMolecule('CCOC(C1(Cc2ccc(Cl)cc2)CCN(C(c2cc(C)nc(C)n2)=O)CC1)=O',
_TestMolecule('Cc1cccc(C=NNC(=O)Cn2c(N)nnn2)n1', 'O=C(Cn1cnnn1)NN=Cc1ccccn1'),
_TestMolecule('CCOC(C1(Cc2ccc(Cl)cc2)CCN(C(c2cc(C)nc(C)n2)=O)CC1)=O',
'O=C(N1CCC(CC1)Cc1ccccc1)c1ccncn1'),
TestMolecule('c1ccc(C(N(CC2OCCC2)C(Cn2nnc3ccccc23)=O)C(NCc2ccc(F)cc2)=O)cc1',
_TestMolecule('c1ccc(C(N(CC2OCCC2)C(Cn2nnc3ccccc23)=O)C(NCc2ccc(F)cc2)=O)cc1',
'O=C(N(C(c1ccccc1)C(=O)NCc1ccccc1)CC1OCCC1)Cn1nnc2c1cccc2'),
TestMolecule('O=C1CSC(c2ccncc2)N1Cc1occc1', 'O=C1CSC(c2ccncc2)N1Cc1occc1'),
TestMolecule('COc1c(OCc2ccccc2)c(Br)cc(C=NNC(=O)Cn2nc([N+]([O-])=O)cc2C)c1',
_TestMolecule('O=C1CSC(c2ccncc2)N1Cc1occc1', 'O=C1CSC(c2ccncc2)N1Cc1occc1'),
_TestMolecule('COc1c(OCc2ccccc2)c(Br)cc(C=NNC(=O)Cn2nc([N+]([O-])=O)cc2C)c1',
'O=C(Cn1nccc1)NN=Cc1ccc(cc1)OCc1ccccc1'),
TestMolecule('Cc1c(Cn2nnc(-c3cc(C(=O)O)ccc3)n2)cccc1', 'c1cccc(-c2nn(nn2)Cc2ccccc2)c1'),
TestMolecule('O=C(c1ccc2snnc2c1)N1CCCC1', 'O=C(c1ccc2snnc2c1)N1CCCC1'),
TestMolecule('c1ccc(CC(NN2C(=O)C(=Cc3c(C(O)=O)cccc3)SC2=S)=O)cc1',
_TestMolecule('Cc1c(Cn2nnc(-c3cc(C(=O)O)ccc3)n2)cccc1', 'c1cccc(-c2nn(nn2)Cc2ccccc2)c1'),
_TestMolecule('O=C(c1ccc2snnc2c1)N1CCCC1', 'O=C(c1ccc2snnc2c1)N1CCCC1'),
_TestMolecule('c1ccc(CC(NN2C(=O)C(=Cc3c(C(O)=O)cccc3)SC2=S)=O)cc1',
'O=C1C(=Cc2ccccc2)SC(=S)N1NC(Cc1ccccc1)=O'),
TestMolecule('Cc1ccccc1OCC(=O)NN=Cc1ccncc1', 'O=C(COc1ccccc1)NN=Cc1ccncc1'),
TestMolecule('O=C(C=Cc1ccccc1)NC(=S)Nc1ccc(CN2CCOCC2)cc1',
_TestMolecule('Cc1ccccc1OCC(=O)NN=Cc1ccncc1', 'O=C(COc1ccccc1)NN=Cc1ccncc1'),
_TestMolecule('O=C(C=Cc1ccccc1)NC(=S)Nc1ccc(CN2CCOCC2)cc1',
'O=C(C=Cc1ccccc1)NC(=S)Nc1ccc(CN2CCOCC2)cc1'),
TestMolecule('COc1ccc(NC(=S)N(Cc2cnccc2)Cc2c(=O)[nH]c3c(c2)cc(OC)c(OC)c3)cc1',
_TestMolecule('COc1ccc(NC(=S)N(Cc2cnccc2)Cc2c(=O)[nH]c3c(c2)cc(OC)c(OC)c3)cc1',
'O=c1c(CN(C(=S)Nc2ccccc2)Cc2cnccc2)cc2ccccc2[nH]1'),
TestMolecule('Nc1ccc2nc3c([nH]c(=O)n(C4CCCCC4)c3=O)nc2c1',
_TestMolecule('Nc1ccc2nc3c([nH]c(=O)n(C4CCCCC4)c3=O)nc2c1',
'c1ccc2nc3[nH]c(n(c(c3nc2c1)=O)C1CCCCC1)=O'),
TestMolecule('Cc1cc(NC(=O)c2ccc(S(Nc3ccccc3)(=O)=O)cc2)no1',
_TestMolecule('Cc1cc(NC(=O)c2ccc(S(Nc3ccccc3)(=O)=O)cc2)no1',
'c1cc(no1)NC(=O)c1ccc(S(=O)(=O)Nc2ccccc2)cc1'),
TestMolecule('Nn1c(Cc2c3c(cccc3)ccc2)nnc1SCc1ccccc1',
_TestMolecule('Nn1c(Cc2c3c(cccc3)ccc2)nnc1SCc1ccccc1',
'c1ccc(CSc2nnc([nH]2)Cc2c3c(cccc3)ccc2)cc1'),
TestMolecule('Cc1[nH]nc(Nc2cc(C)ccc2)c1[N+](=O)[O-]', 'c1ccc(cc1)Nc1n[nH]cc1'),
TestMolecule('CC1Cn2c(nc3n(C)c(=O)[nH]c(=O)c23)O1', 'O=c1[nH]c2nc3n(c2c([nH]1)=O)CCO3'),
TestMolecule('c1csc(C(OCC(NC23CC4CC(C2)CC(C3)C4)=O)=O)c1',
_TestMolecule('Cc1[nH]nc(Nc2cc(C)ccc2)c1[N+](=O)[O-]', 'c1ccc(cc1)Nc1n[nH]cc1'),
_TestMolecule('CC1Cn2c(nc3n(C)c(=O)[nH]c(=O)c23)O1', 'O=c1[nH]c2nc3n(c2c([nH]1)=O)CCO3'),
_TestMolecule('c1csc(C(OCC(NC23CC4CC(C2)CC(C3)C4)=O)=O)c1',
'c1csc(C(OCC(NC23CC4CC(C2)CC(C3)C4)=O)=O)c1'),
TestMolecule('c1ccc(S(NC2=NC(=O)C(=Cc3cnccc3)S2)(=O)=O)cc1',
_TestMolecule('c1ccc(S(NC2=NC(=O)C(=Cc3cnccc3)S2)(=O)=O)cc1',
'c1ccc(S(NC2=NC(=O)C(=Cc3cnccc3)S2)(=O)=O)cc1'),
TestMolecule('CCCn1c(N2CCN(C)CC2)nc2n(C)c(=O)[nH]c(=O)c12',
_TestMolecule('CCCn1c(N2CCN(C)CC2)nc2n(C)c(=O)[nH]c(=O)c12',
'O=c1[nH]c([nH]c2nc([nH]c12)N1CCNCC1)=O'),
TestMolecule('CCn1c(SCC(Nc2cc(S(N3CCOCC3)(=O)=O)ccc2OC)=O)nnc1-c1ccncc1',
_TestMolecule('CCn1c(SCC(Nc2cc(S(N3CCOCC3)(=O)=O)ccc2OC)=O)nnc1-c1ccncc1',
'c1cc(S(=O)(=O)N2CCOCC2)cc(NC(=O)CSc2nnc(-c3ccncc3)[nH]2)c1'),
TestMolecule('C#CCNC(=O)C1=CC(c2ccc(Br)cc2)CC(OCc2ccc(CO)cc2)O1',
_TestMolecule('C#CCNC(=O)C1=CC(c2ccc(Br)cc2)CC(OCc2ccc(CO)cc2)O1',
'c1cccc(c1)C1C=COC(OCc2ccccc2)C1'),
TestMolecule('CCc1c(SCC(=O)Nc2cc(C)on2)nc2ccc(C)cc2c1', 'O=C(Nc1ccon1)CSc1ccc2c(cccc2)n1'),
TestMolecule('CCOCCCN(C(C(NC1CCCC1)=O)c1cccc(OC)c1OC)C(c1ccco1)=O',
_TestMolecule('CCc1c(SCC(=O)Nc2cc(C)on2)nc2ccc(C)cc2c1', 'O=C(Nc1ccon1)CSc1ccc2c(cccc2)n1'),
_TestMolecule('CCOCCCN(C(C(NC1CCCC1)=O)c1cccc(OC)c1OC)C(c1ccco1)=O',
'c1cc(ccc1)C(NC(c1occc1)=O)C(=O)NC1CCCC1'),
TestMolecule('Cc1ccc(C(=O)NC(=S)NNS(c2ccccc2)(=O)=O)cc1',
_TestMolecule('Cc1ccc(C(=O)NC(=S)NNS(c2ccccc2)(=O)=O)cc1',
'c1cccc(c1)C(NC(=S)NNS(=O)(=O)c1ccccc1)=O'),
TestMolecule('COc1ccc(CC(N)=NOC(=O)c2sccc2)cc1', 'O=C(ON=CCc1ccccc1)c1sccc1'),
TestMolecule('c1ccc(C(O)=C2C(c3ncccc3)N(CC(OC)OC)C(=O)C2=O)cc1',
_TestMolecule('COc1ccc(CC(N)=NOC(=O)c2sccc2)cc1', 'O=C(ON=CCc1ccccc1)c1sccc1'),
_TestMolecule('c1ccc(C(O)=C2C(c3ncccc3)N(CC(OC)OC)C(=O)C2=O)cc1',
'c1cc(C=C2C(=O)C(=O)NC2c2ncccc2)ccc1'),
TestMolecule('COC(=O)CSc1nc(C)cc(Oc2ccccc2)n1', 'c1ccc(Oc2ccncn2)cc1'),
TestMolecule('COc1ccc(Cn2c(C)ccc2C)cc1', 'c1ccc(cc1)Cn1cccc1'),
TestMolecule('COc1cccc(N2CCN(C3CC(=O)N(c4ccc(C)c(Cl)c4)C3=O)CC2)c1',
_TestMolecule('COC(=O)CSc1nc(C)cc(Oc2ccccc2)n1', 'c1ccc(Oc2ccncn2)cc1'),
_TestMolecule('COc1ccc(Cn2c(C)ccc2C)cc1', 'c1ccc(cc1)Cn1cccc1'),
_TestMolecule('COc1cccc(N2CCN(C3CC(=O)N(c4ccc(C)c(Cl)c4)C3=O)CC2)c1',
'O=C1N(c2ccccc2)C(=O)C(C1)N1CCN(c2ccccc2)CC1'),
TestMolecule('COc1cccc(OC)c1OCCN(C)C.OC(=O)C(O)=O', 'c1ccccc1'),
TestMolecule('C1CCC(NC(=O)c2ccc(S(N3CCCC3)(=O)=O)cc2)C1',
_TestMolecule('COc1cccc(OC)c1OCCN(C)C.OC(=O)C(O)=O', 'c1ccccc1'),
_TestMolecule('C1CCC(NC(=O)c2ccc(S(N3CCCC3)(=O)=O)cc2)C1',
'C1CCC(NC(=O)c2ccc(S(N3CCCC3)(=O)=O)cc2)C1'),
TestMolecule('CCCN(C(=O)Cn1ncc2c(=O)oc3c(c12)cccc3)c1cc(C)ccc1',
_TestMolecule('CCCN(C(=O)Cn1ncc2c(=O)oc3c(c12)cccc3)c1cc(C)ccc1',
'O=C(Cn1ncc2c(oc3c(cccc3)c12)=O)Nc1ccccc1'),
TestMolecule('CNC(NC(CSc1nnc(C(F)(F)F)n1C)=O)=O', 'n1nc[nH]c1'),
TestMolecule('CCOCCCN1C(=O)CC(C(NCCc2ccc(C)cc2)=O)C1', 'O=C1NCC(C1)C(NCCc1ccccc1)=O'),
TestMolecule('COc1c([N+](=O)[O-])cc(CSc2n[nH]c(C)n2)cc1', 'c1ccc(CSc2nc[nH]n2)cc1'),
TestMolecule('CN(C)CC(=O)c1ccc(-c2ccccc2)cc1', 'c1cccc(c1)-c1ccccc1'),
TestMolecule('CC1(O)C(=O)c2c(cccc2)N(c2ccccc2)C1=O', 'O=C1CC(=O)N(c2c1cccc2)c1ccccc1'),
TestMolecule('CN(S(c1ccccc1)(=O)=O)CC(=O)NCCc1ccccc1', 'c1ccc(CCNC(=O)CNS(=O)(=O)c2ccccc2)cc1'),
TestMolecule('CCNc1ccccc1C(=O)O', 'c1ccccc1'),
TestMolecule('CC1(C)C(CSc2nc3ccccc3[nH]2)C1(Cl)Cl', 'c1ccc2c(nc([nH]2)SCC2CC2)c1'),
TestMolecule('CC(C)c1ccc(OCC(=O)NC(=S)Nc2c3cccc4c3c(cc2)CC4)cc1',
_TestMolecule('CNC(NC(CSc1nnc(C(F)(F)F)n1C)=O)=O', 'n1nc[nH]c1'),
_TestMolecule('CCOCCCN1C(=O)CC(C(NCCc2ccc(C)cc2)=O)C1', 'O=C1NCC(C1)C(NCCc1ccccc1)=O'),
_TestMolecule('COc1c([N+](=O)[O-])cc(CSc2n[nH]c(C)n2)cc1', 'c1ccc(CSc2nc[nH]n2)cc1'),
_TestMolecule('CN(C)CC(=O)c1ccc(-c2ccccc2)cc1', 'c1cccc(c1)-c1ccccc1'),
_TestMolecule('CC1(O)C(=O)c2c(cccc2)N(c2ccccc2)C1=O', 'O=C1CC(=O)N(c2c1cccc2)c1ccccc1'),
_TestMolecule('CN(S(c1ccccc1)(=O)=O)CC(=O)NCCc1ccccc1', 'c1ccc(CCNC(=O)CNS(=O)(=O)c2ccccc2)cc1'),
_TestMolecule('CCNc1ccccc1C(=O)O', 'c1ccccc1'),
_TestMolecule('CC1(C)C(CSc2nc3ccccc3[nH]2)C1(Cl)Cl', 'c1ccc2c(nc([nH]2)SCC2CC2)c1'),
_TestMolecule('CC(C)c1ccc(OCC(=O)NC(=S)Nc2c3cccc4c3c(cc2)CC4)cc1',
'O=C(NC(=S)Nc1c2cccc3c2c(cc1)CC3)COc1ccccc1'),
TestMolecule('CN(C)c1ccc(NC(CN2CCC(C(c3ccc(F)cc3)=O)CC2)=O)cc1',
_TestMolecule('CN(C)c1ccc(NC(CN2CCC(C(c3ccc(F)cc3)=O)CC2)=O)cc1',
'c1cccc(c1)NC(CN1CCC(CC1)C(=O)c1ccccc1)=O'),
TestMolecule('CCCCN(C)C(=O)Cc1c(OC)ccc2cc(Br)ccc21', 'c1c2ccccc2ccc1'),
TestMolecule('Cc1ccc(NC(CSc2sc(NC(CN3CCOCC3)=O)nn2)=O)cc1',
_TestMolecule('CCCCN(C)C(=O)Cc1c(OC)ccc2cc(Br)ccc21', 'c1c2ccccc2ccc1'),
_TestMolecule('Cc1ccc(NC(CSc2sc(NC(CN3CCOCC3)=O)nn2)=O)cc1',
'O=C(Nc1ccccc1)CSc1sc(nn1)NC(=O)CN1CCOCC1'),
TestMolecule('COCCNC(=S)NNc1cccc(C(=O)O)c1', 'c1ccccc1'),
TestMolecule('O=C(CNc1ccccc1)NN=Cc1ccc2c(c1)OCCO2', 'O=C(CNc1ccccc1)NN=Cc1ccc2c(c1)OCCO2'),
TestMolecule('COc1cc2ccccc2cc1C(=O)NCC(c1sccc1)N(C)C', 'O=C(NCCc1sccc1)c1cc2c(cc1)cccc2'),
TestMolecule('COc1ccc(C(N(C)C)CNC(=O)CCOc2ccccc2)cc1', 'O=C(NCCc1ccccc1)CCOc1ccccc1'),
TestMolecule('Cl.CCN(CC)CCCN1C(=O)CSC1c1ccc([N+]([O-])=O)cc1', 'O=C1CSC(c2ccccc2)N1'),
TestMolecule('CCC(Nc1ccc(OC)cc1OC)=C1C(=O)NC(=O)NC1=O', 'c1cc(NC=C2C(=O)NC(=O)NC2=O)ccc1'),
TestMolecule('c1coc(-c2cc(C(F)(F)F)nc(NCc3ccc(F)cc3)n2)c1', 'c1ccc(CNc2nccc(n2)-c2occc2)cc1'),
TestMolecule('CCOC(Nc1sc(C)c(C)c1C(OCC)=O)=O', 'c1ccsc1'),
TestMolecule('O=CN1CCN(C(C(=O)NC2CCCCC2)c2cc3c(cc2[N+]([O-])=O)OCO3)CC1',
_TestMolecule('COCCNC(=S)NNc1cccc(C(=O)O)c1', 'c1ccccc1'),
_TestMolecule('O=C(CNc1ccccc1)NN=Cc1ccc2c(c1)OCCO2', 'O=C(CNc1ccccc1)NN=Cc1ccc2c(c1)OCCO2'),
_TestMolecule('COc1cc2ccccc2cc1C(=O)NCC(c1sccc1)N(C)C', 'O=C(NCCc1sccc1)c1cc2c(cc1)cccc2'),
_TestMolecule('COc1ccc(C(N(C)C)CNC(=O)CCOc2ccccc2)cc1', 'O=C(NCCc1ccccc1)CCOc1ccccc1'),
_TestMolecule('Cl.CCN(CC)CCCN1C(=O)CSC1c1ccc([N+]([O-])=O)cc1', 'O=C1CSC(c2ccccc2)N1'),
_TestMolecule('CCC(Nc1ccc(OC)cc1OC)=C1C(=O)NC(=O)NC1=O', 'c1cc(NC=C2C(=O)NC(=O)NC2=O)ccc1'),
_TestMolecule('c1coc(-c2cc(C(F)(F)F)nc(NCc3ccc(F)cc3)n2)c1', 'c1ccc(CNc2nccc(n2)-c2occc2)cc1'),
_TestMolecule('CCOC(Nc1sc(C)c(C)c1C(OCC)=O)=O', 'c1ccsc1'),
_TestMolecule('O=CN1CCN(C(C(=O)NC2CCCCC2)c2cc3c(cc2[N+]([O-])=O)OCO3)CC1',
'O=C(C(N1CCNCC1)c1ccc2c(c1)OCO2)NC1CCCCC1'),
TestMolecule('COc1cc(C2N(c3ccc(Br)cc3)C(=O)c3n[nH]c(C)c32)ccc1O',
_TestMolecule('COc1cc(C2N(c3ccc(Br)cc3)C(=O)c3n[nH]c(C)c32)ccc1O',
'O=C1c2n[nH]cc2C(N1c1ccccc1)c1ccccc1'),
TestMolecule('c1cc(NC(=O)c2ccccc2[N+]([O-])=O)c(N2CCOCC2)cc1',
_TestMolecule('c1cc(NC(=O)c2ccccc2[N+]([O-])=O)c(N2CCOCC2)cc1',
'O=C(Nc1c(cccc1)N1CCOCC1)c1ccccc1'),
TestMolecule('N#Cc1cc2c(nc1SCC(=O)N1CCCCC1)CCCCC2', 'O=C(N1CCCCC1)CSc1ccc2c(n1)CCCCC2'),
TestMolecule('CCN(CC)c1ccc(CN(C(=O)c2cc(OC)c(OC)c(OC)c2)C2CCS(=O)(=O)C2)cc1',
_TestMolecule('N#Cc1cc2c(nc1SCC(=O)N1CCCCC1)CCCCC2', 'O=C(N1CCCCC1)CSc1ccc2c(n1)CCCCC2'),
_TestMolecule('CCN(CC)c1ccc(CN(C(=O)c2cc(OC)c(OC)c(OC)c2)C2CCS(=O)(=O)C2)cc1',
'O=S1(=O)CCC(N(Cc2ccccc2)C(=O)c2ccccc2)C1'),
TestMolecule('COc1cc(NC(=S)N2CCN(Cc3ccccc3)CC2)cc(OC)c1', 'S=C(N1CCN(CC1)Cc1ccccc1)Nc1ccccc1'),
TestMolecule('CC(=O)C(=CNc1ccc(OCc2ccccc2)cc1)c1ccccc1', 'c1cccc(c1)COc1ccc(NC=Cc2ccccc2)cc1'),
TestMolecule('CC(C)C(C(NC(C)C(N)=O)=O)NC(C1CCCN1C(OC(C)(C)C)=O)=O', 'C1CCNC1'),
TestMolecule('CCOc1ccc(N2CC(C(=O)Nc3cccc(S(NC4=NCCC4)(=O)=O)c3)CC2=O)cc1',
_TestMolecule('COc1cc(NC(=S)N2CCN(Cc3ccccc3)CC2)cc(OC)c1', 'S=C(N1CCN(CC1)Cc1ccccc1)Nc1ccccc1'),
_TestMolecule('CC(=O)C(=CNc1ccc(OCc2ccccc2)cc1)c1ccccc1', 'c1cccc(c1)COc1ccc(NC=Cc2ccccc2)cc1'),
_TestMolecule('CC(C)C(C(NC(C)C(N)=O)=O)NC(C1CCCN1C(OC(C)(C)C)=O)=O', 'C1CCNC1'),
_TestMolecule('CCOc1ccc(N2CC(C(=O)Nc3cccc(S(NC4=NCCC4)(=O)=O)c3)CC2=O)cc1',
'c1cccc(c1)N1CC(C(=O)Nc2cccc(S(=O)(=O)NC3=NCCC3)c2)CC1=O'),
TestMolecule('O=C(NCc1ccccc1Cl)CSc1ccc(-c2cccs2)nn1', 'O=C(NCc1ccccc1)CSc1ccc(nn1)-c1sccc1'),
TestMolecule('COc1ccc(OC)c(N=c2ssnc2Cl)c1', 'c1cccc(c1)N=c1ssnc1'),
TestMolecule('CC(=O)C1=C(C)NC(=O)CC1c1c(Cl)cccc1', 'O=C1CC(C=CN1)c1ccccc1'),
TestMolecule('CCC(=O)N=C(N)Nc1nc(C)c2cc(C)c(C)cc2n1', 'c1cc2c(cc1)ncnc2'),
TestMolecule('Cc1ccccc1C(OC1OC(=O)C(Cl)=C1Nc1ccc(C(O)=O)cc1)=O',
_TestMolecule('O=C(NCc1ccccc1Cl)CSc1ccc(-c2cccs2)nn1', 'O=C(NCc1ccccc1)CSc1ccc(nn1)-c1sccc1'),
_TestMolecule('COc1ccc(OC)c(N=c2ssnc2Cl)c1', 'c1cccc(c1)N=c1ssnc1'),
_TestMolecule('CC(=O)C1=C(C)NC(=O)CC1c1c(Cl)cccc1', 'O=C1CC(C=CN1)c1ccccc1'),
_TestMolecule('CCC(=O)N=C(N)Nc1nc(C)c2cc(C)c(C)cc2n1', 'c1cc2c(cc1)ncnc2'),
_TestMolecule('Cc1ccccc1C(OC1OC(=O)C(Cl)=C1Nc1ccc(C(O)=O)cc1)=O',
'O=C(OC1OC(C=C1Nc1ccccc1)=O)c1ccccc1'),
TestMolecule('CCOc1cc(CN2CCC(CO)(Cc3cccc(C(F)(F)F)c3)CC2)ccc1OC',
_TestMolecule('CCOc1cc(CN2CCC(CO)(Cc3cccc(C(F)(F)F)c3)CC2)ccc1OC',
'c1ccc(cc1)CC1CCN(Cc2ccccc2)CC1'),
TestMolecule('Cc1cc2c([nH]c(=O)c(CCNC(c3cccs3)=O)c2)cc1C',
_TestMolecule('Cc1cc2c([nH]c(=O)c(CCNC(c3cccs3)=O)c2)cc1C',
'O=C(NCCc1cc2ccccc2[nH]c1=O)c1cccs1'),
TestMolecule('Cc1ccc(Nc2cc(=O)[nH]c(=O)[nH]2)cc1C', 'c1cccc(c1)Nc1cc([nH]c([nH]1)=O)=O'),
TestMolecule('Cc1cc(OCC(=O)NC2CCS(=O)(=O)C2)c2c(oc(=O)c3c2CCC3)c1',
_TestMolecule('Cc1ccc(Nc2cc(=O)[nH]c(=O)[nH]2)cc1C', 'c1cccc(c1)Nc1cc([nH]c([nH]1)=O)=O'),
_TestMolecule('Cc1cc(OCC(=O)NC2CCS(=O)(=O)C2)c2c(oc(=O)c3c2CCC3)c1',
'O=C(NC1CCS(=O)(C1)=O)COc1c2c(ccc1)oc(c1c2CCC1)=O'),
TestMolecule('CCc1sc(NC(CCC(NCCc2ccc(OC)c(OC)c2)=O)=O)nn1',
_TestMolecule('CCc1sc(NC(CCC(NCCc2ccc(OC)c(OC)c2)=O)=O)nn1',
'c1cc(ccc1)CCNC(=O)CCC(=O)Nc1scnn1'),
TestMolecule('N#CC1=C(SCc2ccccc2)NC(=O)CC1c1ccc(O)cc1', 'O=C1NC(=CC(C1)c1ccccc1)SCc1ccccc1'),
TestMolecule('O=C(NCCN1CCOCC1)c1csc2c1CCCC2', 'O=C(NCCN1CCOCC1)c1csc2c1CCCC2'),
TestMolecule('CCCCC(=O)Nc1cc(OC)c(NC(C2CCCCC2)=O)cc1OC', 'O=C(Nc1ccccc1)C1CCCCC1'),
TestMolecule('Cc1ccc(C(C(C)OC(C2CC(=O)N(C3CCCCC3)C2)=O)=O)cc1',
_TestMolecule('N#CC1=C(SCc2ccccc2)NC(=O)CC1c1ccc(O)cc1', 'O=C1NC(=CC(C1)c1ccccc1)SCc1ccccc1'),
_TestMolecule('O=C(NCCN1CCOCC1)c1csc2c1CCCC2', 'O=C(NCCN1CCOCC1)c1csc2c1CCCC2'),
_TestMolecule('CCCCC(=O)Nc1cc(OC)c(NC(C2CCCCC2)=O)cc1OC', 'O=C(Nc1ccccc1)C1CCCCC1'),
_TestMolecule('Cc1ccc(C(C(C)OC(C2CC(=O)N(C3CCCCC3)C2)=O)=O)cc1',
'c1cc(C(=O)COC(C2CC(=O)N(C2)C2CCCCC2)=O)ccc1'),
TestMolecule('Cc1ccc(S(C(C#N)c2c(N3CCCC3)nc3ccccc3n2)(=O)=O)cc1C',
_TestMolecule('Cc1ccc(S(C(C#N)c2c(N3CCCC3)nc3ccccc3n2)(=O)=O)cc1C',
'c1ccc(cc1)S(=O)(=O)Cc1c(nc2ccccc2n1)N1CCCC1'),
TestMolecule('CC1(C)OC(=O)C(=Cc2[nH]ccc2)C(=O)O1', 'O=C1OCOC(=O)C1=Cc1[nH]ccc1'),
TestMolecule('Cc1cc(C)cc(Oc2nc3n(cccc3C)c(=O)c2C=C(C#N)C(=O)NC2CCS(=O)(=O)C2)c1',
_TestMolecule('CC1(C)OC(=O)C(=Cc2[nH]ccc2)C(=O)O1', 'O=C1OCOC(=O)C1=Cc1[nH]ccc1'),
_TestMolecule('Cc1cc(C)cc(Oc2nc3n(cccc3C)c(=O)c2C=C(C#N)C(=O)NC2CCS(=O)(=O)C2)c1',
'c1ccc(cc1)Oc1c(c(=O)n2ccccc2n1)C=CC(=O)NC1CCS(=O)(=O)C1'),
TestMolecule('COc1cc(NC(=O)NCc2c(C)onc2-c2ccccc2)ccc1', 'O=C(NCc1conc1-c1ccccc1)Nc1ccccc1'),
TestMolecule('c1ccc(C(Oc2cc3c(cc2)C(=O)CO3)=O)cc1', 'c1ccc(C(Oc2cc3c(cc2)C(=O)CO3)=O)cc1'),
TestMolecule('CCN1C(=O)C2C(c3cccs3)N3C4C(=O)N(CC)C(=O)C4C(c4cccs4)N3C2C1=O',
_TestMolecule('COc1cc(NC(=O)NCc2c(C)onc2-c2ccccc2)ccc1', 'O=C(NCc1conc1-c1ccccc1)Nc1ccccc1'),
_TestMolecule('c1ccc(C(Oc2cc3c(cc2)C(=O)CO3)=O)cc1', 'c1ccc(C(Oc2cc3c(cc2)C(=O)CO3)=O)cc1'),
_TestMolecule('CCN1C(=O)C2C(c3cccs3)N3C4C(=O)N(CC)C(=O)C4C(c4cccs4)N3C2C1=O',
'c1cc(sc1)C1C2C(NC(=O)C2N2N1C1C(=O)NC(=O)C1C2c1cccs1)=O'),
TestMolecule('Cc1cc(C(N2CCCC(C(c3cc(F)ccc3F)=O)C2)=O)c(C)o1',
_TestMolecule('Cc1cc(C(N2CCCC(C(c3cc(F)ccc3F)=O)C2)=O)c(C)o1',
'O=C(N1CCCC(C(=O)c2ccccc2)C1)c1cocc1'),
TestMolecule('COc1cc(C=NO)ccc1Oc1c([N+]([O-])=O)cc([N+]([O-])=O)cc1', 'c1cccc(Oc2ccccc2)c1'),
TestMolecule('Cc1ccc(N(Cc2c(=O)[nH]c3ccc(C)cc3c2)C(c2cccs2)=O)cc1',
_TestMolecule('COc1cc(C=NO)ccc1Oc1c([N+]([O-])=O)cc([N+]([O-])=O)cc1', 'c1cccc(Oc2ccccc2)c1'),
_TestMolecule('Cc1ccc(N(Cc2c(=O)[nH]c3ccc(C)cc3c2)C(c2cccs2)=O)cc1',
'O=C(N(c1ccccc1)Cc1c([nH]c2c(cccc2)c1)=O)c1cccs1'),
TestMolecule('COc1ccc(C(=O)Nn2c(C)nnc2-n2c(C)cc(C)n2)cc1OC', 'O=C(c1ccccc1)Nn1cnnc1-n1nccc1'),
TestMolecule('Cc1c(NC(=O)c2c(C)c(Cl)c(C)nc2Cl)cccc1', 'O=C(c1cccnc1)Nc1ccccc1'),
TestMolecule('c1ccc(CNC(CC(C(=O)NCc2ccccc2)c2nc(=O)c3ccccc3[nH]2)=O)cc1',
_TestMolecule('COc1ccc(C(=O)Nn2c(C)nnc2-n2c(C)cc(C)n2)cc1OC', 'O=C(c1ccccc1)Nn1cnnc1-n1nccc1'),
_TestMolecule('Cc1c(NC(=O)c2c(C)c(Cl)c(C)nc2Cl)cccc1', 'O=C(c1cccnc1)Nc1ccccc1'),
_TestMolecule('c1ccc(CNC(CC(C(=O)NCc2ccccc2)c2nc(=O)c3ccccc3[nH]2)=O)cc1',
'c1ccc(CNC(CC(C(=O)NCc2ccccc2)c2nc(=O)c3ccccc3[nH]2)=O)cc1'),
TestMolecule('CNc1n(-c2ccccc2)ncc1[N+](=O)[O-]', 'c1n(ncc1)-c1ccccc1'),
TestMolecule('CC1SC2(NC1=O)C1CC3CC(C1)CC2C3', 'O=C1CSC2(N1)C1CC3CC(C1)CC2C3'),
TestMolecule('CCc1ccccc1NC(=S)N(C(C)c1occc1)CCOC', 'S=C(NCc1occc1)Nc1ccccc1'),
TestMolecule('CCC(C)NC(=O)C1CCCN(S(c2ccc(-n3cnnn3)cc2)(=O)=O)C1',
_TestMolecule('CNc1n(-c2ccccc2)ncc1[N+](=O)[O-]', 'c1n(ncc1)-c1ccccc1'),
_TestMolecule('CC1SC2(NC1=O)C1CC3CC(C1)CC2C3', 'O=C1CSC2(N1)C1CC3CC(C1)CC2C3'),
_TestMolecule('CCc1ccccc1NC(=S)N(C(C)c1occc1)CCOC', 'S=C(NCc1occc1)Nc1ccccc1'),
_TestMolecule('CCC(C)NC(=O)C1CCCN(S(c2ccc(-n3cnnn3)cc2)(=O)=O)C1',
'C1CCN(CC1)S(=O)(=O)c1ccc(cc1)-n1nnnc1'),
TestMolecule('COc1c2c(ccc1)C1CC(C)(O2)N(Cc2ccccc2)C(=O)N1', 'O=C1NC2CC(Oc3ccccc32)N1Cc1ccccc1'),
TestMolecule('COc1ccc(C2NC(=O)c3c(cccc3)O2)c(OC)c1OC', 'O=C1NC(Oc2c1cccc2)c1ccccc1'),
TestMolecule('O=C(NNC=C1C=Nc2ccccc21)c1ccn(Cc2c(Cl)cc(Cl)cc2)n1',
_TestMolecule('COc1c2c(ccc1)C1CC(C)(O2)N(Cc2ccccc2)C(=O)N1', 'O=C1NC2CC(Oc3ccccc32)N1Cc1ccccc1'),
_TestMolecule('COc1ccc(C2NC(=O)c3c(cccc3)O2)c(OC)c1OC', 'O=C1NC(Oc2c1cccc2)c1ccccc1'),
_TestMolecule('O=C(NNC=C1C=Nc2ccccc21)c1ccn(Cc2c(Cl)cc(Cl)cc2)n1',
'O=C(NNC=C1c2c(cccc2)N=C1)c1nn(cc1)Cc1ccccc1'),
TestMolecule('c1ccc(NS(c2ccc(OCC(=O)NCc3cnccc3)cc2)(=O)=O)cc1',
_TestMolecule('c1ccc(NS(c2ccc(OCC(=O)NCc3cnccc3)cc2)(=O)=O)cc1',
'c1ccc(NS(c2ccc(OCC(=O)NCc3cnccc3)cc2)(=O)=O)cc1'),
TestMolecule('COC1=CC(=O)C(=C2NNC(C(F)(F)F)=C2c2cc3ccccc3o2)C=C1',
_TestMolecule('COC1=CC(=O)C(=C2NNC(C(F)(F)F)=C2c2cc3ccccc3o2)C=C1',
'O=C1C=CC=CC1=C1NNC=C1c1cc2ccccc2o1'),
TestMolecule('CCOC(=O)c1c(C(COC(C=Cc2ccc(Cl)cc2)=O)=O)c(C)[nH]c1C',
_TestMolecule('CCOC(=O)c1c(C(COC(C=Cc2ccc(Cl)cc2)=O)=O)c(C)[nH]c1C',
'c1ccc(C=CC(OCC(=O)c2cc[nH]c2)=O)cc1'),
TestMolecule('Cc1nc2ncnn2c(N2CCN(c3nnnn3-c3ccccc3)CC2)c1',
_TestMolecule('Cc1nc2ncnn2c(N2CCN(c3nnnn3-c3ccccc3)CC2)c1',
'c1nc2ncnn2c(c1)N1CCN(c2nnnn2-c2ccccc2)CC1'),
TestMolecule('CC(C)Oc1ccc(C(=O)Nc2ccc(NC(c3ccco3)=O)c(Cl)c2)cc1',
_TestMolecule('CC(C)Oc1ccc(C(=O)Nc2ccc(NC(c3ccco3)=O)c(Cl)c2)cc1',
'O=C(Nc1ccc(cc1)NC(=O)c1ccccc1)c1occc1'),
TestMolecule('CC(c1ccccc1)NC(C(NCC1OCCC1)=O)=O', 'O=C(NCc1ccccc1)C(=O)NCC1OCCC1'),
TestMolecule('CCCCOc1ccc(NC(=O)CCSc2nccn2C)cc1', 'O=C(Nc1ccccc1)CCSc1ncc[nH]1'),
TestMolecule('O=C(OCc1ncccc1)c1oc(COc2c(Cl)cccc2)cc1', 'O=C(OCc1ncccc1)c1ccc(o1)COc1ccccc1'),
TestMolecule('COc1ccc(C=NNC(=O)OC(C)(C)C)cc1OC', 'c1ccccc1'),
TestMolecule('CC1CCCCC1NC(COC(c1ccc(S(NCc2ccco2)(=O)=O)cc1)=O)=O',
_TestMolecule('CC(c1ccccc1)NC(C(NCC1OCCC1)=O)=O', 'O=C(NCc1ccccc1)C(=O)NCC1OCCC1'),
_TestMolecule('CCCCOc1ccc(NC(=O)CCSc2nccn2C)cc1', 'O=C(Nc1ccccc1)CCSc1ncc[nH]1'),
_TestMolecule('O=C(OCc1ncccc1)c1oc(COc2c(Cl)cccc2)cc1', 'O=C(OCc1ncccc1)c1ccc(o1)COc1ccccc1'),
_TestMolecule('COc1ccc(C=NNC(=O)OC(C)(C)C)cc1OC', 'c1ccccc1'),
_TestMolecule('CC1CCCCC1NC(COC(c1ccc(S(NCc2ccco2)(=O)=O)cc1)=O)=O',
'c1coc(c1)CNS(=O)(=O)c1ccc(cc1)C(=O)OCC(=O)NC1CCCCC1'),
TestMolecule('Nn1c(SCC(=O)Nc2cccc(F)c2)nnc1C1CCCCC1', 'O=C(CSc1[nH]c(nn1)C1CCCCC1)Nc1ccccc1'),
TestMolecule('Cc1n[nH]c(NC2CCCCC2)nc1=O', 'O=c1cn[nH]c(n1)NC1CCCCC1'),
TestMolecule('CCCCCCCCC(=O)NC(C(Cl)(Cl)Cl)NC(=S)N1CCOCC1', 'C1NCCOC1'),
TestMolecule('CCCc1ccc(Oc2coc3cc(OCC(Nc4c(C)cccc4)=O)ccc3c2=O)cc1',
_TestMolecule('Nn1c(SCC(=O)Nc2cccc(F)c2)nnc1C1CCCCC1', 'O=C(CSc1[nH]c(nn1)C1CCCCC1)Nc1ccccc1'),
_TestMolecule('Cc1n[nH]c(NC2CCCCC2)nc1=O', 'O=c1cn[nH]c(n1)NC1CCCCC1'),
_TestMolecule('CCCCCCCCC(=O)NC(C(Cl)(Cl)Cl)NC(=S)N1CCOCC1', 'C1NCCOC1'),
_TestMolecule('CCCc1ccc(Oc2coc3cc(OCC(Nc4c(C)cccc4)=O)ccc3c2=O)cc1',
'c1cccc(c1)Oc1c(c2ccc(cc2oc1)OCC(=O)Nc1ccccc1)=O'),
TestMolecule('Cc1ccc(C(=O)NN=C2CCSC2)cc1[N+]([O-])=O', 'O=C(NN=C1CCSC1)c1ccccc1'),
TestMolecule('N#CC1=C2SCN(c3ccc(F)cc3)CN2C(=O)CC1c1cc(F)ccc1',
_TestMolecule('Cc1ccc(C(=O)NN=C2CCSC2)cc1[N+]([O-])=O', 'O=C(NN=C1CCSC1)c1ccccc1'),
_TestMolecule('N#CC1=C2SCN(c3ccc(F)cc3)CN2C(=O)CC1c1cc(F)ccc1',
'O=C1N2CN(c3ccccc3)CSC2=CC(c2ccccc2)C1'),
TestMolecule('c1ccc(CN2C(=O)CC(Nc3cc4c(cc3)cccc4)C2=O)cc1',
_TestMolecule('c1ccc(CN2C(=O)CC(Nc3cc4c(cc3)cccc4)C2=O)cc1',
'c1ccc(CN2C(=O)CC(Nc3cc4c(cc3)cccc4)C2=O)cc1'),
TestMolecule('COc1ccc(NC(C)=O)cc1NC(=O)CN1CCN(CC(=O)Nc2ccc(Cl)cc2)CC1',
_TestMolecule('COc1ccc(NC(C)=O)cc1NC(=O)CN1CCN(CC(=O)Nc2ccc(Cl)cc2)CC1',
'O=C(Nc1ccccc1)CN1CCN(CC1)CC(=O)Nc1ccccc1'),
TestMolecule('Clc1c(Cl)c(C2NC(=O)CCC2[N+]([O-])=O)ccc1', 'O=C1NC(CCC1)c1ccccc1'),
TestMolecule('CCN(C(=O)CSc1n(-c2ccccc2)c(-c2ccccc2)nn1)CC', 'c1ccc(cc1)-n1cnnc1-c1ccccc1'),
TestMolecule('CC(=O)CCCCn1cnc2n(C)c(=O)n(C)c(=O)c12', 'O=c1[nH]c(c2c(nc[nH]2)[nH]1)=O'),
TestMolecule('CC1=NN(c2ccccc2)C(=N)C1=NNc1ccc(Cl)cc1', 'N=C1C(=NNc2ccccc2)C=NN1c1ccccc1'),
TestMolecule('CCc1ccc(OCC(=O)N(CC)CC)cc1', 'c1ccccc1'),
TestMolecule('CN(CC(=O)N1CCCCC1)S(c1ccc(Cl)cc1)(=O)=O', 'O=C(CNS(=O)(=O)c1ccccc1)N1CCCCC1'),
TestMolecule('CSc1ncc(C=C2C(=O)NC(=O)N(c3ccc(C)cc3)C2=O)cn1',
_TestMolecule('Clc1c(Cl)c(C2NC(=O)CCC2[N+]([O-])=O)ccc1', 'O=C1NC(CCC1)c1ccccc1'),
_TestMolecule('CCN(C(=O)CSc1n(-c2ccccc2)c(-c2ccccc2)nn1)CC', 'c1ccc(cc1)-n1cnnc1-c1ccccc1'),
_TestMolecule('CC(=O)CCCCn1cnc2n(C)c(=O)n(C)c(=O)c12', 'O=c1[nH]c(c2c(nc[nH]2)[nH]1)=O'),
_TestMolecule('CC1=NN(c2ccccc2)C(=N)C1=NNc1ccc(Cl)cc1', 'N=C1C(=NNc2ccccc2)C=NN1c1ccccc1'),
_TestMolecule('CCc1ccc(OCC(=O)N(CC)CC)cc1', 'c1ccccc1'),
_TestMolecule('CN(CC(=O)N1CCCCC1)S(c1ccc(Cl)cc1)(=O)=O', 'O=C(CNS(=O)(=O)c1ccccc1)N1CCCCC1'),
_TestMolecule('CSc1ncc(C=C2C(=O)NC(=O)N(c3ccc(C)cc3)C2=O)cn1',
'c1ccc(N2C(NC(=O)C(=Cc3cncnc3)C2=O)=O)cc1'),
TestMolecule('COCCNC(=S)Nc1c(Cc2ccccc2)cccc1', 'c1ccc(Cc2ccccc2)cc1'),
TestMolecule('COc1cc(C(=O)Nc2nnc(C(C)(C)C)s2)c([N+]([O-])=O)cc1OC', 'O=C(Nc1nncs1)c1ccccc1'),
TestMolecule('CCOC(=O)c1ccc(NC(=O)c2cc(OC)c(OC(C)C)cc2)cc1', 'O=C(Nc1ccccc1)c1ccccc1'),
TestMolecule('COc1ccc(C(=O)C=C2Sc3cc4c(cc3N2C)OCO4)cc1', 'O=C(C=C1Sc2cc3c(cc2N1)OCO3)c1ccccc1'),
TestMolecule('CCCC1=NN(c2sc3c(n2)cccc3)C(=O)C1=CNCCCN(CC)CC', 'C=C1C=NN(C1=O)c1sc2ccccc2n1'),
TestMolecule('COc1ccc(C(COC(CN2C(=O)NC(C)(C)C2=O)=O)=O)cc1OC',
_TestMolecule('COCCNC(=S)Nc1c(Cc2ccccc2)cccc1', 'c1ccc(Cc2ccccc2)cc1'),
_TestMolecule('COc1cc(C(=O)Nc2nnc(C(C)(C)C)s2)c([N+]([O-])=O)cc1OC', 'O=C(Nc1nncs1)c1ccccc1'),
_TestMolecule('CCOC(=O)c1ccc(NC(=O)c2cc(OC)c(OC(C)C)cc2)cc1', 'O=C(Nc1ccccc1)c1ccccc1'),
_TestMolecule('COc1ccc(C(=O)C=C2Sc3cc4c(cc3N2C)OCO4)cc1', 'O=C(C=C1Sc2cc3c(cc2N1)OCO3)c1ccccc1'),
_TestMolecule('CCCC1=NN(c2sc3c(n2)cccc3)C(=O)C1=CNCCCN(CC)CC', 'C=C1C=NN(C1=O)c1sc2ccccc2n1'),
_TestMolecule('COc1ccc(C(COC(CN2C(=O)NC(C)(C)C2=O)=O)=O)cc1OC',
'c1ccc(C(=O)COC(=O)CN2C(=O)CNC2=O)cc1'),
TestMolecule('O=C(Oc1ccc(Br)cc1)C1CC(=O)N(c2ccc(F)cc2)C1',
_TestMolecule('O=C(Oc1ccc(Br)cc1)C1CC(=O)N(c2ccc(F)cc2)C1',
'O=C(C1CC(N(C1)c1ccccc1)=O)Oc1ccccc1'),
TestMolecule('O=c1nc(-c2ccccn2)[nH]c(C(F)(F)F)c1Br', 'O=c1cc[nH]c(-c2ncccc2)n1'),
TestMolecule('CCOC(c1oc2ccccc2c1NC(CN1CCN(C)CC1)=O)=O', 'O=C(CN1CCNCC1)Nc1coc2ccccc21'),
TestMolecule('CSc1nsc(NN=Cc2ccc3c(c2)OCO3)c1C#N', 'c1cc(sn1)NN=Cc1ccc2OCOc2c1'),
TestMolecule('CC(C)(C)NC(NC(CSc1nc(C)c(C)c(C)n1)=O)=O', 'c1cncnc1'),
TestMolecule('Cc1cccnc1CN1CCN(Cc2onc(C(c3ccccc3)c3ccccc3)n2)CC1',
_TestMolecule('O=c1nc(-c2ccccn2)[nH]c(C(F)(F)F)c1Br', 'O=c1cc[nH]c(-c2ncccc2)n1'),
_TestMolecule('CCOC(c1oc2ccccc2c1NC(CN1CCN(C)CC1)=O)=O', 'O=C(CN1CCNCC1)Nc1coc2ccccc21'),
_TestMolecule('CSc1nsc(NN=Cc2ccc3c(c2)OCO3)c1C#N', 'c1cc(sn1)NN=Cc1ccc2OCOc2c1'),
_TestMolecule('CC(C)(C)NC(NC(CSc1nc(C)c(C)c(C)n1)=O)=O', 'c1cncnc1'),
_TestMolecule('Cc1cccnc1CN1CCN(Cc2onc(C(c3ccccc3)c3ccccc3)n2)CC1',
'c1cccnc1CN1CCN(CC1)Cc1onc(n1)C(c1ccccc1)c1ccccc1'),
TestMolecule('COc1ccc(Nc2oc3cc(=O)ccc-3cc2C(=O)Nc2ncccc2)cc1OC',
_TestMolecule('COc1ccc(Nc2oc3cc(=O)ccc-3cc2C(=O)Nc2ncccc2)cc1OC',
'c1ccc(cc1)Nc1oc2-c(ccc(c2)=O)cc1C(Nc1ncccc1)=O'),
TestMolecule('c1cc(C)c(OCC(NS(c2ccc(C)cc2)(=O)=O)=O)cc1', 'O=C(COc1ccccc1)NS(=O)(=O)c1ccccc1'),
TestMolecule('CCOc1ccc(-c2scc(CSc3sc(N)nn3)n2)cc1OC', 'c1cccc(c1)-c1nc(cs1)CSc1scnn1'),
TestMolecule('c1ccc(C(=O)COC(=O)CN2C(=O)C3C4CC(C3C2=O)C=C4)cc1',
_TestMolecule('c1cc(C)c(OCC(NS(c2ccc(C)cc2)(=O)=O)=O)cc1', 'O=C(COc1ccccc1)NS(=O)(=O)c1ccccc1'),
_TestMolecule('CCOc1ccc(-c2scc(CSc3sc(N)nn3)n2)cc1OC', 'c1cccc(c1)-c1nc(cs1)CSc1scnn1'),
_TestMolecule('c1ccc(C(=O)COC(=O)CN2C(=O)C3C4CC(C3C2=O)C=C4)cc1',
'c1ccc(C(=O)COC(=O)CN2C(=O)C3C4CC(C3C2=O)C=C4)cc1'),
TestMolecule('Cc1occc1C(=O)NC(C)c1ccc2c(c1)OCO2', 'O=C(NCc1ccc2c(c1)OCO2)c1ccoc1'),
TestMolecule('CCn1c(SCC(=O)Nc2c(Cl)nccc2)nnc1-c1ccccc1',
_TestMolecule('Cc1occc1C(=O)NC(C)c1ccc2c(c1)OCO2', 'O=C(NCc1ccc2c(c1)OCO2)c1ccoc1'),
_TestMolecule('CCn1c(SCC(=O)Nc2c(Cl)nccc2)nnc1-c1ccccc1',
'O=C(Nc1cnccc1)CSc1[nH]c(nn1)-c1ccccc1'),
TestMolecule('CCC(C)N(C)C1CCN(C(=S)Nc2cc(OC)ccc2)CC1', 'S=C(Nc1ccccc1)N1CCCCC1'),
TestMolecule('Brc1oc(C(=O)N2CC(=O)Nc3c(cc(Br)cc3)C2c2ccccc2)cc1',
_TestMolecule('CCC(C)N(C)C1CCN(C(=S)Nc2cc(OC)ccc2)CC1', 'S=C(Nc1ccccc1)N1CCCCC1'),
_TestMolecule('Brc1oc(C(=O)N2CC(=O)Nc3c(cc(Br)cc3)C2c2ccccc2)cc1',
'O=C(N1CC(Nc2ccccc2C1c1ccccc1)=O)c1occc1'),
TestMolecule('CN(C(=O)CCSc1nc(-c2cc3c(cc2)OCO3)cc(C(F)(F)F)n1)Cc1ccccc1',
_TestMolecule('CN(C(=O)CCSc1nc(-c2cc3c(cc2)OCO3)cc(C(F)(F)F)n1)Cc1ccccc1',
'O=C(NCc1ccccc1)CCSc1nc(ccn1)-c1cc2c(cc1)OCO2'),
TestMolecule('[Br-].COc1c(OC)c(OC)cc(-c2nc3c[n+](CC(=O)c4ccccc4)ccc3n2C)c1',
_TestMolecule('[Br-].COc1c(OC)c(OC)cc(-c2nc3c[n+](CC(=O)c4ccccc4)ccc3n2C)c1',
'O=C(C[n+]1cc2nc([nH]c2cc1)-c1ccccc1)c1ccccc1'),
TestMolecule('CCOC(CSc1n(-c2c(OC)cccc2)c(CNC(Cc2ccccc2)=O)nn1)=O',
_TestMolecule('CCOC(CSc1n(-c2c(OC)cccc2)c(CNC(Cc2ccccc2)=O)nn1)=O',
'O=C(Cc1ccccc1)NCc1n(cnn1)-c1ccccc1'),
TestMolecule('CS(N(Cc1ccccc1)c1ccc(C(Nc2c(Sc3ccccc3)cccc2)=O)cc1)(=O)=O',
_TestMolecule('CS(N(Cc1ccccc1)c1ccc(C(Nc2c(Sc3ccccc3)cccc2)=O)cc1)(=O)=O',
'O=C(c1ccc(NCc2ccccc2)cc1)Nc1c(cccc1)Sc1ccccc1'),
TestMolecule('Cc1nc(C2N(C(=O)c3cn(C)c4c(c3=O)cccc4)CCc3c4c([nH]c32)cccc4)ccc1',
_TestMolecule('Cc1nc(C2N(C(=O)c3cn(C)c4c(c3=O)cccc4)CCc3c4c([nH]c32)cccc4)ccc1',
'O=C(c1c[nH]c2c(cccc2)c1=O)N1C(c2ncccc2)c2[nH]c3ccccc3c2CC1'),
TestMolecule('CCCCc1nc(N2CCOCC2)c(C#N)c2c1CCCC2', 'c1nc(cc2c1CCCC2)N1CCOCC1'),
TestMolecule('O=C(NN=Cc1cc([N+]([O-])=O)ccc1Cl)c1nccnc1', 'O=C(NN=Cc1ccccc1)c1nccnc1'),
TestMolecule('COc1ccc(-n2c(SCC(=O)c3ccc4c(c3)OCCO4)nnn2)cc1',
_TestMolecule('CCCCc1nc(N2CCOCC2)c(C#N)c2c1CCCC2', 'c1nc(cc2c1CCCC2)N1CCOCC1'),
_TestMolecule('O=C(NN=Cc1cc([N+]([O-])=O)ccc1Cl)c1nccnc1', 'O=C(NN=Cc1ccccc1)c1nccnc1'),
_TestMolecule('COc1ccc(-n2c(SCC(=O)c3ccc4c(c3)OCCO4)nnn2)cc1',
'O=C(c1ccc2c(c1)OCCO2)CSc1n(nnn1)-c1ccccc1'),
TestMolecule('COc1c(C=CC(=O)Nc2cc(S(NC3=NCCCCC3)(=O)=O)ccc2)cccc1',
_TestMolecule('COc1c(C=CC(=O)Nc2cc(S(NC3=NCCCCC3)(=O)=O)ccc2)cccc1',
'O=C(Nc1cc(ccc1)S(=O)(=O)NC1=NCCCCC1)C=Cc1ccccc1'),
TestMolecule('Cc1nn(-c2ccc(F)cc2)c(Cl)c1C=C(CC(=O)O)c1sc2ccccc2n1',
_TestMolecule('Cc1nn(-c2ccc(F)cc2)c(Cl)c1C=C(CC(=O)O)c1sc2ccccc2n1',
'c1cc2sc(nc2cc1)C=Cc1cn(nc1)-c1ccccc1'),
TestMolecule('COc1c(OC)c(OC)cc(C2N(c3ccccc3)OC3C2C(=O)N(Cc2ccccc2)C3=O)c1',
_TestMolecule('COc1c(OC)c(OC)cc(C2N(c3ccccc3)OC3C2C(=O)N(Cc2ccccc2)C3=O)c1',
'c1cccc(c1)CN1C(=O)C2C(N(OC2C1=O)c1ccccc1)c1ccccc1'),
TestMolecule('COCCNC(=S)Nc1cc(OC)c(NC(=O)c2ccco2)cc1OC', 'O=C(Nc1ccccc1)c1occc1'),
TestMolecule('N#Cc1c(SCC(=O)c2cc3c(oc2=O)cccc3)nc(-c2ccccc2)cc1',
_TestMolecule('COCCNC(=S)Nc1cc(OC)c(NC(=O)c2ccco2)cc1OC', 'O=C(Nc1ccccc1)c1occc1'),
_TestMolecule('N#Cc1c(SCC(=O)c2cc3c(oc2=O)cccc3)nc(-c2ccccc2)cc1',
'O=C(c1cc2c(cccc2)oc1=O)CSc1cccc(n1)-c1ccccc1'),
TestMolecule('O=C(N1CCCC1)c1nc2ccccn2c1CN1CCCC(OCc2ccccc2)C1',
_TestMolecule('O=C(N1CCCC1)c1nc2ccccn2c1CN1CCCC(OCc2ccccc2)C1',
'O=C(N1CCCC1)c1nc2ccccn2c1CN1CCCC(OCc2ccccc2)C1'),
TestMolecule('Brc1cccc(OCCSc2ncccn2)c1', 'c1cccc(c1)OCCSc1ncccn1'),
TestMolecule('CC(C)(C)NC(=O)C12CCC(C)(C1(C)C)c1nc3ccccc3nc12', 'c1cccc2nc3C4CC(CC4)c3nc12'),
TestMolecule('[I-].CC(C)C1C(OCC(O)C[N+]2(C)CCCCC2)CC(C)CC1', 'C1CC[NH+](CC1)CCCOC1CCCCC1'),
TestMolecule('Cc1ccccc1NS(=O)(=O)c1ccc(OCC(=O)N2CCCCC2)cc1',
_TestMolecule('Brc1cccc(OCCSc2ncccn2)c1', 'c1cccc(c1)OCCSc1ncccn1'),
_TestMolecule('CC(C)(C)NC(=O)C12CCC(C)(C1(C)C)c1nc3ccccc3nc12', 'c1cccc2nc3C4CC(CC4)c3nc12'),
_TestMolecule('[I-].CC(C)C1C(OCC(O)C[N+]2(C)CCCCC2)CC(C)CC1', 'C1CC[NH+](CC1)CCCOC1CCCCC1'),
_TestMolecule('Cc1ccccc1NS(=O)(=O)c1ccc(OCC(=O)N2CCCCC2)cc1',
'c1cc(ccc1)NS(=O)(=O)c1ccc(cc1)OCC(=O)N1CCCCC1'),
TestMolecule('Cc1cc(NC(=O)CSc2nc3c(c(=O)n2-c2ccc(Br)cc2)SCC3)no1',
_TestMolecule('Cc1cc(NC(=O)CSc2nc3c(c(=O)n2-c2ccc(Br)cc2)SCC3)no1',
'O=C(CSc1nc2c(c(n1-c1ccccc1)=O)SCC2)Nc1ccon1'),
TestMolecule('Cc1ccccc1C(NC(C(C)C)C(OCC(c1[nH]ccc1)=O)=O)=O',
_TestMolecule('Cc1ccccc1C(NC(C(C)C)C(OCC(c1[nH]ccc1)=O)=O)=O',
'c1cc([nH]c1)C(COC(CNC(=O)c1ccccc1)=O)=O'),
TestMolecule('Cc1ccnc(NS(c2ccc(NS(C)(=O)=O)cc2)(=O)=O)n1', 'c1ccc(S(=O)(=O)Nc2ncccn2)cc1'),
TestMolecule('Cn1c(-c2ccc(Cl)cc2)cnc1NCc1cc2c(cc1[N+]([O-])=O)OCO2.OC(=O)C(O)=O',
_TestMolecule('Cc1ccnc(NS(c2ccc(NS(C)(=O)=O)cc2)(=O)=O)n1', 'c1ccc(S(=O)(=O)Nc2ncccn2)cc1'),
_TestMolecule('Cn1c(-c2ccc(Cl)cc2)cnc1NCc1cc2c(cc1[N+]([O-])=O)OCO2.OC(=O)C(O)=O',
'c1cc(ccc1)-c1[nH]c(nc1)NCc1cc2c(cc1)OCO2'),
TestMolecule('CC1Cc2ccccc2N1C(=O)CON=Cc1ccc(OC(F)F)cc1', 'O=C(CON=Cc1ccccc1)N1CCc2c1cccc2'),
TestMolecule('C=C1C(=O)OC2C(O)C(C)=CC(=O)C=C(C)CC(OC(C(C)=CC)=O)C12',
_TestMolecule('CC1Cc2ccccc2N1C(=O)CON=Cc1ccc(OC(F)F)cc1', 'O=C(CON=Cc1ccccc1)N1CCc2c1cccc2'),
_TestMolecule('C=C1C(=O)OC2C(O)C(C)=CC(=O)C=C(C)CC(OC(C(C)=CC)=O)C12',
'C=C1C2CCC=CC(C=CCC2OC1=O)=O'),
TestMolecule('O=C1C2N(CSC2)c2c(cc(C(F)(F)F)cc2)N1Cc1cccc(F)c1',
_TestMolecule('O=C1C2N(CSC2)c2c(cc(C(F)(F)F)cc2)N1Cc1cccc(F)c1',
'O=C1C2N(CSC2)c2ccccc2N1Cc1ccccc1'),
TestMolecule('Cc1ccc(OCC(=O)Nc2c[nH]c(=O)[nH]c2=O)cc1C',
_TestMolecule('Cc1ccc(OCC(=O)Nc2c[nH]c(=O)[nH]c2=O)cc1C',
'O=C(COc1ccccc1)Nc1c[nH]c([nH]c1=O)=O'),
TestMolecule('Cn1c(CN2CCOCC2)nc2cc(NC(=O)c3ccccc3Cl)ccc12',
_TestMolecule('Cn1c(CN2CCOCC2)nc2cc(NC(=O)c3ccccc3Cl)ccc12',
'O=C(c1ccccc1)Nc1ccc2[nH]c(nc2c1)CN1CCOCC1'),
TestMolecule('O=c1oc2ccc(O)cc2c(CN2CCN(CC=Cc3ccccc3)CC2)c1',
_TestMolecule('O=c1oc2ccc(O)cc2c(CN2CCN(CC=Cc3ccccc3)CC2)c1',
'O=c1oc2ccccc2c(c1)CN1CCN(CC1)CC=Cc1ccccc1'),
TestMolecule('Cn1c(Cc2ccccc2)nnc1SCCC(=O)Nc1ccccc1', 'O=C(CCSc1nnc([nH]1)Cc1ccccc1)Nc1ccccc1'),
TestMolecule('c1cc2nc(CC(=O)c3cc([N+]([O-])=O)ccc3)[nH]c2cc1',
_TestMolecule('Cn1c(Cc2ccccc2)nnc1SCCC(=O)Nc1ccccc1', 'O=C(CCSc1nnc([nH]1)Cc1ccccc1)Nc1ccccc1'),
_TestMolecule('c1cc2nc(CC(=O)c3cc([N+]([O-])=O)ccc3)[nH]c2cc1',
'O=C(Cc1nc2ccccc2[nH]1)c1ccccc1'),
TestMolecule('c1cc2cc(C(=O)N3CCN(c4ccc(N5CCOCC5)nn4)CC3)c(=O)oc2cc1',
_TestMolecule('c1cc2cc(C(=O)N3CCN(c4ccc(N5CCOCC5)nn4)CC3)c(=O)oc2cc1',
'c1cc2cc(C(=O)N3CCN(c4ccc(N5CCOCC5)nn4)CC3)c(=O)oc2cc1'),
TestMolecule('COc1ccccc1-n1c(=S)[nH]nc1CCn1nc(C)c(Br)c1C', 'S=c1[nH]nc(n1-c1ccccc1)CCn1cccn1'),
TestMolecule('CCC(=O)NC(=S)Nc1ccc(N2CCOCC2)cc1', 'c1cccc(c1)N1CCOCC1'),
TestMolecule('CCCCCC(=O)N1CCN(CCNC=C2C(=O)CC(c3ccc(OC)c(OC)c3)CC2=O)CC1',
_TestMolecule('COc1ccccc1-n1c(=S)[nH]nc1CCn1nc(C)c(Br)c1C', 'S=c1[nH]nc(n1-c1ccccc1)CCn1cccn1'),
_TestMolecule('CCC(=O)NC(=S)Nc1ccc(N2CCOCC2)cc1', 'c1cccc(c1)N1CCOCC1'),
_TestMolecule('CCCCCC(=O)N1CCN(CCNC=C2C(=O)CC(c3ccc(OC)c(OC)c3)CC2=O)CC1',
'c1ccc(cc1)C1CC(=O)C(C(=O)C1)=CNCCN1CCNCC1'),
TestMolecule('CN1CCN(C(=O)CN(S(C)(=O)=O)Cc2ccc(Cl)cc2)CC1', 'O=C(CNCc1ccccc1)N1CCNCC1'),
TestMolecule('COc1cc(OC)cc(C(=O)NCc2cccnc2)c1', 'O=C(NCc1cccnc1)c1ccccc1'),
TestMolecule('c1cncc(NC(=O)C2CCCN(S(c3cccc4c3nsn4)(=O)=O)C2)c1',
_TestMolecule('CN1CCN(C(=O)CN(S(C)(=O)=O)Cc2ccc(Cl)cc2)CC1', 'O=C(CNCc1ccccc1)N1CCNCC1'),
_TestMolecule('COc1cc(OC)cc(C(=O)NCc2cccnc2)c1', 'O=C(NCc1cccnc1)c1ccccc1'),
_TestMolecule('c1cncc(NC(=O)C2CCCN(S(c3cccc4c3nsn4)(=O)=O)C2)c1',
'c1cncc(NC(=O)C2CCCN(S(c3cccc4c3nsn4)(=O)=O)C2)c1'),
TestMolecule('CC(NC1=NN(C(C)=O)C(C)(c2cccs2)S1)=O', 'c1cc(sc1)C1SC=NN1'),
TestMolecule('CCCC(=O)Nc1ccc(-c2nc3cc(C)c(C)cc3o2)cc1', 'c1cccc(c1)-c1nc2ccccc2o1'),
TestMolecule('Cc1c(C)n(CC(O)CN2CCOCC2)c2ccccc12.OC(=O)C(O)=O', 'c1cn(c2ccccc12)CCCN1CCOCC1'),
TestMolecule('Cc1occc1-c1n(CCc2ccccc2)c(SCC(=O)Nc2sccn2)nn1',
_TestMolecule('CC(NC1=NN(C(C)=O)C(C)(c2cccs2)S1)=O', 'c1cc(sc1)C1SC=NN1'),
_TestMolecule('CCCC(=O)Nc1ccc(-c2nc3cc(C)c(C)cc3o2)cc1', 'c1cccc(c1)-c1nc2ccccc2o1'),
_TestMolecule('Cc1c(C)n(CC(O)CN2CCOCC2)c2ccccc12.OC(=O)C(O)=O', 'c1cn(c2ccccc12)CCCN1CCOCC1'),
_TestMolecule('Cc1occc1-c1n(CCc2ccccc2)c(SCC(=O)Nc2sccn2)nn1',
'O=C(Nc1sccn1)CSc1n(c(nn1)-c1cocc1)CCc1ccccc1'),
TestMolecule('Cc1oc(-c2cc(F)ccc2)nc1CN1C(CCc2ncccc2)CCCC1',
_TestMolecule('Cc1oc(-c2cc(F)ccc2)nc1CN1C(CCc2ncccc2)CCCC1',
'c1ccc(cc1)-c1nc(co1)CN1C(CCCC1)CCc1ncccc1'),
TestMolecule('COc1c(OC)c(C(O)=O)c(C=NNC(c2cc(NC(c3ccc(F)cc3)=O)ccc2)=O)cc1',
_TestMolecule('COc1c(OC)c(C(O)=O)c(C=NNC(c2cc(NC(c3ccc(F)cc3)=O)ccc2)=O)cc1',
'O=C(Nc1cc(ccc1)C(=O)NN=Cc1ccccc1)c1ccccc1'),
TestMolecule('CCn1c(Cc2ccccc2)nnc1SCC(=O)Nc1ccc(S(N)(=O)=O)cc1',
_TestMolecule('CCn1c(Cc2ccccc2)nnc1SCC(=O)Nc1ccc(S(N)(=O)=O)cc1',
'O=C(CSc1[nH]c(nn1)Cc1ccccc1)Nc1ccccc1'),
TestMolecule('CCn1c(COc2nn(-c3ccccc3)c(=O)cc2)nnc1SCc1ccc(OC)cc1',
_TestMolecule('CCn1c(COc2nn(-c3ccccc3)c(=O)cc2)nnc1SCc1ccc(OC)cc1',
'O=c1ccc(nn1-c1ccccc1)OCc1[nH]c(nn1)SCc1ccccc1'),
TestMolecule('CC1=NC(=O)C(=C2CC(O)(C(F)(F)F)ON2)C(C)=C1', 'O=C1C(=C2NOCC2)C=CC=N1'),
TestMolecule('COc1ccc(NC(=S)Nc2ccccc2C(F)(F)F)cc1', 'S=C(Nc1ccccc1)Nc1ccccc1'),
TestMolecule('CCCc1cc(=O)nc(SCC(=O)c2cc(C)n(CCOC)c2C)[nH]1',
_TestMolecule('CC1=NC(=O)C(=C2CC(O)(C(F)(F)F)ON2)C(C)=C1', 'O=C1C(=C2NOCC2)C=CC=N1'),
_TestMolecule('COc1ccc(NC(=S)Nc2ccccc2C(F)(F)F)cc1', 'S=C(Nc1ccccc1)Nc1ccccc1'),
_TestMolecule('CCCc1cc(=O)nc(SCC(=O)c2cc(C)n(CCOC)c2C)[nH]1',
'O=C(c1c[nH]cc1)CSc1[nH]ccc(=O)n1'),
TestMolecule('CC(=O)Nc1ccc2c(c1)C(C)(C)C(C)N2C', 'c1ccc2c(c1)NCC2'),
TestMolecule('CCN1CCN(C(c2ccc(OCC(Nc3ccc(F)cc3)=O)c(OC)c2)=O)CC1',
_TestMolecule('CC(=O)Nc1ccc2c(c1)C(C)(C)C(C)N2C', 'c1ccc2c(c1)NCC2'),
_TestMolecule('CCN1CCN(C(c2ccc(OCC(Nc3ccc(F)cc3)=O)c(OC)c2)=O)CC1',
'c1cc(ccc1)NC(=O)COc1ccc(C(N2CCNCC2)=O)cc1'),
TestMolecule('CCCCN1C2CCCC1CC(NC(=O)c1ccc(OC)c(OC)c1)C2', 'O=C(NC1CC2NC(CCC2)C1)c1ccccc1'),
TestMolecule('c1ccc(N(CC(=O)N2CCOCC2)S(c2ccccc2)(=O)=O)cc1',
_TestMolecule('CCCCN1C2CCCC1CC(NC(=O)c1ccc(OC)c(OC)c1)C2', 'O=C(NC1CC2NC(CCC2)C1)c1ccccc1'),
_TestMolecule('c1ccc(N(CC(=O)N2CCOCC2)S(c2ccccc2)(=O)=O)cc1',
'c1ccc(N(CC(=O)N2CCOCC2)S(c2ccccc2)(=O)=O)cc1'),
TestMolecule('CCn1c(C)nc2cc(C(=O)NN=Cc3ccc(OC)c(O)c3)ccc12',
_TestMolecule('CCn1c(C)nc2cc(C(=O)NN=Cc3ccc(OC)c(O)c3)ccc12',
'O=C(NN=Cc1ccccc1)c1ccc2[nH]cnc2c1'),
TestMolecule('[Cl-].NC(=O)CN1C=CC(=C[NH+]=O)C=C1', 'C=C1C=CNC=C1'),
TestMolecule('Cn1cnnc1SC1C(NS(c2ccccc2)(=O)=O)c2c3c(ccc2)cccc31',
_TestMolecule('[Cl-].NC(=O)CN1C=CC(=C[NH+]=O)C=C1', 'C=C1C=CNC=C1'),
_TestMolecule('Cn1cnnc1SC1C(NS(c2ccccc2)(=O)=O)c2c3c(ccc2)cccc31',
'O=S(=O)(NC1C(Sc2[nH]cnn2)c2cccc3c2c1ccc3)c1ccccc1'),
TestMolecule('COc1ccc(Nc2nc(NCc3ccco3)nc(NN=Cc3ccccc3F)n2)cc1',
_TestMolecule('COc1ccc(Nc2nc(NCc3ccco3)nc(NN=Cc3ccccc3F)n2)cc1',
'c1ccc(Nc2nc(nc(n2)NN=Cc2ccccc2)NCc2ccco2)cc1'),
TestMolecule('CC1=CC(=O)C(=C2C=C(c3ccccc3[N+]([O-])=O)NN2)C=C1',
_TestMolecule('CC1=CC(=O)C(=C2C=C(c3ccccc3[N+]([O-])=O)NN2)C=C1',
'O=C1C(=C2NNC(=C2)c2ccccc2)C=CC=C1'),
TestMolecule('COc1ccc(CC2[N+]([O-])(C)CCc3cc(OC)c(O)cc32)cc1O',
_TestMolecule('COc1ccc(CC2[N+]([O-])(C)CCc3cc(OC)c(O)cc32)cc1O',
'c1ccc(cc1)CC1c2c(cccc2)CC[NH2+]1'),
TestMolecule('Cl.NC(N)=Nc1nc(=O)c2cc(Br)ccc2[nH]1', 'O=c1nc[nH]c2ccccc21'),
TestMolecule('CC(=O)N1CCC(=NNc2ccc(S(=O)(=O)N3CCOCC3)cc2[N+]([O-])=O)CC1',
_TestMolecule('Cl.NC(N)=Nc1nc(=O)c2cc(Br)ccc2[nH]1', 'O=c1nc[nH]c2ccccc21'),
_TestMolecule('CC(=O)N1CCC(=NNc2ccc(S(=O)(=O)N3CCOCC3)cc2[N+]([O-])=O)CC1',
'c1cc(ccc1NN=C1CCNCC1)S(=O)(=O)N1CCOCC1'),
TestMolecule('Cc1cc(S(N(Cc2ccc(F)cc2)CC2OCCC2)(=O)=O)ccc1-n1cnnn1',
_TestMolecule('Cc1cc(S(N(Cc2ccc(F)cc2)CC2OCCC2)(=O)=O)ccc1-n1cnnn1',
'c1cc(ccc1)CN(CC1OCCC1)S(c1ccc(cc1)-n1cnnn1)(=O)=O'),
TestMolecule('CC1(C)OCc2c(c3c(sc4c(NCCCO)ncnc43)nc2-c2ccco2)C1',
_TestMolecule('CC1(C)OCc2c(c3c(sc4c(NCCCO)ncnc43)nc2-c2ccco2)C1',
'c1ncnc2c1sc1nc(c3c(c12)CCOC3)-c1ccco1'),
TestMolecule('COc1ccc(CCNC(=O)CSc2n(-c3ccc(OC)c(OC)c3)nnn2)cc1OC',
_TestMolecule('COc1ccc(CCNC(=O)CSc2n(-c3ccc(OC)c(OC)c3)nnn2)cc1OC',
'O=C(CSc1n(-c2ccccc2)nnn1)NCCc1ccccc1'),
TestMolecule('CC(C)(CC(O)=O)CC(NCc1c(Cl)cccc1Sc1ccc(Cl)cc1)=O', 'c1ccc(Sc2ccccc2)cc1'),
TestMolecule('COc1ccc(-c2cc(CCCC(=O)NCCc3cc(OC)ccc3OC)no2)cc1',
_TestMolecule('CC(C)(CC(O)=O)CC(NCc1c(Cl)cccc1Sc1ccc(Cl)cc1)=O', 'c1ccc(Sc2ccccc2)cc1'),
_TestMolecule('COc1ccc(-c2cc(CCCC(=O)NCCc3cc(OC)ccc3OC)no2)cc1',
'O=C(NCCc1ccccc1)CCCc1noc(c1)-c1ccccc1'),
TestMolecule('Cc1ccc(-c2ncns2)cc1', 'c1ccc(cc1)-c1sncn1'),
TestMolecule('C(O)CCn1c(=O)c2c(nc1C=Cc1ccc([N+]([O-])=O)o1)cccc2',
_TestMolecule('Cc1ccc(-c2ncns2)cc1', 'c1ccc(cc1)-c1sncn1'),
_TestMolecule('C(O)CCn1c(=O)c2c(nc1C=Cc1ccc([N+]([O-])=O)o1)cccc2',
'O=c1[nH]c(C=Cc2ccco2)nc2c1cccc2'),
TestMolecule('COC(CC(O)CC(O)C(C)OCc1ccccc1)OC', 'c1ccccc1'),
TestMolecule('Cl.CCCC(N1CCN(C(=O)c2occc2)CC1)c1n(C(C)(C)C)nnn1',
_TestMolecule('COC(CC(O)CC(O)C(C)OCc1ccccc1)OC', 'c1ccccc1'),
_TestMolecule('Cl.CCCC(N1CCN(C(=O)c2occc2)CC1)c1n(C(C)(C)C)nnn1',
'O=C(N1CCN(Cc2nnn[nH]2)CC1)c1ccco1'),
TestMolecule('O=C(NC(CO)c1ccccc1)c1occc1', 'O=C(NCc1ccccc1)c1occc1'),
TestMolecule('O=C(Nc1ccc(N2CCOCC2)cc1)c1c(Cl)cc(F)c(F)c1', 'O=C(Nc1ccc(N2CCOCC2)cc1)c1ccccc1'),
TestMolecule('CCc1sc(N2C(=O)c3ccc(Oc4ccc([N+]([O-])=O)cc4)cc3C2=O)nn1',
_TestMolecule('O=C(NC(CO)c1ccccc1)c1occc1', 'O=C(NCc1ccccc1)c1occc1'),
_TestMolecule('O=C(Nc1ccc(N2CCOCC2)cc1)c1c(Cl)cc(F)c(F)c1', 'O=C(Nc1ccc(N2CCOCC2)cc1)c1ccccc1'),
_TestMolecule('CCc1sc(N2C(=O)c3ccc(Oc4ccc([N+]([O-])=O)cc4)cc3C2=O)nn1',
'O=C1N(C(=O)c2cc(Oc3ccccc3)ccc21)c1scnn1'),
TestMolecule('CC(C)Cc1ccc(C(C)C(=O)O)cc1', 'c1ccccc1'),
TestMolecule('Cl.N=c1sccn1CC(=O)Nc1cc(S(N2CCCC2)(=O)=O)ccc1Cl',
_TestMolecule('CC(C)Cc1ccc(C(C)C(=O)O)cc1', 'c1ccccc1'),
_TestMolecule('Cl.N=c1sccn1CC(=O)Nc1cc(S(N2CCCC2)(=O)=O)ccc1Cl',
'N=c1n(CC(=O)Nc2cccc(S(=O)(N3CCCC3)=O)c2)ccs1'),
TestMolecule('c1ccc(-c2ccc(C(=O)OC3CC4OC(=O)CC4C3CO)cc2)cc1',
_TestMolecule('c1ccc(-c2ccc(C(=O)OC3CC4OC(=O)CC4C3CO)cc2)cc1',
'c1ccc(cc1)-c1ccc(C(=O)OC2CC3CC(=O)OC3C2)cc1'),
TestMolecule('CN(CCC#N)CC(=O)Nc1ccc(S(N)(=O)=O)cc1', 'c1ccccc1'),
TestMolecule('Cc1nc(-c2ccc([N+]([O-])=O)cc2)sc1C(=O)O', 'c1cc(-c2sccn2)ccc1'),
TestMolecule('c1coc(C(=O)N2CCN(C(Cn3nnc(-c4ccc(NC(c5ccc(F)cc5)=O)cc4)n3)=O)CC2)c1',
_TestMolecule('CN(CCC#N)CC(=O)Nc1ccc(S(N)(=O)=O)cc1', 'c1ccccc1'),
_TestMolecule('Cc1nc(-c2ccc([N+]([O-])=O)cc2)sc1C(=O)O', 'c1cc(-c2sccn2)ccc1'),
_TestMolecule('c1coc(C(=O)N2CCN(C(Cn3nnc(-c4ccc(NC(c5ccc(F)cc5)=O)cc4)n3)=O)CC2)c1',
'O=C(N1CCN(C(=O)Cn2nc(nn2)-c2ccc(NC(=O)c3ccccc3)cc2)CC1)c1ccco1'),
TestMolecule('Cc1onc(-c2c(Cl)cccc2Cl)c1C(N)=S', 'c1ccc(cc1)-c1nocc1'),
TestMolecule('CCOC(=O)c1cnc2ccccc2c1NCCO', 'c1cnc2ccccc2c1'),
TestMolecule('Cc1ccc(C)c(NC(=O)Cn2nnc(-c3ccc(N4CCOCC4)cc3)n2)c1',
_TestMolecule('Cc1onc(-c2c(Cl)cccc2Cl)c1C(N)=S', 'c1ccc(cc1)-c1nocc1'),
_TestMolecule('CCOC(=O)c1cnc2ccccc2c1NCCO', 'c1cnc2ccccc2c1'),
_TestMolecule('Cc1ccc(C)c(NC(=O)Cn2nnc(-c3ccc(N4CCOCC4)cc3)n2)c1',
'O=C(Cn1nnc(n1)-c1ccc(cc1)N1CCOCC1)Nc1ccccc1'),
TestMolecule('CC(C)(C)c1cc(C(=O)NNc2ccc(OC(F)(F)F)cc2)n(Cc2ccccc2)n1',
_TestMolecule('CC(C)(C)c1cc(C(=O)NNc2ccc(OC(F)(F)F)cc2)n(Cc2ccccc2)n1',
'O=C(NNc1ccccc1)c1ccnn1Cc1ccccc1'),
TestMolecule('CCCCCOC(=O)C1=C(C)N=C2N(NN=N2)C1c1ccc(OC)c(OC)c1OC',
_TestMolecule('CCCCCOC(=O)C1=C(C)N=C2N(NN=N2)C1c1ccc(OC)c(OC)c1OC',
'c1cccc(c1)C1N2NN=NC2=NC=C1'),
TestMolecule('Cc1cc2cc(CNC(=O)C3CC3)ccc2n1C', 'O=C(NCc1ccc2c(cc[nH]2)c1)C1CC1'),
TestMolecule('Cc1ccccc1C(NC(CC(C)C)C(Nc1cc(S(N(C)C)(=O)=O)ccc1)=O)=O',
_TestMolecule('Cc1cc2cc(CNC(=O)C3CC3)ccc2n1C', 'O=C(NCc1ccc2c(cc[nH]2)c1)C1CC1'),
_TestMolecule('Cc1ccccc1C(NC(CC(C)C)C(Nc1cc(S(N(C)C)(=O)=O)ccc1)=O)=O',
'c1ccc(cc1)NC(CNC(=O)c1ccccc1)=O'),
TestMolecule('COCCCNC(=S)N1CCC(NC(=O)c2ccco2)CC1', 'O=C(NC1CCNCC1)c1ccco1'),
TestMolecule('Cn1c(C=Cc2oc([N+]([O-])=O)cc2)nc2ccccc2c1=O', 'O=c1[nH]c(C=Cc2occc2)nc2ccccc12'),
TestMolecule('c1cc2nc(SCc3cc(=O)n4ccsc4n3)n(CCCO)c(=O)c2cc1',
_TestMolecule('COCCCNC(=S)N1CCC(NC(=O)c2ccco2)CC1', 'O=C(NC1CCNCC1)c1ccco1'),
_TestMolecule('Cn1c(C=Cc2oc([N+]([O-])=O)cc2)nc2ccccc2c1=O', 'O=c1[nH]c(C=Cc2occc2)nc2ccccc12'),
_TestMolecule('c1cc2nc(SCc3cc(=O)n4ccsc4n3)n(CCCO)c(=O)c2cc1',
'c1ccc2nc(SCc3cc(=O)n4ccsc4n3)[nH]c(=O)c2c1'),
TestMolecule('c1ccc2c(c1)cccc2NC(=O)CC1SC(NCC2OCCC2)=NC1=O',
_TestMolecule('c1ccc2c(c1)cccc2NC(=O)CC1SC(NCC2OCCC2)=NC1=O',
'c1ccc2c(c1)cccc2NC(=O)CC1SC(NCC2OCCC2)=NC1=O'),
]

View File

@@ -1,17 +0,0 @@
"""
Run unit tests and doctests for MurckoScaffolds
"""
tests = [
("python", "UnitTestMurckoScaffold.py", {}),
("python", "MurckoScaffold.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestEnumerator.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,11 +0,0 @@
tests = [
("python", "UnitTestSubshape.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,13 +0,0 @@
tests = [
("python", "UnitTestSDMolSupplier.py", {}),
("python", "UnitTestSmilesMolSupplier.py", {}),
("python", "UnitTestDbMolSupplier.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -11,9 +11,6 @@ import numpy
from rdkit import Chem, RDConfig, rdBase
from rdkit.Chem import PandasTools
if (getattr(doctest, 'ELLIPSIS_MARKER')):
doctest.ELLIPSIS_MARKER = '*...*'
try:
import IPython
except ImportError:
@@ -51,12 +48,6 @@ class TestPandasTools(unittest.TestCase):
PandasTools.highlightSubstructures = self._highlightSubstructures
PandasTools.UninstallPandasTools()
def testDoctest(self):
# We need to do it like this to ensure that default RDkit functionality is restored
failed, _ = doctest.testmod(PandasTools,
optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE)
self.assertFalse(failed)
def test_RestoreMonkeyPatch(self):
sio = getStreamIO(methane + peroxide)
df = PandasTools.LoadSDF(sio)
@@ -454,4 +445,6 @@ $$$$
"""
if __name__ == '__main__': # pragma: nocover
if (getattr(doctest, 'ELLIPSIS_MARKER')):
doctest.ELLIPSIS_MARKER = '*...*'
unittest.main()

View File

@@ -7,7 +7,7 @@ from rdkit import Chem, RDConfig
from rdkit.Chem import QED
doLong = False
TestData = namedtuple('TestData', 'lineNo,smiles,mol,expected')
_TestData = namedtuple('_TestData', 'lineNo,smiles,mol,expected')
dataNCI200 = os.path.join(RDConfig.RDCodeDir, 'Chem', 'test_data', 'QED', 'NCI_200_qed.csv')
dataRegression = os.path.join(RDConfig.RDCodeDir, 'Chem', 'test_data', 'QED', 'Regression_qed.csv')
@@ -89,7 +89,7 @@ def readTestData(filename):
mol = Chem.MolFromSmiles(smiles)
if not mol:
raise AssertionError('molecule construction failed on line %d' % lineNo)
yield TestData(lineNo, smiles, mol, float(expected))
yield _TestData(lineNo, smiles, mol, float(expected))
def updateTestData():

View File

@@ -19,7 +19,7 @@ from rdkit import Chem, RDConfig
from rdkit.Chem import MolSurf
doLong = False
TestData = namedtuple('TestData', 'lineNo,smiles,mol,expected')
_TestData = namedtuple('_TestData', 'lineNo,smiles,mol,expected')
class TestCase(unittest.TestCase):
@@ -218,7 +218,7 @@ def readPSAtestData(filename):
mol = Chem.MolFromSmiles(smiles)
if not mol:
raise AssertionError('molecule construction failed on line %d' % lineNo)
yield TestData(lineNo, smiles, mol, float(expected))
yield _TestData(lineNo, smiles, mol, float(expected))
def readRegressionData(filename, col):
@@ -235,7 +235,7 @@ def readRegressionData(filename, col):
if mol is None:
raise AssertionError('line %d, smiles: %s' % (lineNum, smi))
expected = float(splitL[col])
yield TestData(lineNum, smi, mol, expected)
yield _TestData(lineNum, smi, mol, expected)
if __name__ == '__main__': # pragma: nocover

View File

@@ -1,64 +0,0 @@
tests = [("python", "UnitTestChem.py", {}), ("python", "UnitTestChemv2.py", {}),
("python", "UnitTestChemAtom.py", {}), ("python", "UnitTestChemBond.py", {}),
("python", "UnitTestChemSmarts.py", {}), ("python", "UnitTestFragmentDescriptors.py", {}),
("python", "UnitTestGraphDescriptors_2.py", {}), ("python", "UnitTestLipinski.py", {}),
("python", "UnitTestMCS.py", {}), ("python", "UnitTestOldBugs.py", {}),
("python", "UnitTestSATIS.py", {}), ("python", "UnitTestSmiles.py", {}),
("python", "UnitTestSuppliers.py", {}), ("python", "UnitTestSurf.py", {}),
("python", "UnitTestMol3D.py", {}), ("python", "UnitTestCatalog.py", {}),
("python", "UnitTestDescriptors.py", {}), ("python", "UnitTestInchi.py", {}),
("python", "UnitTestFunctionalGroups.py", {}), ("python", "UnitTestCrippen.py", {}),
("python", "UnitTestPandasTools.py", {}), ("python", "UnitTestDocTestsChem.py", {}),
("python", "UnitTestFeatFinderCLI.py", {}), ("python", "UnitTestQED.py", {}), ("python", "UnitTestSpacialScore.py", {}),
("python", "BRICS.py", {}), ("python", "EnumerateStereoisomers.py", {}),
("python", "UnitTestSaltRemover.py", {}), ("python", "test_list.py", {
'dir': 'AtomPairs'
}), ("python", "test_list.py", {
'dir': 'ChemUtils'
}), ("python", "test_list.py", {
'dir': 'EState'
}), ("python", "test_list.py", {
'dir': 'FeatMaps'
}), ("python", "test_list.py", {
'dir': 'Fingerprints'
}), ("python", "test_list.py", {
'dir': 'Pharm2D'
}), ("python", "test_list.py", {
'dir': 'Pharm3D'
}), ("python", "test_list.py", {
'dir': 'Subshape'
}), ("python", "test_list.py", {
'dir': 'Suppliers'
}), ("python", "test_list.py", {
'dir': 'Scaffolds'
}), ("python", "test_list.py", {
'dir': 'Draw'
}), ("python", "test_list.py", {
'dir': 'Fraggle'
}), ("python", "test_list.py", {
'dir': 'SimpleEnum'
}), ("python", "test_list.py", {
'dir': 'Features'
}), ("python", "test_list.py", {
'dir': 'MolStandardize'
}), ("python", "UnitTestRegistrationHash.py", {})]
# only attempt the MolKey tests if we have the pre-reqs:
try:
from rdkit.Chem.MolKey import MolKey
tests.append(("python", "test_list.py", {'dir': 'MolKey'}))
except ImportError:
pass
longTests = [
("python", "UnitTestArom.py", {}),
("python", "UnitTestGraphDescriptors.2.py -l", {}),
("python", "UnitTestSurf.py -l", {}),
]
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,14 +0,0 @@
tests = [
("python", "UnitTestDocTests.py", {}),
("python", "UnitTestcBitVect.py", {}),
("python", "UnitTestBitEnsemble.py", {}),
("python", "UnitTestTopNContainer.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,16 +0,0 @@
tests = [
("python", "UnitTestStorageUtils.py", {}),
("python", "UnitTestDbConnect.py", {}),
("python", "UnitTestDbInfo.py", {}),
("python", "UnitTestDbUtils.py", {}),
("python", "UnitTestDbResultSet.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestCluster.py", {}),
("python", "UnitTestButina.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,92 +0,0 @@
#
# Copyright (C) 2001 greg Landrum
#
# unit testing code for the composite model COM server
import unittest
from rdkit import RDConfig
try:
from win32com.client import Dispatch
except ImportError:
Dispatch = None
@unittest.skipIf(Dispatch is None, 'Test for Windows only')
class TestCase(unittest.TestCase):
def testConnect(self):
# connecting to COM server
ok = 1
try:
c = Dispatch('RD.Composite')
except Exception:
ok = 0
assert ok and c is not None, 'connection to COM server failed'
def testLoad(self):
# loading a composite
c = Dispatch('RD.Composite')
ok = 1
try:
c.LoadComposite(RDConfig.RDCodeDir + '/ml/composite/test_data/composite_base.pkl')
except Exception:
ok = 0
assert ok, 'LoadComposite failed'
def testNames(self):
# testing descriptor names
c = Dispatch('RD.Composite')
c.LoadComposite(RDConfig.RDCodeDir + '/ml/composite/test_data/composite_base.pkl')
names = c.GetDescriptorNames()
expectedNames = ('composition', 'max_atomic', 'has3d', 'has4d', 'has5d', 'elconc', 'atvol',
'isferro')
assert names == expectedNames, 'GetDescriptorNames failed'
def testInputOrder(self):
# testing input order
c = Dispatch('RD.Composite')
c.LoadComposite(RDConfig.RDCodeDir + '/ml/composite/test_data/composite_base.pkl')
names = c.GetDescriptorNames()
ok = 1
try:
c.SetInputOrder(names)
except Exception:
ok = 0
assert ok, 'SetInputOrder failed'
def testClassify(self):
# testing classification
argV = [
'CrPt3', 'fcc', 'AuCu3', 58.09549962, 36, 4, 0.228898, 2.219, 1, 3.67481803894, 1, 0, 1,
0.619669341609, 14.523874905
]
nameV = [
'composition', 'Structure', 'Structure_Type', 'Volume', 'Electrons_Per_Unit',
'Atoms_Per_Unit', 'Hardness', 'DOS_Ef', 'isferro', 'max_atomic', 'has3d', 'has4d', 'has5d',
'elconc', 'atvol'
]
c = Dispatch('RD.Composite')
c.LoadComposite(RDConfig.RDCodeDir + '/ml/composite/test_data/composite_base.pkl')
c.SetInputOrder(nameV)
res = c.ClassifyExample(argV)
expected = [1, 1.0]
assert res[0] == expected[0], 'bad prediction'
assert res[1] == expected[1], 'bad confidence'
def TestSuite(): # pragma: nocover
suite = unittest.TestSuite()
suite.addTest(TestCase('testConnect'))
suite.addTest(TestCase('testLoad'))
suite.addTest(TestCase('testNames'))
suite.addTest(TestCase('testInputOrder'))
suite.addTest(TestCase('testClassify'))
return suite
if __name__ == '__main__': # pragma: nocover
suite = TestSuite()
unittest.TextTestRunner().run(suite)

View File

@@ -1,11 +0,0 @@
tests = [
("python", "UnitTestComposite.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,8 +1,7 @@
from rdkit import RDConfig
from rdkit.Dbase import DbUtils
from io import StringIO
import RDConfig
from Dbase import DbUtils
basic_2class = """ID,VAL,ACT
id-1,1.0,0
id-2,23.0,1

View File

@@ -1,16 +0,0 @@
tests = [
("python", "UnitTestFilter.py", {}),
("python", "UnitTestMLData.py", {}),
("python", "UnitTestQuantize.py", {}),
("python", "UnitTestStats.py", {}),
("python", "SplitData.py", {}),
("python", "DataUtils.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,17 +0,0 @@
tests = [
("python", "UnitTestTreeUtils.py", {}),
("python", "UnitTestTree.py", {}),
("python", "UnitTestXVal.py", {}),
("python", "UnitTestID3.py", {}),
("python", "UnitTestPrune.py", {}),
("python", "UnitTestQuantTree.py", {}),
("python", "UnitTestSigTree.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,60 +0,0 @@
#
# Copyright (C) 2001 greg Landrum
#
""" unit testing code for the descriptor COM server
"""
import unittest
import numpy as np
from rdkit import RDConfig
try:
from win32com.client import Dispatch
except ImportError:
Dispatch = None
@unittest.skipIf(Dispatch is None, 'Windows test')
class TestCase(unittest.TestCase):
def setUp(self):
print('\n%s: ' % self.shortDescription(), end='')
def testConnectToCOMServer(self):
# " testing connection "
Dispatch('RD.DescCalc')
def testLoadCalculator(self):
# " testing load "
c = Dispatch('RD.DescCalc')
c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
def testNames(self):
# " testing GetDescriptorNames "
c = Dispatch('RD.DescCalc')
c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
names = c.GetDescriptorNames()
expectedNames = ('MAX_DED', 'has3d', 'has4d', 'has5d', 'elconc', 'atvol')
assert names == expectedNames, 'GetDescriptorNames failed (%s != %s)' % (repr(names),
repr(expectedNames))
def testCalc(self):
# " testing descriptor calculation "
argV = ['CrPt3', 'fcc', 'AuCu3', 58.09549962, 1, 4, 0.228898, 8.876, 1]
nameV = [
'Compound', 'Structure', 'Structure_Type', 'Volume', 'Z', 'Atoms_per_Formula_Unit',
'Hardness', 'RawDOS_Ef', 'IsFerromagnetic'
]
c = Dispatch('RD.DescCalc')
c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
descVect = np.array(c.CalcDescriptors(argV, nameV))
expected = np.array((3.67481803894, 1, 0, 1, 0.619669341609, 14.523874905))
diffV = abs(descVect - expected)
assert max(diffV) < 0.0001, 'bad descriptors: %s, %s' % (str(expected), str(descVect))
if __name__ == '__main__': # pragma: nocover
unittest.main()

View File

@@ -1,13 +0,0 @@
tests = [
("python", "UnitTestParser.py", {}),
("python", "UnitTestMolDescriptors.py", {}),
("python", "UnitTestDescriptors.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,13 +0,0 @@
tests = [
("python", "UnitTestCorrMatGen.py", {}),
]
longTests = [
("python", "UnitTestBitRanker.py", {}),
]
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestKNN.py", {}),
("python", "DistFunctions.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,11 +0,0 @@
tests = [
("python", "UnitTestPackage.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,11 +0,0 @@
tests = [
("python", "UnitTestNB.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestTrainer.py", {}),
("python", "UnitTestOther.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,11 +0,0 @@
tests = [
("python", "UnitTestRisk.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestScoring.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,20 +0,0 @@
tests = [
("python", "UnitTestBuildComposite.py", {}),
("python", "UnitTestScreenComposite.py", {}),
("python", "UnitTestAnalyzeComposite.py", {}),
]
for d in [
'Cluster', 'Composite', 'Data', 'DecTree', 'Descriptors', 'InfoTheory', 'KNN', 'ModelPackage',
'NaiveBayes', 'Neural', 'SLT', 'Scoring'
]:
tests.append(('python', 'test_list.py', {'dir': d}))
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "SimilarityPickers.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2003-2010 Greg Landrum and Rational Discovery LLC
# Copyright (c) 2003-2023 Greg Landrum and other RDKit contributors
#
# @@ All Rights Reserved @@
# This file is part of the RDKit.
@@ -10,17 +10,6 @@
import os
import sys
import time
from rdkit import RDConfig
try:
import subprocess
except ImportError:
subprocess = None
TEST_FAILED = -1
TEST_PASSED = 0
BUILD_TYPE_ENVVAR = 'RDKIT_BUILD_TYPE'
@@ -32,177 +21,6 @@ def isDebugBuild():
return False
def RunTest(exeName, args, extras):
if exeName == "python":
exeName = RDConfig.pythonExe
args = args.split(' ')
startDir = os.getcwd()
if 'dir' in extras:
os.chdir(extras['dir'])
expectedReturn = extras.get('returns', 0)
if not subprocess:
raise NotImplementedError('cannot run tests if the subprocess module is not available.')
else:
try:
retVal = subprocess.call([exeName] + list(args))
except OSError:
print("Could not find executable: %s." % exeName, file=sys.stderr)
return TEST_FAILED
if 'dir' in extras:
os.chdir(startDir)
if retVal != expectedReturn:
return TEST_FAILED
else:
return TEST_PASSED
def RunScript(script, doLongTests, verbose):
# support python 2.7 style -f argument for failfast
if sys.argv[-1] == '-f':
# setting environment allows this setting to recursively pass to all child
# processes
os.environ['PYTHON_TEST_FAILFAST'] = '1'
if len(sys.argv) >= 3 and sys.argv[1] == '--testDir':
os.chdir(sys.argv[2])
if len(sys.argv) >= 5 and sys.argv[3] == '--buildType':
os.environ[BUILD_TYPE_ENVVAR] = sys.argv[4].upper()
# -------------------------------------------------------
# this is pretty funny. Whatever directory we started python in
# will be in the search path, and if we've changed to another
# directory, that'll be there too. HOWEVER... the starting
# directory will be searched first (at least in python2.2), so we
# need to make sure that '.' is at the front of the search path
if sys.path[0] != '.':
sys.path = ['.'] + sys.path
script = script.split('.py')[0]
mod = __import__(script)
try:
tests = mod.tests
except AttributeError:
return [], 0
longTests = []
if doLongTests:
try:
longTests = mod.longTests
except AttributeError:
pass
failed = []
for i, entry in enumerate(tests):
try:
exeName, args, extras = entry
except ValueError:
print('bad entry:', entry)
sys.exit(-1)
try:
res = RunTest(exeName, args, extras)
except Exception:
import traceback
traceback.print_exc()
res = TEST_FAILED
if res != TEST_PASSED:
failed.append((exeName, args, extras))
# check failfast setting
if os.environ.get('PYTHON_TEST_FAILFAST', '') == '1':
# return immediately
sys.stderr.write("Exiting from %s\n" % str([exeName] + list(args)))
return failed, i + 1
for i, (exeName, args, extras) in enumerate(longTests):
res = RunTest(exeName, args, extras)
if res != TEST_PASSED:
failed.append((exeName, args, extras))
if os.environ.get('PYTHON_TEST_FAILFAST', '') == '1':
# return immediately
sys.stderr.write("Exitng from %s\n" % str([exeName] + list(args)))
return failed, len(tests) + i + 1
nTests = len(tests) + len(longTests)
del sys.modules[script]
if verbose and failed:
for exeName, args, extras in failed:
print("!!! TEST FAILURE: ", exeName, args, extras, file=sys.stderr)
return failed, nTests
def ReportResults(script, failedTests, nTests, runTime, verbose, dest):
if not nTests:
dest.write('!-!-!-!-!-!-!-!-!-!-!\n')
dest.write('\tScript: %s. No tests run!\n' % (script))
elif not len(failedTests):
dest.write('-----------------\n')
dest.write('\tScript: %s. Passed %d tests in %.2f seconds\n' % (script, nTests, runTime))
else:
dest.write('!-!-!-!-!-!-!-!-!-!-!\n')
dest.write('\tScript: %s. Failed %d (of %d) tests in %.2f seconds\n' %
(script, len(failedTests), nTests, runTime))
if verbose:
for exeName, args, extras in failedTests:
dirName = extras.get('dir', '.')
dirName = os.path.abspath(dirName)
dest.write('\t\t(%s): %s %s\n' % (dirName, exeName, args))
if __name__ == '__main__':
import getopt
args, extras = getopt.getopt(sys.argv[1:], 'lv')
doLongTests = 0
verbose = 1
for arg, val in args:
if arg == '-l':
doLongTests = 1
elif arg == '-v':
verbose = 0
pwd = os.getcwd()
totNumFailed = 0
totNumRun = 0
failures = []
timeAccum = 0.0
for script in extras:
try:
open(script, 'r')
except IOError:
sys.stderr.write('ERROR: Test script %s could not be opened.\n' % (script))
else:
dirName = os.path.dirname(script)
scriptBase = os.path.basename(script)
if dirName:
os.chdir(dirName)
try:
t1 = time.time()
failed, nTests = RunScript(scriptBase, doLongTests, verbose)
t2 = time.time()
except ImportError:
import traceback
traceback.print_exc()
sys.stderr.write('ERROR: Could not import test script %s\n' % (script))
else:
runTime = t2 - t1
ReportResults(script, failed, nTests, runTime, verbose, sys.stderr)
timeAccum += runTime
if dirName:
os.chdir(pwd)
if len(extras) > 1:
totNumFailed += len(failed)
totNumRun += nTests
if len(failed):
failures.append(script)
if totNumRun > 1:
sys.stderr.write('\n\n-*-*-*-*-*-*- Test Results Summary -*-*-*-*-*-*-\n')
sys.stderr.write('\t\tTotal run time: %.2f seconds\n' % (timeAccum))
if totNumFailed:
sys.stderr.write('!!!!!--- %d Failures in %d tests ---!!!!!\n' % (totNumFailed, totNumRun))
sys.stderr.write('\tModules with failures:\n')
for failure in failures:
sys.stderr.write('\t\t%s\n' % failure)
else:
sys.stderr.write(' All %d tests (in %d modules) passed\n' % (totNumRun, len(extras)))
sys.exit(totNumFailed)
class _RedirectStream:
_stream = None

View File

@@ -46,10 +46,9 @@ dupeFilter.AddParent(atsFilter)
# should be 4 here
print('post-dupes:', len([x for x in dupeFilter]))
import StringIO
from io import StringIO
# a StringIO object acts like a file:
io = StringIO.StringIO()
io = StringIO()
output = SmilesOutput.OutputNode(dest=io, delim=', ', idField='Name')
output.AddParent(dupeFilter)
print('post-output:', len([x for x in output]))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestNodeLib.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,15 +0,0 @@
tests = [
("python", "UnitTestVLib.py", {}),
("python", "test_list.py", {
'dir': 'NodeLib'
}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

25
rdkit/conftest.py Normal file
View File

@@ -0,0 +1,25 @@
# additional pytest configuration
collect_ignore = []
collect_ignore_glob = []
try:
import win32com
except ImportError:
collect_ignore.extend(['Chem/DSViewer.py'])
try:
from rdkit.Avalon import pyAvalonTools
except ImportError:
collect_ignore_glob.extend(['**Chem/MolKey/*.py'])
from rdkit.Chem import inchi
if not inchi.INCHI_AVAILABLE:
collect_ignore_glob.extend(['**Chem/MolKey/*.py'])
try:
import IPython
except ImportError:
collect_ignore.extend([
'Chem/Draw/IPythonConsole.py', 'Chem/Draw/InteractiveRenderer.py',
'Chem/Draw/UnitTestIPython.py'
])

8
rdkit/pytest.ini Normal file
View File

@@ -0,0 +1,8 @@
[pytest]
python_files = UnitTest*.py
doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
addopts = --doctest-modules --ignore-glob='**/test_data/*' --ignore=sping --ignore-glob='**/*Canvas.py' --ignore=six.py --ignore-glob='utils/chemdraw*'
--ignore=Chem/Subshape/demoCombined.py --ignore=Chem/Pharm2D/LazyGenerator.py --ignore='Chem/MolDb/Loader_sa.py' --ignore="DataStructs/HierarchyVis.py"
--ignore="VLib/NodeLib/DbMolSupply.py" --ignore='Dbase/StorageUtils.py' --ignore="Chem/FastSDMolSupplier.py" --ignore="Chem/MCS.py" --ignore='Chem/DSViewer.py'
--ignore='Chem/PandasPatcher.py' --ignore='utils/comhack.py'

View File

@@ -1,684 +0,0 @@
"""Utilities for writing code that runs on Python 2 and 3"""
# Copyright (c) 2010-2014 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import operator
import sys
import types
__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.6.1"
# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes
MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
if sys.platform.startswith("java"):
# Jython always uses 32 bits.
MAXSIZE = int((1 << 31) - 1)
else:
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
class X(object):
def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X
def _add_doc(func, doc):
"""Add documentation to a function."""
func.__doc__ = doc
def _import_module(name):
"""Import module, returning the module after the last dot."""
__import__(name)
return sys.modules[name]
class _LazyDescr(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, tp):
try:
result = self._resolve()
except ImportError:
# See the nice big comment in MovedModule.__getattr__.
raise AttributeError("%s could not be imported " % self.name)
setattr(obj, self.name, result) # Invokes __set__.
# This is a bit ugly, but it avoids running this again.
delattr(obj.__class__, self.name)
return result
class MovedModule(_LazyDescr):
def __init__(self, name, old, new=None):
super(MovedModule, self).__init__(name)
if PY3:
if new is None:
new = name
self.mod = new
else:
self.mod = old
def _resolve(self):
return _import_module(self.mod)
def __getattr__(self, attr):
# It turns out many Python frameworks like to traverse sys.modules and
# try to load various attributes. This causes problems if this is a
# platform-specific module on the wrong platform, like _winreg on
# Unixes. Therefore, we silently pretend unimportable modules do not
# have any attributes. See issues #51, #53, #56, and #63 for the full
# tales of woe.
#
# First, if possible, avoid loading the module just to look at __file__,
# __name__, or __path__.
if (attr in ("__file__", "__name__", "__path__") and self.mod not in sys.modules):
raise AttributeError(attr)
try:
_module = self._resolve()
except ImportError:
raise AttributeError(attr)
value = getattr(_module, attr)
setattr(self, attr, value)
return value
class _LazyModule(types.ModuleType):
def __init__(self, name):
super(_LazyModule, self).__init__(name)
self.__doc__ = self.__class__.__doc__
def __dir__(self):
attrs = ["__doc__", "__name__"]
attrs += [attr.name for attr in self._moved_attributes]
return attrs
# Subclasses should override this
_moved_attributes = []
class MovedAttribute(_LazyDescr):
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
super(MovedAttribute, self).__init__(name)
if PY3:
if new_mod is None:
new_mod = name
self.mod = new_mod
if new_attr is None:
if old_attr is None:
new_attr = name
else:
new_attr = old_attr
self.attr = new_attr
else:
self.mod = old_mod
if old_attr is None:
old_attr = name
self.attr = old_attr
def _resolve(self):
module = _import_module(self.mod)
return getattr(module, self.attr)
class _MovedItems(_LazyModule):
"""Lazy loading of moved objects"""
_moved_attributes = [
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
MovedAttribute("reduce", "__builtin__", "functools"),
MovedAttribute("StringIO", "StringIO", "io"),
MovedAttribute("UserDict", "UserDict", "collections"),
MovedAttribute("UserList", "UserList", "collections"),
MovedAttribute("UserString", "UserString", "collections"),
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
MovedModule("builtins", "__builtin__"),
MovedModule("configparser", "ConfigParser"),
MovedModule("copyreg", "copy_reg"),
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
MovedModule("http_cookies", "Cookie", "http.cookies"),
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
MovedModule("html_parser", "HTMLParser", "html.parser"),
MovedModule("http_client", "httplib", "http.client"),
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
MovedModule("cPickle", "cPickle", "pickle"),
MovedModule("queue", "Queue"),
MovedModule("reprlib", "repr"),
MovedModule("socketserver", "SocketServer"),
MovedModule("_thread", "thread", "_thread"),
MovedModule("tkinter", "Tkinter"),
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"),
MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"),
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"),
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
MovedModule("xmlrpc_server", "xmlrpclib", "xmlrpc.server"),
MovedModule("winreg", "_winreg"),
]
for attr in _moved_attributes:
setattr(_MovedItems, attr.name, attr)
if isinstance(attr, MovedModule):
sys.modules[__name__ + ".moves." + attr.name] = attr
del attr
_MovedItems._moved_attributes = _moved_attributes
moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves")
class Module_six_moves_urllib_parse(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_parse"""
_urllib_parse_moved_attributes = [
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
MovedAttribute("quote", "urllib", "urllib.parse"),
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote", "urllib", "urllib.parse"),
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
MovedAttribute("urlencode", "urllib", "urllib.parse"),
MovedAttribute("splitquery", "urllib", "urllib.parse"),
]
for attr in _urllib_parse_moved_attributes:
setattr(Module_six_moves_urllib_parse, attr.name, attr)
del attr
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[
__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ +
".moves.urllib_parse")
class Module_six_moves_urllib_error(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_error"""
_urllib_error_moved_attributes = [
MovedAttribute("URLError", "urllib2", "urllib.error"),
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
]
for attr in _urllib_error_moved_attributes:
setattr(Module_six_moves_urllib_error, attr.name, attr)
del attr
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[
__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ +
".moves.urllib.error")
class Module_six_moves_urllib_request(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_request"""
_urllib_request_moved_attributes = [
MovedAttribute("urlopen", "urllib2", "urllib.request"),
MovedAttribute("install_opener", "urllib2", "urllib.request"),
MovedAttribute("build_opener", "urllib2", "urllib.request"),
MovedAttribute("pathname2url", "urllib", "urllib.request"),
MovedAttribute("url2pathname", "urllib", "urllib.request"),
MovedAttribute("getproxies", "urllib", "urllib.request"),
MovedAttribute("Request", "urllib2", "urllib.request"),
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
MovedAttribute("URLopener", "urllib", "urllib.request"),
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
]
for attr in _urllib_request_moved_attributes:
setattr(Module_six_moves_urllib_request, attr.name, attr)
del attr
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[
__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ +
".moves.urllib.request")
class Module_six_moves_urllib_response(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_response"""
_urllib_response_moved_attributes = [
MovedAttribute("addbase", "urllib", "urllib.response"),
MovedAttribute("addclosehook", "urllib", "urllib.response"),
MovedAttribute("addinfo", "urllib", "urllib.response"),
MovedAttribute("addinfourl", "urllib", "urllib.response"),
]
for attr in _urllib_response_moved_attributes:
setattr(Module_six_moves_urllib_response, attr.name, attr)
del attr
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[
__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ +
".moves.urllib.response")
class Module_six_moves_urllib_robotparser(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
_urllib_robotparser_moved_attributes = [
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
]
for attr in _urllib_robotparser_moved_attributes:
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
del attr
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[
__name__ +
".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ +
".moves.urllib.robotparser")
class Module_six_moves_urllib(types.ModuleType):
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
parse = sys.modules[__name__ + ".moves.urllib_parse"]
error = sys.modules[__name__ + ".moves.urllib_error"]
request = sys.modules[__name__ + ".moves.urllib_request"]
response = sys.modules[__name__ + ".moves.urllib_response"]
robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"]
def __dir__(self):
return ['parse', 'error', 'request', 'response', 'robotparser']
sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib")
def add_move(move):
"""Add an item to six.moves."""
setattr(_MovedItems, move.name, move)
def remove_move(name):
"""Remove item from six.moves."""
try:
delattr(_MovedItems, name)
except AttributeError:
try:
del moves.__dict__[name]
except KeyError:
raise AttributeError("no such move, %r" % (name, ))
if PY3:
_meth_func = "__func__"
_meth_self = "__self__"
_func_closure = "__closure__"
_func_code = "__code__"
_func_defaults = "__defaults__"
_func_globals = "__globals__"
else:
_meth_func = "im_func"
_meth_self = "im_self"
_func_closure = "func_closure"
_func_code = "func_code"
_func_defaults = "func_defaults"
_func_globals = "func_globals"
try:
advance_iterator = next
except NameError:
def advance_iterator(it):
return it.next()
next = advance_iterator
try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
if PY3:
def get_unbound_function(unbound):
return unbound
create_bound_method = types.MethodType
Iterator = object
else:
def get_unbound_function(unbound):
return unbound.im_func
def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)
class Iterator(object):
def next(self):
return type(self).__next__(self)
callable = callable
_add_doc(get_unbound_function, """Get the function out of a possibly unbound function""")
get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)
if PY3:
def iterkeys(d, **kw):
return iter(d.keys(**kw))
def itervalues(d, **kw):
return iter(d.values(**kw))
def iteritems(d, **kw):
return iter(d.items(**kw))
def iterlists(d, **kw):
return iter(d.lists(**kw))
else:
def iterkeys(d, **kw):
return iter(d.iterkeys(**kw))
def itervalues(d, **kw):
return iter(d.itervalues(**kw))
def iteritems(d, **kw):
return iter(d.iteritems(**kw))
def iterlists(d, **kw):
return iter(d.iterlists(**kw))
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
_add_doc(iteritems, "Return an iterator over the (key, value) pairs of a dictionary.")
_add_doc(iterlists, "Return an iterator over the (key, [values]) pairs of a dictionary.")
if PY3:
def b(s):
return s.encode("latin-1")
def u(s):
return s
unichr = chr
if sys.version_info[1] <= 1:
def int2byte(i):
return bytes((i, ))
else:
# This is about 2x faster than the implementation above on 3.2+
int2byte = operator.methodcaller("to_bytes", 1, "big")
byte2int = operator.itemgetter(0)
indexbytes = operator.getitem
iterbytes = iter
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
else:
def b(s):
return s
# Workaround for standalone backslash
def u(s):
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
unichr = unichr
int2byte = chr
def byte2int(bs):
return ord(bs[0])
def indexbytes(buf, i):
return ord(buf[i])
def iterbytes(buf):
return (ord(byte) for byte in buf)
import StringIO
StringIO = BytesIO = StringIO.StringIO
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")
if PY3:
exec_ = getattr(moves.builtins, "exec")
def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
else:
def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")
exec_("""def reraise(tp, value, tb=None):
raise tp, value, tb
""")
print_ = getattr(moves.builtins, "print", None)
if print_ is None:
def print_(*args, **kwargs):
"""The new-style print function for Python 2.4 and 2.5."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return
def write(data):
if not isinstance(data, basestring):
data = str(data)
# If the file has an encoding, encode unicode with it.
if (isinstance(fp, file) and isinstance(data, unicode) and fp.encoding is not None):
errors = getattr(fp, "errors", None)
if errors is None:
errors = "strict"
data = data.encode(fp.encoding, errors)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
_add_doc(reraise, """Reraise an exception.""")
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
return meta("NewBase", bases, {})
def add_metaclass(metaclass):
"""Class decorator for creating a class with a metaclass."""
def wrapper(cls):
orig_vars = cls.__dict__.copy()
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str):
slots = [slots]
for slots_var in slots:
orig_vars.pop(slots_var)
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper
# added as part of the RDKit port
if PY3:
def cmp(t1, t2):
return (t1 < t2) * -1 or (t1 > t2) * 1
else:
cmp = cmp

View File

@@ -1,14 +0,0 @@
tests = [
("python", "test_list.py", {
'dir': 'tests'
}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,12 +0,0 @@
tests = [
("python", "testallps.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,14 +0,0 @@
tests = [
# Only local unit tests go in here!
# Subdirectories get their own entries in ./CMakeLists.txt
("python", "UnitTestLogging.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))

View File

@@ -1,78 +0,0 @@
"""
$Id$
Original author: Thorsten Henninger <henni@brainbot.com>
Info about this file: http://mail.python.org/pipermail/python-win32/2003-December/001453.html
Use this in confuction with McMillan-Installer, if you need COM-Support in your application.
McMillan Installer as well as PythonCOM do overwrite the import Method for their needs.
_myimport advises the imports to either PythonCOM-Import or McMillan Import.
set_gen_path: use this method to specify the gencache-path, where all Python-COMObjects will be
automatically generated in.
One needs to Patch the McMillan Installer such that the Python-nativ import has to be saved as
__oldimport__
Use this hack in your application with
import comhack
set_gen_path(mypath)
Then everything will work ...
"""
import sys
import __builtin__
#save the import-Method (either McMillan's import or Python's)
mcimport = __builtin__.__import__
def _myimport(name, globals=None, locals=None, fromlist=None):
"""
Tell all modules to imported by McMillan's (or Python's) import.method,
besides win32com modules automatically genrated by win32com.gencache
"""
try:
#fails with ImportError, if McMillan has overwritten Python's native import
#and win32com.gen_py tries to generate a module
return mcimport(name, globals, locals, fromlist)
except ImportError as err:
if name.startswith('win32com.gen_py'):
#this is the Python-Native Import Method, if a patched McMillan-Installer exists
return __oldimport__(name, globals, locals, fromlist)
else:
#win32com needs this ImportError
raise err
def set_gen_path(path):
"""
Set the gencache Path
If not set, all Modules (win32com) will be generated to support/gen_py of your apllication.
"""
import os
import win32com
import win32com.gen_py
path = os.path.abspath(path)
if not os.path.exists(path):
os.makedirs(path)
#check, if McMillan runs ...
frozen = sys.__dict__.get("frozen", 0)
#set the gencache path
win32com.gen_py.__path__ = [path]
win32com.__gen_path__ = path
if not frozen:
return
#setup our import method, if McMillan runs.
__builtin__.__import__ = _myimport

View File

@@ -1,12 +0,0 @@
tests = [
("python", "UnitTestUtils.py", {}),
]
longTests = []
if __name__ == '__main__':
import sys
from rdkit import TestRunner
failed, tests = TestRunner.RunScript('test_list.py', 0, 1)
sys.exit(len(failed))