Skip to content

Reference¤

wraeblast.filtering.parsers.extended special ¤

Extended filter parsing.

loads(s, ctx, globals=None, options=None, pre_rendered=False) ¤

Load a Jinja2 + YAML formatted extended filter from a string.

Source code in extended/__init__.py
def loads(
    s: typing.Union[str, bytes],
    ctx: "insights.ItemFilterContext",
    globals: typing.Optional[dict[str, typing.Any]] = None,
    options: typing.Optional[config.ItemFilterPrerenderOptions] = None,
    pre_rendered: bool = False,
) -> elements.ItemFilter:
    """Load a Jinja2 + YAML formatted extended filter from a string."""
    if not pre_rendered:
        rendered_template = render(
            s=s,
            ctx=ctx,
            globals=globals,
            options=options,
        )
    else:
        rendered_template = s
    yaml = ruamel.yaml.YAML(typ="safe")
    document = yaml.load(rendered_template)
    item_filter = elements.ItemFilter(**document)
    return item_filter

render(s, ctx, globals=None, options=None) ¤

Render a Jinja2 + YAML filter template to YAML.

Source code in extended/__init__.py
def render(
    s: typing.Union[str, bytes],
    ctx: "insights.ItemFilterContext",
    globals: typing.Optional[dict[str, typing.Any]] = None,
    options: typing.Optional[config.ItemFilterPrerenderOptions] = None,
) -> str:
    """Render a Jinja2 + YAML filter template to YAML."""
    globals = update_template_globals(
        ctx=ctx,
        globals=globals,
        options=options,
    )
    jinja_env = jinja2.sandbox.SandboxedEnvironment()
    template = jinja_env.from_string(str(s), globals=globals)
    return template.render()

config ¤

ItemValue ¤

An enumeration representing tiers of loot based on value.

env ¤

Helpers available in the Jinja template environment.

change_brightness(color, brightness) ¤

Change the brightness (luminance) of the given color.

Source code in extended/env.py
def change_brightness(color: str, brightness: float) -> colors.Color:
    """Change the brightness (luminance) of the given color."""
    c = colors.Color(color)
    c.set_luminance(brightness)
    return c

colormap_pick(cmap_or_name, value, vmax, vmin=1, log_scale=True) ¤

Get the individual color for a value from the given colormap.

Source code in extended/env.py
def colormap_pick(
    cmap_or_name: typing.Union[str, matplotlib.colors.Colormap],
    value: float,
    vmax: float,
    vmin: float = 1,
    log_scale: bool = True,
) -> colors.Color:
    """Get the individual color for a value from the given colormap."""
    if isinstance(cmap_or_name, str):
        cmap = colors.get_colormap_by_name(cmap_or_name)
    else:
        cmap = cmap_or_name
    if log_scale:
        value = math.log(value) if value > 0 else vmin
        vmin = math.log(vmin)
        vmax = math.log(vmax)
    return colors.get_color_for_value(
        colormap=cmap,
        value=value,
        vmax=vmax,
        vmin=vmin,
    )

round_down(i, k) ¤

Round down an integer.

Source code in extended/env.py
def round_down(i: float, k: int) -> int:
    """Round down an integer."""
    return int(k * (i // k))

text_color(color, lum_threshold=0.5, dark_color=None, light_color=None, monochrome=False, lum_shift=0.6) ¤

Get a contrasting color for the given color.

Source code in extended/env.py
def text_color(
    color: typing.Union[colors.Color, str],
    lum_threshold: float = 0.5,
    dark_color: typing.Optional[colors.Color] = None,
    light_color: typing.Optional[colors.Color] = None,
    monochrome: bool = False,
    lum_shift: float = 0.6,
) -> colors.Color:
    """Get a contrasting color for the given color."""
    c = colors.Color(color)
    if c.luminance >= lum_threshold:
        if dark_color:
            return dark_color
        if monochrome:
            return colors.Color("black")
        lum = lum if (lum := c.get_luminance() - abs(lum_shift)) >= 0 else 0
    else:
        if light_color:
            return light_color
        if monochrome:
            return colors.Color("white")
        lum = lum if (lum := c.get_luminance() + abs(lum_shift)) <= 1 else 1.0
    c.set_luminance(lum)
    return c

tts(s, filename=None, output_path='output', prefix='', overwrite=False, volume=1.0, rate=200, volume_boost=0, voice_id='Aria') ¤

Generate and save a text-to-speech sound clip to a file.

If AWS credentials are present in the environment, Polly will be used instead of pyttsx3 to synthesize the given text.

Parameters:

Name Type Description Default
s str

The text to synthesize.

required
filename Optional[str]

Destination filename. By default, a slugified filename based on the input text is generated.

None
output_path str

Output directory.

'output'
prefix str

Directory to prefix filename with. Appended after output directory, and is also used for S3 key prefix.

''
overwrite bool

If True, regenerates existing files. Defaults to False.

False
volume float

Only used by pyttsx3. Controls media volume, in an accepted range of 0 to 1.0. Defaults to 1.0.

1.0
rate int

Only used by pyttsx3. Controls rate of speech. Defaults to 200.

200
volume_boost int

If non-zero, post-processes TTS files and increases their volume by the given value in dB. Note that when using AWS Polly, the post processing is only performed locally and not reflected in the S3 cache. Defaults to 0.

0
voice_id str

AWS Polly voice ID. Defaults to Aria.

'Aria'

Returns:

Type Description
str

str: The path to the generated TTS clip, relative to the filter.

Source code in extended/env.py
def tts(
    s: str,
    filename: typing.Optional[str] = None,
    output_path: str = "output",
    prefix: str = "",
    overwrite: bool = False,
    volume: float = 1.0,
    rate: int = 200,
    volume_boost: int = 0,
    voice_id: str = "Aria",
) -> str:
    """Generate and save a text-to-speech sound clip to a file.

    If AWS credentials are present in the environment, Polly will be
    used instead of pyttsx3 to synthesize the given text.

    Args:
        s (str): The text to synthesize.
        filename (str, optional): Destination filename. By default,
            a slugified filename based on the input text is generated.
        output_path (str, optional): Output directory.
        prefix (str, optional): Directory to prefix filename with.
            Appended after output directory, and is also used for
            S3 key prefix.
        overwrite (bool, optional): If True, regenerates existing files.
            Defaults to False.
        volume (float, optional): Only used by pyttsx3. Controls media
            volume, in an accepted range of 0 to 1.0. Defaults to 1.0.
        rate (int, optional): Only used by pyttsx3. Controls rate of
            speech. Defaults to 200.
        volume_boost (int, optional): If non-zero, post-processes TTS
            files and increases their volume by the given value in dB.
            Note that when using AWS Polly, the post processing is only
            performed locally and not reflected in the S3 cache.
            Defaults to 0.
        voice_id (str, optional): AWS Polly voice ID. Defaults to
            *Aria*.

    Returns:
        str: The path to the generated TTS clip, relative to the filter.

    """
    aws_enabled = "AWS_ACCESS_KEY_ID" in os.environ
    if filename is None:
        filename = f"{slugify_filename(s)}.mp3"
        if aws_enabled:
            filename = str(pathlib.Path(voice_id) / filename)
    else:
        filename_path = pathlib.Path(filename)
        filename = str(
            filename_path.with_stem(slugify_filename(filename_path.stem))
        )

    filepath = pathlib.Path(output_path) / pathlib.Path(prefix) / filename
    if overwrite or not filepath.exists():
        filepath.parent.mkdir(parents=True, exist_ok=True)
        if aws_enabled:
            tts_polly(
                s=s,
                key=filename,
                dest=filepath,
                voice_id=voice_id,
            )
        elif "CI" not in os.environ:
            tts_pyttsx3(
                s=s,
                dest=filepath,
                volume=volume,
                rate=rate,
            )
        if "CI" not in os.environ and volume_boost:
            seg = pydub.AudioSegment.from_mp3(str(filepath))
            boosted_seg = seg + volume_boost  # type: ignore
            boosted_seg.export(filepath, format="mp3")

    return str(pathlib.Path(prefix) / filename)

wraeblast.filtering.parsers.extended.config ¤

ItemValue ¤

An enumeration representing tiers of loot based on value.

wraeblast.filtering.parsers.extended.env ¤

Helpers available in the Jinja template environment.

change_brightness(color, brightness) ¤

Change the brightness (luminance) of the given color.

Source code in extended/env.py
def change_brightness(color: str, brightness: float) -> colors.Color:
    """Change the brightness (luminance) of the given color."""
    c = colors.Color(color)
    c.set_luminance(brightness)
    return c

colormap_pick(cmap_or_name, value, vmax, vmin=1, log_scale=True) ¤

Get the individual color for a value from the given colormap.

Source code in extended/env.py
def colormap_pick(
    cmap_or_name: typing.Union[str, matplotlib.colors.Colormap],
    value: float,
    vmax: float,
    vmin: float = 1,
    log_scale: bool = True,
) -> colors.Color:
    """Get the individual color for a value from the given colormap."""
    if isinstance(cmap_or_name, str):
        cmap = colors.get_colormap_by_name(cmap_or_name)
    else:
        cmap = cmap_or_name
    if log_scale:
        value = math.log(value) if value > 0 else vmin
        vmin = math.log(vmin)
        vmax = math.log(vmax)
    return colors.get_color_for_value(
        colormap=cmap,
        value=value,
        vmax=vmax,
        vmin=vmin,
    )

round_down(i, k) ¤

Round down an integer.

Source code in extended/env.py
def round_down(i: float, k: int) -> int:
    """Round down an integer."""
    return int(k * (i // k))

text_color(color, lum_threshold=0.5, dark_color=None, light_color=None, monochrome=False, lum_shift=0.6) ¤

Get a contrasting color for the given color.

Source code in extended/env.py
def text_color(
    color: typing.Union[colors.Color, str],
    lum_threshold: float = 0.5,
    dark_color: typing.Optional[colors.Color] = None,
    light_color: typing.Optional[colors.Color] = None,
    monochrome: bool = False,
    lum_shift: float = 0.6,
) -> colors.Color:
    """Get a contrasting color for the given color."""
    c = colors.Color(color)
    if c.luminance >= lum_threshold:
        if dark_color:
            return dark_color
        if monochrome:
            return colors.Color("black")
        lum = lum if (lum := c.get_luminance() - abs(lum_shift)) >= 0 else 0
    else:
        if light_color:
            return light_color
        if monochrome:
            return colors.Color("white")
        lum = lum if (lum := c.get_luminance() + abs(lum_shift)) <= 1 else 1.0
    c.set_luminance(lum)
    return c

tts(s, filename=None, output_path='output', prefix='', overwrite=False, volume=1.0, rate=200, volume_boost=0, voice_id='Aria') ¤

Generate and save a text-to-speech sound clip to a file.

If AWS credentials are present in the environment, Polly will be used instead of pyttsx3 to synthesize the given text.

Parameters:

Name Type Description Default
s str

The text to synthesize.

required
filename Optional[str]

Destination filename. By default, a slugified filename based on the input text is generated.

None
output_path str

Output directory.

'output'
prefix str

Directory to prefix filename with. Appended after output directory, and is also used for S3 key prefix.

''
overwrite bool

If True, regenerates existing files. Defaults to False.

False
volume float

Only used by pyttsx3. Controls media volume, in an accepted range of 0 to 1.0. Defaults to 1.0.

1.0
rate int

Only used by pyttsx3. Controls rate of speech. Defaults to 200.

200
volume_boost int

If non-zero, post-processes TTS files and increases their volume by the given value in dB. Note that when using AWS Polly, the post processing is only performed locally and not reflected in the S3 cache. Defaults to 0.

0
voice_id str

AWS Polly voice ID. Defaults to Aria.

'Aria'

Returns:

Type Description
str

str: The path to the generated TTS clip, relative to the filter.

Source code in extended/env.py
def tts(
    s: str,
    filename: typing.Optional[str] = None,
    output_path: str = "output",
    prefix: str = "",
    overwrite: bool = False,
    volume: float = 1.0,
    rate: int = 200,
    volume_boost: int = 0,
    voice_id: str = "Aria",
) -> str:
    """Generate and save a text-to-speech sound clip to a file.

    If AWS credentials are present in the environment, Polly will be
    used instead of pyttsx3 to synthesize the given text.

    Args:
        s (str): The text to synthesize.
        filename (str, optional): Destination filename. By default,
            a slugified filename based on the input text is generated.
        output_path (str, optional): Output directory.
        prefix (str, optional): Directory to prefix filename with.
            Appended after output directory, and is also used for
            S3 key prefix.
        overwrite (bool, optional): If True, regenerates existing files.
            Defaults to False.
        volume (float, optional): Only used by pyttsx3. Controls media
            volume, in an accepted range of 0 to 1.0. Defaults to 1.0.
        rate (int, optional): Only used by pyttsx3. Controls rate of
            speech. Defaults to 200.
        volume_boost (int, optional): If non-zero, post-processes TTS
            files and increases their volume by the given value in dB.
            Note that when using AWS Polly, the post processing is only
            performed locally and not reflected in the S3 cache.
            Defaults to 0.
        voice_id (str, optional): AWS Polly voice ID. Defaults to
            *Aria*.

    Returns:
        str: The path to the generated TTS clip, relative to the filter.

    """
    aws_enabled = "AWS_ACCESS_KEY_ID" in os.environ
    if filename is None:
        filename = f"{slugify_filename(s)}.mp3"
        if aws_enabled:
            filename = str(pathlib.Path(voice_id) / filename)
    else:
        filename_path = pathlib.Path(filename)
        filename = str(
            filename_path.with_stem(slugify_filename(filename_path.stem))
        )

    filepath = pathlib.Path(output_path) / pathlib.Path(prefix) / filename
    if overwrite or not filepath.exists():
        filepath.parent.mkdir(parents=True, exist_ok=True)
        if aws_enabled:
            tts_polly(
                s=s,
                key=filename,
                dest=filepath,
                voice_id=voice_id,
            )
        elif "CI" not in os.environ:
            tts_pyttsx3(
                s=s,
                dest=filepath,
                volume=volume,
                rate=rate,
            )
        if "CI" not in os.environ and volume_boost:
            seg = pydub.AudioSegment.from_mp3(str(filepath))
            boosted_seg = seg + volume_boost  # type: ignore
            boosted_seg.export(filepath, format="mp3")

    return str(pathlib.Path(prefix) / filename)

wraeblast.filtering.parsers.standard.transformers ¤

wraeblast.filtering.colors ¤

Color ¤

Represents a color.

rgb_as_bytes: tuple property readonly ¤

Return an RGB tuple as bytes (range of 0-255).

rgba_as_bytes: tuple property readonly ¤

Return an RGBA tuple as bytes (range of 0-255).

from_rgb_bytes(rgb) classmethod ¤

Create a color instance from the given RGB bytes.

Source code in filtering/colors.py
@classmethod
def from_rgb_bytes(cls, rgb: ColorType_RGB) -> "Color":
    """Create a color instance from the given RGB bytes."""
    return Color(rgb=ColorType_RGBA(c / 255 for c in rgb))

from_rgba_bytes(rgba) classmethod ¤

Create a color instance from the given RGBA bytes.

Source code in filtering/colors.py
@classmethod
def from_rgba_bytes(cls, rgba: ColorType_RGBA) -> "Color":
    """Create a color instance from the given RGBA bytes."""
    rgba = ColorType_RGBA(c / 255 for c in rgba)
    alpha = rgba[3] if len(rgba) == 4 else 1
    return Color(rgb=rgba[:3], alpha=alpha)

NamedColor ¤

An enumeration.

get_color_for_value(colormap, value, vmax, vmin=1) ¤

Return the color from a colormap for the given value.

Source code in filtering/colors.py
def get_color_for_value(
    colormap: matplotlib.colors.Colormap,
    value: float,
    vmax: float,
    vmin: float = 1,
) -> "Color":
    """Return the color from a colormap for the given value."""
    norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
    rgba = colormap(norm(value))
    return Color(rgb=rgba[:3])

get_colormap_by_name(name) ¤

Return a colormap by name.

Supported colormaps are pulled from the matplotlib, palettable, and colorcet libraries.

Source code in filtering/colors.py
def get_colormap_by_name(name: str) -> matplotlib.colors.Colormap:
    """Return a colormap by name.

    Supported colormaps are pulled from the matplotlib, palettable,
    and colorcet libraries.

    """
    return _colormaps[name]
    # try:
    #     return matplotlib.cm.get_cmap(name)
    # except ValueError:
    #     if name in dir(colorcet.cm):
    #         return getattr(colorcet.cm, name)
    #     else:
    #         for mod in _palettable_modules:
    #             if name in dir(mod):
    #                 return getattr(mod, name).mpl_colormap
    # raise ValueError(name)

linear_colormap_from_color_list(name, colors) ¤

Build a linear segmented colormap from a list of colors.

Source code in filtering/colors.py
def linear_colormap_from_color_list(
    name: str,
    colors: list["Color"],
) -> matplotlib.colors.Colormap:
    """Build a linear segmented colormap from a list of colors."""
    return matplotlib.colors.LinearSegmentedColormap.from_list(
        name=name,
        colors=[c.rgb for c in colors],
    )

wraeblast.filtering.elements ¤

Action pydantic-model ¤

A loot filter action.

ActionType ¤

An enum representing supported loot filter actions.

Condition pydantic-model ¤

A loot filter condition.

ConditionType ¤

An enum representing supported loot filter conditions.

ItemFilter pydantic-model ¤

Represents a loot filter.

apply_default_preset(self) ¤

Apply the default preset to all rules in the filter.

Source code in filtering/elements.py
def apply_default_preset(self) -> None:
    """Apply the default preset to all rules in the filter."""
    if "default" in self.presets:
        self.apply_preset(preset_name="default")

apply_preset(self, preset_name='default') ¤

Apply the given preset to all rules in the filter.

Source code in filtering/elements.py
def apply_preset(self, preset_name: str = "default") -> None:
    """Apply the given preset to all rules in the filter."""
    preset = self.presets[preset_name]
    log = logger.bind(preset=preset_name)
    log.debug("preset.apply")
    for rule in self.rules:
        # Replace tags
        for source_tag, target_tag in preset.tags.replace.items():
            source_tags = set(
                source_tag
                if isinstance(source_tag, list)
                else [source_tag]
            )
            if source_tags.issubset(rule.tags):
                target_tags = set(
                    target_tag
                    if isinstance(target_tag, list)
                    else [target_tag]
                )
                rule.tags -= {t for t in source_tags if t is not None}
                rule.tags |= {t for t in target_tags if t is not None}

        # Disable visibility for hidden tags
        for hidden_tag in preset.tags.hidden:
            hidden_tags = set(
                hidden_tag
                if isinstance(hidden_tag, list)
                else [hidden_tag]
            )
            if hidden_tags.issubset(rule.tags):
                rule.visibility = Visibility.HIDE

        # Enable visibility for visible tags
        for visible_tag in preset.tags.visible:
            visible_tags = set(
                visible_tag
                if isinstance(visible_tag, list)
                else [visible_tag]
            )
            if visible_tags.issubset(rule.tags):
                rule.visibility = Visibility.SHOW
    self.resolve_styles()

get_styles_for_tags(self, tags) ¤

Get a list of styles that match the given tags.

Source code in filtering/elements.py
def get_styles_for_tags(
    self,
    tags: typing.Iterable[typing.Union[list[str], str]],
) -> list[Style]:
    """Get a list of styles that match the given tags."""
    tags = set(tags)
    styles = []
    for _, style in self.styles.items():
        for style_tags in style.tags:
            if not isinstance(style_tags, list):
                style_tags = [style_tags]
            if set(style_tags).issubset(tags):
                styles.append(style)
    return styles

remove_hidden_rules(self) ¤

Remove all hidden rules.

Source code in filtering/elements.py
def remove_hidden_rules(self) -> None:
    """Remove all hidden rules."""
    self.rules = [
        rule for rule in self.rules if rule.visibility == Visibility.SHOW
    ]

resolve_styles(self, ignore_errors=False, apply_default=True) ¤

Apply all styles to applicable rules across the filter.

Source code in filtering/elements.py
def resolve_styles(
    self,
    ignore_errors: bool = False,
    apply_default: bool = True,
) -> None:
    """Apply all styles to applicable rules across the filter."""
    logger.debug("styles.apply")
    default_style = None
    if apply_default and "default" in self.styles:
        default_style = self.styles["default"]
    for rule in self.rules:
        # Apply a style named "default", if it exists
        if default_style is not None:
            rule.apply_style(default_style, replace=True)
        # First apply styles with matching tag names...
        styles = self.get_styles_for_tags(rule.tags)
        # ...then apply any explicit style names from the given rule
        if rule.style:
            if isinstance(rule.style, list):
                style_names = rule.style
            else:
                style_names = [rule.style]
            try:
                for style_name in style_names:
                    styles.append(self.styles[style_name])
            except KeyError:
                if not ignore_errors:
                    raise
        for style in styles:
            rule.apply_style(style, replace=True)

NamedColor ¤

An enum representing supported loot filter named colors.

Operator ¤

An enum representing comparison operators.

Preset pydantic-model ¤

Template-level configuration for a loot filter.

Presets allow a single item filter template to be used to generate many complementary filters. Currently, presets only control visibility of rules based on tag names.

PresetTags pydantic-model ¤

Stores lists of tags that control rule visibility.

  • visible: a single tag or a list of tags that are forced to be shown in the rendered loot filter.
  • hidden: a single tag or a list of tags that are forced to be hidden in the rendered loot filter.

Rule pydantic-model ¤

Represents a loot filter rule.

apply_style(self, style, replace=True) ¤

Apply the given style to the rule.

If replace is False, returns a copy of the Rule. Otherwise, the current instance is mutated.

Source code in filtering/elements.py
def apply_style(self, style: Style, replace: bool = True) -> "Rule":
    """Apply the given style to the rule.

    If **replace** is ``False``, returns a copy of the ``Rule``. Otherwise,
    the current instance is mutated.

    """
    return _merge_rule_and_style_actions(self, style, replace=replace)

Shape ¤

An enum representing supported loot filter shapes.

Style pydantic-model ¤

Represents a loot filter style.

Styles contain actions and (optionally) tags.

Visibility ¤

An enum representing loot filter visibility states.

wraeblast.constants ¤

AltQuality ¤

An enumeration.

ClusterJewelMinorPassive ¤

An enumeration.

FilterFormat ¤

An enumeration.

Influence ¤

An enumeration.

SocketColor ¤

An enumeration.

SocketGroup pydantic-model ¤

__str__(self) special ¤

Return str(self).

Source code in wraeblast/constants.py
def __str__(self) -> str:
    s = ""
    if self.links:
        s += str(self.links)
    for color, count in self.sockets:
        s += color.value * count
    return s

wraeblast.insights ¤

CurrencyType ¤

An enumeration.

ItemFilterContext pydantic-model ¤

Entrypoint for accessing economy data from poe.ninja.

ItemType ¤

An enumeration.

PoEOfficial ¤

get_leagues(self) ¤

List leagues.

Source code in wraeblast/insights.py
@uplink.response_handler(raise_for_status)
@get_json("league")  # type: ignore
def get_leagues(self):
    """List leagues."""

get_economy_overview(league, client, type_) async ¤

Request an economy overview from poe.ninja.

Source code in wraeblast/insights.py
async def get_economy_overview(
    league: str,
    client: "PoENinja",
    type_: InsightsType,
) -> "EconomyOverview":
    """Request an economy overview from poe.ninja."""
    if type_ in CurrencyType:
        meth = client.get_currency_overview
    elif type_ in ItemType:
        meth = client.get_item_overview
    else:
        raise RuntimeError()
    logger.info(
        "overview.get",
        client=".".join([client.__module__, client.__class__.__name__]),
        type=type_.value,
    )
    return await meth(league=league, type=type_.value)  # type: ignore

get_overviews(league, types) ¤

Request all economy overviews from poe.ninja.

Source code in wraeblast/insights.py
async def get_overviews(
    league: str,
    types: list[InsightsType],
) -> typing.AsyncGenerator[InsightsResultType, None]:
    """Request all economy overviews from poe.ninja."""
    logger.info("all_insights.get", league=league)
    session = aiohttp.ClientSession()
    client = uplink.AiohttpClient(session=session)
    ninja = PoENinja(
        base_url=PoENinja.default_base_url,
        client=client,
    )
    for t in types:
        overview = await get_economy_overview(
            league=league,
            client=ninja,
            type_=t,
        )
        yield (t, overview)
    await session.close()

initialize_filter_context(initialize_cache=True, league=None, cache=None, cache_expire=18000, no_sync=False) async ¤

Create an ItemFilterContext from cached economy data.

Source code in wraeblast/insights.py
async def initialize_filter_context(
    initialize_cache: bool = True,
    league: typing.Optional[str] = None,
    cache: typing.Optional[diskcache.Cache] = None,
    cache_expire: int = 60 * 60 * 5,
    no_sync: bool = False,
) -> "ItemFilterContext":
    """Create an ``ItemFilterContext`` from cached economy data."""
    if initialize_cache:
        if league is None:
            raise RuntimeError("league must be provided if initializing cache")
        cache = await initialize_insights_cache(
            league=league,
            cache=cache,
            cache_expire=cache_expire,
            no_sync=no_sync,
        )
    elif cache is None:
        cache = _cache
    else:
        raise RuntimeError("cache not provided")
    ctx = {}
    for t in get_all_insights_types():
        overview = cache.get(f"insights:{t.value}")
        ctx[ItemFilterContext.ctx_name_for_insights_type(t)] = overview
    return ItemFilterContext(**ctx)

initialize_insights_cache(league, cache=None, cache_expire=18000, no_sync=False) async ¤

Fetch and cache economy insights as needed.

Source code in wraeblast/insights.py
async def initialize_insights_cache(
    league: str,
    cache: typing.Optional[diskcache.Cache] = None,
    cache_expire: int = 60 * 60 * 5,
    no_sync: bool = False,
) -> diskcache.Cache:
    """Fetch and cache economy insights as needed."""
    if cache is None:
        cache = _cache
    # log = logger.bind(league=league, cache_dir=cache.directory)
    log = logger.bind(league=league)
    log.info("cache.initialize", league=league, dir=cache.directory)
    missing_overviews = []
    for t in get_all_insights_types():
        overview = cache.get(f"insights:{t.value}")
        if overview is None:
            log.debug("cache.miss", type=t.value)
            missing_overviews.append(t)
        else:
            log.debug("cache.hit", type=t.value)
    if missing_overviews and no_sync:
        raise errors.WraeblastError("insights cache is incomplete")
    async for t, overview in get_overviews(
        league=league,
        types=missing_overviews,
    ):
        log.info(
            "overview.response",
            lines=len(overview.lines),
            type=t.value,
        )
        cache.add(
            key=f"insights:{t.value}",
            value=overview.dict(by_alias=True),
            expire=cache_expire,
        )
    return cache

raise_for_status(response) ¤

Checks whether or not the response was successful.

Source code in wraeblast/insights.py
def raise_for_status(response):
    """Checks whether or not the response was successful."""
    if 200 <= response.status_code < 300:
        return response

    raise errors.UnsuccessfulInsightsRequest(
        f"error {response.status_code}: {response.url}"
    )