Documentation Index
Fetch the complete documentation index at: https://docs.law4devs.eu/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Every list endpoint returns a Page[T] object. You can either paginate manually using the .links and .meta fields, or let the SDK handle it automatically with iter().
The Page[T] Object
page = client.frameworks.list()
# The items on this page
page.data # list[Framework]
# Metadata about the full result set
page.meta.total # int — total items across all pages
page.meta.page # int — current page number (1-indexed)
page.meta.per_page # int — items per page
page.meta.pages # int — total number of pages
# Navigation links (None if not applicable)
page.links.next # str | None — URL of the next page
page.links.prev # str | None — URL of the previous page
Loop through pages yourself by checking page.links.next:
from law4devs import Law4DevsClient
client = Law4DevsClient()
page_num = 1
while True:
page = client.frameworks.list(page=page_num, per_page=10)
for fw in page.data:
print(fw.name)
if page.links.next is None:
break
page_num += 1
print(f"Done. Total frameworks: {page.meta.total}")
Every resource exposes an iter() method that fetches pages on demand and yields items one at a time. This is the recommended approach for processing complete result sets.
Iterate all frameworks
for fw in client.frameworks.iter():
print(fw.slug, fw.name)
Iterate all articles in a framework
for article in client.articles.iter("gdpr"):
print(f"Art. {article.article_number}: {article.title}")
Iterate with a custom page size
Use per_page to control how many items are fetched per HTTP request. Larger values reduce the number of requests but use more memory per page.
# Fetch 100 articles per request instead of the default 20
for article in client.articles.iter("gdpr", per_page=100):
print(article.article_number)
Collecting Results into a List
# Collect all requirements for a framework into a list
all_requirements = list(client.requirements.iter(framework_slug="gdpr"))
print(f"Loaded {len(all_requirements)} requirements")
For large frameworks, collecting everything into a list can use significant memory. Prefer streaming with a for loop when you don’t need random access.
The per_page Parameter
All list() and iter() methods accept a per_page parameter:
- Minimum:
1
- Maximum:
100
- Default:
20
# Smallest possible pages (useful for sampling)
page = client.articles.list("gdpr", per_page=1)
print(f"GDPR has {page.meta.total} articles total")
# Largest pages (fewer HTTP requests)
for article in client.articles.iter("cra", per_page=100):
process(article)
Checking Total Count Without Fetching All Items
Request a single item to read meta.total without loading the full data set:
page = client.requirements.list(framework_slug="nis2", per_page=1)
print(f"NIS2 has {page.meta.total} requirements")
Detailed Examples
Process all frameworks with progress reporting
frameworks = list(client.frameworks.iter())
total = len(frameworks)
for i, fw in enumerate(frameworks, 1):
print(f"[{i}/{total}] Processing {fw.slug}...")
articles = list(client.articles.iter(fw.slug))
print(f" {len(articles)} articles")
Collect all requirements across all frameworks
all_requirements = []
for fw in client.frameworks.iter():
for req in client.requirements.iter(framework_slug=fw.slug):
all_requirements.append(req)
print(f"Total requirements across all frameworks: {len(all_requirements)}")
Paginate with an offset (skip first N items)
# Skip the first 40 items (pages 1–2 at per_page=20) and start from page 3
page = client.articles.list("gdpr", page=3, per_page=20)
for article in page.data:
print(article.article_number)
Stop iteration early
Because iter() yields lazily, you can stop at any point without fetching the remaining pages:
import itertools
# Only process the first 50 articles, regardless of total count
for article in itertools.islice(client.articles.iter("gdpr"), 50):
print(article.title)
iter() is lazy — it only fetches the next page when the current page’s items are exhausted. If you break out of the loop early, no unnecessary HTTP requests are made.