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

Add pip_build.py and required __init__.py files, update README.md. #6

Merged
merged 1 commit into from
Oct 29, 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
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)