Skip to content

Commit db056df

Browse files
authored
SG-42305 Packaging for v3.10.2 (#448)
* add update_certifi script to automate certifi update * move scripts to dev folder * update certifi to 2026.6.17
1 parent e831414 commit db056df

9 files changed

Lines changed: 174 additions & 641 deletions

File tree

HISTORY.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Flow Production Tracking Python API Changelog
44

55
Here you can see the full list of changes between each Python API release.
66

7+
v3.10.2 (2026 Jun 26)
8+
=====================
9+
10+
- Update bundled certifi to version 2026.6.17.
11+
712
v3.10.1 (2026 Feb 10)
813
=====================
914

developer/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11

22
# Updating HTTPLib2
33

4-
The API comes with a copy of the `httplib2` inside the `shotgun_api3/lib` folder. To update the copy to a more recent version of the API, you can run the `update_httplib2.py` script at the root of this repository like this:
4+
The API comes with a copy of the `httplib2` inside the `shotgun_api3/lib` folder. To update the copy to a more recent version of the API, you can run the `update_httplib2.py` script from the `developer/` directory like this:
55

66
python update_httplib2.py vX.Y.Z
77

8-
where `vX.Y.Z` is a release found on `httplib2`'s [release page](https://github.com/httplib2/httplib2/releases).
8+
where `vX.Y.Z` is a release found on `httplib2`'s [tags page](https://github.com/httplib2/httplib2/tags).
9+
10+
# Updating Certifi
11+
12+
The API comes with a copy of `certifi` inside the `shotgun_api3/lib` folder. To update the copy to a more recent version of the API, you can run the `update_certifi.py` script from the `developer/` directory like this:
13+
14+
python update_certifi.py YYYY.MM.DD
15+
16+
where `YYYY.MM.DD` is a release found on `certifi`'s [release page](https://pypi.org/project/certifi/#history).
917

1018

1119
# Release process

developer/update_certifi.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Updates the bundled certifi module.
5+
6+
Run as "./update_certifi.py YYYY.MM.DD" to get a specific release from PyPI.
7+
"""
8+
9+
import pathlib
10+
import re
11+
import shutil
12+
import subprocess
13+
import sys
14+
import tempfile
15+
16+
17+
class Utilities:
18+
def download_wheel(self, version, dest_dir):
19+
"""Download the certifi wheel from PyPI."""
20+
print(f"Downloading certifi {version}")
21+
subprocess.check_output(
22+
[
23+
"pip",
24+
"download",
25+
f"certifi=={version}",
26+
"--no-deps",
27+
"--index-url",
28+
"https://pypi.org/simple/",
29+
"-d",
30+
str(dest_dir),
31+
]
32+
)
33+
34+
def unzip_archive(self, file_path, temp_dir):
35+
"""Unzip in a temp dir."""
36+
print(f"Unzipping {file_path.name}")
37+
subprocess.check_output(["unzip", str(file_path), "-d", str(temp_dir)])
38+
39+
def remove_folder(self, path):
40+
"""Remove a folder recursively."""
41+
print(f"Removing the folder {path}")
42+
shutil.rmtree(path, ignore_errors=True)
43+
44+
def git_remove(self, target):
45+
print(f"Removing {target} in git.")
46+
try:
47+
subprocess.check_output(["git", "rm", "-rf"] + target)
48+
except Exception:
49+
pass
50+
51+
def copy_folder(self, source, target):
52+
"""Copy a folder recursively."""
53+
shutil.copytree(source, target)
54+
55+
def update_requirements(self, req_file, version):
56+
"""Update the certifi version pin in requirements.txt."""
57+
content = req_file.read_text()
58+
content = re.sub(r"certifi==[\d.]+", f"certifi=={version}", content)
59+
req_file.write_text(content)
60+
61+
62+
def main(temp_path, repo_root, version):
63+
certifi_dir = repo_root / "shotgun_api3" / "lib" / "certifi"
64+
req_file = repo_root / "shotgun_api3" / "lib" / "requirements.txt"
65+
66+
utilities = Utilities()
67+
68+
# Download the wheel from PyPI
69+
utilities.download_wheel(version, temp_path)
70+
71+
# Find the downloaded wheel file
72+
wheels = list(temp_path.glob("certifi-*.whl"))
73+
if not wheels:
74+
raise RuntimeError("No certifi wheel found after download")
75+
76+
# Unzip into a temp dir
77+
unzipped = temp_path / "unzipped"
78+
unzipped.mkdir()
79+
utilities.unzip_archive(wheels[0], unzipped)
80+
81+
# Remove old certifi from git and disk
82+
utilities.git_remove([str(certifi_dir)])
83+
utilities.remove_folder(certifi_dir)
84+
85+
# Copy new certifi into place (only the certifi/ package, not .dist-info)
86+
print("Copying new version of certifi")
87+
utilities.copy_folder(str(unzipped / "certifi"), str(certifi_dir))
88+
89+
# Update requirements.txt version pin
90+
print("Updating requirements.txt")
91+
utilities.update_requirements(req_file, version)
92+
93+
# Stage changes
94+
print("Adding to git")
95+
subprocess.check_output(
96+
["git", "add", str(certifi_dir), str(req_file)]
97+
) # nosec B607
98+
99+
100+
def find_repo_root():
101+
path = pathlib.Path(__file__).resolve()
102+
for parent in [path, *path.parents]:
103+
if (parent / ".git").exists():
104+
return parent
105+
raise RuntimeError("Could not find repo root (no .git directory found)")
106+
107+
108+
if __name__ == "__main__":
109+
try:
110+
temp_path = pathlib.Path(tempfile.mkdtemp())
111+
main(temp_path, find_repo_root(), sys.argv[1])
112+
finally:
113+
shutil.rmtree(temp_path)
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44
Updates the httplib2 module.
55
6-
Run as "./upgrade_httplib2.py vX.Y.Z" to get a specific release from github.
6+
Run as "./update_httplib2.py vX.Y.Z" to get a specific release from github.
77
"""
88

99
import pathlib
@@ -93,7 +93,11 @@ def main(temp_path, repo_root, version):
9393
# Copies a new version into place.
9494
print("Copying new version of httplib2")
9595
root_folder = unzipped_folder / f"httplib2-{version[1:]}"
96-
utilities.copy_folder(str(root_folder / "python3" / "httplib2"), httplib2_dir)
96+
# Older releases had python3/httplib2/; newer ones have httplib2/ at root.
97+
python3_path = root_folder / "python3" / "httplib2"
98+
flat_path = root_folder / "httplib2"
99+
src_path = python3_path if python3_path.exists() else flat_path
100+
utilities.copy_folder(str(src_path), httplib2_dir)
97101
utilities.remove_folder(f"{httplib2_dir}/test")
98102

99103
# Patches the httplib2 imports so they are relative instead of absolute.
@@ -106,9 +110,17 @@ def main(temp_path, repo_root, version):
106110
subprocess.check_output(["git", "add", str(httplib2_dir)]) # nosec B607
107111

108112

113+
def find_repo_root():
114+
path = pathlib.Path(__file__).resolve()
115+
for parent in [path, *path.parents]:
116+
if (parent / ".git").exists():
117+
return parent
118+
raise RuntimeError("Could not find repo root (no .git directory found)")
119+
120+
109121
if __name__ == "__main__":
110122
try:
111123
temp_path = pathlib.Path(tempfile.mkdtemp())
112-
main(temp_path, pathlib.Path(__file__).parent, sys.argv[1])
124+
main(temp_path, find_repo_root(), sys.argv[1])
113125
finally:
114126
shutil.rmtree(temp_path)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
setup(
2222
name="shotgun_api3",
23-
version="3.10.0",
23+
version="3.10.2",
2424
description="Flow Production Tracking Python API",
2525
long_description=readme,
2626
author="Autodesk",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from .core import contents, where
22

33
__all__ = ["contents", "where"]
4-
__version__ = "2026.01.04"
4+
__version__ = "2026.06.17"

0 commit comments

Comments
 (0)