Skip to content

🤖 A fully featured, easy to use Python wrapper for the Lovdata API

License

Notifications You must be signed in to change notification settings

DiFronzo/python-lovdata

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

python-lovdata

🤖 A fully featured, easy to use Python wrapper for the Lovdata API

Python 3.8+ License: MIT

Features

  • Modular Architecture - Organized by API resource groups for clarity
  • 🔄 Session & Request Handling - Automatic retries, connection pooling, and timeout management
  • 🔐 Authentication & Security - Secure API key handling with X-API-Key header
  • 🐍 Pythonic Interface - Context managers, type hints, and intuitive method names
  • 🛡️ Error Handling - Comprehensive exception hierarchy for different error types
  • 📊 Rate Limiting - Automatic tracking of API rate limits
  • 📚 Well Documented - Complete docstrings and usage examples
  • 🧪 Tested - Comprehensive test suite with pytest
  • 🚀 Easy to Extend - Plugin architecture for adding new endpoints

Installation

pip install python-lovdata

Or install from source:

git clone https://github.com/DiFronzo/python-lovdata.git
cd python-lovdata
pip install -e .

Quick Start

from lovdata import LovdataAPI

# Initialize the API client
with LovdataAPI(api_key="your-api-key") as api:
    # Check authentication
    user_info = api.services.get_user_info()
    print(f"Logged in as: {user_info['login']}")
    
    # Search for documents
    results = api.search.search(emne1="straffelov", rows=10)
    print(f"Found {len(results)} results")
    
    # Get document metadata
    doc = api.content.get_document_meta("NL/lov/2005-05-20-28")
    print(f"Document title: {doc.get('title')}")

Usage Examples

Authentication

The library supports authentication via API key using the X-API-Key header:

from lovdata import LovdataAPI

# Using context manager (recommended)
with LovdataAPI(api_key="your-api-key") as api:
    user_info = api.services.get_user_info()
    print(f"User ID: {user_info['userID']}")
    print(f"Company ID: {user_info['companyID']}")

# Without context manager
api = LovdataAPI(api_key="your-api-key")
try:
    user_info = api.services.get_user_info()
finally:
    api.close()

Content Services

Access document lists, metadata, and rendering:

# Get document metadata
doc_meta = api.content.get_document_meta("NL/lov/2005-05-20-28")

# Get document index (table of contents)
index = api.content.get_document_index("NL/lov/1997-02-28-19")

# Get document history
history = api.content.get_document_history("lov/2005-05-20-28")

# List documents in a legal source
docs = api.content.list_base("NL")

# Get change history for a legal source
changes = api.content.get_base_history(
    base="NL",
    from_date="2024-01-01",
    to_date="2024-12-31",
    limit=50
)

# Render document as HTML
html = api.content.render_ref_id("lov/2005-05-20-28/§4", format="html")

# Download document in various formats
pdf_content = api.content.download_document(
    dok_id="NL/lov/2005-05-20-28",
    file_type="pdf"
)

# Check if document exists
exists = api.content.lookup(ref_id="lov/2005-05-20-28")

# List all legal sources
sources = api.content.list_legal_sources()

Structured Rules

Get complete documents in structured HTML5/XML format:

# List available legal sources
bases = api.structured_rules.list_bases()

# List documents in a legal source
docs = api.structured_rules.list_documents("NL")

# Get a document in structured format
doc = api.structured_rules.get_document("NL", "lov-2005-05-20-28.xml")

# Get document version at specific date
doc_at_date = api.structured_rules.get_document_at_date(
    "NL",
    "lov-2005-05-20-28.xml",
    "2024-01-01"
)

# Get document timeline (all versions)
timeline = api.structured_rules.get_timeline("NL", "lov-2005-05-20-28.xml")

Search

Perform full-text search across legal sources:

# Simple search
results = api.search.search(emne1="straffelov", rows=10)

# Advanced search with multiple terms
results = api.search.search(
    emne1="straff",
    emne2="bot",
    base="NL",
    from_date="2020-01-01",
    to_date="2024-12-31",
    rows=50,
    offset=0,
    sort_field="date",
    sort_order="DESC"
)

# Search with text references
results = api.search.search(
    teksthenvisning="§ 12",
    base="NL"
)

Services

Miscellaneous utility functions:

# Ping service to check if it's running
status = api.services.ping()

# Get user information
user_info = api.services.get_user_info()

# Locate references in text (genref)
result = api.services.genref(
    text="Se straffeloven § 4 og § 5",
    dok_id="NL/lov/2005-05-20-28"
)
print(result['appliedString'])  # Text with hyperlinks
print(result['model']['matches'])  # Found references

Public Data

Access public data under NLOD 2.0 license:

# List available public data packages
packages = api.public_data.list()

# Download a public data file
data = api.public_data.get("filename.zip")
with open("output.zip", "wb") as f:
    f.write(data)

AI Functionality

Advanced AI-powered search and text generation:

# Strategy search
results = api.ai.strategy_search(
    text="What are the penalties for theft?",
    strategy="LovSourcedReferenceGraphStrategy",
    legal_areas="STRAFF"
)

# Generate AI response
responses = api.ai.generate_response(
    query="Explain § 4 of the Penal Code",
    section_ids=[12345, 12346],
    message_history=[
        {"type": "USER", "content": "Previous question"},
        {"type": "SYSTEM", "content": "Previous answer"}
    ]
)

Error Handling

The library provides comprehensive exception handling:

from lovdata import (
    LovdataAPI,
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    RateLimitError,
    ServerError,
    NetworkError,
    TimeoutError,
    ValidationError,
)

try:
    with LovdataAPI(api_key="your-api-key") as api:
        doc = api.content.get_document_meta("NL/lov/2005-05-20-28")
except AuthenticationError:
    print("Invalid API key")
except AuthorizationError:
    print("Not authorized to access this resource")
except NotFoundError:
    print("Document not found")
except RateLimitError:
    print("Rate limit exceeded")
except ValidationError as e:
    print(f"Invalid parameters: {e.message}")
except ServerError:
    print("Server error occurred")
except NetworkError:
    print("Network connection error")
except TimeoutError:
    print("Request timed out")

Rate Limiting

The library automatically tracks rate limit information:

api = LovdataAPI(api_key="your-api-key")

# Make some requests
results = api.search.search(emne1="test")

# Check rate limit info
rate_info = api.client.get_rate_limit_info()
print(f"Limit: {rate_info['limit']}")
print(f"Remaining: {rate_info['remaining']}")
print(f"Reset at: {rate_info['reset']}")

api.close()

Configuration Options

Customize client behavior:

from lovdata import LovdataAPI

api = LovdataAPI(
    api_key="your-api-key",
    base_url="https://api.lovdata.no",  # Custom base URL
    timeout=60,  # Request timeout in seconds (default: 30)
    max_retries=5,  # Max retries for failed requests (default: 3)
    backoff_factor=1.0,  # Backoff factor for retries (default: 0.5)
    verify_ssl=True,  # SSL verification (default: True)
)

API Documentation

For complete API documentation, see the Lovdata API Swagger documentation.

For XML format documentation, see Lovdata XML documentation.

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/DiFronzo/python-lovdata.git
cd python-lovdata

# Install development dependencies
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=lovdata --cov-report=html

# Run specific test file
pytest tests/test_client.py

Code Quality

# Format code with black
black lovdata tests

# Lint with ruff
ruff check lovdata tests

# Type check with mypy
mypy lovdata

Document Identifiers

The Lovdata API uses FRBR-based document identifiers:

  • refID: FRBR "work" - Can refer to multiple expressions of the same work

    • Example: lov/2005-05-20-28 (any version of the Penal Code)
  • dokID: FRBR "expression" - Unique identifier for a specific version

    • Example: NL/lov/2005-05-20-28 (consolidated Penal Code)
    • Example: LTI/lov/2005-05-20-28 (originally promulgated version)
    • Example: NLE/lov/2005-05-20-28 (English version)

Legal Sources

Common legal source abbreviations:

  • NL - Norwegian Laws (Norsk Lovtidend)
  • SF - Government Regulations (Sentral forskrift)
  • LF - Local Regulations (Lokal forskrift)
  • DEL - Delegated legislation
  • INS - Instructions
  • STV - Stortinget (Parliament) decisions

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Support

For API-related questions, contact Lovdata API tech support at api@lovdata.no

For library issues, please open an issue on GitHub.

About

🤖 A fully featured, easy to use Python wrapper for the Lovdata API

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages