def directory_contents(dir_path: Path) -> list[Path]: dir_path = Path(dir_path) if not dir_path.is_dir(): raise exc.QgrRuntimeError( f'`dir_path` must be a directory. Got {dir_path}') return sorted(dir_path.glob('**/*'), )
def make_map_layer(layer_node: LayerNode) -> qgc.QgsMapLayer: layer_path = _layer_path(layer_node=layer_node, ) layer_type = vector_or_raster(layer_node) if layer_type == 'Vector': provider = 'ogr' qgs_layer_creator = qgc.QgsVectorLayer elif layer_type == 'Raster': provider = 'gdal' qgs_layer_creator = qgc.QgsRasterLayer # For online layers, the provider is specified in the config. layer_cfg = layer_node.layer_cfg if type(layer_cfg.input.asset) is OnlineAsset: provider = layer_cfg.input.asset.provider creator = functools.partial( qgs_layer_creator, str(layer_path), layer_cfg.title, provider, ) map_layer = _create_layer_with_side_effects( creator, layer_node=layer_node, ) if not map_layer.isValid(): raise exc.QgrRuntimeError( f'Invalid QgsMapLayer created for layer {layer_cfg.id}', ) add_layer_metadata(map_layer, layer_cfg) if style_filepath := layer_cfg.style_filepath: _load_qml_style(map_layer, style_filepath)
def get_layer_fp(layer_dir: Path) -> Path: """Look for one and only one standard file type 'gpkg' or 'tif'.""" # TODO: Extract standard file types into some structure rasters = list(layer_dir.glob('*.tif')) vectors = list(layer_dir.glob('*.gpkg')) files = rasters + vectors if len(files) != 1: raise exc.QgrRuntimeError( 'Expected exactly 1 .tif or .gpkg in layer output directory' f' {layer_dir}. Found: {files}.', ) return files[0]
def fetch_and_write_file( # noqa:C901 url: str, *, output_dir: Path, session=None, verify=True, ): """Attempt to download and write file from url. Assumes filename from URL or content-disposition header. """ if url.startswith('ftp://'): if not verify: raise exc.QgrRuntimeError( 'Ignoring TLS certificate verification is not supported for FTP' ' sources.', ) _ftp_fetch_and_write(url, output_dir) else: # TODO: Share the session across requests somehow? if not session: session = create_earthdata_authenticated_session(hosts=[url], verify=verify) with session.get( url, timeout=REQUEST_TIMEOUT, stream=True, headers={'User-Agent': 'QGreenland'}, ) as resp: # Try to extract the filename from the `content-disposition` header if ((disposition := resp.headers.get('content-disposition')) and 'filename' in disposition): # Sometimes the filename is quoted, sometimes it's not. parsed = cgi.parse_header(disposition) # Handle case where disposition itself (usually "attachment") # isn't present (geothermal heat flux :bell:). matcher = re.compile('filename="?(.*)"?') if ('filename' in parsed[0] and (match := matcher.match(parsed[0]))): fn = match.groups()[0].strip('\'"') else:
# Try to extract the filename from the `content-disposition` header if ((disposition := resp.headers.get('content-disposition')) and 'filename' in disposition): # Sometimes the filename is quoted, sometimes it's not. parsed = cgi.parse_header(disposition) # Handle case where disposition itself (usually "attachment") # isn't present (geothermal heat flux :bell:). matcher = re.compile('filename="?(.*)"?') if ('filename' in parsed[0] and (match := matcher.match(parsed[0]))): fn = match.groups()[0].strip('\'"') else: fn = parsed[1]['filename'] else: if not (fn := _filename_from_url(url)): raise exc.QgrRuntimeError( f'Failed to retrieve output filename from {url}', ) if resp.status_code != 200: raise exc.QgrRuntimeError( f"Received '{resp.status_code}' from {resp.request.url}." f' Content: {resp.text}', ) fp = output_dir / fn with open(fp, 'wb') as f: for chunk in resp.iter_content(chunk_size=CHUNK_SIZE): f.write(chunk) return fp