Skip to content

Commit

Permalink
Use setuptools_scm for versioning
Browse files Browse the repository at this point in the history
Instead of checking in the version.  This means we can tag a new release
without needing to make a commit, just create a git tag.  And then the
stuff in the next commit will auto publish when that happens also.

Topic: sf-auto-version
  • Loading branch information
aaron-skydio committed Jan 3, 2025
1 parent 079830a commit 2a5d6a2
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 72 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/build_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ jobs:
CIBW_BUILD_FRONTEND: build
# For arm64; for x86, it's at /usr/local but cmake finds that ok already
GMP_ROOT: /opt/homebrew
CIBW_BEFORE_BUILD: brew install gmp
CIBW_ENVIRONMENT: SYMFORCE_REWRITE_LOCAL_DEPENDENCIES=True MACOSX_DEPLOYMENT_TARGET=13.0
CIBW_BEFORE_BUILD: brew install gmp && python3 -m pip install setuptools_scm
CIBW_ENVIRONMENT: SYMFORCE_REWRITE_LOCAL_DEPENDENCIES=$(python3 -m setuptools_scm) MACOSX_DEPLOYMENT_TARGET=13.0

- name: Upload wheels
uses: actions/upload-artifact@v4
Expand All @@ -77,8 +77,8 @@ jobs:
env:
CIBW_BUILD: ${{ matrix.python-version }}-manylinux_x86_64
CIBW_BUILD_FRONTEND: build
CIBW_BEFORE_BUILD: yum install -y gmp-devel git
CIBW_ENVIRONMENT: SYMFORCE_REWRITE_LOCAL_DEPENDENCIES=True
CIBW_BEFORE_BUILD: yum install -y gmp-devel git && python3 -m pip install setuptools_scm
CIBW_ENVIRONMENT: SYMFORCE_REWRITE_LOCAL_DEPENDENCIES=$(python3 -m setuptools_scm)

- name: Upload Wheels
uses: actions/upload-artifact@v4
Expand Down
42 changes: 15 additions & 27 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,35 +237,23 @@ else()

add_custom_target(symforce_eigen_lcm_py ALL DEPENDS eigen_lcm_py)

# Get SymForce version
execute_process(
COMMAND ${SYMFORCE_PYTHON} -c "from _version import version; print(version, end='')"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/symforce
RESULT_VARIABLE STATUS
OUTPUT_VARIABLE SYMFORCE_VERSION
ERROR_VARIABLE SYMFORCE_VERSION_STDERR
)
if(STATUS AND NOT STATUS EQUAL 0)
message(FATAL_ERROR
"Failed getting symforce version with exit code ${STATUS} and output ${SYMFORCE_VERSION}, stderr ${SYMFORCE_VERSION_STDERR}"
)
endif()

file(WRITE
${CMAKE_CURRENT_BINARY_DIR}/lcmtypes/python2.7/setup.py
${CMAKE_CURRENT_BINARY_DIR}/lcmtypes/python2.7/pyproject.toml
"
from setuptools import setup, find_packages
setup(
name='lcmtypes',
version='${SYMFORCE_VERSION}',
description='lcmtype python bindings (installed by SymForce)',
long_description='lcmtype python bindings (installed by SymForce)',
author='Skydio, Inc',
author_email='hayk@skydio.com',
license='Apache 2.0',
packages=find_packages(),
zip_safe=False,
)
[build-system]
requires = ['setuptools', 'setuptools-scm>=8']
build-backend = 'setuptools.build_meta'
[project]
name = 'lcmtypes'
description='lcmtype python bindings (installed by SymForce)'
authors = [{ name = 'Skydio, Inc.', email = 'hayk@skydio.com' }]
license = { text = 'Apache 2.0' }
requires-python = '>=3.5'
dynamic = ['version']
[tool.setuptools_scm]
root = '../../..'
"
)
endif()
Expand Down
6 changes: 6 additions & 0 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ packaging==24.0
# matplotlib
# nbconvert
# plotly
# setuptools-scm
# sphinx
pandas==2.0.3
# via symforce (setup.py)
Expand Down Expand Up @@ -267,6 +268,8 @@ ruff==0.7.1
# via symforce (setup.py)
scipy==1.10.1
# via symforce (setup.py)
setuptools-scm==8.1.0
# via symforce (setup.py)
six==1.16.0
# via
# asttokens
Expand Down Expand Up @@ -321,6 +324,7 @@ tomli==2.0.1
# build
# mypy
# pip-tools
# setuptools-scm
tornado==6.4
# via
# ipykernel
Expand Down Expand Up @@ -349,6 +353,7 @@ typing-extensions==4.11.0
# via
# ipython
# mypy
# setuptools-scm
tzdata==2024.1
# via pandas
urllib3==2.2.1
Expand Down Expand Up @@ -378,4 +383,5 @@ pip==24.0
setuptools==69.5.1
# via
# pip-tools
# setuptools-scm
# symforce (setup.py)
4 changes: 2 additions & 2 deletions docs/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ You should be able to build Python wheels of symforce the standard ways. We rec
``build``, i.e. running ``python3 -m build --wheel`` from the ``symforce`` directory. By default,
this will build a wheel that includes local dependencies on the ``skymarshal`` and ``symforce-sym``
packages (which are separate Python packages from ``symforce`` itself). For distribution, you'll
typically want to set the environment variable ``SYMFORCE_REWRITE_LOCAL_DEPENDENCIES=True`` when
building, and also run ``python3 -m build --wheel third_party/skymarshal`` and
typically want to set the environment variable ``SYMFORCE_REWRITE_LOCAL_DEPENDENCIES`` to the
release version when building, and also run ``python3 -m build --wheel third_party/skymarshal`` and
``python3 -m build --wheel gen/python`` to build wheels for those packages separately.

For SymForce releases, all of this is handled by the ``build_wheels`` GitHub Actions workflow. This
Expand Down
7 changes: 5 additions & 2 deletions gen/python/pyproject.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ dynamic = ["version", "readme", "dependencies", "optional-dependencies"]
"Bug Tracker" = "https://github.com/symforce-org/symforce/issues"
Source = "https://github.com/symforce-org/symforce"

[tool.setuptools_scm]
# Empty, presence enables setuptools_scm

# --------------------------------------------------------------------------------
# Ruff
# --------------------------------------------------------------------------------
Expand Down
29 changes: 4 additions & 25 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# This source code is under the Apache 2.0 license found in the LICENSE file.
# ----------------------------------------------------------------------------

import distutils.util
import multiprocessing
import os
import re
Expand All @@ -25,18 +24,6 @@
ESCAPED_SOURCE_DIR = Path(str(SOURCE_DIR).replace(" ", "%20"))


def symforce_version() -> str:
"""
Fetch the current symforce version from _version.py
We can't import the version here, so we have to do some text parsing
"""
version_file_contents = (Path(__file__).parent / "symforce" / "_version.py").read_text()
version_match = re.search(r'^version = "(.+)"$', version_file_contents, flags=re.MULTILINE)
assert version_match is not None
return version_match.group(1)


class CMakeExtension(Extension):
"""
CMake extension type.
Expand Down Expand Up @@ -227,31 +214,23 @@ class SymForceEggInfo(egg_info):

def initialize_options(self) -> None:
super().initialize_options()
self.rewrite_local_dependencies = False
self.rewrite_local_dependencies: T.Optional[str] = None

def finalize_options(self) -> None:
super().finalize_options()

if not isinstance(self.rewrite_local_dependencies, bool):
self.rewrite_local_dependencies = bool(
distutils.util.strtobool(self.rewrite_local_dependencies)
)

if "SYMFORCE_REWRITE_LOCAL_DEPENDENCIES" in os.environ:
self.rewrite_local_dependencies = bool(
distutils.util.strtobool(os.environ["SYMFORCE_REWRITE_LOCAL_DEPENDENCIES"])
)
self.rewrite_local_dependencies = os.environ["SYMFORCE_REWRITE_LOCAL_DEPENDENCIES"]

def run(self) -> None:
# Rewrite dependencies from the local `file:` versions to generic pinned package versions.
# This is what we want when e.g. building wheels for PyPI, where those local dependencies
# are hosted as their own PyPI packages. We can't just decide whether to do this e.g. based
# on whether we're building a wheel, since `pip install .` also builds a wheel to install.
if self.rewrite_local_dependencies:

def filter_local(s: str) -> str:
if "@" in s:
s = f"{s.split('@')[0]}=={symforce_version()}"
s = f"{s.split('@')[0]}=={self.rewrite_local_dependencies}"
return s

self.distribution.install_requires = [ # type: ignore[attr-defined]
Expand Down Expand Up @@ -338,6 +317,7 @@ def run(self) -> None:

setup_requirements = [
"setuptools>=62.3.0", # For package data globs
"setuptools-scm>=8",
"wheel",
"pip",
"cmake>=3.17,<3.27",
Expand Down Expand Up @@ -404,7 +384,6 @@ def fixed_readme() -> str:

if __name__ == "__main__":
setup(
version=symforce_version(),
long_description=fixed_readme(),
long_description_content_type="text/markdown",
# The SymForce package is a namespace package (important for data-only subdirectories
Expand Down
15 changes: 14 additions & 1 deletion symforce/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@
# -------------------------------------------------------------------------------------------------

# isort: split
from ._version import version as __version__
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version

try:
__version__ = version("symforce")
except PackageNotFoundError:
# package is not installed. Try running setuptools_scm
import setuptools_scm

try:
__version__ = setuptools_scm.get_version()
except LookupError:
pass


# -------------------------------------------------------------------------------------------------
# Logging configuration
Expand Down
6 changes: 0 additions & 6 deletions symforce/_version.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@
# ---------------------------------------------------------------------------- #}

[build-system]
requires = ["setuptools"]
requires = ["setuptools", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[project]
name = "{{ package_name }}"
description = "{{ description }} (installed by SymForce)"
authors = [{ name = "Skydio, Inc.", email = "hayk@skydio.com" }]
license = { text = "Apache 2.0" }
version = "{{ version }}"
dependencies = ["numpy"]
requires-python = ">=3.5"
dynamic = ["version"]

[project.urls]
SymForce = "https://symforce.org"
"Bug Tracker" = "https://github.com/symforce-org/symforce/issues"
Source = "https://github.com/symforce-org/symforce/tree/main/gen/python"

[tool.setuptools_scm]
root = "../.."
1 change: 0 additions & 1 deletion test/symforce_gen_codegen_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def test_gen_package_codegen_python(self) -> None:
output_path=output_dir / "pyproject.toml",
data=dict(
package_name="symforce-sym",
version=symforce.__version__,
description="generated numerical python package",
),
config=dataclasses.replace(config.render_template_config, autoformat=False),
Expand Down
7 changes: 5 additions & 2 deletions third_party/skymarshal/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
[build-system]
requires = ["setuptools"]
requires = ["setuptools", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[project]
name = "skymarshal"
description = "Python implementation of marshalling for LCM messages"
version = "0.9.0"
authors = [{ name = "Skydio, Inc." }]
license = { text = "LGPL-2.1-or-later" }
readme = "README.md"
Expand All @@ -20,10 +19,14 @@ classifiers = [
]
requires-python = ">=3.8"
dependencies = ["argh", "jinja2", "numpy", "ply"]
dynamic = ["version"]

[project.urls]
"Bug Tracker" = "https://github.com/symforce-org/symforce/issues"
Source = "https://github.com/symforce-org/symforce/tree/main/third_party/skymarshal"

[tool.setuptools_scm]
root = "../.."

[tool.setuptools.packages.find]
include = ["skymarshal", "skymarshal.*"]

0 comments on commit 2a5d6a2

Please sign in to comment.