Skip to content

Commit db60cab

Browse files
AmitMYclaude
andcommitted
chore: migrate from pylint to ruff, update CI workflows
- Replace pylint with ruff for linting and formatting - Update CI workflows to use uv and correct package name - Add release workflow for PyPI publishing - Add requires-python constraint - Fix code style issues (imports, quotes, comparisons) - Add initial test for get_mean_appearance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent bc4eaa6 commit db60cab

File tree

12 files changed

+134
-70
lines changed

12 files changed

+134
-70
lines changed

.github/workflows/lint.yaml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,31 @@ name: Lint
33

44
on:
55
push:
6-
branches: [ master, main ]
6+
branches: [ main ]
77
pull_request:
8-
branches: [ master, main ]
8+
branches: [ main ]
99

1010

1111
jobs:
12-
test:
12+
lint:
1313
name: Lint
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v3
18-
- uses: actions/setup-python@v4
17+
- uses: actions/checkout@v6
18+
19+
- name: Setup uv
20+
uses: astral-sh/setup-uv@v7
1921
with:
20-
python-version: '3.10'
22+
python-version: "3.9"
23+
enable-cache: true
24+
activate-environment: true
25+
26+
- name: Install dependencies
27+
run: uv pip install ".[dev]"
2128

22-
- name: Install Requirements
23-
run: pip install .[dev]
29+
- name: Lint code
30+
run: uv run ruff check pose_anonymization
2431

25-
- name: Lint Code
26-
run: pylint pose_anonymization
32+
- name: Check formatting
33+
run: uv run ruff format --check pose_anonymization

.github/workflows/release.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Publish Python Package
2+
on:
3+
release:
4+
types: [ created ]
5+
6+
jobs:
7+
pypi-publish:
8+
name: Upload release to PyPI
9+
runs-on: ubuntu-latest
10+
environment:
11+
name: pypi
12+
url: https://pypi.org/p/pose-anonymization
13+
permissions:
14+
id-token: write
15+
steps:
16+
- uses: actions/checkout@v5
17+
18+
- uses: actions/setup-python@v6
19+
with:
20+
python-version: "3.12"
21+
22+
- name: Extract release version
23+
id: get_version
24+
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
25+
26+
- name: Update version in pyproject.toml
27+
run: |
28+
sed -i 's/^version = .*/version = "${{ env.version }}"/' pyproject.toml
29+
30+
- name: Install build dependencies
31+
run: pip install build
32+
33+
- name: Build a binary wheel dist
34+
run: |
35+
rm -rf dist
36+
python -m build
37+
38+
- name: Publish distribution 📦 to PyPI
39+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/test.yaml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: Test
33

44
on:
55
push:
6-
branches: [ master, main ]
6+
branches: [ main ]
77
pull_request:
8-
branches: [ master, main ]
8+
branches: [ main ]
99

1010

1111
jobs:
@@ -14,13 +14,17 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v3
18-
- uses: actions/setup-python@v4
17+
- uses: actions/checkout@v6
18+
19+
- name: Setup uv
20+
uses: astral-sh/setup-uv@v7
1921
with:
20-
python-version: '3.10'
22+
python-version: "3.9"
23+
enable-cache: true
24+
activate-environment: true
2125

22-
- name: Install Requirements
23-
run: pip install .[dev]
26+
- name: Install dependencies
27+
run: uv pip install ".[dev]"
2428

2529
- name: Test Code
26-
run: pytest pose_anonymization
30+
run: uv run pytest

pose_anonymization/appearance.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import numpy as np
44
from pose_format import Pose
55
from pose_format.numpy import NumPyPoseBody
6-
from pose_format.utils.generic import pose_normalization_info
6+
from pose_format.utils.generic import normalize_pose_size, pose_normalization_info
77

88
from pose_anonymization.data import load_mean_and_std, load_pose_header
9-
from pose_format.utils.generic import normalize_pose_size
109

1110

1211
def get_pose_appearance(pose: Pose, include_end_frame=False):
@@ -27,7 +26,7 @@ def change_appearace(pose: Pose, appearance: np.ndarray):
2726
new_pose_data = pose.body.data - appearance
2827

2928
# Bring back the hands
30-
hand_components = ['LEFT_HAND_LANDMARKS', 'RIGHT_HAND_LANDMARKS']
29+
hand_components = ["LEFT_HAND_LANDMARKS", "RIGHT_HAND_LANDMARKS"]
3130
for component in pose.header.components:
3231
if component.name in hand_components:
3332
# pylint: disable=protected-access
@@ -36,12 +35,12 @@ def change_appearace(pose: Pose, appearance: np.ndarray):
3635
new_pose_data[:, :, start:end] = pose.body.data[:, :, start:end]
3736

3837
# Bring back the wrists
39-
body_component = next(c for c in pose.header.components if c.name == 'POSE_LANDMARKS')
40-
points = [f'{hand}_{point}' for hand in ['LEFT', 'RIGHT'] for point in ['WRIST', 'PINKY', 'INDEX', 'THUMB']]
38+
body_component = next(c for c in pose.header.components if c.name == "POSE_LANDMARKS")
39+
points = [f"{hand}_{point}" for hand in ["LEFT", "RIGHT"] for point in ["WRIST", "PINKY", "INDEX", "THUMB"]]
4140
existing_points = [p for p in points if p in body_component.points]
4241
for point in existing_points:
4342
# pylint: disable=protected-access
44-
wrist_index = pose.header._get_point_index('POSE_LANDMARKS', point)
43+
wrist_index = pose.header._get_point_index("POSE_LANDMARKS", point)
4544
new_pose_data[:, :, wrist_index] = pose.body.data[:, :, wrist_index]
4645

4746
pose.body.data = new_pose_data
@@ -69,8 +68,7 @@ def transfer_appearance(pose: Pose, appearance_pose: Pose, include_end_frame=Fal
6968
pose_components_points = {c.name: c.points for c in pose.header.components}
7069
appearance_pose = appearance_pose.get_components(pose_components, pose_components_points)
7170

72-
assert pose.header.total_points() == appearance_pose.header.total_points(), \
73-
"Appearance pose missing points"
71+
assert pose.header.total_points() == appearance_pose.header.total_points(), "Appearance pose missing points"
7472

7573
pose, appearance = get_pose_appearance(pose, include_end_frame)
7674
_, new_appearance = get_pose_appearance(appearance_pose, include_end_frame)

pose_anonymization/bin.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
import argparse
44

55
from pose_format import Pose
6-
from pose_format.utils.generic import reduce_holistic, correct_wrists
6+
from pose_format.utils.generic import correct_wrists, reduce_holistic
77

88
from pose_anonymization.appearance import remove_appearance, transfer_appearance
99

1010

1111
def get_args():
1212
parser = argparse.ArgumentParser()
13-
parser.add_argument('--input', required=True, type=str, help='path to input pose file')
14-
parser.add_argument('--appearance', type=str, help='path to appearance pose file')
15-
parser.add_argument('--output', required=True, type=str, help='path to output pose file')
13+
parser.add_argument("--input", required=True, type=str, help="path to input pose file")
14+
parser.add_argument("--appearance", type=str, help="path to appearance pose file")
15+
parser.add_argument("--output", required=True, type=str, help="path to output pose file")
1616
return parser.parse_args()
1717

1818

@@ -37,5 +37,5 @@ def main():
3737
pose.write(f)
3838

3939

40-
if __name__ == '__main__':
40+
if __name__ == "__main__":
4141
main()

pose_anonymization/data/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pathlib import Path
33

44
import numpy as np
5-
from pose_format import PoseHeader, Pose
5+
from pose_format import Pose, PoseHeader
66
from pose_format.numpy import NumPyPoseBody
77
from pose_format.utils.reader import BufferReader
88

@@ -18,7 +18,8 @@ def load_pose_header():
1818
@lru_cache(maxsize=1)
1919
def load_mean_and_std():
2020
import json
21-
with open(CURRENT_DIR / "pose_normalization.json", "r", encoding="utf-8") as f:
21+
22+
with open(CURRENT_DIR / "pose_normalization.json", encoding="utf-8") as f:
2223
data = json.load(f)
2324

2425
mean, std = [], []
@@ -33,6 +34,7 @@ def load_mean_and_std():
3334

3435
return np.array(mean), std
3536

37+
3638
@lru_cache(maxsize=1)
3739
def load_mean_and_std_pose():
3840
pose_header = load_pose_header()

pose_anonymization/data/calc_mean_std.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111

1212

1313
def process_file(file, pose_header: PoseHeader):
14-
with open(file, 'rb') as pose_file:
14+
with open(file, "rb") as pose_file:
1515
pose = Pose.read(pose_file.read())
1616
pose = pre_process_pose(pose, pose_header=pose_header)
1717
tensor = pose.body.data.filled(0)
1818

1919
frames_sum = np.sum(tensor, axis=(0, 1))
2020
frames_squared_sum = np.sum(np.square(tensor), axis=(0, 1))
21-
unmasked_frames = pose.body.data[:, :, :, 0:1].mask == False
21+
unmasked_frames = ~pose.body.data[:, :, :, 0:1].mask
2222
num_unmasked_frames = np.sum(unmasked_frames, axis=(0, 1))
2323

2424
return frames_sum, frames_squared_sum, num_unmasked_frames
@@ -47,7 +47,7 @@ def main(poses_location: str):
4747
print(f"Processing {len(files)} files")
4848

4949
# get a single random pose
50-
with open(files[0], 'rb') as pose_file:
50+
with open(files[0], "rb") as pose_file:
5151
pose = Pose.read(pose_file.read())
5252
pose = pre_process_pose(pose)
5353

@@ -62,10 +62,7 @@ def main(poses_location: str):
6262
for component in pose.header.components:
6363
component_info = {}
6464
for point in component.points:
65-
component_info[point] = {
66-
"mean": mean[i].tolist(),
67-
"std": std[i].tolist()
68-
}
65+
component_info[point] = {"mean": mean[i].tolist(), "std": std[i].tolist()}
6966
i += 1
7067
mean_std_info[component.name] = component_info
7168

@@ -78,9 +75,10 @@ def main(poses_location: str):
7875
if __name__ == "__main__":
7976
import argparse
8077

81-
parser = argparse.ArgumentParser(description='Collect normalization info')
82-
parser.add_argument('--dir', type=str, help='Directory containing the pose files',
83-
default="/Volumes/Echo/GCS/sign-mt-poses")
78+
parser = argparse.ArgumentParser(description="Collect normalization info")
79+
parser.add_argument(
80+
"--dir", type=str, help="Directory containing the pose files", default="/Volumes/Echo/GCS/sign-mt-poses"
81+
)
8482

8583
args = parser.parse_args()
8684

pose_anonymization/data/draw_mean_pose.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
unshift_hands(mean_pose)
1414
normalize_pose_size(mean_pose)
1515

16-
poses = {
17-
"full": mean_pose,
18-
"reduced": reduce_holistic(mean_pose)
19-
}
16+
poses = {"full": mean_pose, "reduced": reduce_holistic(mean_pose)}
2017
for name, pose in poses.items():
2118
pose.focus()
2219

pose_anonymization/data/normalization.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
from pose_format import Pose, PoseHeader
2-
from pose_format.utils.generic import pose_normalization_info, correct_wrists, hands_components
2+
from pose_format.utils.generic import correct_wrists, hands_components, pose_normalization_info
33

4-
from pose_anonymization.data import load_mean_and_std, load_mean_and_std_pose
4+
from pose_anonymization.data import load_mean_and_std_pose
55

66

77
def shift_hand(pose: Pose, hand_component: str, wrist_name: str):
88
# pylint: disable=protected-access
99
wrist_index = pose.header._get_point_index(hand_component, wrist_name)
10-
hand = pose.body.data[:, :, wrist_index: wrist_index + 21]
10+
hand = pose.body.data[:, :, wrist_index : wrist_index + 21]
1111
wrist = hand[:, :, 0:1]
12-
pose.body.data[:, :, wrist_index: wrist_index + 21] = hand - wrist
12+
pose.body.data[:, :, wrist_index : wrist_index + 21] = hand - wrist
1313

1414

1515
def shift_hands(pose: Pose):
@@ -21,12 +21,12 @@ def shift_hands(pose: Pose):
2121
def unshift_hand(pose: Pose, hand_component: str):
2222
# pylint: disable=protected-access
2323
wrist_index = pose.header._get_point_index(hand_component, "WRIST")
24-
hand = pose.body.data[:, :, wrist_index: wrist_index + 21]
24+
hand = pose.body.data[:, :, wrist_index : wrist_index + 21]
2525
body_wrist_name = "LEFT_WRIST" if hand_component == "LEFT_HAND_LANDMARKS" else "RIGHT_WRIST"
2626
# pylint: disable=protected-access
2727
body_wrist_index = pose.header._get_point_index("POSE_LANDMARKS", body_wrist_name)
28-
body_wrist = pose.body.data[:, :, body_wrist_index: body_wrist_index + 1]
29-
pose.body.data[:, :, wrist_index: wrist_index + 21] = hand + body_wrist
28+
body_wrist = pose.body.data[:, :, body_wrist_index : body_wrist_index + 1]
29+
pose.body.data[:, :, wrist_index : wrist_index + 21] = hand + body_wrist
3030

3131

3232
def unshift_hands(pose: Pose):
@@ -58,8 +58,7 @@ def load_mean_and_std_for_pose(pose: Pose):
5858
mean_pose, std_pose = load_mean_and_std_pose()
5959
mean_pose = pose_like(mean_pose, pose.header)
6060
std_pose = pose_like(std_pose, pose.header)
61-
return (mean_pose.body.data.reshape((-1, 3)),
62-
std_pose.body.data.reshape((-1, 3)))
61+
return (mean_pose.body.data.reshape((-1, 3)), std_pose.body.data.reshape((-1, 3)))
6362

6463

6564
def normalize_mean_std(pose: Pose):

pose_anonymization/evaluate_example_stitching.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
for directory in [example_dir / "original", example_dir / "anonymized"]:
1717
poses = []
1818
for word in ["kleine", "kinder", "essen", "pizza"]:
19-
with open(directory / f"{word}.pose", 'rb') as pose_file:
19+
with open(directory / f"{word}.pose", "rb") as pose_file:
2020
poses.append(Pose.read(pose_file.read()))
2121

2222
concatenated = concatenate_poses(poses).get_components(["FACE_LANDMARKS"])
@@ -27,7 +27,7 @@
2727
plt.plot(flow, label=directory.name.capitalize())
2828

2929
plt.yticks([])
30-
plt.legend(loc='upper left')
30+
plt.legend(loc="upper left")
3131
plt.ylabel("Optical Flow")
3232
plt.tight_layout()
3333
fig.show()

0 commit comments

Comments
 (0)