dbbasic-rss


Namedbbasic-rss JSON
Version 1.0.0 PyPI version JSON
download
home_pageNone
SummarySimple, composable RSS feed generation for Python. Framework-agnostic, works with TSV/CSV/JSON, follows Unix philosophy.
upload_time2025-10-19 23:46:32
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT
keywords rss feed atom xml dbbasic blog podcast syndication
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # dbbasic-rss

Simple, composable RSS feed generation for Python. Framework-agnostic, works with TSV/CSV/JSON, follows Unix philosophy.

## Features

- **Simple Day-1 Usage**: One-liner to generate RSS feeds
- **Framework Agnostic**: Works with Flask, Django, FastAPI, static sites, or plain Python
- **Multiple Data Sources**: TSV, CSV, JSON, Python lists, or directories of files
- **No Heavy Dependencies**: Pure stdlib for core functionality
- **Composable**: Works naturally with `dbbasic-tsv` and other modules
- **Standards Compliant**: Generates valid RSS 2.0 feeds
- **Git-Friendly**: Generate static RSS files to commit
- **Type-Safe**: Full type hints for better IDE support

## Installation

```bash
pip install dbbasic-rss
```

Optional dependencies:

```bash
# For TSV support with dbbasic-tsv
pip install dbbasic-rss[tsv]

# For YAML frontmatter in from_directory()
pip install dbbasic-rss[yaml]

# For development
pip install dbbasic-rss[dev]
```

## Quick Start

### One-Liner

```python
import dbbasic_rss as rss

# Auto-detects format and generates feed
rss.generate('articles.tsv', 'feed.xml',
             title='My Blog',
             url_pattern='https://example.com/{slug}/')
```

### From TSV File

```python
import dbbasic_rss as rss

feed = rss.from_tsv(
    'articles.tsv',
    title='My Blog',
    link='https://example.com',
    description='Articles about Python and web development',
    url_pattern='https://example.com/{slug}/'
)

# Save to file
feed.write('feed.xml')

# Or get as string
xml = feed.to_xml()
print(xml)
```

### From Python List

```python
import dbbasic_rss as rss

posts = [
    {
        'title': 'Getting Started with Python',
        'date': '2025-10-19',
        'content': 'Learn the basics...',
        'slug': 'getting-started-python',
        'author': 'Dan Quellhorst'
    },
    {
        'title': 'Advanced Python Tips',
        'date': '2025-10-18',
        'content': 'Expert techniques...',
        'slug': 'advanced-python-tips'
    }
]

feed = rss.from_posts(
    posts,
    title='Python Blog',
    link='https://example.com',
    description='Learn Python programming',
    url_pattern='https://example.com/posts/{slug}/'
)

feed.write('feed.xml')
```

### Manual Feed Building

```python
import dbbasic_rss as rss

# Create feed
feed = rss.Feed(
    title='My Tech Blog',
    link='https://example.com',
    description='Articles about software engineering',
    language='en',
    author='Dan Quellhorst',
    author_email='dan@example.com'
)

# Add posts
feed.add_post(
    title='Understanding RSS Feeds',
    link='https://example.com/understanding-rss/',
    description='A comprehensive guide to RSS',
    content='<p>Full HTML content here...</p>',
    pub_date='2025-10-19',
    author='Dan Quellhorst',
    categories=['rss', 'web', 'tutorial']
)

feed.add_post(
    title='Python Web Frameworks',
    link='https://example.com/python-frameworks/',
    description='Comparing Flask, Django, and FastAPI',
    pub_date='2025-10-18',
    categories=['python', 'web']
)

# Generate XML
xml = feed.to_xml()

# Or write to file
feed.write('feed.xml')
```

## Framework Integration

### Flask

```python
from flask import Flask, Response
import dbbasic_rss as rss

app = Flask(__name__)

@app.route('/rss')
def rss_feed():
    # Load your posts data
    posts = load_posts()  # Your data loading logic

    feed = rss.from_posts(
        posts,
        title='My Blog',
        link='https://example.com',
        description='Latest blog posts',
        url_pattern='https://example.com/{slug}/'
    )

    return Response(feed.to_xml(), mimetype='application/rss+xml')
```

### Django

```python
from django.http import HttpResponse
import dbbasic_rss as rss

def rss_feed(request):
    # Query your models
    articles = Article.objects.all().order_by('-published_date')[:20]

    # Convert to list of dicts
    posts = list(articles.values('title', 'slug', 'content', 'published_date', 'author__name'))

    feed = rss.from_posts(
        posts,
        title='My Django Blog',
        link='https://example.com',
        description='Latest articles',
        url_pattern='https://example.com/articles/{slug}/',
        date_field='published_date',
        author_field='author__name'
    )

    return HttpResponse(feed.to_xml(), content_type='application/rss+xml')
```

### FastAPI

```python
from fastapi import FastAPI
from fastapi.responses import Response
import dbbasic_rss as rss

app = FastAPI()

@app.get('/rss', response_class=Response)
async def rss_feed():
    posts = await get_posts()  # Your async data loading

    feed = rss.from_posts(
        posts,
        title='FastAPI Blog',
        link='https://example.com',
        description='Latest posts',
        url_pattern='https://example.com/posts/{id}/'
    )

    return Response(content=feed.to_xml(), media_type='application/rss+xml')
```

### Static Site Generator

```python
import dbbasic_rss as rss

# Generate from markdown files
feed = rss.from_directory(
    'content/posts/',
    pattern='*.md',
    extract_metadata=True,  # Reads YAML frontmatter
    title='My Static Blog',
    link='https://example.com',
    description='Static blog posts',
    url_pattern='https://example.com/posts/{stem}/'
)

# Write static file
feed.write('public/rss.xml')
```

## Data Sources

### From TSV

```python
# articles.tsv:
# title	slug	date	description	author
# Post 1	post-1	2025-10-19	Description...	Dan

feed = rss.from_tsv(
    'articles.tsv',
    title='Blog',
    url_pattern='https://example.com/{slug}/'
)
```

### From CSV

```python
feed = rss.from_csv(
    'posts.csv',
    title='Blog',
    url_pattern='https://example.com/{id}/'
)
```

### From JSON

```python
# posts.json:
# [
#   {"title": "Post 1", "url": "https://...", "date": "2025-10-19"},
#   ...
# ]

feed = rss.from_json(
    'posts.json',
    title='Blog',
    link='https://example.com'
)
```

### From Directory of Markdown Files

```python
# Reads markdown files with YAML frontmatter:
# ---
# title: My Post
# date: 2025-10-19
# author: Dan
# ---
# Content here...

feed = rss.from_directory(
    'posts/',
    pattern='*.md',
    extract_metadata=True,
    title='Blog',
    url_pattern='https://example.com/{stem}/'
)
```

## Advanced Features

### Custom Field Mapping

```python
posts = [
    {
        'headline': 'My Article',
        'published': '2025-10-19',
        'body': 'Article content...',
        'permalink': 'https://example.com/articles/my-article'
    }
]

feed = rss.from_posts(
    posts,
    title_field='headline',
    date_field='published',
    content_field='body',
    url_field='permalink'
)
```

### Categories/Tags

```python
posts = [
    {
        'title': 'Python Tutorial',
        'url': 'https://example.com/tutorial',
        'tags': 'python,tutorial,beginner'  # Comma-separated
    }
]

feed = rss.from_posts(
    posts,
    categories_field='tags'
)
```

### HTML Content with Separate Description

```python
feed.add_post(
    title='Article Title',
    link='https://example.com/article',
    description='Short plain-text description for RSS readers',
    content='<p>Full <strong>HTML</strong> content for readers that support it</p>',
    pub_date='2025-10-19'
)
```

### Feed Image/Logo

```python
feed = rss.Feed(
    title='My Blog',
    link='https://example.com',
    description='Blog description',
    image_url='https://example.com/logo.png',
    image_title='My Blog Logo',
    image_link='https://example.com'
)
```

### Podcast Support (Enclosures)

```python
feed.add_post(
    title='Episode 1: Introduction',
    link='https://example.com/podcast/ep1',
    description='In this episode...',
    pub_date='2025-10-19',
    enclosure={
        'url': 'https://example.com/audio/ep1.mp3',
        'type': 'audio/mpeg',
        'length': '12345678'  # Size in bytes
    }
)
```

### Feed Validation

```python
feed = rss.Feed(title='', link='https://example.com')
warnings = feed.validate()

for warning in warnings:
    print(f"Warning: {warning}")
# Output: Warning: Feed title is missing
```

### Feed Statistics

```python
print(f"Total posts: {feed.count()}")
print(f"Oldest post: {feed.oldest()}")
print(f"Newest post: {feed.newest()}")
```

## Working with dbbasic-tsv

```python
from dbbasic_tsv import TSV
import dbbasic_rss as rss

# Read and query with dbbasic-tsv
db = TSV('articles.tsv')
posts = db.query(category='python', limit=10)

# Generate RSS feed
feed = rss.from_posts(
    posts,
    title='Python Articles',
    url_pattern='https://example.com/{slug}/'
)

feed.write('python-feed.xml')
```

## API Reference

### `Feed(title, link, description, ...)`

Main feed class.

**Parameters:**
- `title` (str): Feed title
- `link` (str): Feed URL
- `description` (str): Feed description
- `language` (str): Language code (default: 'en')
- `author` (str): Author name
- `author_email` (str): Author email
- `image_url` (str): Feed image/logo URL
- `ttl` (int): Cache time-to-live in minutes
- `category` (str): Feed category

**Methods:**
- `add_post(**kwargs)`: Add a post to the feed
- `to_xml()`: Generate RSS XML string
- `write(filepath)`: Write feed to file
- `validate()`: Return list of validation warnings
- `count()`: Return number of items
- `oldest()`: Return oldest publication date
- `newest()`: Return newest publication date

### `from_posts(posts, ...)`

Generate feed from list of dictionaries.

**Parameters:**
- `posts` (list): List of post dictionaries
- `title` (str): Feed title
- `link` (str): Feed URL
- `description` (str): Feed description
- `url_pattern` (str): URL pattern with {field} placeholders
- `title_field` (str): Field name for title (default: 'title')
- `date_field` (str): Field name for date (default: 'date')
- `content_field` (str): Field name for content (default: 'content')
- `author_field` (str): Field name for author (default: 'author')
- `url_field` (str): Field name for URL (default: 'url')
- `categories_field` (str): Field name for categories
- `**kwargs`: Additional Feed() arguments

### `from_tsv(filepath, ...)`, `from_csv(filepath, ...)`, `from_json(filepath, ...)`

Generate feed from file. Same parameters as `from_posts()`.

### `from_directory(directory, pattern='*.md', ...)`

Generate feed from directory of files.

**Additional Parameters:**
- `directory` (str): Directory path
- `pattern` (str): Glob pattern (default: '*.md')
- `extract_metadata` (bool): Extract YAML frontmatter (default: True)

### `generate(source, output, ...)`

One-liner to generate feed from file to file.

**Parameters:**
- `source` (str): Input file path (.tsv, .csv, .json)
- `output` (str): Output XML file path
- `**kwargs`: Same as `from_posts()`

## Why dbbasic-rss?

### Unix Philosophy

- **Do one thing well**: Generate RSS feeds
- **Plain text**: Works with TSV, CSV, JSON files
- **Composable**: Pipes data through functions
- **No vendor lock-in**: Framework-agnostic

### Comparison to Other Libraries

**feedgen** (most popular):
- ❌ Heavy API, steep learning curve
- ❌ Framework-specific patterns
- ❌ Complex for simple use cases

**dbbasic-rss**:
- ✅ One-liner for 80% of use cases
- ✅ Works with any framework
- ✅ Composable with other tools
- ✅ Educational (shows how RSS works)

### Teaching Tool

RSS is just XML! `dbbasic-rss` helps you understand RSS by providing:
- Clear, readable code
- Simple templates (no magic)
- Standards compliance
- Incremental learning (simple → advanced)

## Contributing

Contributions welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass: `pytest`
5. Submit a pull request

## License

MIT License - see LICENSE file for details.

## Links

- **GitHub**: https://github.com/askrobots/dbbasic-rss
- **PyPI**: https://pypi.org/project/dbbasic-rss/
- **Documentation**: https://github.com/askrobots/dbbasic-rss#readme
- **Issues**: https://github.com/askrobots/dbbasic-rss/issues

## Credits

Created by [Ask Robots](https://askrobots.com) as part of the DBBasic framework.

Inspired by the Unix philosophy and built for simplicity, composability, and ease of learning.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "dbbasic-rss",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "rss, feed, atom, xml, dbbasic, blog, podcast, syndication",
    "author": null,
    "author_email": "Ask Robots <hello@askrobots.com>",
    "download_url": "https://files.pythonhosted.org/packages/5d/68/5a4669c7e7e291d29ffb8cecee66833fa9db2afa7e0ff9aeb117410b02b1/dbbasic_rss-1.0.0.tar.gz",
    "platform": null,
    "description": "# dbbasic-rss\n\nSimple, composable RSS feed generation for Python. Framework-agnostic, works with TSV/CSV/JSON, follows Unix philosophy.\n\n## Features\n\n- **Simple Day-1 Usage**: One-liner to generate RSS feeds\n- **Framework Agnostic**: Works with Flask, Django, FastAPI, static sites, or plain Python\n- **Multiple Data Sources**: TSV, CSV, JSON, Python lists, or directories of files\n- **No Heavy Dependencies**: Pure stdlib for core functionality\n- **Composable**: Works naturally with `dbbasic-tsv` and other modules\n- **Standards Compliant**: Generates valid RSS 2.0 feeds\n- **Git-Friendly**: Generate static RSS files to commit\n- **Type-Safe**: Full type hints for better IDE support\n\n## Installation\n\n```bash\npip install dbbasic-rss\n```\n\nOptional dependencies:\n\n```bash\n# For TSV support with dbbasic-tsv\npip install dbbasic-rss[tsv]\n\n# For YAML frontmatter in from_directory()\npip install dbbasic-rss[yaml]\n\n# For development\npip install dbbasic-rss[dev]\n```\n\n## Quick Start\n\n### One-Liner\n\n```python\nimport dbbasic_rss as rss\n\n# Auto-detects format and generates feed\nrss.generate('articles.tsv', 'feed.xml',\n             title='My Blog',\n             url_pattern='https://example.com/{slug}/')\n```\n\n### From TSV File\n\n```python\nimport dbbasic_rss as rss\n\nfeed = rss.from_tsv(\n    'articles.tsv',\n    title='My Blog',\n    link='https://example.com',\n    description='Articles about Python and web development',\n    url_pattern='https://example.com/{slug}/'\n)\n\n# Save to file\nfeed.write('feed.xml')\n\n# Or get as string\nxml = feed.to_xml()\nprint(xml)\n```\n\n### From Python List\n\n```python\nimport dbbasic_rss as rss\n\nposts = [\n    {\n        'title': 'Getting Started with Python',\n        'date': '2025-10-19',\n        'content': 'Learn the basics...',\n        'slug': 'getting-started-python',\n        'author': 'Dan Quellhorst'\n    },\n    {\n        'title': 'Advanced Python Tips',\n        'date': '2025-10-18',\n        'content': 'Expert techniques...',\n        'slug': 'advanced-python-tips'\n    }\n]\n\nfeed = rss.from_posts(\n    posts,\n    title='Python Blog',\n    link='https://example.com',\n    description='Learn Python programming',\n    url_pattern='https://example.com/posts/{slug}/'\n)\n\nfeed.write('feed.xml')\n```\n\n### Manual Feed Building\n\n```python\nimport dbbasic_rss as rss\n\n# Create feed\nfeed = rss.Feed(\n    title='My Tech Blog',\n    link='https://example.com',\n    description='Articles about software engineering',\n    language='en',\n    author='Dan Quellhorst',\n    author_email='dan@example.com'\n)\n\n# Add posts\nfeed.add_post(\n    title='Understanding RSS Feeds',\n    link='https://example.com/understanding-rss/',\n    description='A comprehensive guide to RSS',\n    content='<p>Full HTML content here...</p>',\n    pub_date='2025-10-19',\n    author='Dan Quellhorst',\n    categories=['rss', 'web', 'tutorial']\n)\n\nfeed.add_post(\n    title='Python Web Frameworks',\n    link='https://example.com/python-frameworks/',\n    description='Comparing Flask, Django, and FastAPI',\n    pub_date='2025-10-18',\n    categories=['python', 'web']\n)\n\n# Generate XML\nxml = feed.to_xml()\n\n# Or write to file\nfeed.write('feed.xml')\n```\n\n## Framework Integration\n\n### Flask\n\n```python\nfrom flask import Flask, Response\nimport dbbasic_rss as rss\n\napp = Flask(__name__)\n\n@app.route('/rss')\ndef rss_feed():\n    # Load your posts data\n    posts = load_posts()  # Your data loading logic\n\n    feed = rss.from_posts(\n        posts,\n        title='My Blog',\n        link='https://example.com',\n        description='Latest blog posts',\n        url_pattern='https://example.com/{slug}/'\n    )\n\n    return Response(feed.to_xml(), mimetype='application/rss+xml')\n```\n\n### Django\n\n```python\nfrom django.http import HttpResponse\nimport dbbasic_rss as rss\n\ndef rss_feed(request):\n    # Query your models\n    articles = Article.objects.all().order_by('-published_date')[:20]\n\n    # Convert to list of dicts\n    posts = list(articles.values('title', 'slug', 'content', 'published_date', 'author__name'))\n\n    feed = rss.from_posts(\n        posts,\n        title='My Django Blog',\n        link='https://example.com',\n        description='Latest articles',\n        url_pattern='https://example.com/articles/{slug}/',\n        date_field='published_date',\n        author_field='author__name'\n    )\n\n    return HttpResponse(feed.to_xml(), content_type='application/rss+xml')\n```\n\n### FastAPI\n\n```python\nfrom fastapi import FastAPI\nfrom fastapi.responses import Response\nimport dbbasic_rss as rss\n\napp = FastAPI()\n\n@app.get('/rss', response_class=Response)\nasync def rss_feed():\n    posts = await get_posts()  # Your async data loading\n\n    feed = rss.from_posts(\n        posts,\n        title='FastAPI Blog',\n        link='https://example.com',\n        description='Latest posts',\n        url_pattern='https://example.com/posts/{id}/'\n    )\n\n    return Response(content=feed.to_xml(), media_type='application/rss+xml')\n```\n\n### Static Site Generator\n\n```python\nimport dbbasic_rss as rss\n\n# Generate from markdown files\nfeed = rss.from_directory(\n    'content/posts/',\n    pattern='*.md',\n    extract_metadata=True,  # Reads YAML frontmatter\n    title='My Static Blog',\n    link='https://example.com',\n    description='Static blog posts',\n    url_pattern='https://example.com/posts/{stem}/'\n)\n\n# Write static file\nfeed.write('public/rss.xml')\n```\n\n## Data Sources\n\n### From TSV\n\n```python\n# articles.tsv:\n# title\tslug\tdate\tdescription\tauthor\n# Post 1\tpost-1\t2025-10-19\tDescription...\tDan\n\nfeed = rss.from_tsv(\n    'articles.tsv',\n    title='Blog',\n    url_pattern='https://example.com/{slug}/'\n)\n```\n\n### From CSV\n\n```python\nfeed = rss.from_csv(\n    'posts.csv',\n    title='Blog',\n    url_pattern='https://example.com/{id}/'\n)\n```\n\n### From JSON\n\n```python\n# posts.json:\n# [\n#   {\"title\": \"Post 1\", \"url\": \"https://...\", \"date\": \"2025-10-19\"},\n#   ...\n# ]\n\nfeed = rss.from_json(\n    'posts.json',\n    title='Blog',\n    link='https://example.com'\n)\n```\n\n### From Directory of Markdown Files\n\n```python\n# Reads markdown files with YAML frontmatter:\n# ---\n# title: My Post\n# date: 2025-10-19\n# author: Dan\n# ---\n# Content here...\n\nfeed = rss.from_directory(\n    'posts/',\n    pattern='*.md',\n    extract_metadata=True,\n    title='Blog',\n    url_pattern='https://example.com/{stem}/'\n)\n```\n\n## Advanced Features\n\n### Custom Field Mapping\n\n```python\nposts = [\n    {\n        'headline': 'My Article',\n        'published': '2025-10-19',\n        'body': 'Article content...',\n        'permalink': 'https://example.com/articles/my-article'\n    }\n]\n\nfeed = rss.from_posts(\n    posts,\n    title_field='headline',\n    date_field='published',\n    content_field='body',\n    url_field='permalink'\n)\n```\n\n### Categories/Tags\n\n```python\nposts = [\n    {\n        'title': 'Python Tutorial',\n        'url': 'https://example.com/tutorial',\n        'tags': 'python,tutorial,beginner'  # Comma-separated\n    }\n]\n\nfeed = rss.from_posts(\n    posts,\n    categories_field='tags'\n)\n```\n\n### HTML Content with Separate Description\n\n```python\nfeed.add_post(\n    title='Article Title',\n    link='https://example.com/article',\n    description='Short plain-text description for RSS readers',\n    content='<p>Full <strong>HTML</strong> content for readers that support it</p>',\n    pub_date='2025-10-19'\n)\n```\n\n### Feed Image/Logo\n\n```python\nfeed = rss.Feed(\n    title='My Blog',\n    link='https://example.com',\n    description='Blog description',\n    image_url='https://example.com/logo.png',\n    image_title='My Blog Logo',\n    image_link='https://example.com'\n)\n```\n\n### Podcast Support (Enclosures)\n\n```python\nfeed.add_post(\n    title='Episode 1: Introduction',\n    link='https://example.com/podcast/ep1',\n    description='In this episode...',\n    pub_date='2025-10-19',\n    enclosure={\n        'url': 'https://example.com/audio/ep1.mp3',\n        'type': 'audio/mpeg',\n        'length': '12345678'  # Size in bytes\n    }\n)\n```\n\n### Feed Validation\n\n```python\nfeed = rss.Feed(title='', link='https://example.com')\nwarnings = feed.validate()\n\nfor warning in warnings:\n    print(f\"Warning: {warning}\")\n# Output: Warning: Feed title is missing\n```\n\n### Feed Statistics\n\n```python\nprint(f\"Total posts: {feed.count()}\")\nprint(f\"Oldest post: {feed.oldest()}\")\nprint(f\"Newest post: {feed.newest()}\")\n```\n\n## Working with dbbasic-tsv\n\n```python\nfrom dbbasic_tsv import TSV\nimport dbbasic_rss as rss\n\n# Read and query with dbbasic-tsv\ndb = TSV('articles.tsv')\nposts = db.query(category='python', limit=10)\n\n# Generate RSS feed\nfeed = rss.from_posts(\n    posts,\n    title='Python Articles',\n    url_pattern='https://example.com/{slug}/'\n)\n\nfeed.write('python-feed.xml')\n```\n\n## API Reference\n\n### `Feed(title, link, description, ...)`\n\nMain feed class.\n\n**Parameters:**\n- `title` (str): Feed title\n- `link` (str): Feed URL\n- `description` (str): Feed description\n- `language` (str): Language code (default: 'en')\n- `author` (str): Author name\n- `author_email` (str): Author email\n- `image_url` (str): Feed image/logo URL\n- `ttl` (int): Cache time-to-live in minutes\n- `category` (str): Feed category\n\n**Methods:**\n- `add_post(**kwargs)`: Add a post to the feed\n- `to_xml()`: Generate RSS XML string\n- `write(filepath)`: Write feed to file\n- `validate()`: Return list of validation warnings\n- `count()`: Return number of items\n- `oldest()`: Return oldest publication date\n- `newest()`: Return newest publication date\n\n### `from_posts(posts, ...)`\n\nGenerate feed from list of dictionaries.\n\n**Parameters:**\n- `posts` (list): List of post dictionaries\n- `title` (str): Feed title\n- `link` (str): Feed URL\n- `description` (str): Feed description\n- `url_pattern` (str): URL pattern with {field} placeholders\n- `title_field` (str): Field name for title (default: 'title')\n- `date_field` (str): Field name for date (default: 'date')\n- `content_field` (str): Field name for content (default: 'content')\n- `author_field` (str): Field name for author (default: 'author')\n- `url_field` (str): Field name for URL (default: 'url')\n- `categories_field` (str): Field name for categories\n- `**kwargs`: Additional Feed() arguments\n\n### `from_tsv(filepath, ...)`, `from_csv(filepath, ...)`, `from_json(filepath, ...)`\n\nGenerate feed from file. Same parameters as `from_posts()`.\n\n### `from_directory(directory, pattern='*.md', ...)`\n\nGenerate feed from directory of files.\n\n**Additional Parameters:**\n- `directory` (str): Directory path\n- `pattern` (str): Glob pattern (default: '*.md')\n- `extract_metadata` (bool): Extract YAML frontmatter (default: True)\n\n### `generate(source, output, ...)`\n\nOne-liner to generate feed from file to file.\n\n**Parameters:**\n- `source` (str): Input file path (.tsv, .csv, .json)\n- `output` (str): Output XML file path\n- `**kwargs`: Same as `from_posts()`\n\n## Why dbbasic-rss?\n\n### Unix Philosophy\n\n- **Do one thing well**: Generate RSS feeds\n- **Plain text**: Works with TSV, CSV, JSON files\n- **Composable**: Pipes data through functions\n- **No vendor lock-in**: Framework-agnostic\n\n### Comparison to Other Libraries\n\n**feedgen** (most popular):\n- \u274c Heavy API, steep learning curve\n- \u274c Framework-specific patterns\n- \u274c Complex for simple use cases\n\n**dbbasic-rss**:\n- \u2705 One-liner for 80% of use cases\n- \u2705 Works with any framework\n- \u2705 Composable with other tools\n- \u2705 Educational (shows how RSS works)\n\n### Teaching Tool\n\nRSS is just XML! `dbbasic-rss` helps you understand RSS by providing:\n- Clear, readable code\n- Simple templates (no magic)\n- Standards compliance\n- Incremental learning (simple \u2192 advanced)\n\n## Contributing\n\nContributions welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Ensure all tests pass: `pytest`\n5. Submit a pull request\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Links\n\n- **GitHub**: https://github.com/askrobots/dbbasic-rss\n- **PyPI**: https://pypi.org/project/dbbasic-rss/\n- **Documentation**: https://github.com/askrobots/dbbasic-rss#readme\n- **Issues**: https://github.com/askrobots/dbbasic-rss/issues\n\n## Credits\n\nCreated by [Ask Robots](https://askrobots.com) as part of the DBBasic framework.\n\nInspired by the Unix philosophy and built for simplicity, composability, and ease of learning.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Simple, composable RSS feed generation for Python. Framework-agnostic, works with TSV/CSV/JSON, follows Unix philosophy.",
    "version": "1.0.0",
    "project_urls": {
        "Documentation": "https://github.com/askrobots/dbbasic-rss#readme",
        "Homepage": "https://github.com/askrobots/dbbasic-rss",
        "Issues": "https://github.com/askrobots/dbbasic-rss/issues",
        "Repository": "https://github.com/askrobots/dbbasic-rss"
    },
    "split_keywords": [
        "rss",
        " feed",
        " atom",
        " xml",
        " dbbasic",
        " blog",
        " podcast",
        " syndication"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b9c4335aa9ee10641b5cdff32cf8f50d2a7d614ce9b4284250bf706886a9549d",
                "md5": "193b7a57b854a0cde5701fe6df6a4f8c",
                "sha256": "5017b3f3774da5e35887b86a2c6ddf4080a9f2cc6acef7426d9e625a4b613a26"
            },
            "downloads": -1,
            "filename": "dbbasic_rss-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "193b7a57b854a0cde5701fe6df6a4f8c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 13299,
            "upload_time": "2025-10-19T23:46:30",
            "upload_time_iso_8601": "2025-10-19T23:46:30.834759Z",
            "url": "https://files.pythonhosted.org/packages/b9/c4/335aa9ee10641b5cdff32cf8f50d2a7d614ce9b4284250bf706886a9549d/dbbasic_rss-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5d685a4669c7e7e291d29ffb8cecee66833fa9db2afa7e0ff9aeb117410b02b1",
                "md5": "4dceb5388adcdee60ac92addc2c63d5b",
                "sha256": "4bfd121c55466ca6d1d66053c76ac3b1339b4d66ce18a854d005ef9d19c9da15"
            },
            "downloads": -1,
            "filename": "dbbasic_rss-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "4dceb5388adcdee60ac92addc2c63d5b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 17853,
            "upload_time": "2025-10-19T23:46:32",
            "upload_time_iso_8601": "2025-10-19T23:46:32.255549Z",
            "url": "https://files.pythonhosted.org/packages/5d/68/5a4669c7e7e291d29ffb8cecee66833fa9db2afa7e0ff9aeb117410b02b1/dbbasic_rss-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-19 23:46:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "askrobots",
    "github_project": "dbbasic-rss#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "dbbasic-rss"
}
        
Elapsed time: 1.55929s