Skip to content

Commit

Permalink
Restructure project to use 'pyproject.toml' as the primary mechanism.
Browse files Browse the repository at this point in the history
Expose optional packages as extras. (#43)
  • Loading branch information
bbassett-tibco committed Jan 9, 2024
1 parent 6da5989 commit 02f28a7
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 117 deletions.
45 changes: 0 additions & 45 deletions .github/scripts/parse_pyproject_toml.py

This file was deleted.

14 changes: 6 additions & 8 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ jobs:
python-version: '3.x'
- name: Install Tools
run: |
mkdir dist
python .github/scripts/parse_pyproject_toml.py --section build-system --key requires --array --string > dist/pyproj-requires.txt
pip install -r dist/pyproj-requires.txt
pip install -r build
- name: Source Packaging
run: |
python setup.py sdist
python -m build --sdist
- uses: actions/upload-artifact@v3
with:
name: sdist
Expand Down Expand Up @@ -68,15 +66,15 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install Build Requirements
run: |
pip install auditwheel -r dist/pyproj-requires.txt
pip install auditwheel build
- name: Build Wheel (Linux)
if: matrix.operating-system == 'ubuntu-latest'
run: |
# Unpack sdist
tar xzf dist/spotfire-*.tar.gz
cd spotfire-*
# Build wheel
python setup.py bdist_wheel
python -m build --wheel
# Convert wheel to manylinux
auditwheel repair -w ../dist --plat manylinux2014_x86_64 dist/*.whl
- name: Build Wheel (Windows)
Expand All @@ -86,7 +84,7 @@ jobs:
tar xzf $((dir dist\spotfire-*.tar.gz).FullName)
cd spotfire-*
# Build wheel
python setup.py bdist_wheel
python -m build --wheel
# Move wheel out of build dir into top-level dist dir
mv dist\*.whl ..\dist
- uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -159,7 +157,7 @@ jobs:
name: analysis-files
- name: Install Tools
run: |
pip install dist/*.whl -r requirements_lint.txt
pip install `ls dist/*.whl`[lint]
- name: Static Analysis with pylint
run: |
pylint spotfire
4 changes: 1 addition & 3 deletions .whitesource.config
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
python.path=python3
python.pipPath=pip3
python.requirementsFileIncludes=requirements_dev.txt
python.requirementsFileIncludes=pyproject.toml
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,17 @@ This package provides functions used for integrating Python with Spotfire, inclu
pip install spotfire
```

Additionally, [extras](https://peps.python.org/pep-0508/#extras) may be specified (as `spotfire[extra]` instead of
simply `spotfire`) to include the required Python packages to support optional functionality:

| Extra | Functionality |
|-----------------------------|----------------------------------------------|
| `spotfire[geo]` | Geographic data processing |
| `spotfire[plot]` | Plotting support with all supported packages |
| `spotfire[plot-matplotlib]` | Plotting support using just `matplotlib` |
| `spotfire[plot-pil]` | Plotting support using just `Pillow` |
| `spotfire[plot-seaborn]` | Plotting support using just `seaborn` |
| `spotfire[dev,lint]` | Internal development |

### License
BSD-type 3-Clause License. See the file ```LICENSE``` included in the package.
65 changes: 64 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,65 @@
[build-system]
requires = ["setuptools", "wheel", "Cython >= 3.0", "oldest-supported-numpy"]
requires = [
"setuptools >= 40.8",
"wheel",
"Cython >= 3.0",
"oldest-supported-numpy",
]
build-backend = "setuptools.build_meta"

[project]
name = "spotfire"
dynamic = ["version"]
description = "Package for Building Python Extensions to Spotfire"
readme = "README.md"
authors = [{ name = "Cloud Software Group, Inc." }]
maintainers = [{ name="Spotfire Python Package Support", email = "spotfirepython@tibco.com" }]
requires-python = ">=3.8"
dependencies = [
# DataFrame support
"pandas>=0.24.0,!=1.0.2,!=1.0.3",
"numpy>=1.22,<2.0",
# Package interactions
"packaging",
"pip >= 21.2",
"setuptools",
"wheel",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Cython",
]

[project.urls]
Homepage = "https://github.com/spotfiresoftware/spotfire-python"

[project.optional-dependencies]
# Geographic data support
geo = [
"geopandas",
"shapely",
]
# Plotting libraries
plot-matplotlib = [
"matplotlib",
]
plot-pil = [
"pillow >= 10.0.0",
]
plot-seaborn = [
"seaborn",
]
plot = [ "spotfire[plot-matplotlib,plot-pil,plot-seaborn]" ]
# Development requirements
dev = [
"spotfire[geo,plot]",
"Cython >= 3.0",
"html-testRunner",
]
# Static analysis requirements
lint = [
"pylint == 2.16.2",
]
9 changes: 0 additions & 9 deletions requirements_dev.txt

This file was deleted.

2 changes: 0 additions & 2 deletions requirements_lint.txt

This file was deleted.

32 changes: 0 additions & 32 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@
import numpy as np


def get_requires(filename):
requirements = []
with open(filename, "rt") as req_file:
for line in req_file.read().splitlines():
if not line.strip().startswith("#"):
requirements.append(line)
return requirements


class BuildExtDebug(build_ext):
def finalize_options(self):
if sys.platform == "win32":
Expand All @@ -33,14 +24,10 @@ def finalize_options(self):
super().finalize_options()


project_requirements = get_requires("spotfire/requirements.txt")
version = {}
with open('spotfire/version.py') as ver_file:
exec(ver_file.read(), version)

with open("README.md", "r") as fh:
long_description = fh.read()

if sys.platform == "win32":
platform_filename = "_windows"
cabfile_libraries = ['cabinet']
Expand Down Expand Up @@ -89,27 +76,8 @@ def finalize_options(self):
]

setup(
name='spotfire',
version=version['__version__'],
description='Package for Building Python Extensions to Spotfire',
long_description=long_description,
long_description_content_type='text/markdown',
author='Cloud Software Group, Inc.',
maintainer='Spotfire Python Package Support',
maintainer_email='spotfirepython@tibco.com',
url='https://github.com/spotfiresoftware/spotfire-python',
license='BSD 3-Clause License',
packages=find_packages(exclude=['spotfire.test.files']),
ext_modules=extensions,
cmdclass={'build_ext_debug': BuildExtDebug},
include_package_data=True,
install_requires=project_requirements,
python_requires='>=3.8',
classifiers=[
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Cython',
],
)
9 changes: 0 additions & 9 deletions spotfire/requirements.txt

This file was deleted.

25 changes: 19 additions & 6 deletions spotfire/spk.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import datetime
import fileinput
import glob
from importlib import metadata as imp_md, resources as imp_res
from importlib import metadata as imp_md
import io
import json
import locale
Expand Down Expand Up @@ -403,9 +403,7 @@ def remove_included_packages(self, tempdir: str, package_versions: typing.Dict[s
:return: `package_versions`, but with duplicate packages removed from the mapping
"""
# Use the spotfire requirements file as a deny list.
with imp_res.files("spotfire").joinpath("requirements.txt").open("r", encoding="utf-8") as deny_file:
deny_requirements = deny_file.read()
deny_list = self.requirements_from(deny_requirements)
deny_list = self.requirements_of("spotfire")

# Find all distributions in the temp directory
dist_info_dirs = glob.glob(os.path.join(tempdir, "*.dist-info"))
Expand Down Expand Up @@ -447,6 +445,17 @@ def _process_package_requirements(self, requirement, extra: str = None, seen: ty
for child_extra in child_req.extras:
self._process_package_requirements(child_req, child_extra, seen)

def requirements_of(self, package: str, extra: str = None) -> typing.Set[str]:
"""Determine the requirements recursively of a package.
:param package: the name of the package
:param extra: the extra for the package
:returns: set of package names that are recursively as requirements of the package
"""
packages_seen = set()
self._process_package_requirements(pkg_req.Requirement(package), extra, packages_seen)
return packages_seen

def requirements_from(self, requirements: str) -> typing.Set[str]:
"""Determine the requirements recursively of a requirements file.
Expand Down Expand Up @@ -807,17 +816,21 @@ def python(args, hook=None) -> None:
package_builder.scan_python_installation(prefix)
package_builder.scan_path_configuration_file(prefix)
package_builder.scan_spotfire_package(prefix)
spotfire_requirements = os.path.join(spotfire.__path__[0], "requirements.txt")
try:
with tempfile.NamedTemporaryFile(mode="wt", prefix="req", suffix=".txt", encoding="utf-8",
delete=False) as spotfire_requirements:
for req in imp_md.requires("spotfire"):
print(req, file=spotfire_requirements)
constraints = getattr(args, "constraint")
package_builder.scan_requirements_txt(spotfire_requirements, constraints, prefix)
package_builder.scan_requirements_txt(spotfire_requirements.name, constraints, prefix)
if hook is not None:
hook.scan_finished(package_builder)

# Build the package
package_builder.build()
finally:
package_builder.cleanup()
os.remove(spotfire_requirements.name)


@subcommand([argument("spk-file", help="path to the SPK file to build"),
Expand Down
2 changes: 0 additions & 2 deletions test_requirements_default.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
-r spotfire/requirements.txt

html-testRunner
geopandas
matplotlib
Expand Down

0 comments on commit 02f28a7

Please sign in to comment.