1- # ruff: noqa: S603, S607
1+ # ruff: noqa: S607
22from __future__ import annotations
33
44import functools
1111from logging import getLogger
1212from pathlib import Path
1313from typing import TYPE_CHECKING , Any
14+ from urllib import request
1415from uuid import uuid4
1516
1617import reactpy
@@ -118,10 +119,13 @@ def extend_pyscript_config(
118119 f"{ REACTPY_PATH_PREFIX .current } static/morphdom/morphdom-esm.js" : "morphdom"
119120 }
120121 },
121- "packages_cache" : "never" ,
122122 }
123123 pyscript_config ["packages" ].extend (extra_py )
124124
125+ # FIXME: https://github.com/pyscript/pyscript/issues/2282
126+ if any (pkg .endswith (".whl" ) for pkg in pyscript_config ["packages" ]):
127+ pyscript_config ["packages_cache" ] = "never"
128+
125129 # Extend the JavaScript dependency list
126130 if extra_js and isinstance (extra_js , str ):
127131 pyscript_config ["js_modules" ]["main" ].update (json .loads (extra_js ))
@@ -142,27 +146,19 @@ def reactpy_version_string() -> str: # nocov
142146 local_version = reactpy .__version__
143147
144148 # Get a list of all versions via `pip index versions`
145- result = cached_pip_index_versions ( "reactpy" )
149+ result = get_reactpy_versions ( )
146150
147151 # Check if the command failed
148- if result . returncode != 0 :
152+ if not result :
149153 _logger .warning (
150154 "Failed to verify what versions of ReactPy exist on PyPi. "
151155 "PyScript functionality may not work as expected." ,
152156 )
153157 return f"reactpy=={ local_version } "
154158
155159 # Have `pip` tell us what versions are available
156- available_version_symbol = "Available versions: "
157- latest_version_symbol = "LATEST: "
158- known_versions : list [str ] = []
159- latest_version : str = ""
160- for line in result .stdout .splitlines ():
161- if line .startswith (available_version_symbol ):
162- known_versions .extend (line [len (available_version_symbol ) :].split (", " ))
163- elif latest_version_symbol in line :
164- symbol_postion = line .index (latest_version_symbol )
165- latest_version = line [symbol_postion + len (latest_version_symbol ) :].strip ()
160+ known_versions : list [str ] = result .get ("versions" , [])
161+ latest_version : str = result .get ("latest" , "" )
166162
167163 # Return early if the version is available on PyPi and we're not in a CI environment
168164 if local_version in known_versions and not GITHUB_ACTIONS :
@@ -171,8 +167,8 @@ def reactpy_version_string() -> str: # nocov
171167 # We are now determining an alternative method of installing ReactPy for PyScript
172168 if not GITHUB_ACTIONS :
173169 _logger .warning (
174- "Your current version of ReactPy isn't available on PyPi. Since a packaged version "
175- "of ReactPy is required for PyScript, we are attempting to find an alternative method..."
170+ "Your ReactPy version isn't available on PyPi. "
171+ "Attempting to find an alternative installation method for PyScript ..." ,
176172 )
177173
178174 # Build a local wheel for ReactPy, if needed
@@ -187,42 +183,51 @@ def reactpy_version_string() -> str: # nocov
187183 check = False ,
188184 cwd = Path (reactpy .__file__ ).parent .parent .parent ,
189185 )
190- wheel_glob = glob (str (dist_dir / f"reactpy-{ local_version } -*.whl" ))
186+ wheel_glob = glob (str (dist_dir / f"reactpy-{ local_version } -*.whl" ))
191187
192- # Building a local wheel failed, try our best to give the user any possible version.
193- if not wheel_glob :
194- if latest_version :
188+ # Move the local wheel to the web modules directory, if it exists
189+ if wheel_glob :
190+ wheel_file = Path (wheel_glob [0 ])
191+ new_path = REACTPY_WEB_MODULES_DIR .current / wheel_file .name
192+ if not new_path .exists ():
195193 _logger .warning (
196- "Failed to build a local wheel for ReactPy, likely due to missing build dependencies. "
197- "PyScript will default to using the latest ReactPy version on PyPi."
194+ "PyScript will utilize local wheel '%s'." ,
195+ wheel_file . name ,
198196 )
199- return f"reactpy=={ latest_version } "
200- _logger .error (
201- "Failed to build a local wheel for ReactPy, and could not determine the latest version on PyPi. "
202- "PyScript functionality may not work as expected." ,
203- )
204- return f"reactpy=={ local_version } "
197+ shutil .copy (wheel_file , new_path )
198+ return f"{ REACTPY_PATH_PREFIX .current } modules/{ wheel_file .name } "
205199
206- # Move the local wheel file to the web modules directory, if needed
207- wheel_file = Path (wheel_glob [0 ])
208- new_path = REACTPY_WEB_MODULES_DIR .current / wheel_file .name
209- if not new_path .exists ():
200+ # Building a local wheel failed, try our best to give the user any version.
201+ if latest_version :
210202 _logger .warning (
211- "PyScript will utilize local wheel '%s'." ,
212- wheel_file . name ,
203+ "Failed to build a local wheel for ReactPy, likely due to missing build dependencies. "
204+ "PyScript will default to using the latest ReactPy version on PyPi."
213205 )
214- shutil .copy (wheel_file , new_path )
215- return f"{ REACTPY_PATH_PREFIX .current } modules/{ wheel_file .name } "
206+ return f"reactpy=={ latest_version } "
207+ _logger .error (
208+ "Failed to build a local wheel for ReactPy, and could not determine the latest version on PyPi. "
209+ "PyScript functionality may not work as expected." ,
210+ )
211+ return f"reactpy=={ local_version } "
216212
217213
218214@functools .cache
219- def cached_pip_index_versions (package_name : str ) -> subprocess .CompletedProcess [str ]:
220- return subprocess .run (
221- ["pip" , "index" , "versions" , package_name ],
222- capture_output = True ,
223- text = True ,
224- check = False ,
225- )
215+ def get_reactpy_versions () -> dict [Any , Any ]:
216+ """Fetches the available versions of a package from PyPI."""
217+ try :
218+ try :
219+ response = request .urlopen ("https://pypi.org/pypi/reactpy/json" , timeout = 5 )
220+ except Exception :
221+ response = request .urlopen ("http://pypi.org/pypi/reactpy/json" , timeout = 5 )
222+ if response .status == 200 :
223+ data = json .load (response )
224+ versions = list (data .get ("releases" , {}).keys ())
225+ latest = data .get ("info" , {}).get ("version" , "" )
226+ if versions and latest :
227+ return {"versions" : versions , "latest" : latest }
228+ except Exception :
229+ _logger .exception ("Error fetching ReactPy package versions from PyPI!" )
230+ return {}
226231
227232
228233@functools .cache
0 commit comments