-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathsync_constraints.py
More file actions
135 lines (104 loc) · 4.37 KB
/
sync_constraints.py
File metadata and controls
135 lines (104 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python3
"""
Script to sync common_constraints.txt into pyproject.toml.
This script downloads the common_constraints.txt file from edx-lint and
updates the [tool.uv.constraint-dependencies] section in pyproject.toml.
"""
import re
import sys
from pathlib import Path
from urllib.request import urlopen
COMMON_CONSTRAINTS_URL = "https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt"
PYPROJECT_PATH = Path(__file__).parent / "pyproject.toml"
CONSTRAINTS_FILE_PATH = (
Path(__file__).parent / "requirements" / "common_constraints.txt"
)
def download_constraints():
"""Download the common_constraints.txt file."""
print(f"Downloading constraints from {COMMON_CONSTRAINTS_URL}...")
try:
with urlopen(COMMON_CONSTRAINTS_URL) as response:
content = response.read().decode("utf-8")
# Save to requirements directory for reference
CONSTRAINTS_FILE_PATH.parent.mkdir(exist_ok=True)
CONSTRAINTS_FILE_PATH.write_text(content)
print(f"Saved constraints to {CONSTRAINTS_FILE_PATH}")
return content
except Exception as e:
print(f"Error downloading constraints: {e}", file=sys.stderr)
# Try to read from local file if download fails
if CONSTRAINTS_FILE_PATH.exists():
print("Using existing local constraints file")
return CONSTRAINTS_FILE_PATH.read_text()
raise
def parse_constraints(content):
"""
Parse constraints from common_constraints.txt.
Returns a list of constraint strings suitable for pyproject.toml.
"""
constraints = []
for line in content.split("\n"):
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith("#"):
continue
# Parse constraint (e.g., "Django<6.0" or "pip<26.0")
# Keep the constraint as-is
constraints.append(line)
return constraints
def update_pyproject_toml(constraints):
"""
Update pyproject.toml with the new constraints.
This function updates the [tool.uv.constraint-dependencies] section.
"""
if not PYPROJECT_PATH.exists():
print(f"Error: {PYPROJECT_PATH} not found", file=sys.stderr)
sys.exit(1)
content = PYPROJECT_PATH.read_text()
# Build the new constraint-dependencies section
constraints_section = "[tool.uv]\nconstraint-dependencies = [\n"
constraints_section += " # Downloaded from edx-lint common_constraints.txt\n"
constraints_section += (
" # DO NOT EDIT - Use 'python sync_constraints.py' to update\n"
)
for constraint in constraints:
# Escape quotes if needed
constraint_str = constraint.replace('"', '\\"')
constraints_section += f' "{constraint_str}",\n'
# Add local constraint (greenlet)
constraints_section += " # Local constraint\n"
constraints_section += ' "greenlet>3.0.1", # playwright and sqlalchemy requirements conflict for greenlet<=3.0.1\n'
constraints_section += "]\n"
# Find and replace the [tool.uv] section
# Pattern to match [tool.uv] section with constraint-dependencies
pattern = r"\[tool\.uv\]\s*\nconstraint-dependencies\s*=\s*\[.*?\]"
if re.search(pattern, content, re.DOTALL):
# Replace existing section
new_content = re.sub(
pattern, constraints_section.rstrip(), content, flags=re.DOTALL
)
else:
# Check if [tool.uv] exists without constraint-dependencies
if "[tool.uv]" in content:
# Insert constraint-dependencies into existing [tool.uv]
new_content = content.replace("[tool.uv]", constraints_section.rstrip())
else:
# Add new [tool.uv] section at the end
new_content = content.rstrip() + "\n\n" + constraints_section
PYPROJECT_PATH.write_text(new_content)
print(f"Updated {PYPROJECT_PATH}")
def main():
"""Main function."""
print("Syncing common_constraints.txt to pyproject.toml...")
# Download constraints
constraints_content = download_constraints()
# Parse constraints
constraints = parse_constraints(constraints_content)
print(f"Found {len(constraints)} constraints")
# Update pyproject.toml
update_pyproject_toml(constraints)
print(
"\nDone! Run 'uv lock --upgrade' to update the lock file with the new constraints."
)
if __name__ == "__main__":
main()