Skip to content

Commit 8dad4fa

Browse files
committed
- Broadly enhanced build infrastructure, allowing dynamic versioning both at installation time and via CLI post installation.
- **New Feature**: - Initially, the dynamic versioning system allows toggling between Lightning unified and standalone imports. - The two conversion operations are individually idempotent and mutually reversible. - utils.py - Core import conversion functionality - toggle_lightning_mode.py - CLI tool - **Package Configuration**: Modernized pyproject.toml to use PEP 639 metadata - **Dependencies**: Replaced hardcoded Lightning dependencies with dynamic detection system - **Version Handling**: Added support for dynamic requirements via commit pins - **Entry Points**: Added CLI command registration for `toggle-lightning-mode` utility - **Environment Variables**: Added `USE_CI_COMMIT_PIN="1"` to GitHub workflows and Azure pipelines - **Docker**: Updated base-cuda Dockerfile to use commit pins and upgrade setuptools - **New File**: Added lightning_pin.txt to track specific Lightning commits - **Removed**: Deleted standalone base requirements file in favor of dynamic generation - **Build**: Enhanced setup.py to handle different Lightning import styles - **Removed**: Cleaned up deprecated code from assistant.py - **Packaging**: Updated MANIFEST.in to exclude tests directory and include toggle script
1 parent 196d515 commit 8dad4fa

File tree

23 files changed

+1128
-268
lines changed

23 files changed

+1128
-268
lines changed

.actions/assistant.py

Lines changed: 1 addition & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -2,124 +2,16 @@
22
import datetime
33
import os
44
import re
5-
import shutil
6-
from collections.abc import ValuesView
7-
from os.path import dirname, isfile
85
from pprint import pprint
9-
from typing import List, Optional, Sequence, Tuple
6+
from typing import Sequence
107

118
REQUIREMENT_FILES = [
129
"requirements/base.txt",
1310
"requirements/extra.txt",
1411
"requirements/examples.txt",
1512
]
1613

17-
18-
def _retrieve_files(directory: str, *ext: str) -> List[str]:
19-
all_files = []
20-
for root, _, files in os.walk(directory):
21-
for fname in files:
22-
if not ext or any(os.path.split(fname)[1].lower().endswith(e) for e in ext):
23-
all_files.append(os.path.join(root, fname))
24-
25-
return all_files
26-
27-
28-
def _replace_standalone_imports(lines: List[str], mapping: List[Tuple[str, str]], lightning_by: str = "") -> List[str]:
29-
"""Replace imports of standalone package to lightning.
30-
31-
Adapted from `assistant._replace_imports`
32-
"""
33-
out = lines[:]
34-
for source_import, target_import in mapping:
35-
for i, ln in enumerate(out):
36-
out[i] = re.sub(
37-
rf"([^_/@]|^){source_import}([^_\w/]|$)",
38-
rf"\1{target_import}\2",
39-
ln,
40-
)
41-
if lightning_by: # in addition, replace base package
42-
out[i] = out[i].replace("from lightning import ", f"from {lightning_by} import ")
43-
out[i] = out[i].replace("import lightning ", f"import {lightning_by} ")
44-
return out
45-
46-
47-
def _replace_unified_imports(lines: List[str], mapping: List[Tuple[str, str]], lightning_by: str = "") -> List[str]:
48-
"""Replace imports of standalone package to unified lightning.
49-
50-
Adapted from `assistant._replace_imports`
51-
"""
52-
out = lines[:]
53-
for source_import, target_import in mapping:
54-
for i, ln in enumerate(out):
55-
out[i] = re.sub(
56-
rf"([^_/@]|^){source_import}([^_\w/]|$)",
57-
rf"\1{target_import}\2",
58-
ln,
59-
)
60-
if lightning_by: # in addition, replace base package
61-
out[i] = out[i].replace("from lightning import ", f"from {lightning_by} import ")
62-
out[i] = out[i].replace("import lightning ", f"import {lightning_by} ")
63-
return out
64-
65-
66-
def copy_replace_imports(
67-
source_dir: str,
68-
source_imports: Sequence[str],
69-
target_imports: Sequence[str],
70-
target_dir: Optional[str] = None,
71-
lightning_by: str = "",
72-
) -> None:
73-
"""Replace package content with import adjustments.
74-
75-
Adapted from `assistant.copy_replace_imports`
76-
"""
77-
print(f"Replacing imports: {locals()}")
78-
assert len(source_imports) == len(target_imports), (
79-
"source and target imports must have the same length, "
80-
f"source: {len(source_imports)}, target: {len(target_imports)}"
81-
)
82-
if target_dir is None:
83-
target_dir = source_dir
84-
85-
ls = _retrieve_files(source_dir)
86-
for fp in ls:
87-
fp_new = fp.replace(source_dir, target_dir)
88-
_, ext = os.path.splitext(fp)
89-
if ext in (".png", ".jpg", ".ico"):
90-
os.makedirs(dirname(fp_new), exist_ok=True)
91-
if not isfile(fp_new):
92-
shutil.copy(fp, fp_new)
93-
continue
94-
elif ext in (".pyc",):
95-
continue
96-
# Try to parse everything else
97-
with open(fp, encoding="utf-8") as fo:
98-
try:
99-
lines = fo.readlines()
100-
except UnicodeDecodeError:
101-
# a binary file, skip
102-
print(f"Skipped replacing imports for {fp}")
103-
continue
104-
lines = _replace_standalone_imports(lines, list(zip(source_imports, target_imports)), lightning_by=lightning_by)
105-
os.makedirs(os.path.dirname(fp_new), exist_ok=True)
106-
with open(fp_new, "w", encoding="utf-8") as fo:
107-
fo.writelines(lines)
108-
109-
110-
def use_standalone_pl(mapping, src_dirs: ValuesView) -> None:
111-
for in_place_path in src_dirs:
112-
for _, _ in mapping.items():
113-
copy_replace_imports(
114-
source_dir=str(in_place_path),
115-
source_imports=mapping.keys(),
116-
target_imports=mapping.values(),
117-
target_dir=str(in_place_path),
118-
)
119-
120-
12114
class AssistantCLI:
122-
12315
_PATH_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
12416

12517
@staticmethod
@@ -171,24 +63,6 @@ def prepare_nightly_version(proj_root: str = _PATH_ROOT) -> None:
17163
with open(path_info, "w") as fp:
17264
fp.write(init)
17365

174-
@staticmethod
175-
def copy_replace_imports(
176-
source_dir: str,
177-
source_import: str,
178-
target_import: str,
179-
target_dir: Optional[str] = None,
180-
lightning_by: str = "",
181-
) -> None:
182-
"""Copy package content in-place with import adjustments.
183-
184-
Adapated from Lightning version of `assistant`.
185-
"""
186-
source_imports = source_import.strip().split(",")
187-
target_imports = target_import.strip().split(",")
188-
copy_replace_imports(
189-
source_dir, source_imports, target_imports, target_dir=target_dir, lightning_by=lightning_by
190-
)
191-
19266

19367
if __name__ == "__main__":
19468
import jsonargparse

.azure-pipelines/gpu-tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ jobs:
7171
. /tmp/venvs/fts_dev/bin/activate
7272
pip install --upgrade pip requests setuptools
7373
pip install -e . --no-warn-script-location --requirement requirements/devel.txt
74-
pip install lightning --upgrade
75-
#env:
76-
#PACKAGE_NAME: "pytorch"
74+
# pip install lightning --upgrade
75+
env:
76+
USE_CI_COMMIT_PIN: "1"
7777
displayName: 'Install dependencies'
7878
7979
- bash: |
8080
. /tmp/venvs/fts_dev/bin/activate
8181
python requirements/collect_env_details.py
82-
python -c "import torch ; mgpu = torch.cuda.device_count() ; assert mgpu >= 2, f'GPU: {mgpu}'"
82+
python -c "import torch ; print(f'PyTorch CUDA version: {torch.version.cuda}') ; mgpu = torch.cuda.device_count() ; assert mgpu >= 2, f'GPU: {mgpu}'"
8383
displayName: 'Env details'
8484
8585
- bash: |

.github/workflows/ci_test-full.yml

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ jobs:
7171
run: python -c "import time; days = time.time() / 60 / 60 / 24; print(f'TIME_PERIOD=d{int(days / 2) * 2}')" >> $GITHUB_ENV
7272

7373
- name: basic setup
74+
env:
75+
USE_CI_COMMIT_PIN: "1"
7476
run: |
7577
pip --version
7678
pip install --requirement requirements/cli.txt --upgrade
@@ -80,6 +82,23 @@ jobs:
8082
run: |
8183
python .actions/assistant.py replace_oldest_ver
8284
85+
# - name: Install Lightning from pin
86+
# env:
87+
# USE_CI_COMMIT_PIN: "1"
88+
# run: |
89+
# # Install Lightning from the pinned commit
90+
# python -c "from src.finetuning_scheduler.dynamic_versioning.utils import get_lightning_requirement; print(f'Installing {get_lightning_requirement(\"unified\", True)}')"
91+
# pip install $(python -c "from src.finetuning_scheduler.dynamic_versioning.utils import get_lightning_requirement; print(get_lightning_requirement(\"unified\", True))")
92+
# pip list | grep -i lightning
93+
94+
- name: Install package with dependencies
95+
env:
96+
USE_CI_COMMIT_PIN: "1"
97+
run: |
98+
# Install the package with all dependencies (including pinned Lightning)
99+
pip install '.[all]'
100+
# pip list | grep -i lightning
101+
83102
# Note: This uses an internal pip API and may not always work
84103
# https://github.com/actions/cache/blob/master/examples.md#multiple-oss-in-a-workflow
85104
# sadly, this env var is not properly abstracted over OS platforms so we set it twice, the second time for windows
@@ -97,13 +116,13 @@ jobs:
97116
restore-keys: |
98117
${{ runner.os }}-pip-td${{ env.TIME_PERIOD }}-py${{ matrix.python-version }}-${{ matrix.release }}-${{ matrix.requires }}-
99118
100-
- name: Install extra dependencies
101-
run: |
102-
pip install --requirement requirements/base.txt --upgrade
103-
pip install --requirement requirements/examples.txt --upgrade
104-
pip install --requirement requirements/test.txt --upgrade
105-
pip list
106-
shell: bash
119+
# - name: Install extra dependencies
120+
# run: |
121+
# pip install --requirement requirements/base.txt --upgrade
122+
# pip install --requirement requirements/examples.txt --upgrade
123+
# pip install --requirement requirements/test.txt --upgrade
124+
# pip list
125+
# shell: bash
107126

108127
- name: Cache datasets
109128
uses: actions/cache@v4

.github/workflows/code-checks.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
- uses: actions/setup-python@v5
1818
with:
1919
python-version: '3.12'
20+
env:
21+
USE_CI_COMMIT_PIN: "1"
2022
- name: Install dependencies
2123
run: |
2224
pip install '.[dev]'

.github/workflows/release-pypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232

3333
- name: Install dependencies
3434
run: >-
35-
python -m pip install --user --upgrade build
35+
python -m pip install --user --upgrade build twine setuptools
3636
3737
- name: Build packages
3838
run: |

MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ recursive-exclude __pycache__ *.py[cod] *.orig lightning_logs
44
prune src/fts_examples/ipynb_src
55
# exclude fts_examples tests
66
exclude src/fts_examples/test_examples.py
7+
# Exclude tests directory
8+
prune tests
79
# Include the README and CHANGELOG
810
include *.md
911
# Include the license file
@@ -13,6 +15,8 @@ include .actions/assistant.py
1315
include *.cff
1416
# Include marker file for PEP 561
1517
include src/finetuning_scheduler/py.typed
18+
# Explicitly include the toggle script to ensure entry points work
19+
include src/finetuning_scheduler/dynamic_versioning/toggle_lightning_mode.py
1620
# Include the Requirements
1721
recursive-include requirements *.txt
1822
include requirements.txt

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ wget https://github.com/speediedan/finetuning-scheduler/releases/download/v${FTS
122122
pip install finetuning-scheduler-${FTS_VERSION}.tar.gz
123123
```
124124

125+
### Toggling Between Unified and Standalone Lightning Imports
126+
127+
FTS provides a command-line tool to easily toggle between unified and standalone imports in your codebase:
128+
129+
```bash
130+
# Toggle from unified to standalone Lightning imports
131+
toggle-lightning-mode --mode standalone
132+
133+
# Toggle from standalone to unified Lightning imports (default)
134+
toggle-lightning-mode --mode unified
135+
# Or simply
136+
toggle-lightning-mode
137+
```
138+
139+
This can be useful when:
140+
141+
- You need to adapt existing code to work with a different Lightning package
142+
- You're switching between projects using different Lightning import styles
143+
- You want to test compatibility with both import styles
144+
125145
______________________________________________________________________
126146

127147
## Examples

dockers/base-cuda/Dockerfile

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@ COPY ./requirements.txt requirements.txt
6464
COPY ./requirements/ ./requirements/
6565

6666
ENV PYTHONPATH=/usr/lib/python${PYTHON_VERSION}/site-packages
67+
ENV USE_CI_COMMIT_PIN="1"
6768

6869
RUN \
6970
wget https://bootstrap.pypa.io/get-pip.py --progress=bar:force:noscroll --no-check-certificate | python${PYTHON_VERSION} && \
7071
python${PYTHON_VERSION} get-pip.py && \
7172
rm get-pip.py && \
72-
python${PYTHON_VERSION} -m pip install --upgrade pip && \
73+
python${PYTHON_VERSION} -m pip install --upgrade pip setuptools && \
7374
# Disable cache
7475
pip config set global.cache-dir false && \
7576
pip install virtualenv && \
@@ -92,22 +93,37 @@ RUN \
9293
# ... test channel
9394
#pip install --pre torch==2.6.0 torchvision --index-url https://download.pytorch.org/whl/test/cu126; \
9495
fi && \
96+
# We avoid installing Lightning and other dependencies here as they are usually upgraded anyway later in
97+
# CI but we may re-enable in the future.
98+
# LIGHTNING_COMMIT=$(cat ./requirements/lightning_pin.txt) && \
99+
# pip install "lightning @ git+https://github.com/Lightning-AI/lightning.git@${LIGHTNING_COMMIT}#egg=lightning" --no-cache-dir && \
95100
# Install all requirements
96-
pip install -r requirements/devel.txt --no-cache-dir && \
101+
# pip install -r requirements/devel.txt --no-cache-dir && \
97102
# Update six
98103
pip install -U six --no-cache-dir && \
99104
chmod -R 777 /tmp/venvs/fts_dev && \
100105
rm -rf requirements.* requirements/
101106

102107
RUN \
108+
set -x && \
103109
. /tmp/venvs/fts_dev/bin/activate && \
110+
echo "Checking CUDA version:" && \
104111
CUDA_VERSION_MAJOR=$(python -c "import torch; print(torch.version.cuda.split('.')[0])") && \
105-
py_ver=$(python -c "print(int('$PYTHON_VERSION'.split('.') >= '3.12'.split('.')))")
112+
echo "CUDA Version Major: ${CUDA_VERSION_MAJOR}" && \
113+
echo "Checking Python version compatibility:" && \
114+
py_ver=$(python -c "print(int('$PYTHON_VERSION'.split('.') >= '3.12'.split('.')))") && \
115+
echo "Python version check result: ${py_ver}"
106116

107117
RUN \
108-
# Show what we have
118+
set -x && \
119+
echo "============= Environment Information =============" && \
109120
. /tmp/venvs/fts_dev/bin/activate && \
121+
echo "Pip version:" && \
110122
pip --version && \
123+
echo "Installed packages:" && \
111124
pip list && \
112-
python -c "import sys; ver = sys.version_info ; assert f'{ver.major}.{ver.minor}' == '$PYTHON_VERSION', ver" && \
113-
python -c "import torch; assert torch.__version__.startswith('$PYTORCH_VERSION'), torch.__version__"
125+
echo "Verifying Python version:" && \
126+
python -c "import sys; ver = sys.version_info; print(f'Python {ver.major}.{ver.minor} detected'); assert f'{ver.major}.{ver.minor}' == '$PYTHON_VERSION', ver" && \
127+
echo "Verifying PyTorch version:" && \
128+
python -c "import torch; print(f'PyTorch {torch.__version__} detected'); assert torch.__version__.startswith('$PYTORCH_VERSION'), torch.__version__" && \
129+
echo "============= Environment Verification Complete ============="

dockers/docker_images_release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ maybe_build(){
4141

4242
build_eval(){
4343
# latest PyTorch image supported by release
44-
declare -A iv=(["cuda"]="12.6.3" ["python"]="3.12" ["pytorch"]="2.6.0" ["lightning"]="2.6" ["cust_build"]="0")
44+
declare -A iv=(["cuda"]="12.6.3" ["python"]="3.12" ["pytorch"]="2.6.0" ["lightning"]="2.6" ["cust_build"]="1")
4545
export latest_pt="base-cu${iv["cuda"]}-py${iv["python"]}-pt${iv["pytorch"]}-pl${iv["lightning"]}"
4646
export latest_azpl="py${iv["python"]}-pt${iv["pytorch"]}-pl${iv["lightning"]}-azpl-init"
4747
maybe_build iv "${latest_pt}" "${latest_azpl}"

0 commit comments

Comments
 (0)