Skip to content
Snippets Groups Projects
Commit 8f081cbf authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

ENH: function to retrieve metadata about one package from one channel. To be

used for a small list of externally hosted (conda-forge) packages.
parent 580848df
No related branches found
No related tags found
1 merge request!45New update_fsl_package script
......@@ -54,6 +54,28 @@ log = logging.getLogger(__name__)
PUBLIC_FSL_CHANNEL = 'https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/'
INTERNAL_FSL_CHANNEL = 'https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/internal/'
EXTERNALLY_HOSTED_PACKAGES = {
'fslpy' : 'conda-forge',
'fsleyes-props' : 'conda-forge',
'fsleyes-widgets' : 'conda-forge',
'fsleyes' : 'conda-forge',
'fmrib-unpack' : 'conda-forge',
'file-tree' : 'conda-forge',
'file-tree-fsl' : 'conda-forge',
'spec2nii' : 'conda-forge',
}
"""List of packages which are considered to be part of FSL, but which are hosted
on an external channel (most likely conda-forge). These packages should still be
considered for updates.
Version information for these packages is only retrieved if they are
specifically requested by the user, or if the --external option is used.
This is because downloading and parsing the conda-forge channeldata information
takes a very long time.
The values in this dictionary can either be a channel name on
https://anaconda.org, or a fully qualified channel URL.
"""
def conda(cmd : str, capture_output=True, **kwargs) -> str:
......@@ -84,6 +106,7 @@ def conda(cmd : str, capture_output=True, **kwargs) -> str:
return result.stdout
@ft.lru_cache
def identify_platform() -> str:
"""Figures out what platform we are running on. Returns a platform
identifier string - one of:
......@@ -243,17 +266,66 @@ def query_installed_packages() -> Dict[str, Package]:
pkgs = {}
# We are only interested in packages
# hosted on the FSL conda channels
# hosted on the FSL conda channels,
# or those listed in the externally
# hosted package list.
for pkg in info:
if pkg['base_url'].rstrip() in channels:
if pkg['base_url'].rstrip() in channels or \
pkg['name'] in EXTERNALLY_HOSTED_PACKAGES:
pkgs[pkg['name']] = Package(pkg['name'],
pkg['version'],
pkg['channel'],
pkg['platform'])
return pkgs
@ft.lru_cache
def download_external_package_metadata(pkgname : str,
channel_url : str,
development : bool) -> Optional[Package]:
"""Downloads metadata about one externally hosted package. The returned
Package object does not contain platform or dependency information.
"""
# if channel_url is a full url, we
# download the full channel metdata
# and look up the package
if any(channel_url.startswith(p) for p in ('https:', 'http:', 'file:')):
chandata = download_channel_metadata(channel_url)
pkgs = identify_packages([chandata], [pkgname], development)
return pkgs.get(pkgname, [None])[-1]
# Othrerwise channel_url is the name
# of an anaconda.org channel - we
# just retrieve information about
# the package
channel = channel_url
api_url = f'https://api.anaconda.org/package/{channel}/'
channel_url = f'https://anaconda.org/{channel}/'
try:
meta = http_request(f'{api_url}{pkgname}')
except Exception:
log.debug(f'Package lookup failed [{pkgname} : {channel_url}]')
return None
# Find the latest available
# version for this platform
thisplat = ('noarch', identify_platform())
for finfo in meta['files'][::-1]:
version = finfo['version']
platform = finfo['attrs']['subdir']
isdev = development or ('dev' not in version)
if isdev and (platform in thisplat):
return Package(pkgname, version, channel_url, platform)
# No suitable version available
else:
return None
@ft.lru_cache
def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
"""Downloads information about packages hosted at the given conda channel.
......@@ -276,7 +348,7 @@ def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
Keyword arguments are passed through to the http_request function.
"""
thisplat = identify_platform()
thisplat = ('noarch', identify_platform())
# Load channel and platform metadata - the
# first gives us a list of all packages that
......@@ -291,7 +363,7 @@ def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
# only consider packages
# relevant to this platform
for platform in chandata['subdirs']:
if platform in ('noarch', thisplat):
if platform in thisplat:
purl = f'{channel_url}/{platform}/repodata.json'
platdata[platform] = http_request(purl)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment