Skip to content

Migration to pyproject #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/distanceprinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def _addPairContribution(self, bnds, sumscale):
distprint._setDoubleAttr('rmax', 10)

def get_pyobjcryst_sphalerite():
from pyobjcryst import loadCrystal
crst = loadCrystal('datafiles/sphalerite.cif')
from pyobjcryst.crystal import create_crystal_from_cif
crst = create_crystal_from_cif('datafiles/sphalerite.cif')
return crst

def main():
Expand Down
4 changes: 2 additions & 2 deletions examples/parallelPDF.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
# load menthol structure and make sure Uiso values are non-zero
if opts.pyobjcryst:
# use pyobjcryst if requested by the user
from pyobjcryst import loadCrystal
from pyobjcryst.crystal import create_crystal_crom_cif
from numpy import pi
menthol = loadCrystal(mentholcif)
menthol = create_crystal_crom_cif(mentholcif)
for sc in menthol.GetScatteringComponentList():
sp = sc.mpScattPow
sp.Biso = sp.Biso or 8 * pi**2 * Uisodefault
Expand Down
56 changes: 56 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[build-system]
requires = ["setuptools>=62.0", "setuptools-git-versioning<2", "numpy"]
build-backend = "setuptools.build_meta"

[project]
name = "diffpy.srreal"
dynamic=['version']
authors = [
{ name="Simon J.L. Billinge group", email="[email protected]" },
]
maintainers = [
{ name="Simon J.L. Billinge group", email="[email protected]" },
]
description = "calculators for PDF, bond valence sum, and other quantities based on atom pair interaction."
keywords = ["PDF BVS atom overlap calculator real-space"]
readme = "README.rst"
requires-python = ">=3.9"
dependencies = [
"diffpy.structure",
]
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX',
'Operating System :: Unix',
'Programming Language :: C++',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Topic :: Scientific/Engineering :: Chemistry',
'Topic :: Scientific/Engineering :: Physics',
'Topic :: Software Development :: Libraries',
]

[project.urls]
Homepage = "https://github.com/diffpy/diffpy.srreal/"
Issues = "https://github.com/diffpy/diffpy.srreal/issues"

[tool.setuptools-git-versioning]
enabled = true
template = "{tag}"
dev_template = "{tag}"
dirty_template = "{tag}"

[tool.setuptools.packages.find]
where = ["src"] # list of folders that contain the packages (["."] by default)
include = ["diffpy*"] # package names should match these glob patterns (["*"] by default)
exclude = ["diffpy.srreal.tests*"] # exclude packages matching these glob patterns (empty by default)
namespaces = false # to disable scanning PEP 420 namespaces (true by default)
114 changes: 5 additions & 109 deletions setup.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
import re
import sys
import glob
from setuptools import setup, find_packages
from setuptools import setup
from setuptools import Extension
from numpy.distutils.misc_util import get_numpy_include_dirs
import numpy as np


# Use this version when git data are not available, like in git zip archive.
Expand All @@ -27,7 +27,7 @@
'libraries' : ['diffpy'],
'extra_compile_args' : ['-std=c++11'],
'extra_link_args' : [],
'include_dirs' : get_numpy_include_dirs(),
'include_dirs' : [np.get_include()],
}

# determine if we run with Python 3.
Expand Down Expand Up @@ -78,116 +78,12 @@ def create_extensions():
return [ext]


# versioncfgfile holds version data for git commit hash and date.
# It must reside in the same directory as version.py.
MYDIR = os.path.dirname(os.path.abspath(__file__))
versioncfgfile = os.path.join(MYDIR, 'src/diffpy/srreal/version.cfg')
gitarchivecfgfile = os.path.join(MYDIR, '.gitarchive.cfg')


def gitinfo():
from subprocess import Popen, PIPE
kw = dict(stdout=PIPE, cwd=MYDIR, universal_newlines=True)
proc = Popen(['git', 'describe', '--match=v[[:digit:]]*'], **kw)
desc = proc.stdout.read()
proc = Popen(['git', 'log', '-1', '--format=%H %ct %ci'], **kw)
glog = proc.stdout.read()
rv = {}
rv['version'] = '.post'.join(desc.strip().split('-')[:2]).lstrip('v')
rv['commit'], rv['timestamp'], rv['date'] = glog.strip().split(None, 2)
return rv


def getversioncfg():
if PY3:
from configparser import RawConfigParser
else:
from ConfigParser import RawConfigParser
vd0 = dict(version=FALLBACK_VERSION, commit='', date='', timestamp=0)
# first fetch data from gitarchivecfgfile, ignore if it is unexpanded
g = vd0.copy()
cp0 = RawConfigParser(vd0)
cp0.read(gitarchivecfgfile)
if len(cp0.get('DEFAULT', 'commit')) > 20:
g = cp0.defaults()
mx = re.search(r'\btag: v(\d[^,]*)', g.pop('refnames'))
if mx:
g['version'] = mx.group(1)
# then try to obtain version data from git.
gitdir = os.path.join(MYDIR, '.git')
if os.path.exists(gitdir) or 'GIT_DIR' in os.environ:
try:
g = gitinfo()
except OSError:
pass
# finally, check and update the active version file
cp = RawConfigParser()
cp.read(versioncfgfile)
d = cp.defaults()
rewrite = not d or (g['commit'] and (
g['version'] != d.get('version') or g['commit'] != d.get('commit')))
if rewrite:
cp.set('DEFAULT', 'version', g['version'])
cp.set('DEFAULT', 'commit', g['commit'])
cp.set('DEFAULT', 'date', g['date'])
cp.set('DEFAULT', 'timestamp', g['timestamp'])
with open(versioncfgfile, 'w') as fp:
cp.write(fp)
return cp

versiondata = getversioncfg()

with open(os.path.join(MYDIR, 'README.rst')) as fp:
long_description = fp.read()

# define distribution
# Extensions not included in pyproject.toml
setup_args = dict(
name = "diffpy.srreal",
version = versiondata.get('DEFAULT', 'version'),
packages = find_packages(os.path.join(MYDIR, 'src')),
package_dir = {'' : 'src'},
test_suite = 'diffpy.srreal.tests',
include_package_data = True,
ext_modules = [],
install_requires = [
'diffpy.structure',
],
zip_safe = False,

author = "Simon J.L. Billinge group",
author_email = "[email protected]",
maintainer = "Pavol Juhas",
maintainer_email = "[email protected]",
description = ("calculators for PDF, bond valence sum, and other "
"quantities based on atom pair interaction."),
long_description = long_description,
long_description_content_type = 'text/x-rst',
license = 'BSD-style license',
url = "https://github.com/diffpy/diffpy.srreal/",
keywords = "PDF BVS atom overlap calculator real-space",
classifiers = [
# List of possible values at
# http://pypi.python.org/pypi?:action=list_classifiers
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX',
'Operating System :: Unix',
'Programming Language :: C++',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Scientific/Engineering :: Chemistry',
'Topic :: Scientific/Engineering :: Physics',
'Topic :: Software Development :: Libraries',
],
)


if __name__ == '__main__':
setup_args['ext_modules'] = create_extensions()
setup(**setup_args)
Expand Down
23 changes: 12 additions & 11 deletions src/diffpy/srreal/_version_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,22 @@

import os.path

from pkg_resources import resource_filename
from importlib.resources import files, as_file


# obtain version information from the version.cfg file
cp = dict(version='', date='', commit='', timestamp='0')
fcfg = resource_filename(__name__, 'version.cfg')
if not os.path.isfile(fcfg): # pragma: no cover
from warnings import warn
warn('Package metadata not found, execute "./setup.py egg_info".')
fcfg = os.devnull
with open(fcfg) as fp:
kwords = [[w.strip() for w in line.split(' = ', 1)]
for line in fp if line[:1].isalpha() and ' = ' in line]
assert all(w[0] in cp for w in kwords), "received unrecognized keyword"
cp.update(kwords)
ref = files(__package__) / 'version.cfg'
with as_file(ref) as fcfg:
if not os.path.isfile(fcfg): # pragma: no cover
from warnings import warn
warn('Package metadata not found, execute "./setup.py egg_info".')
fcfg = os.devnull
with open(fcfg) as fp:
kwords = [[w.strip() for w in line.split(' = ', 1)]
for line in fp if line[:1].isalpha() and ' = ' in line]
assert all(w[0] in cp for w in kwords), "received unrecognized keyword"
cp.update(kwords)

__version__ = cp['version']
__date__ = cp['date']
Expand Down
47 changes: 24 additions & 23 deletions src/diffpy/srreal/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,31 @@ def testsuite(pattern=''):
import re
from os.path import dirname
from itertools import chain
from pkg_resources import resource_filename
from importlib.resources import files, as_file
loader = unittest.defaultTestLoader
thisdir = resource_filename(__name__, '')
depth = __name__.count('.') + 1
topdir = thisdir
for i in range(depth):
topdir = dirname(topdir)
suite_all = loader.discover(thisdir, top_level_dir=topdir)
# always filter the suite by pattern to test-cover the selection code.
suite = unittest.TestSuite()
rx = re.compile(pattern)
tsuites = list(chain.from_iterable(suite_all))
tsok = all(isinstance(ts, unittest.TestSuite) for ts in tsuites)
if not tsok: # pragma: no cover
return suite_all
tcases = chain.from_iterable(tsuites)
for tc in tcases:
tcwords = tc.id().split('.')
shortname = '.'.join(tcwords[-3:])
if rx.search(shortname):
suite.addTest(tc)
# verify all tests are found for an empty pattern.
assert pattern or suite_all.countTestCases() == suite.countTestCases()
return suite
ref = files(__package__)
with as_file(ref) as thisdir:
depth = __name__.count('.') + 1
topdir = thisdir
for i in range(depth):
topdir = dirname(topdir)
suite_all = loader.discover(thisdir, top_level_dir=topdir)
# always filter the suite by pattern to test-cover the selection code.
suite = unittest.TestSuite()
rx = re.compile(pattern)
tsuites = list(chain.from_iterable(suite_all))
tsok = all(isinstance(ts, unittest.TestSuite) for ts in tsuites)
if not tsok: # pragma: no cover
return suite_all
tcases = chain.from_iterable(tsuites)
for tc in tcases:
tcwords = tc.id().split('.')
shortname = '.'.join(tcwords[-3:])
if rx.search(shortname):
suite.addTest(tc)
# verify all tests are found for an empty pattern.
assert pattern or suite_all.countTestCases() == suite.countTestCases()
return suite


def test():
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srreal/tests/testoverlapcalculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def test_gradients(self):
tso0 = olc.totalsquareoverlap
dx = 1e-8
rutile2 = loadDiffPyStructure('rutile.cif')
rutile2[2].xyz_cartn += [dx, 0.0, 0.0]
rutile2[2].xyz_cartn[0] += dx
olc.eval(rutile2)
g2nx = (olc.totalsquareoverlap - tso0) / dx
self.assertAlmostEqual(g2[0], g2nx, 6)
Expand Down
4 changes: 2 additions & 2 deletions src/diffpy/srreal/tests/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ def datafile(filename):


def loadObjCrystCrystal(filename):
from pyobjcryst import loadCrystal
from pyobjcryst.crystal import create_crystal_from_cif
fullpath = datafile(filename)
crst = loadCrystal(fullpath)
crst = create_crystal_from_cif(fullpath)
return crst


Expand Down