Skip to content

Commit

Permalink
Add pip_build.py and required __init__.py files, update `README.m…
Browse files Browse the repository at this point in the history
…d`. (#6)
  • Loading branch information
hertschuh authored Oct 29, 2024
1 parent f5558c7 commit 167a1d1
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 1 deletion.
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@ This library is an extension of the core Keras API; all high-level modules
receive that same level of polish as core Keras. If you are familiar with Keras,
congratulations! You already understand most of Keras Recommenders.

## Installation

Keras Recommenders is available on PyPI as `keras-rs`:

```bash
pip install keras-rs
```

To try out the latest version of Keras Recommenders, you can use our nightly
package:

```bash
pip install keras-rs-nightly
```

Read [Getting started with Keras](https://keras.io/getting_started/) for more
information on installing Keras 3 and compatibility with different frameworks.

> [!IMPORTANT]
> We recommend using Keras Recommenders with TensorFlow 2.16 or later, as
> TF 2.16 packages Keras 3 by default.
## Configuring your backend

If you have Keras 3 installed in your environment (see installation above), you
Expand All @@ -27,7 +49,7 @@ Or in Colab, with:
import os
os.environ["KERAS_BACKEND"] = "jax"

import keras_recommenders
import keras_rs
```

> [!IMPORTANT]
Expand Down
Empty file added keras_rs/src/__init__.py
Empty file.
Empty file added keras_rs/src/layers/__init__.py
Empty file.
Empty file.
140 changes: 140 additions & 0 deletions pip_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Script to create (and optionally install) a `.whl` archive for Keras RS.
Usage:
1. Create a `.whl` file in `dist/`:
```
python3 pip_build.py
```
2. Also install the new package immediately after:
```
python3 pip_build.py --install
```
"""

import argparse
import datetime
import os
import pathlib
import re
import shutil

package = "keras_rs"
build_directory = "tmp_build_dir"
dist_directory = "dist"
to_copy = ["setup.py", "README.md"]


def ignore_files(path: str, filenames: list[str]) -> list[str]:
if path.endswith("testing"):
return filenames
return [f for f in filenames if f.endswith("_test.py")]


def update_version(
build_path: pathlib.Path, version: str, is_nightly: bool
) -> None:
"""Export Version and Package Name."""
if is_nightly:
date = datetime.datetime.now()
version += f".dev{date.strftime('%Y%m%d%H')}"
# Replaces `name="keras-rs"` in `setup.py` with `keras-rs-nightly`
with open(build_path / "setup.py") as f:
setup_contents = f.read()
with open(build_path / "setup.py", "w") as f:
setup_contents = setup_contents.replace(
'name="keras-rs"', 'name="keras-rs-nightly"'
)
f.write(setup_contents)

# Make sure to export the __version__ string
version_utils = build_path / package / "src" / "version_utils.py"
with open(version_utils) as f:
contents = f.read()
with open(version_utils, "w") as f:
contents = re.sub(
"\n__version__ = .*\n",
f'\n__version__ = "{version}"\n',
contents,
)
f.write(contents)


def copy_source_to_build_directory(root_path: pathlib.Path) -> None:
# Copy sources (`keras_rs/` directory and setup files) to build directory
shutil.copytree(
root_path / package,
root_path / build_directory / package,
ignore=ignore_files,
)
for fname in to_copy:
shutil.copy(root_path / fname, root_path / build_directory / fname)


def build_wheel(
build_path: pathlib.Path, dist_path: pathlib.Path, __version__: str
) -> pathlib.Path:
# Build the package
os.chdir(build_path)
os.system("python3 -m build")

# Save the dist files generated by the build process
if not os.path.exists(dist_path):
os.mkdir(dist_path)
for fpath in (build_path / dist_directory).glob("*.*"):
shutil.copy(fpath, dist_path)

# Find the .whl file path
for fname in os.listdir(dist_path):
if __version__ in fname and fname.endswith(".whl"):
whl_path = dist_path / fname
print(f"Build successful. Wheel file available at {whl_path}")
return whl_path
raise FileNotFoundError("Build failed")


def build(root_path: pathlib.Path, is_nightly: bool) -> pathlib.Path:
if os.path.exists(build_directory):
raise ValueError(f"Directory already exists: {build_directory}")

try:
build_path = root_path / build_directory
dist_path = root_path / dist_directory
os.mkdir(build_path)

from keras_rs.src.version_utils import __version__ # noqa: E402

copy_source_to_build_directory(root_path)
update_version(build_path, __version__, is_nightly)
return build_wheel(build_path, dist_path, __version__)
finally:
# Clean up: remove the build directory (no longer needed)
os.chdir(root_path)
shutil.rmtree(root_path / build_directory)


def install_whl(whl_fpath: pathlib.Path) -> None:
print(f"Installing wheel file: {whl_fpath}")
os.system(f"pip3 install {whl_fpath} --force-reinstall --no-dependencies")


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--install",
action="store_true",
help="Whether to install the generated wheel file.",
)
parser.add_argument(
"--nightly",
action="store_true",
help="Whether to generate nightly wheel file.",
)
args = parser.parse_args()
root_path = pathlib.Path(__file__).parent.resolve()
whl_path = build(root_path, args.nightly)
if whl_path and args.install:
install_whl(whl_path)

0 comments on commit 167a1d1

Please sign in to comment.