fava.util

Some small utility functions.

fava.util.filter_api_changed(record)

Filter out LogRecords for requests that poll for changes.

Return type:

bool

fava.util.get_translations(locale)

Check whether Fava has translations for the locale.

Parameters:

locale (Locale) – The locale to search for

Returns:

str | None – The path to the found translations or None if none matched.

fava.util.listify(func)

Make generator function return a list (decorator).

Return type:

Callable[[ParamSpec(P, bound= None)], list[TypeVar(Item)]]

fava.util.next_key(basekey, keys)

Return the next unused key for basekey in the supplied dictionary.

The first try is basekey, followed by basekey-2, basekey-3, etc until a free one is found.

Return type:

str

fava.util.send_file_inline(filename)

Send a file inline, including the original filename.

Ref: http://test.greenbytes.de/tech/tc2231/.

Return type:

Response

fava.util.setup_debug_logging()

Set up debug level logging for Fava.

Return type:

None

fava.util.setup_logging()

Set up logging for Fava.

Return type:

None

fava.util.simple_wsgi(_, start_response)

Return an empty response (a simple WSGI app).

Return type:

list[bytes]

fava.util.slugify(string)

Slugify a string.

Parameters:

string (str) – A string.

Returns:

str – A ‘slug’ of the string suitable for URLs. Retains non-ascii characters.

fava.util.timefunc(func)

Time function for debugging (decorator).

Return type:

Callable[[ParamSpec(P, bound= None)], TypeVar(T)]

fava.util.date

Date-related functionality.

Note

Date ranges are always tuples (start, end) from the (inclusive) start date to the (exclusive) end date.

class fava.util.date.DateRange(begin, end)

A range of dates, usually matching an interval.

begin: date

The inclusive start date of this range of dates.

end: date

The exclusive end date of this range of dates.

property end_inclusive: date

The last day of this interval.

fava.util.date.END_OF_YEAR = FiscalYearEnd(month=12, day=31)

Default fiscal year (12-31).

class fava.util.date.FiscalQuarter(fye)

A fiscal quarter interval, for a specific fiscal year end.

format_date(date)

Format a date for this interval for the Fava time filter.

Return type:

str

fye: FiscalYearEnd
get_next(date)

Get the start date of the next interval following the date.

Return type:

date

get_prev(date)

Get the start date of the interval in which the date falls.

Return type:

date

property label: str

The label for the interval.

class fava.util.date.FiscalYear(fye)

A fiscal year interval, for a specific fiscal year end.

format_date(date)

Format a date for this interval for the Fava time filter.

Return type:

str

fye: FiscalYearEnd
get_next(date)

Get the start date of the next interval following the date.

Return type:

date

get_prev(date)

Get the start date of the interval in which the date falls.

Return type:

date

property label: str

The label for the interval.

class fava.util.date.FiscalYearEnd(month, day)

Month and day that specify the end of the fiscal year.

begin_date_for_year(year)

Calculate the begin date of a fiscal year.

Return type:

date

day: int

Day of the fiscal year end.

fiscal_year(date)

The fiscal year that a date is in.

Return type:

int

month: int

Month of the fiscal year end - can be between 1 and 24.

month_of_year: int

Actual month of the year.

start_day
start_month_of_year
year_offset: int

Number of years that this is offset into the future.

class fava.util.date.FiscalYearEnds

Some common fiscal year ends, used in tests.

AU_NZ = FiscalYearEnd(month=6, day=30)

Fiscal year for Australia / New Zealand (06-30).

JP = FiscalYearEnd(month=15, day=31)

Fiscal year for Japan (15-31).

UK = FiscalYearEnd(month=4, day=5)

Fiscal year for the UK (04-05).

US = FiscalYearEnd(month=9, day=30)

Fiscal year for the US (09-30).

ZA = FiscalYearEnd(month=2, day=28)

Fiscal year for the personal tax year in South Africa (02-28).

exception fava.util.date.FyeHasNoQuartersError

Only fiscal years that start on the first of a month have quarters.

class fava.util.date.Interval

An interval.

abstractmethod format_date(date)

Format a date for this interval for the Fava time filter.

Return type:

str

abstractmethod get_next(date)

Get the start date of the next interval following the date.

Return type:

date

abstractmethod get_prev(date)

Get the start date of the interval in which the date falls.

Return type:

date

abstract property label: str

The label for the interval.

number_of_days(date)

Get number of days in the surrounding interval.

Return type:

int

exception fava.util.date.InvalidDateRangeError

End date needs to be after begin date.

fava.util.date.dateranges(begin, end, interval, *, complete)

Get date ranges for the given begin and end date.

Parameters:
  • begin (date) – The begin date - the first interval date range will include this date

  • end (date) – The end date - the last interval will end on or after date

  • interval (Interval) – The type of interval to generate ranges for.

  • complete (bool) – Whether to complete starting and ending intervals.

Yields:

Date ranges for all intervals between begin and end date.

Return type:

Iterable[DateRange]

fava.util.date.days_in_daterange(start_date, end_date)

Yield a datetime for every day in the specified interval.

Parameters:
  • start_date (date) – A start date.

  • end_date (date) – An end date (exclusive).

Yields:

All days between start_date to end_date.

fava.util.date.get_interval(value, fye)

Get the interval for a string name.

Return type:

Interval | None

fava.util.date.interval_ends(begin, end, interval, *, complete)

Get interval ends.

Yields:

The ends of the intervals.

fava.util.date.local_today()

Today as a date in the local timezone.

Return type:

date

fava.util.date.month_offset(date, months)

Offsets a date by a given number of months.

Return type:

date

fava.util.date.parse_fye_string(fye)

Parse a string option for the fiscal year end.

Parameters:

fye (str) – The end of the fiscal year to parse.

Return type:

FiscalYearEnd | None

fava.util.date_parser

Parsing of the date expressions that Fava’s time filter supports.

See parse_date() for the supported syntax.

class fava.util.date_parser.FiscalYearPeriod(begin, fye)

A fiscal year, which can be refined to one of its quarters.

interval: FiscalYear
refine(token)

Narrow this period down, e.g. a year to one of its months.

Return type:

Period

class fava.util.date_parser.MonthPeriod(year, month)

A month, which can be refined to one of its days.

refine(token)

Narrow this period down, e.g. a year to one of its months.

Return type:

Period

exception fava.util.date_parser.NoSuchPeriodError

A date expression is valid syntax but denotes no existing period.

This covers dates that do not exist, like the 30th of February or week 99, years outside the range that dates support, and fiscal quarters for a fiscal year end that does not have any.

class fava.util.date_parser.Period(begin, interval)

A period given by its first day and the interval that it spans.

property date_range: DateRange

The range of dates that this period spans.

refine(token)

Narrow this period down, e.g. a year to one of its months.

Return type:

Period

fava.util.date_parser.Variable

The variables that denote a period around the current day.

alias of Literal[‘fiscal_year’, ‘fiscal_quarter’, ‘year’, ‘quarter’, ‘month’, ‘week’, ‘day’]

class fava.util.date_parser.YearPeriod(year)

A calendar year, which can be refined to a month, quarter or week.

refine(token)

Narrow this period down, e.g. a year to one of its months.

Return type:

Period

fava.util.date_parser.parse_date(string, fye=FiscalYearEnd(month=12, day=31))

Parse a date.

Example of supported formats:

  • 2010-03-15, 2010-03, 2010

  • 2010-W01, 2010-Q3

  • FY2012, FY2012-Q2

Instead of a year, month, etc., one of the variables ‘year’, ‘quarter’, ‘month’, ‘week’, ‘day’, ‘fiscal_year’ and ‘fiscal_quarter’ can be used to refer to the period around the current day. They support addition and subtraction of an offset of up to three digits, e.g. ‘month-2’ - four digits are a year and hence start a range. To subtract from the date instead of shifting the period, put the variable in parentheses - ‘month-10’ is ten months ago whereas ‘(month)-10’ is the tenth of the current month.

A range of dates can be expressed as ‘start - end’, where start and end look like one of the above examples.

Parameters:
  • string (str) – A date(range) in our custom format.

  • fye (FiscalYearEnd) – The fiscal year end to consider.

Returns:

DateRange – The range of dates.

Raises:

fava.util.excel

Writing query results to CSV and spreadsheet documents.

exception fava.util.excel.InvalidResultFormatError(result_format)
fava.util.excel.to_csv(types, rows)

Save result to CSV.

Parameters:
Returns:

BytesIO – The (binary) file contents.

fava.util.excel.to_excel(types, rows, result_format, query_string)

Save result to spreadsheet document.

Parameters:
  • types (Sequence[Column]) – query result_types.

  • rows (Sequence[tuple[object, ...]]) – query result_rows.

  • result_format (str) – ‘xlsx’ or ‘ods’.

  • query_string (str) – The query string (is written to the document).

Returns:

BytesIO – The (binary) file contents.

fava.util.parsing

Lexing and parsing helpers.

class fava.util.parsing.KeywordTokenKind(keywords)

A token for one of the keywords of a typing.Literal.

convert: Callable[[str], T]
pattern: str
class fava.util.parsing.Lexer(rules, /, *, error=<class 'fava.util.parsing.UnexpectedTokenError'>, flags=0, skip='\\\\s+')

Splits strings into tokens of the given kinds.

They are matched in the order in which they are given. Text matching the skip pattern is ignored and any other character that does not start a token is an error.

Parameters:
  • rules (Sequence[TokenKind[Any]]) – The kinds of token to split the string into.

  • error (Callable[[str], Exception]) – The exception to raise for a character that cannot start a token - it is passed that character.

  • flags (int) – re flags to apply.

  • skip (str) – A pattern for the text between tokens, which is ignored.

tokenize(string)

Split a string into tokens.

Yields:

The tokens of the given string.

Raises:

Exception – The error for a character that cannot start a token.

class fava.util.parsing.LiteralTokenKind(char)

A token for a literal character or string.

convert: Callable[[str], T]
pattern: str
exception fava.util.parsing.ParseError

An expression could not be parsed.

class fava.util.parsing.ParserBase(tokens)

A parser base class.

accept(kind)

Consume the current token if it is of the given kind.

Return type:

bool

advance()

Consume and return the current token.

Return type:

Token

expect(kind)

Consume the current token of the given kind and get its value.

Return type:

TypeVar(T)

peek(offset=0)

The token at the given offset from the current position.

Return type:

Token | None

peek_kind(offset=0)

The token kind at the given offset from the current position.

Return type:

TokenKind[Any] | None

class fava.util.parsing.Token(kind, text)

A token, of some kind and with the text that it matched.

kind: TokenKind[Any]

The kind of token that matched.

text: str

The matched text.

class fava.util.parsing.TokenKind(pattern, convert)

A token type: pattern and how to get the value of such a token.

convert: Callable[[str], T]
pattern: str
value(token)

The value of a token, which has to be of this kind.

Return type:

TypeVar(T)

exception fava.util.parsing.UnexpectedEndError

An expression ended before it was complete.

exception fava.util.parsing.UnexpectedTokenError(unexpected)

An expression contained something that does not belong there.

fava.util.ranking

Ranking utilities.

class fava.util.ranking.ExponentialDecayRanker(list_=None, rate=0.0018990333713971104)

Rank a list by exponential decay.

Maintains scores for the items in a list. We can think of this as the sum of all ‘likes’, where the value of a ‘like’ starts at 1 and decays exponentially. So the current score would be given by (where t is the current time and l is the time of the ‘like’)

s = Σ exp(-RATE * (t - l))

As only the relative order on the items is relevant, we can multiply all scores by exp(RATE * t) and so we need to compute the following score:

s = Σ exp(RATE * l)

To avoid huge numbers, we actually compute and store the logarithm of that sum.

Parameters:
  • list_ (Sequence[str] | None) – If given, this list is ranked is by .sort() otherwise all items with at least one ‘like’ will be ranked.

  • rate (float) – This sets the rate of decay. 1/rate will be the time (in days) that it takes for the value of a ‘like’ to decrease by 1/e. The default rate is set to math.log(2) * 1/365 so that a ‘like’ from a year ago will count half as much as one from today.

get(item)

Get the current score for an item, or zero.

Return type:

float

list
rate
scores: dict[str, float]
sort()

Return items sorted by rank.

Return type:

list[str]

update(item, date)

Add ‘like’ for item.

Parameters:
  • item (str) – An item in the list that is being ranked.

  • date (date) – The date on which the item has been liked.

Return type:

None

fava.util.sets

Utils for Python sets.

fava.util.sets.add_to_set(set_, new)

Add an entry to a set (or create it if doesn’t exist).

Parameters:
  • set_ (Set[str] | None) – The (optional) set to add an element to.

  • new (str) – The string to add to the set.

Return type:

set[str]