Skip to content
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

Transition from using setup.py to pyproject.toml to specify project metadata #89

Merged
merged 12 commits into from
Mar 4, 2024
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install invoke rundoc .
python -m pip install tomli
python -m pip install packaging
- name: Run the README.md
run: invoke readme
4 changes: 2 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ This will perform the following actions:
2. Bump the current version to the next release candidate, ``X.Y.Z.dev(N+1)``

After this is done, the new pre-release can be installed by including the ``dev`` section in the
dependency specification, either in ``setup.py``::
dependency specification, either in ``pyproject.toml``::

install_requires = [
dependencies = [
...
'deepecho>=X.Y.Z.dev',
...
Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,7 @@ coverage: ## check code coverage quickly with the default Python

.PHONY: dist
dist: clean ## builds source and wheel package
python setup.py sdist
python setup.py bdist_wheel
python -m build --wheel --sdist
ls -l dist

.PHONY: publish-confirm
Expand Down
107 changes: 53 additions & 54 deletions setup.py → pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
[build-system]
requires = ['setuptools', 'wheel']
build-backend = 'setuptools.build_meta'

"""The setup script."""

from setuptools import setup, find_packages

with open('README.md', encoding='utf-8') as readme_file:
readme = readme_file.read()

with open('HISTORY.md', encoding='utf-8') as history_file:
history = history_file.read()

install_requires = [
[project]
name = 'deepecho'
description = 'Create sequential synthetic data of mixed types using a GAN.'
authors = [{ name = 'DataCebo, Inc.', email = '[email protected]' }]
classifiers = [
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: Free for non-commercial use',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
]
keywords = ['deepecho', 'DeepEcho']
version = '0.5.1.dev0'
license = { text = 'BSL-1.1' }
requires-python = '>=3.8,<3.12'
readme = 'README.md'
dependencies = [
"numpy>=1.20.0,<2;python_version<'3.10'",
"numpy>=1.23.3,<2;python_version>='3.10'",
"pandas>=1.1.3;python_version<'3.10'",
Expand All @@ -23,19 +35,25 @@
'tqdm>=4.15,<5',
]

setup_requires = [
'pytest-runner>=2.11.1',
]
[project.urls]
"Source Code"= "https://github.com/sdv-dev/Deepecho/"
"Issue Tracker" = "https://github.com/sdv-dev/Deepecho/issues"
"Twitter" = "https://twitter.com/sdv_dev"
"Chat" = "https://bit.ly/sdv-slack-invite"

tests_require = [
[project.optional-dependencies]
test = [
'pytest>=3.4.2',
'pytest-cov>=2.6.0',
'pytest-rerunfailures>=9.0.0,<10',
'jupyter>=1.0.0,<2',
'rundoc>=0.4.3,<0.5',
'pytest-runner >= 2.11.1',
'tomli>=2.0.0,<3',
]
dev = [
'deepecho[test]',

development_requires = [
# general
'setuptools<49.2',
'bumpversion>=0.5.3,<0.6',
Expand Down Expand Up @@ -79,39 +97,20 @@
'invoke'
]

setup(
author='DataCebo, Inc.',
author_email='[email protected]',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: Free for non-commercial use',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
],
description='Create sequential synthetic data of mixed types using a GAN.',
extras_require={
'test': tests_require,
'dev': development_requires + tests_require,
},
include_package_data=True,
install_requires=install_requires,
keywords='deepecho deepecho DeepEcho',
license='BSL-1.1',
long_description=readme + '\n\n' + history,
long_description_content_type='text/markdown',
name='deepecho',
packages=find_packages(include=['deepecho', 'deepecho.*']),
python_requires='>=3.8,<3.12',
setup_requires=setup_requires,
test_suite='tests',
tests_require=tests_require,
url='https://github.com/sdv-dev/DeepEcho',
version='0.5.1.dev0',
zip_safe=False,
)
[tool.setuptools]
include-package-data = true

[tool.setuptools.packages.find]
include = ['deepecho', 'deepecho.*']
namespaces = false

[tool.isort]
include_trailing_comment = true
line_length = 99
lines_between_types = 0
multi_line_output = 4
not_skip = ['__init__.py']
use_parentheses = true

[tool.pytest.ini_options]
collect_ignore = ['pyproject.toml']
13 changes: 1 addition & 12 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ values =

[bumpversion:part:candidate]

[bumpversion:file:setup.py]
[bumpversion:file:pyproject.toml]
search = version='{current_version}'
replace = version='{new_version}'

Expand All @@ -43,20 +43,9 @@ ignore-names =
Y,
Y_padded

[isort]
include_trailing_comment = True
line_length = 99
lines_between_types = 0
multi_line_output = 4
not_skip = __init__.py
use_parentheses = True

[aliases]
test = pytest

[tool:pytest]
collect_ignore = ['setup.py']

[pylint]
persistent = no
extension-pkg-whitelist = numpy
Expand Down
79 changes: 38 additions & 41 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import inspect
import operator
import os
import re
import pkg_resources
import platform
import shutil
import stat
import sys
from pathlib import Path

import tomli
from invoke import task

from packaging.requirements import Requirement
from packaging.version import Version

COMPARISONS = {
'>=': operator.ge,
Expand Down Expand Up @@ -39,48 +39,45 @@ def unit(c):
c.run('python -m pytest ./tests/unit --reruns 3')


def _validate_python_version(line):
is_valid = True
for python_version_match in re.finditer(r"python_version(<=?|>=?|==)\'(\d\.?)+\'", line):
python_version = python_version_match.group(0)
comparison = re.search(r'(>=?|<=?|==)', python_version).group(0)
version_number = python_version.split(comparison)[-1].replace("'", "")
comparison_function = COMPARISONS[comparison]
is_valid = is_valid and comparison_function(
pkg_resources.parse_version(platform.python_version()),
pkg_resources.parse_version(version_number),
)
def _get_minimum_versions(dependencies, python_version):
min_versions = {}
for dependency in dependencies:
if '@' in dependency:
name, url = dependency.split(' @ ')
min_versions[name] = f'{name} @ {url}'
continue

req = Requirement(dependency)
if ';' in dependency:
marker = req.marker
if marker and not marker.evaluate({'python_version': python_version}):
continue # Skip this dependency if the marker does not apply to the current Python version

if req.name not in min_versions:
min_version = next((spec.version for spec in req.specifier if spec.operator in ('>=', '==')), None)
if min_version:
min_versions[req.name] = f'{req.name}=={min_version}'

return is_valid
elif '@' not in min_versions[req.name]:
existing_version = Version(min_versions[req.name].split('==')[1])
new_version = next((spec.version for spec in req.specifier if spec.operator in ('>=', '==')), existing_version)
if new_version > existing_version:
min_versions[req.name] = f'{req.name}=={new_version}' # Change when a valid newer version is found

return list(min_versions.values())


@task
def install_minimum(c):
with open('setup.py', 'r') as setup_py:
lines = setup_py.read().splitlines()

versions = []
started = False
for line in lines:
if started:
if line == ']':
break

line = line.strip()
if _validate_python_version(line):
requirement = re.match(r'[^>]*', line).group(0)
requirement = re.sub(r"""['",]""", '', requirement)
version = re.search(r'>=?(\d\.?)+', line).group(0)
if version:
version = re.sub(r'>=?', '==', version)
version = re.sub(r"""['",]""", '', version)
requirement += version
versions.append(requirement)

elif line.startswith('install_requires = ['):
started = True

c.run(f'python -m pip install {" ".join(versions)}')
with open('pyproject.toml', 'rb') as pyproject_file:
pyproject_data = tomli.load(pyproject_file)

dependencies = pyproject_data.get('project', {}).get('dependencies', [])
python_version = '.'.join(map(str, sys.version_info[:2]))
minimum_versions = _get_minimum_versions(dependencies, python_version)

if minimum_versions:
c.run(f'python -m pip install {" ".join(minimum_versions)}')


@task
Expand Down
38 changes: 38 additions & 0 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Tests for the ``tasks.py`` file."""
from tasks import _get_minimum_versions


def test_get_minimum_versions():
"""Test the ``_get_minimum_versions`` method.

The method should return the minimum versions of the dependencies for the given python version.
If a library is linked to an URL, the minimum version should be the URL.
"""
# Setup
dependencies = [
"numpy>=1.20.0,<2;python_version<'3.10'",
"numpy>=1.23.3,<2;python_version>='3.10'",
"pandas>=1.2.0,<2;python_version<'3.10'",
"pandas>=1.3.0,<2;python_version>='3.10'",
'humanfriendly>=8.2,<11',
'pandas @ git+https://github.com/pandas-dev/pandas.git@master#egg=pandas'
]

# Run
minimum_versions_39 = _get_minimum_versions(dependencies, '3.9')
minimum_versions_310 = _get_minimum_versions(dependencies, '3.10')

# Assert
expected_versions_39 = [
'numpy==1.20.0',
'pandas @ git+https://github.com/pandas-dev/pandas.git@master#egg=pandas',
'humanfriendly==8.2',
]
expected_versions_310 = [
'numpy==1.23.3',
'pandas @ git+https://github.com/pandas-dev/pandas.git@master#egg=pandas',
'humanfriendly==8.2',
]

assert minimum_versions_39 == expected_versions_39
assert minimum_versions_310 == expected_versions_310
Loading