Skip to content
Snippets Groups Projects

New update_fsl_package script

Merged Paul McCarthy requested to merge mnt/update-fsl-package into master
1 file
+ 77
5
Compare changes
  • Side-by-side
  • Inline
@@ -54,6 +54,28 @@ log = logging.getLogger(__name__)
@@ -54,6 +54,28 @@ log = logging.getLogger(__name__)
PUBLIC_FSL_CHANNEL = 'https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/'
PUBLIC_FSL_CHANNEL = 'https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/'
INTERNAL_FSL_CHANNEL = 'https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/internal/'
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:
def conda(cmd : str, capture_output=True, **kwargs) -> str:
@@ -84,6 +106,7 @@ 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
return result.stdout
 
@ft.lru_cache
def identify_platform() -> str:
def identify_platform() -> str:
"""Figures out what platform we are running on. Returns a platform
"""Figures out what platform we are running on. Returns a platform
identifier string - one of:
identifier string - one of:
@@ -243,17 +266,66 @@ def query_installed_packages() -> Dict[str, Package]:
@@ -243,17 +266,66 @@ def query_installed_packages() -> Dict[str, Package]:
pkgs = {}
pkgs = {}
# We are only interested in packages
# 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:
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'],
pkgs[pkg['name']] = Package(pkg['name'],
pkg['version'],
pkg['version'],
pkg['channel'],
pkg['channel'],
pkg['platform'])
pkg['platform'])
return pkgs
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
@ft.lru_cache
def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
"""Downloads information about packages hosted at the given conda channel.
"""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]:
@@ -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.
Keyword arguments are passed through to the http_request function.
"""
"""
thisplat = identify_platform()
thisplat = ('noarch', identify_platform())
# Load channel and platform metadata - the
# Load channel and platform metadata - the
# first gives us a list of all packages that
# first gives us a list of all packages that
@@ -291,7 +363,7 @@ def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
@@ -291,7 +363,7 @@ def download_channel_metadata(channel_url : str, **kwargs) -> Tuple[Dict, Dict]:
# only consider packages
# only consider packages
# relevant to this platform
# relevant to this platform
for platform in chandata['subdirs']:
for platform in chandata['subdirs']:
if platform in ('noarch', thisplat):
if platform in thisplat:
purl = f'{channel_url}/{platform}/repodata.json'
purl = f'{channel_url}/{platform}/repodata.json'
platdata[platform] = http_request(purl)
platdata[platform] = http_request(purl)
Loading