diff --git a/Code/GraphMol/Descriptors/test_data/pmi.py b/Code/GraphMol/Descriptors/test_data/pmi.py index 858bccac0..a00794e74 100644 --- a/Code/GraphMol/Descriptors/test_data/pmi.py +++ b/Code/GraphMol/Descriptors/test_data/pmi.py @@ -13,16 +13,17 @@ from rdkit.Chem import AllChem import numpy as np from numpy import linalg + def GetMoments(mol, includeWeights): conf = mol.GetConformer() if includeWeights: weights = [x.GetMass() for x in mol.GetAtoms()] else: - weights = [1.0]*mol.GetNumAtoms() + weights = [1.0] * mol.GetNumAtoms() pts = [conf.GetAtomPosition(i) for i in range(mol.GetNumAtoms())] wSum = sum(weights) - origin = np.sum([pts[i]*weights[i] for i in range(mol.GetNumAtoms())], 0) + origin = np.sum([pts[i] * weights[i] for i in range(mol.GetNumAtoms())], 0) origin /= wSum sumXX = 0 sumXY = 0 @@ -31,8 +32,8 @@ def GetMoments(mol, includeWeights): sumYZ = 0 sumZZ = 0 sums = np.zeros((3, 3), np.double) - for j,pt in enumerate(pts): - dp = weights[j]*(pt - origin) + for j, pt in enumerate(pts): + dp = weights[j] * (pt - origin) for i in range(3): sums[i, i] += dp[i] * dp[i] for j in range(i + 1, 3): @@ -43,10 +44,12 @@ def GetMoments(mol, includeWeights): vals = sorted(vals) return vals + if __name__ == '__main__': suppl = Chem.SDMolSupplier('./PBF_egfr.sdf', removeHs=False) output = open('./PMI_egfr.out', 'w+') for m in suppl: - i1,i2,i3 = GetMoments(m,True) - mi1,mi2,mi3 = GetMoments(m,False) - print("%s %.4f %.4f %.4f %.4f %.4f %.4f"%(m.GetProp("_Name"),i1,i2,i3,mi1,mi2,mi3),file=output) + i1, i2, i3 = GetMoments(m, True) + mi1, mi2, mi3 = GetMoments(m, False) + print("%s %.4f %.4f %.4f %.4f %.4f %.4f" % (m.GetProp("_Name"), i1, i2, i3, mi1, mi2, mi3), + file=output) diff --git a/Code/GraphMol/MolDraw2D/test_dir/test_rdkit_draw.py b/Code/GraphMol/MolDraw2D/test_dir/test_rdkit_draw.py index 4ab4de042..57892daf1 100755 --- a/Code/GraphMol/MolDraw2D/test_dir/test_rdkit_draw.py +++ b/Code/GraphMol/MolDraw2D/test_dir/test_rdkit_draw.py @@ -1,5 +1,5 @@ #!/usr/bin/env python - +from __future__ import print_function from rdkit import RDConfig import os, sys from rdkit import Chem @@ -12,11 +12,11 @@ if sys.argv[1].endswith('.sdf'): elif sys.argv[1].endswith('.smi'): suppl = Chem.SmilesMolSupplier(sys.argv[1]) else: - print 'Need a file ending in .sdf or .smi' + print('Need a file ending in .sdf or .smi') exit(1) for mol in suppl: - print mol.GetProp('_Name') + print(mol.GetProp('_Name')) fn = mol.GetProp('_Name') + '.png' AllChem.Compute2DCoords(mol) Draw.MolToFile(mol, fn) diff --git a/Code/GraphMol/StructChecker/Wrap/rough_test.py b/Code/GraphMol/StructChecker/Wrap/rough_test.py index 22d5172d0..b5f7fe88d 100644 --- a/Code/GraphMol/StructChecker/Wrap/rough_test.py +++ b/Code/GraphMol/StructChecker/Wrap/rough_test.py @@ -159,20 +159,21 @@ M CHG 1 11 1 M END """ -class TestCase(unittest.TestCase): - def testStructOptions(self): - rdStructChecker.StructCheckerOptions() - def testStructChecker(self): - checker = rdStructChecker.StructChecker() - - - m = Chem.MolFromMolBlock(data) - self.assertTrue(m) - - res = checker.CheckMolStructure(m) - self.assertEquals(res, rdStructChecker.StructureFlags.ATOM_CHECK_FAILED) +class TestCase(unittest.TestCase): + + def testStructOptions(self): + rdStructChecker.StructCheckerOptions() + + def testStructChecker(self): + checker = rdStructChecker.StructChecker() + + m = Chem.MolFromMolBlock(data) + self.assertTrue(m) + + res = checker.CheckMolStructure(m) + self.assertEquals(res, rdStructChecker.StructureFlags.ATOM_CHECK_FAILED) + if __name__ == '__main__': - unittest.main() - + unittest.main() diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index 687dcda40..b48e0ad9e 100755 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -514,14 +514,11 @@ class TestCase(unittest.TestCase): m.SetProp("int", "1000") m.SetProp("double", "10000.123") print(m.GetPropsAsDict()) - self.assertEquals(m.GetPropsAsDict(), - {"int":1000, - "double":10000.123}) + self.assertEquals(m.GetPropsAsDict(), {"int": 1000, "double": 10000.123}) self.assertEquals(type(m.GetPropsAsDict()['int']), int) self.assertEquals(type(m.GetPropsAsDict()['double']), float) - def test17Kekulize(self): m = Chem.MolFromSmiles('c1ccccc1') smi = Chem.MolToSmiles(m) diff --git a/Code/GraphMol/Wrap/testConformer.py b/Code/GraphMol/Wrap/testConformer.py index 99b7d0039..418d29279 100644 --- a/Code/GraphMol/Wrap/testConformer.py +++ b/Code/GraphMol/Wrap/testConformer.py @@ -122,7 +122,6 @@ class TestCase(unittest.TestCase): confs = m.GetConformers() self.assertTrue(confs == ()) - def test5PositionsArray(self): smi = 'c1ccccc1' m = Chem.MolFromSmiles(smi) @@ -133,7 +132,7 @@ class TestCase(unittest.TestCase): for conf in confs: pos = conf.GetPositions() - self.assertTrue(pos.shape, (6,3)) + self.assertTrue(pos.shape, (6, 3)) m.RemoveAllConformers() self.assertTrue(m.GetNumConformers() == 0) diff --git a/Code/cmake/Modules/fixup_coverage.py b/Code/cmake/Modules/fixup_coverage.py index 5b2c89eb3..472c0c5c9 100644 --- a/Code/cmake/Modules/fixup_coverage.py +++ b/Code/cmake/Modules/fixup_coverage.py @@ -3,10 +3,10 @@ the coverage tool mistakenly finds in the build tree. It replaces the paths with the ones from the source tree n.b. if a file with the same name (i.e. sln.yy) is found twice in the source tree, this will break""" - +from __future__ import print_function import os, sys source_dir, info_file = sys.argv[1:3] -print source_dir, info_file +print(source_dir, info_file) paths = {} for root, dir, files in os.walk(source_dir): @@ -20,13 +20,13 @@ for line in lines: if "SF:" in line: fn = line.split("SF:")[-1].strip() if not os.path.exists(fn): - print "Does not exist:", fn.strip() + print("Does not exist:", fn.strip()) head, rest = os.path.split(fn) potential = paths[rest] if len(potential) == 1: line = "SF:" + potential[0] else: - asdf + raise NotImplementedError('asdf') newlines.append(line) open(info_file, 'w').write("\n".join(newlines)) diff --git a/Scripts/PythonFormat.py b/Scripts/PythonFormat.py new file mode 100644 index 000000000..2305256d6 --- /dev/null +++ b/Scripts/PythonFormat.py @@ -0,0 +1,69 @@ +''' + +Script will test the RDkit python code for conformance with the agreed format using +yapf. + +For each Python file that is found in $RDBASE (excluding the build and External +directories), yapf is used with the style configuration in $RDBASE/setup.cfg. +If a change is required, the difference is printed. At the end of the process, +all non-conformant files are listed and the required yapf command(s) printed. + +If changes are found, the script will exit with error code 1, otherwise 0. + +''' +from __future__ import print_function +import os +from yapf.yapflib.yapf_api import FormatCode +import sys + +rdbase = os.environ.get('RDBASE', '') +styleConfig = os.path.join(rdbase, 'setup.cfg') + +excludeDirs = [os.path.join(rdbase, 'build'), + os.path.join(rdbase, 'External'), ] + + +def pythonFiles(dirname=rdbase): + """ Find all python files below directory dirname """ + for root, _, files in os.walk(dirname): + if any(root.startswith(d) for d in excludeDirs): + continue + for file in files: + if file.endswith(".py"): + yield os.path.join(root, file) + + +def yapfChanges(filename): + """ Use yapf with the default settings to format file filename """ + try: + with open(filename) as f: + codeBefore = f.read() + except UnicodeError: + with open(filename, encoding='latin-1') as f: + codeBefore = f.read() + try: + changes, changed = FormatCode(codeBefore, style_config=styleConfig, print_diff=True, + filename=filename) + except Exception: + print(filename) + raise + if changed: + print(changes) + return changed + + +if __name__ == "__main__": + changedFiles = [] + for s in pythonFiles(): + if yapfChanges(s): + changedFiles.append(s) + print() + if changedFiles: + print('yapf will make changes to the following files:') + print('\n'.join(sorted(changedFiles))) + print('To apply the required changes to your code use the following command(s)') + for s in sorted(set(s.replace(rdbase, '').split(os.sep)[1] for s in changedFiles)): + print('yapf --style $RDBASE/setup.cfg --in-place --recursive $RDBASE/{0}'.format(s)) + sys.exit(1) + print('Code complies with the agreed formatting rules.') + sys.exit(0) diff --git a/rdkit/Chem/Descriptors3D.py b/rdkit/Chem/Descriptors3D.py index 7cc0fccf4..6ae16fc08 100644 --- a/rdkit/Chem/Descriptors3D.py +++ b/rdkit/Chem/Descriptors3D.py @@ -13,10 +13,10 @@ from __future__ import print_function from rdkit.Chem import rdMolDescriptors -if hasattr(rdMolDescriptors,'CalcPMI1'): - PMI1 = lambda *x,**y:rdMolDescriptors.CalcPMI1(*x,**y) - PMI1.version = rdMolDescriptors._CalcPMI1_version - PMI1.__doc__= """ First (smallest) principal moment of inertia +if hasattr(rdMolDescriptors, 'CalcPMI1'): + PMI1 = lambda *x, **y: rdMolDescriptors.CalcPMI1(*x, **y) + PMI1.version = rdMolDescriptors._CalcPMI1_version + PMI1.__doc__ = """ First (smallest) principal moment of inertia **Arguments** @@ -27,9 +27,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - PMI2 = lambda *x,**y:rdMolDescriptors.CalcPMI2(*x,**y) - PMI2.version = rdMolDescriptors._CalcPMI2_version - PMI2.__doc__= """ Second principal moment of inertia + PMI2 = lambda *x, **y: rdMolDescriptors.CalcPMI2(*x, **y) + PMI2.version = rdMolDescriptors._CalcPMI2_version + PMI2.__doc__ = """ Second principal moment of inertia **Arguments** @@ -40,9 +40,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - PMI3 = lambda *x,**y:rdMolDescriptors.CalcPMI3(*x,**y) - PMI3.version = rdMolDescriptors._CalcPMI3_version - PMI3.__doc__= """ Third (largest) principal moment of inertia + PMI3 = lambda *x, **y: rdMolDescriptors.CalcPMI3(*x, **y) + PMI3.version = rdMolDescriptors._CalcPMI3_version + PMI3.__doc__ = """ Third (largest) principal moment of inertia **Arguments** @@ -53,9 +53,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - NPR1 = lambda *x,**y:rdMolDescriptors.CalcNPR1(*x,**y) - NPR1.version = rdMolDescriptors._CalcNPR1_version - NPR1.__doc__= """ Normalized principal moments ratio 1 (=I1/I3) + NPR1 = lambda *x, **y: rdMolDescriptors.CalcNPR1(*x, **y) + NPR1.version = rdMolDescriptors._CalcNPR1_version + NPR1.__doc__ = """ Normalized principal moments ratio 1 (=I1/I3) from Sauer and Schwarz JCIM 43:987-1003 (2003) https://dx.doi.org/10.1021/ci025599w @@ -70,9 +70,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - NPR2 = lambda *x,**y:rdMolDescriptors.CalcNPR2(*x,**y) - NPR2.version = rdMolDescriptors._CalcNPR2_version - NPR2.__doc__= """ Normalized principal moments ratio 2 (=I2/I3) + NPR2 = lambda *x, **y: rdMolDescriptors.CalcNPR2(*x, **y) + NPR2.version = rdMolDescriptors._CalcNPR2_version + NPR2.__doc__ = """ Normalized principal moments ratio 2 (=I2/I3) from Sauer and Schwarz JCIM 43:987-1003 (2003) https://dx.doi.org/10.1021/ci025599w @@ -87,9 +87,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - RadiusOfGyration = lambda *x,**y:rdMolDescriptors.CalcRadiusOfGyration(*x,**y) - RadiusOfGyration.version = rdMolDescriptors._CalcRadiusOfGyration_version - RadiusOfGyration.__doc__= """ Radius of gyration + RadiusOfGyration = lambda *x, **y: rdMolDescriptors.CalcRadiusOfGyration(*x, **y) + RadiusOfGyration.version = rdMolDescriptors._CalcRadiusOfGyration_version + RadiusOfGyration.__doc__ = """ Radius of gyration from Todeschini and Consoni "Descriptors from Molecular Geometry" Handbook of Chemoinformatics @@ -108,9 +108,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - InertialShapeFactor = lambda *x,**y:rdMolDescriptors.CalcInertialShapeFactor(*x,**y) - InertialShapeFactor.version = rdMolDescriptors._CalcInertialShapeFactor_version - InertialShapeFactor.__doc__= """ Inertial shape factor + InertialShapeFactor = lambda *x, **y: rdMolDescriptors.CalcInertialShapeFactor(*x, **y) + InertialShapeFactor.version = rdMolDescriptors._CalcInertialShapeFactor_version + InertialShapeFactor.__doc__ = """ Inertial shape factor from Todeschini and Consoni "Descriptors from Molecular Geometry" Handbook of Chemoinformatics @@ -128,9 +128,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - Eccentricity = lambda *x,**y:rdMolDescriptors.CalcEccentricity(*x,**y) - Eccentricity.version = rdMolDescriptors._CalcEccentricity_version - Eccentricity.__doc__= """ molecular eccentricity + Eccentricity = lambda *x, **y: rdMolDescriptors.CalcEccentricity(*x, **y) + Eccentricity.version = rdMolDescriptors._CalcEccentricity_version + Eccentricity.__doc__ = """ molecular eccentricity from Todeschini and Consoni "Descriptors from Molecular Geometry" Handbook of Chemoinformatics @@ -148,9 +148,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - Asphericity = lambda *x,**y:rdMolDescriptors.CalcAsphericity(*x,**y) - Asphericity.version = rdMolDescriptors._CalcAsphericity_version - Asphericity.__doc__= """ molecular asphericity + Asphericity = lambda *x, **y: rdMolDescriptors.CalcAsphericity(*x, **y) + Asphericity.version = rdMolDescriptors._CalcAsphericity_version + Asphericity.__doc__ = """ molecular asphericity from Todeschini and Consoni "Descriptors from Molecular Geometry" Handbook of Chemoinformatics @@ -168,9 +168,9 @@ if hasattr(rdMolDescriptors,'CalcPMI1'): - useAtomicMasses: (optional) toggles use of atomic masses in the calculation. Defaults to True """ - SpherocityIndex = lambda *x,**y:rdMolDescriptors.CalcSpherocityIndex(*x,**y) - SpherocityIndex.version = rdMolDescriptors._CalcSpherocityIndex_version - SpherocityIndex.__doc__= """ Molecular spherocityIndex + SpherocityIndex = lambda *x, **y: rdMolDescriptors.CalcSpherocityIndex(*x, **y) + SpherocityIndex.version = rdMolDescriptors._CalcSpherocityIndex_version + SpherocityIndex.__doc__ = """ Molecular spherocityIndex from Todeschini and Consoni "Descriptors from Molecular Geometry" Handbook of Chemoinformatics diff --git a/rdkit/Chem/Draw/IPythonConsole.py b/rdkit/Chem/Draw/IPythonConsole.py index f55bebd01..8491a8d47 100644 --- a/rdkit/Chem/Draw/IPythonConsole.py +++ b/rdkit/Chem/Draw/IPythonConsole.py @@ -60,6 +60,7 @@ shader_3d = "lambert" # in the IPythonConsole not the server logs. Chem.WrapLogs() + def _toJSON(mol): """For IPython notebook, renders 3D webGL objects.""" @@ -220,8 +221,7 @@ def InstallIPythonRenderer(): _MolsToGridImageSaved = Draw.MolsToGridImage Draw.MolsToGridImage = ShowMols rdchem.Mol.__DebugMol = rdchem.Mol.Debug - rdchem.Mol.Debug = lambda self,useStdout=False:self.__DebugMol(useStdout=useStdout) - + rdchem.Mol.Debug = lambda self, useStdout=False: self.__DebugMol(useStdout=useStdout) InstallIPythonRenderer() diff --git a/rdkit/Chem/Draw/UnitTestIPython.py b/rdkit/Chem/Draw/UnitTestIPython.py index e734f42c8..c6eb2e814 100644 --- a/rdkit/Chem/Draw/UnitTestIPython.py +++ b/rdkit/Chem/Draw/UnitTestIPython.py @@ -13,31 +13,29 @@ import unittest from rdkit import Chem from rdkit.Chem import Draw try: - from rdkit.Chem.Draw import IPythonConsole - from IPython.core.display import SVG + from rdkit.Chem.Draw import IPythonConsole + from IPython.core.display import SVG except ImportError: - IPythonConsole = None + IPythonConsole = None + class TestCase(unittest.TestCase): + def testGithub1089(self): if IPythonConsole is None: - return + return m = Chem.MolFromSmiles('CCCC') IPythonConsole.ipython_useSVG = False - res = Draw.MolsToGridImage((m,m)) - self.assertFalse(isinstance(res,SVG)) + res = Draw.MolsToGridImage((m, m)) + self.assertFalse(isinstance(res, SVG)) - res = Draw.MolsToGridImage((m,m),useSVG=True) - self.assertTrue(isinstance(res,SVG)) + res = Draw.MolsToGridImage((m, m), useSVG=True) + self.assertTrue(isinstance(res, SVG)) IPythonConsole.ipython_useSVG = True - res = Draw.MolsToGridImage((m,m)) - self.assertTrue(isinstance(res,SVG)) - - - - + res = Draw.MolsToGridImage((m, m)) + self.assertTrue(isinstance(res, SVG)) if __name__ == '__main__': diff --git a/rdkit/Chem/Draw/cairoCanvas.py b/rdkit/Chem/Draw/cairoCanvas.py index 95af7558a..bdc4ddc67 100644 --- a/rdkit/Chem/Draw/cairoCanvas.py +++ b/rdkit/Chem/Draw/cairoCanvas.py @@ -126,7 +126,7 @@ if not 'RDK_NOPANGO' in os.environ: except ImportError: exec(libType + ' = None') have_pango = (pango and pangocairo) - + if not hasattr(cairo.ImageSurface,'get_data') and \ not hasattr(cairo.ImageSurface,'get_data_as_rgba'): raise ImportError('cairo version too old') @@ -296,7 +296,7 @@ class Canvas(CanvasBase): # for whatever reason, the font size using pango is larger # than that w/ default cairo (at least for me) pangoCoeff = 0.8 - + if (have_cairocffi): measureLout = pangocairo.pango_cairo_create_layout(self.ctx._pointer) pango.pango_layout_set_alignment(measureLout, pango.PANGO_ALIGN_LEFT) @@ -307,25 +307,25 @@ class Canvas(CanvasBase): fnt = pango.pango_font_description_new() pango.pango_font_description_set_family(fnt, font.face.encode('latin1')) pango.pango_font_description_set_size(fnt, - int(round(font.size * pango.PANGO_SCALE * pangoCoeff))) + int(round(font.size * pango.PANGO_SCALE * pangoCoeff))) pango.pango_layout_set_font_description(lout, fnt) pango.pango_layout_set_font_description(measureLout, fnt) pango.pango_font_description_free(fnt) else: - cctx=pangocairo.CairoContext(self.ctx) + cctx = pangocairo.CairoContext(self.ctx) measureLout = cctx.create_layout() measureLout.set_alignment(pango.ALIGN_LEFT) measureLout.set_markup(plainText) lout = cctx.create_layout() lout.set_alignment(pango.ALIGN_LEFT) lout.set_markup(text) - fnt = pango.FontDescription('%s %d'%(font.face,font.size*pangoCoeff)) + fnt = pango.FontDescription('%s %d' % (font.face, font.size * pangoCoeff)) lout.set_font_description(fnt) measureLout.set_font_description(fnt) # this is a bit kludgy, but empirically we end up with too much # vertical padding if we use the text box with super and subscripts - # for the measurement. + # for the measurement. if (have_cairocffi): iext = ffi.new('PangoRectangle *') lext = ffi.new('PangoRectangle *') diff --git a/rdkit/TestRunner.py b/rdkit/TestRunner.py index 308dbfd6e..50f793650 100755 --- a/rdkit/TestRunner.py +++ b/rdkit/TestRunner.py @@ -107,8 +107,8 @@ def RunScript(script, doLongTests, verbose): 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) + for exeName, args, extras in failed: + print("!!! TEST FAILURE: ", exeName, args, extras, file=sys.stderr) return failed, nTests