88UPLOAD_URL_PREFIX = os.getenv("UPLOAD_URL_PREFIX", "https://www.python.org/ftp/")
99UPLOAD_PATH_PREFIX = os.getenv("UPLOAD_PATH_PREFIX", "/srv/www.python.org/ftp/")
1010UPLOAD_URL = os.getenv("UPLOAD_URL")
11- UPLOAD_DIR = os.getenv("UPLOAD_DIR")
11+ UPLOAD_DIR = os.getenv("UPLOAD_DIR", "dist" )
1212UPLOAD_HOST = os.getenv("UPLOAD_HOST", "")
1313UPLOAD_HOST_KEY = os.getenv("UPLOAD_HOST_KEY", "")
1414UPLOAD_KEYFILE = os.getenv("UPLOAD_KEYFILE", "")
@@ -126,6 +126,25 @@ def url2path(url):
126126 return UPLOAD_PATH_PREFIX + url[len(UPLOAD_URL_PREFIX) :]
127127
128128
129+ def appinstaller_uri_matches(file, name):
130+ NS = {}
131+ with open(file, "r", encoding="utf-8") as f:
132+ NS = dict(e for _, e in ET.iterparse(f, events=("start-ns",)))
133+ for k, v in NS.items():
134+ ET.register_namespace(k, v)
135+ NS["x"] = NS[""]
136+
137+ with open(file, "r", encoding="utf-8") as f:
138+ xml = ET.parse(f)
139+
140+ self_uri = xml.find(".[@Uri]", NS).get("Uri")
141+ if not self_uri:
142+ print("##[error]Empty Uri attribute in appinstaller file")
143+ sys.exit(2)
144+
145+ return self_uri.rpartition("/")[2].casefold() == name.casefold()
146+
147+
129148def validate_appinstaller(file, uploads):
130149 NS = {}
131150 with open(file, "r", encoding="utf-8") as f:
@@ -141,10 +160,8 @@ def validate_appinstaller(file, uploads):
141160 if not self_uri:
142161 print("##[error]Empty Uri attribute in appinstaller file")
143162 sys.exit(2)
144- if not any(
145- u.casefold() == self_uri.casefold() and f == file
146- for f, u, _ in uploads
147- ):
163+ upload_targets = [u for f, u, _ in uploads if f == file]
164+ if not any(u.casefold() == self_uri.casefold() for u in upload_targets):
148165 print("##[error]Uri", self_uri, "in appinstaller file is not where "
149166 "the appinstaller file is being uploaded.")
150167 sys.exit(2)
@@ -164,6 +181,8 @@ def validate_appinstaller(file, uploads):
164181 print(file, "checked:")
165182 print("-", package_uri, "is part of this upload")
166183 print("-", self_uri, "is the destination of this file")
184+ if len(upload_targets) > 1:
185+ print(" - other destinations:", *(set(upload_targets) - set([self_uri])))
167186 print()
168187
169188
@@ -185,20 +204,29 @@ def purge(url):
185204 u = UPLOAD_URL + f.name
186205 UPLOADS.append((f, u, url2path(u)))
187206else:
188- for pat in ("python-manager-*.msix", "python-manager-*.msi", "pymanager.appinstaller" ):
207+ for pat in ("python-manager-*.msix", "python-manager-*.msi"):
189208 for f in UPLOAD_DIR.glob(pat):
190209 u = UPLOAD_URL + f.name
191210 UPLOADS.append((f, u, url2path(u)))
192211
212+ # pymanager.appinstaller may be uploaded to either the preview URL or both.
213+ f = UPLOAD_DIR / "pymanager.appinstaller"
214+ if f.is_file():
215+ u = UPLOAD_URL + "pymanager-preview.appinstaller"
216+ UPLOADS.append((f, u, url2path(u)))
217+
218+ if not appinstaller_uri_matches(f, "pymanager-preview.appinstaller"):
219+ u = UPLOAD_URL + f.name
220+ UPLOADS.append((f, u, url2path(u)))
221+
193222print("Planned uploads:")
194223for f, u, p in UPLOADS:
195224 print(f"{f} -> {p}")
196225 print(f" Final URL: {u}")
197226print()
198227
199- for f, *_ in UPLOADS:
200- if f.match("*.appinstaller"):
201- validate_appinstaller(f, UPLOADS)
228+ for f in {f for f, *_ in UPLOADS if f.match("*.appinstaller")}:
229+ validate_appinstaller(f, UPLOADS)
202230
203231for f, u, p in UPLOADS:
204232 print("Upload", f, "to", p)
0 commit comments