Skip to content

Commit

Permalink
Add in-development version support
Browse files Browse the repository at this point in the history
This adds support for in-development versioning of jars and wheels. Specifically, this PR translates the java version qualifier (anything after "-") to a python "local version label" (`<public version identifier>[+<local version label>]`). For example, the java version "1.2.3-SNAPSHOT" becomes python version "1.2.3+SNAPSHOT"; the java version "4.5.6-my-custom-build123" becomes python version "4.5.6+my.custom.build123". By using a "local version identifier", these wheels become development-only artifacts - they can't be publicly published. While we could contemplate using "development release segments" (ie, python versios that look like "X.Y.Z.devN"), we wouldn't be able to generally translate java versions to python versions without enforcing more structure onto our java versions.

As an added benefit, this PR also reduces some of the duplication of version numbers by sourcing the version number as appropriate during the wheel building process; and then also in the runtime python code, sourcing the version information via the appropriate importlib metadata APIs.

See https://packaging.python.org/en/latest/specifications/version-specifiers/#
See https://peps.python.org/pep-0440/

Partial #3466
Fixes #4654
  • Loading branch information
devinrsmith committed Nov 20, 2023
1 parent fe4b551 commit 9e2d846
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 74 deletions.
11 changes: 1 addition & 10 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,18 +247,9 @@ mention the version explicitly. These files are listed below:

```
#
# Edit files for version change, updating from 0.31.0 to 0.32.0
# Edit files for version change, updating from 0.31.0-SNAPSHOT to 0.32.0-SNAPSHOT
#
authorization-codegen/protoc-gen-contextual-auth-wiring
authorization-codegen/protoc-gen-service-auth-wiring
buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle
py/client-ticking/README.md
py/client-ticking/setup.py
py/client/README.md
py/client/pydeephaven/__init__.py
py/client/setup.py
py/embedded-server/deephaven_server/__init__.py
py/server/deephaven/__init__.py
R/rdeephaven/DESCRIPTION
```

Expand Down
2 changes: 1 addition & 1 deletion authorization-codegen/protoc-gen-contextual-auth-wiring
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# protoc-gen-contextual-auth-wiring
java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.31.0-all.jar io.deephaven.auth.codegen.GenerateContextualAuthWiring
java -cp "authorization-codegen/build/libs/deephaven-authorization-codegen-${DEEPHAVEN_VERSION}-all.jar" io.deephaven.auth.codegen.GenerateContextualAuthWiring
2 changes: 1 addition & 1 deletion authorization-codegen/protoc-gen-service-auth-wiring
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# protoc-gen-service-auth-wiring
java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.31.0-all.jar io.deephaven.auth.codegen.GenerateServiceAuthWiring
java -cp "authorization-codegen/build/libs/deephaven-authorization-codegen-${DEEPHAVEN_VERSION}-all.jar" io.deephaven.auth.codegen.GenerateServiceAuthWiring
9 changes: 6 additions & 3 deletions authorization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ Here is a sample bash script to generate the provided authorizing wiring if you
```bash
./gradlew :authorization-codegen:shadowJar

DEEPHAVEN_VERSION="$(./gradlew printVersion -q)"
OUT_DIR=authorization/src/main/java/
PROTO_DIR=proto/proto-backplane-grpc/src/main/proto/
ROOT_DIR=$PROTO_DIR/deephaven/proto

PATH=authorization-codegen:$PATH protoc --service-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
DEEPHAVEN_VERSION=${DEEPHAVEN_VERSION} PATH=authorization-codegen:$PATH protoc --service-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
$ROOT_DIR/application.proto \
$ROOT_DIR/console.proto \
$ROOT_DIR/config.proto \
Expand All @@ -41,7 +42,7 @@ PATH=authorization-codegen:$PATH protoc --service-auth-wiring_out=$OUT_DIR -I $P
$ROOT_DIR/storage.proto \
$ROOT_DIR/ticket.proto

PATH=authorization-codegen:$PATH protoc --contextual-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
DEEPHAVEN_VERSION=${DEEPHAVEN_VERSION} PATH=authorization-codegen:$PATH protoc --contextual-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
$ROOT_DIR/table.proto \
$ROOT_DIR/inputtable.proto \
$ROOT_DIR/partitionedtable.proto \
Expand All @@ -51,6 +52,8 @@ OUT_DIR=authorization/src/main/java/
PROTO_DIR=../grpc/src/proto/grpc/health/v1/
ROOT_DIR=$PROTO_DIR

PATH=authorization-codegen:$PATH protoc --service-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
DEEPHAVEN_VERSION=${DEEPHAVEN_VERSION} PATH=authorization-codegen:$PATH protoc --service-auth-wiring_out=$OUT_DIR -I $PROTO_DIR \
$ROOT_DIR/health.proto

./gradlew :authorization:spotlessApply
```
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = 'io.deephaven'
version = '0.31.0'
version = '0.31.0-SNAPSHOT'

if (!name.startsWith('deephaven-')) {
archivesBaseName = "deephaven-${name}"
Expand Down
2 changes: 1 addition & 1 deletion py/client-ticking/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Then install the package.
Note the actual name of the `.whl` file may be different depending on system details.

```
pip3 install --force --no-deps dist/pydeephaven_ticking-0.31.0-cp310-cp310-linux_x86_64.whl
pip3 install --force --no-deps dist/pydeephaven_ticking-<x.y.z>-cp310-cp310-linux_x86_64.whl
```

The reason for the "--force" flag is to overwrite any previously-built version of the package that
Expand Down
5 changes: 3 additions & 2 deletions py/client-ticking/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,16 @@ def buildPyClientTicking = Docker.registerDockerTask(project, 'pyClientTicking')
copyFile('README.md', "${prefix}/src/py-client-ticking")
copyFile('src/', "${prefix}/src/py-client-ticking/src/")
copyFile('wheels/', "${prefix}/src/py-client-ticking/in-wheels")
runCommand("PREFIX=${prefix}; " +
runCommand("PREFIX=${prefix}; DEEPHAVEN_VERSION=${project.version};" +
'''set -eux ; \
cd "${PREFIX}/src/py-client-ticking"; \
. "${PREFIX}/env.sh"; \
MAKEFLAGS="-j${NCPUS}" \
CFLAGS="-I${DHCPP}/include" \
LDFLAGS="-L${DHCPP}/lib" \
DEEPHAVEN_VERSION="${DEEPHAVEN_VERSION}" \
python3 setup.py build_ext -i; \
python3 setup.py bdist_wheel; \
DEEPHAVEN_VERSION="${DEEPHAVEN_VERSION}" python3 setup.py bdist_wheel; \
pip3 install in-wheels/*.whl; \
pip3 install --force --no-deps dist/*.whl; \
ln dist/*.whl /out; \
Expand Down
32 changes: 25 additions & 7 deletions py/client-ticking/setup.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
#
# Copyright (c) 2016-2023 Deephaven Data Labs and Patent Pending
#
import os
import pathlib

# Note: pkg_resources is deprecated https://setuptools.pypa.io/en/latest/pkg_resources.html, and it is suggested
# to use an external library `packaging`. From the context of building a wheel though, we'd prefer to not have to
# install extra dependencies, at least until we can more properly manage the build environment (pyproject.toml)
from pkg_resources import parse_version
from setuptools import find_packages, setup, Extension
from Cython.Build import cythonize

# The directory containing this file
HERE = pathlib.Path(__file__).parent
def _get_readme() -> str:
# The directory containing this file
HERE = pathlib.Path(__file__).parent
# The text of the README file
return (HERE / "README.md").read_text()

def _normalize_version(java_version):
partitions = java_version.partition("-")
regular_version = partitions[0]
local_segment = partitions[2]
python_version = f"{regular_version}+{local_segment}" if local_segment else regular_version
return str(parse_version(python_version))

def _compute_version():
return _normalize_version(os.environ['DEEPHAVEN_VERSION'])

# The text of the README file
README = (HERE / "README.md").read_text()
_version = _compute_version()

setup(
name='pydeephaven-ticking',
version='0.30.0.dev0',
version=_version,
description='The Deephaven Python Client for Ticking Tables',
long_description=README,
long_description=_get_readme(),
long_description_content_type="text/markdown",
packages=find_packages(where="src", exclude=("tests",)),
package_dir={"": "src"},
Expand Down Expand Up @@ -44,5 +62,5 @@
libraries=["dhcore_static"]
)]),
python_requires='>=3.8',
install_requires=['pydeephaven==0.31.0']
install_requires=[f"pydeephaven=={_version}"]
)
2 changes: 1 addition & 1 deletion py/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $ python3 -m examples.demo_asof_join
Note the actual name of the `.whl` file may be different depending on system details.

``` shell
$ pip3 install dist/pydeephaven-0.31.0-py3-none-any.whl
$ pip3 install dist/pydeephaven-<x.y.z>-py3-none-any.whl
```
## Quick start

Expand Down
8 changes: 7 additions & 1 deletion py/client/pydeephaven/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
>>> session.close()
"""

import importlib.metadata

from .session import Session
from .dherror import DHError
from ._table_interface import SortDirection
Expand All @@ -35,4 +37,8 @@
pass

__all__ = ["Session", "DHError", "SortDirection"]
__version__ = "0.31.0"

# Note: this is the _distribution_ name, not the _package_ name. Until 3.10, there is not an easy way to get the
# distribution name from the package name.
# https://docs.python.org/3/library/importlib.metadata.html#package-distributions
__version__ = importlib.metadata.version('pydeephaven')
28 changes: 22 additions & 6 deletions py/client/setup.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
#
# Copyright (c) 2016-2021 Deephaven Data Labs and Patent Pending
#
import os
import pathlib

# Note: pkg_resources is deprecated https://setuptools.pypa.io/en/latest/pkg_resources.html, and it is suggested
# to use an external library `packaging`. From the context of building a wheel though, we'd prefer to not have to
# install extra dependencies, at least until we can more properly manage the build environment (pyproject.toml)
from pkg_resources import parse_version
from setuptools import find_packages, setup

# The directory containing this file
HERE = pathlib.Path(__file__).parent
def _get_readme() -> str:
# The directory containing this file
HERE = pathlib.Path(__file__).parent
# The text of the README file
return (HERE / "README.md").read_text()

def _normalize_version(java_version):
partitions = java_version.partition("-")
regular_version = partitions[0]
local_segment = partitions[2]
python_version = f"{regular_version}+{local_segment}" if local_segment else regular_version
return str(parse_version(python_version))

# The text of the README file
README = (HERE / "README.md").read_text()
def _compute_version():
return _normalize_version(os.environ['DEEPHAVEN_VERSION'])

setup(
name='pydeephaven',
version='0.31.0',
version=_compute_version(),
description='The Deephaven Python Client',
long_description=README,
long_description=_get_readme(),
long_description_content_type="text/markdown",
packages=find_packages(exclude=("tests",)),
url='https://deephaven.io/',
Expand Down
8 changes: 7 additions & 1 deletion py/embedded-server/deephaven_server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#
# Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
#
__version__ = "0.31.0"

import importlib.metadata

from .start_jvm import DEFAULT_JVM_PROPERTIES, DEFAULT_JVM_ARGS, start_jvm
from .server import Server

from deephaven_internal.jvm import check_py_env
check_py_env()

# Note: this is the _distribution_ name, not the _package_ name. Until 3.10, there is not an easy way to get the
# distribution name from the package name.
# https://docs.python.org/3/library/importlib.metadata.html#package-distributions
__version__ = importlib.metadata.version('deephaven-server')
41 changes: 22 additions & 19 deletions py/embedded-server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,36 @@
#
import os
import pathlib
from setuptools.extern import packaging
from setuptools import find_namespace_packages, setup

# The directory containing this file
HERE = pathlib.Path(__file__).parent

# The text of the README file
README = (HERE / "README_PyPi.md").read_text()
# Note: pkg_resources is deprecated https://setuptools.pypa.io/en/latest/pkg_resources.html, and it is suggested
# to use an external library `packaging`. From the context of building a wheel though, we'd prefer to not have to
# install extra dependencies, at least until we can more properly manage the build environment (pyproject.toml)
from pkg_resources import parse_version
from setuptools import find_namespace_packages, setup

def _get_readme() -> str:
# The directory containing this file
HERE = pathlib.Path(__file__).parent
# The text of the README file
return (HERE / "README_PyPi.md").read_text()

# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
# todo: does DH versions align w/ PEP440?
# see https://github.com/pypa/setuptools/blob/v40.8.0/setuptools/dist.py#L470
def normalize_version(version):
return str(packaging.version.Version(version))
def _normalize_version(java_version) -> str:
partitions = java_version.partition("-")
regular_version = partitions[0]
local_segment = partitions[2]
python_version = f"{regular_version}+{local_segment}" if local_segment else regular_version
return str(parse_version(python_version))

def _compute_version():
return _normalize_version(os.environ['DEEPHAVEN_VERSION'])

__deephaven_version__ = os.environ['DEEPHAVEN_VERSION']
__normalized_version__ = normalize_version(__deephaven_version__)
_version = _compute_version()

setup(
name='deephaven-server',
version=__normalized_version__,
version=_version,
description='Deephaven Embedded Server Python Package',
long_description=README,
long_description=_get_readme(),
long_description_content_type='text/markdown',
packages=find_namespace_packages(exclude=("tests")),
package_data={'deephaven_server': ['jars/*']},
Expand All @@ -56,6 +59,6 @@ def normalize_version(version):
install_requires=[
'jpy>=0.14.0',
"java-utilities",
f"deephaven-core[autocomplete]=={__normalized_version__}",
f"deephaven-core[autocomplete]=={_version}",
]
)
7 changes: 6 additions & 1 deletion py/server/deephaven/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"""

__version__ = "0.31.0"
import importlib.metadata

from deephaven_internal import jvm

Expand All @@ -31,3 +31,8 @@
__all__ = ["read_csv", "write_csv", "kafka_consumer", "kafka_producer", "empty_table", "time_table", "merge",
"merge_sorted", "new_table", "input_table", "ring_table", "function_generated_table", "DynamicTableWriter",
"TableReplayer", "garbage_collect", "read_sql", "DHError", "SortDirection"]

# Note: this is the _distribution_ name, not the _package_ name. Until 3.10, there is not an easy way to get the
# distribution name from the package name.
# https://docs.python.org/3/library/importlib.metadata.html#package-distributions
__version__ = importlib.metadata.version('deephaven-core')
39 changes: 20 additions & 19 deletions py/server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,34 @@
#
import os
import pathlib
from setuptools.extern import packaging
from setuptools import find_namespace_packages, setup

# The directory containing this file
HERE = pathlib.Path(__file__).parent

# The text of the README file
README = (HERE / "README.md").read_text()

# Note: pkg_resources is deprecated https://setuptools.pypa.io/en/latest/pkg_resources.html, and it is suggested
# to use an external library `packaging`. From the context of building a wheel though, we'd prefer to not have to
# install extra dependencies, at least until we can more properly manage the build environment (pyproject.toml)
from pkg_resources import parse_version
from setuptools import find_namespace_packages, setup

# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
# todo: does DH versions align w/ PEP440?
# see https://github.com/pypa/setuptools/blob/v40.8.0/setuptools/dist.py#L470
def normalize_version(version):
return str(packaging.version.Version(version))
def _get_readme() -> str:
# The directory containing this file
HERE = pathlib.Path(__file__).parent
# The text of the README file
return (HERE / "README.md").read_text()

def _normalize_version(java_version) -> str:
partitions = java_version.partition("-")
regular_version = partitions[0]
local_segment = partitions[2]
python_version = f"{regular_version}+{local_segment}" if local_segment else regular_version
return str(parse_version(python_version))

__deephaven_version__ = os.environ['DEEPHAVEN_VERSION']
__normalized_version__ = normalize_version(__deephaven_version__)
def _compute_version():
return _normalize_version(os.environ['DEEPHAVEN_VERSION'])

setup(
name='deephaven-core',
version=__normalized_version__,
version=_compute_version(),
description='Deephaven Engine Python Package',
long_description=README,
long_description=_get_readme(),
long_description_content_type='text/markdown',
packages=find_namespace_packages(exclude=("tests", "tests.*", "integration-tests", "test_helper")),
url='https://deephaven.io/',
Expand Down

0 comments on commit 9e2d846

Please sign in to comment.