from typing import Mapping, Optional
import memdf.name
import memdf.util.config
import memdf.util.pretty
import numpy as np from memdf import DF, Config, ConfigDescription
def split_size(config: Config, key: str) -> None:
src = key.split('.')
dst = src[:-1] + ['limit']
splits = [s.split(':') for s in config.getl(src, [])]
config.putl(src, [x[0] for x in splits])
config.putl(dst, {
x[0]: memdf.util.config.parse_size(x[1])
for x in splits if len(x) > 1
})
def get_limit(config: Config, column: str, name: str) -> int:
return config.getl([column, 'limit', name], config.get('report.limit', 0))
def postprocess_selections(config: Config, key: str, info: Mapping) -> None:
split_size(config, key)
choice, select = key.split('.')
assert select == 'select'
selections = config.get(key)
if not config.getl([choice, 'ignore-all'], False):
if defaults := config.getl([choice, 'default']):
for i in config.getl([choice, 'ignore']):
if i in defaults:
defaults.remove(i)
selections += defaults
config.put(key, frozenset(selections))
def select_and_ignore_config_desc(key: str) -> ConfigDescription:
return {
Config.group_map(key): {
'group': 'select'
},
f'{key}.select': {
'help':
f'{key.capitalize()}(s) to process; otherwise all not ignored',
'metavar': 'NAME',
'default': [],
'argparse': {
'alias': [f'--{key}'],
},
'postprocess': postprocess_selections
},
f'{key}.select-all': {
'help': f'Select all {key}s',
'default': False,
},
key + '.ignore': {
'help': f'{key.capitalize()}(s) to ignore',
'metavar': 'NAME',
'default': [],
},
f'{key}.ignore-all': {
'help': f'Ignore all {key}s unless explicitly selected',
'default': False,
},
}
SECTION_CONFIG = select_and_ignore_config_desc('section')
SYMBOL_CONFIG = select_and_ignore_config_desc('symbol')
REGION_CONFIG = select_and_ignore_config_desc('region')
CONFIG: ConfigDescription = {
Config.group_def('select'): {
'title': 'selection options',
},
**SECTION_CONFIG,
**SYMBOL_CONFIG,
**REGION_CONFIG,
}
COLLECTED_CHOICES = ['symbol', 'section']
SYNTHETIC_CHOICES = ['region']
SELECTION_CHOICES = COLLECTED_CHOICES + SYNTHETIC_CHOICES
def is_selected(config: Config, column, name) -> bool:
if config.getl([column, 'select-all']):
return True
if name in config.getl([column, 'select'], []):
return True
return False
def synthesize_region(config: Config, df: DF, column: str) -> DF:
cmap = config.transpose_dictlist(config.get('region.sections', {}))
memdf.util.pretty.debug(cmap)
df[column] = df['section'].map(lambda x: cmap.get(x, memdf.name.UNKNOWN))
return df
def groupby_region(df: DF):
return df[(df['size'] > 0) | (df['region'] != memdf.name.UNKNOWN)]
SYNTHESIZE = {
'region': (synthesize_region, groupby_region),
}
def synthesize_column(config: Config, df: DF, column: str) -> DF:
if column not in df.columns:
SYNTHESIZE[column][0](config, df, column)
return df
def select_configured_column(config: Config, df: DF, column: str) -> DF:
if column in df and not config.getl([column, 'select-all']):
selections = config.getl([column, 'select'], [])
if selections:
df = df.loc[df[column].isin(selections)]
return df
def select_configured(config: Config, df: DF, columns=SELECTION_CHOICES) -> DF:
for column in columns:
df = select_configured_column(config, df, column)
return df
def groupby(config: Config, df: DF, by: Optional[str] = None):
if not by:
by = config['report.by']
df = df[[by, 'size']].groupby(by).aggregate(np.sum).reset_index()
if by in SYNTHESIZE:
df = SYNTHESIZE[by][1](df)
return df