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 pyroject.toml to specify project metadata #379

Merged
merged 4 commits into from
Mar 1, 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: 1 addition & 1 deletion .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install invoke rundoc .
python -m pip install invoke tomli rundoc .
- name: Run the README.md
run: invoke readme
2 changes: 1 addition & 1 deletion .github/workflows/tutorials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ jobs:
- name: Install package and dependencies
run: |
python -m pip install --upgrade pip
python -m pip install invoke jupyter .[tutorials]
python -m pip install invoke tomli jupyter .[tutorials]
- name: invoke tutorials
run: invoke tutorials
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,7 @@ serve-docs: ## compile the docs watching for changes

.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
130 changes: 64 additions & 66 deletions setup.py → pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#.dev0!/usr/bin/env python
# -*- coding: utf-8 -*-

"""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 = 'copulas'
description = 'Create tabular synthetic data using copulas-based modeling.'
authors = [{name = 'DataCebo, Inc.', email = 'info@sdv.dev' }]
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 = [ 'copulas' ]
version = '0.10.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 @@ -22,7 +30,34 @@
"scipy>=1.9.2,<2;python_version>='3.10'",
]

development_requires = [
[project.urls]
"Source Code"= "https://github.com/sdv-dev/Copulas/"
"Issue Tracker" = "https://github.com/sdv-dev/Copulas/issues"
"Changes" = "https://github.com/sdv-dev/Copulas/blob/main/HISTORY.md"
frances-h marked this conversation as resolved.
Show resolved Hide resolved
"Twitter" = "https://twitter.com/sdv_dev"
"Chat" = "https://bit.ly/sdv-slack-invite"

[build-system]
requires = ['setuptools', 'wheel']
build-backend = 'setuptools.build_meta'

[project.optional-dependencies]
tutorials = [
'markupsafe<=2.0.1',
'scikit-learn>=0.24,<1.2',
'jupyter>=1.0.0,<2',
]
test = [
'copulas[tutorials]',
'pytest>=6.2.5,<7',
'pytest-cov>=2.6.0,<3',
'pytest-rerunfailures>=9.0.0,<10',
'rundoc>=0.4.3,<0.5',
'tomli>=2.0.0,<3',
]
dev = [
'copulas[tutorials, test]',

# general
'pip>=9.0.1',
'bumpversion>=0.5.3,<0.6',
Expand Down Expand Up @@ -84,57 +119,20 @@
'docutils>=0.10,<0.15'
]

tutorials_require = [
'markupsafe<=2.0.1',
'scikit-learn>=0.24,<1.2',
'jupyter>=1.0.0,<2',
]
[tool.isort]
line_length = 99
lines_between_types = 0
multi_line_output = 4
use_parentheses = true
not_skip = ['__init__.py']

tests_require = [
'pytest>=6.2.5,<7',
'pytest-cov>=2.6.0,<3',
'pytest-rerunfailures>=9.0.0,<10',
'rundoc>=0.4.3,<0.5',
]
[tool.pydocstyle]
convention = 'google'
add-ignore = ['D107', 'D407', 'D417']

setup_requires = [
'pytest-runner>=2.11.1',
]
[tool.setuptools]
include-package-data = true

setup(
author='DataCebo, Inc.',
author_email='info@sdv.dev',
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 tabular synthetic data using copulas-based modeling.',
extras_require={
'tutorials': tutorials_require,
'test': tests_require + tutorials_require,
'dev': tests_require + development_requires + tutorials_require,
},
install_requires=install_requires,
license='BSL-1.1',
long_description=readme + '\n\n' + history,
long_description_content_type='text/markdown',
include_package_data=True,
keywords='copulas',
name='copulas',
packages=find_packages(include=['copulas', 'copulas.*']),
python_requires='>=3.8,<3.12',
setup_requires=setup_requires,
test_suite='tests',
tests_require=tests_require,
url='https://github.com/sdv-dev/Copulas',
version='0.10.1.dev0',
zip_safe=False,
)
[tool.setuptools.packages.find]
include = ['copulas', 'copulas.*']
namespaces = false
15 changes: 1 addition & 14 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 @@ -40,23 +40,10 @@ extend-ignore = D107, # Missing docstring in __init__
per-file-ignores =
large_scale_evaluation.py:T001

[pydocstyle]
convention = google
add-ignore = D107, D407, D417

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

[aliases]
test = pytest

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

[doc8]
max-line-length = 99

72 changes: 44 additions & 28 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import inspect
import operator
import os
import re
import pkg_resources
import platform
import tomli
import sys
from packaging.requirements import Requirement
from packaging.version import Version
import shutil
import stat
from pathlib import Path
Expand Down Expand Up @@ -60,33 +61,48 @@ def _validate_python_version(line):
return is_valid


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}'

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:
# Change when a valid newer version is found
min_versions[req.name] = f'{req.name}=={new_version}'

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
36 changes: 36 additions & 0 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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