We'll look at two analysis functions that we can use to filter and analyze the individual AccessDetails objects. The first function, a filter() function, will pass only specific paths. The second function will summarize the occurrences of each distinct path.
We'll define a small book_in_path() function and combine this with the built-in filter() function to apply the function to the details. Here is the composite book_filter() function:
from typing import Iterable, Iterator
def book_filter(
access_details_iter: Iterable[AccessDetails]
) -> Iterator[AccessDetails]:
def book_in_path(detail: AccessDetails) -> bool:
path = tuple(
item
for item in detail.url.path.split('/')
if item
)
return path[0] == 'book' and len(path) > 1
return filter(book_in_path, access_details_iter)
We've defined a rule, through the book_in_path() function, which we'll apply to each AccessDetails object. If the path is not empty and the first-level attribute of the path is book, then we're interested in these objects. All other AccessDetails objects can be quietly rejected.
The reduce_book_total() function is the final reduction that we're interested in:
from collections import Counter
def reduce_book_total(
access_details_iter: Iterable[AccessDetails]
) -> Dict[str, int]:
counts: Dict[str, int] = Counter()
for detail in access_details_iter:
counts[detail.url.path] += 1
return counts
This function will produce a Counter() object that shows the frequency of each path in an AccessDetails object. In order to focus on a particular set of paths, we'll use the reduce_total(book_filter(details)) method. This provides a summary of only items that are passed by the given filter.
Because Counter objects can be applied to a wide variety of types, a type hint is required to provide a narrow specification. In this case, the hint is Dict[str, int] to show the mypy tool that string representations of paths will be counted.