mirror of
https://github.com/kemayo/leech
synced 2025-12-06 16:33:16 +01:00
Use the newer syntax for attrs
This commit is contained in:
parent
d6d23e4c60
commit
a39e1e9f89
3 changed files with 56 additions and 60 deletions
|
|
@ -8,7 +8,7 @@ import html
|
|||
import unicodedata
|
||||
import datetime
|
||||
import requests
|
||||
import attr
|
||||
from attrs import define, asdict
|
||||
|
||||
html_template = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
|
||||
|
|
@ -66,17 +66,16 @@ frontmatter_template = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|||
'''
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class CoverOptions:
|
||||
fontname = attr.ib(default=None, converter=attr.converters.optional(str))
|
||||
fontsize = attr.ib(default=None, converter=attr.converters.optional(int))
|
||||
width = attr.ib(default=None, converter=attr.converters.optional(int))
|
||||
height = attr.ib(default=None, converter=attr.converters.optional(int))
|
||||
wrapat = attr.ib(default=None, converter=attr.converters.optional(int))
|
||||
bgcolor = attr.ib(default=None, converter=attr.converters.optional(tuple))
|
||||
textcolor = attr.ib(
|
||||
default=None, converter=attr.converters.optional(tuple))
|
||||
cover_url = attr.ib(default=None, converter=attr.converters.optional(str))
|
||||
fontname: str = None
|
||||
fontsize: int = None
|
||||
width: int = None
|
||||
height: int = None
|
||||
wrapat: int = None
|
||||
bgcolor: tuple = None
|
||||
textcolor: tuple = None
|
||||
cover_url: str = None
|
||||
|
||||
|
||||
def chapter_html(
|
||||
|
|
@ -187,8 +186,7 @@ def generate_epub(story, cover_options={}, image_options=None, output_filename=
|
|||
'height', 'wrapat', 'bgcolor', 'textcolor', 'cover_url')
|
||||
cover_options = CoverOptions(
|
||||
**{k: v for k, v in cover_options.items() if k in valid_cover_options})
|
||||
cover_options = attr.asdict(
|
||||
cover_options, filter=lambda k, v: v is not None, retain_collection_types=True)
|
||||
cover_options = asdict(cover_options, filter=lambda k, v: v is not None)
|
||||
|
||||
if cover_options and "cover_url" in cover_options:
|
||||
image = make_cover_from_url(
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import glob
|
|||
import os
|
||||
import random
|
||||
import uuid
|
||||
import datetime
|
||||
import time
|
||||
import logging
|
||||
import urllib
|
||||
import re
|
||||
import attr
|
||||
from attrs import define, field, Factory
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -21,32 +22,32 @@ def _default_uuid_string(self):
|
|||
return str(uuid.UUID(int=rd.getrandbits(8*16), version=4))
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class Image:
|
||||
path = attr.ib()
|
||||
contents = attr.ib()
|
||||
content_type = attr.ib()
|
||||
path: str
|
||||
contents: str
|
||||
content_type: str
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class Chapter:
|
||||
title = attr.ib()
|
||||
contents = attr.ib()
|
||||
date = attr.ib(default=False)
|
||||
images = attr.ib(default=attr.Factory(list))
|
||||
title: str
|
||||
contents: str
|
||||
date: datetime.datetime = False
|
||||
images: list = Factory(list)
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class Section:
|
||||
title = attr.ib()
|
||||
author = attr.ib()
|
||||
url = attr.ib()
|
||||
cover_url = attr.ib(default='')
|
||||
id = attr.ib(default=attr.Factory(_default_uuid_string, takes_self=True), converter=str)
|
||||
contents = attr.ib(default=attr.Factory(list))
|
||||
footnotes = attr.ib(default=attr.Factory(list))
|
||||
tags = attr.ib(default=attr.Factory(list))
|
||||
summary = attr.ib(default='')
|
||||
title: str
|
||||
author: str
|
||||
url: str
|
||||
cover_url: str = ''
|
||||
id: str = Factory(_default_uuid_string, takes_self=True)
|
||||
contents: list = Factory(list)
|
||||
footnotes: list = Factory(list)
|
||||
tags: list = Factory(list)
|
||||
summary: str = ''
|
||||
|
||||
def __iter__(self):
|
||||
return self.contents.__iter__()
|
||||
|
|
@ -74,17 +75,17 @@ class Section:
|
|||
yield chapter.date
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class Site:
|
||||
"""A Site handles checking whether a URL might represent a site, and then
|
||||
extracting the content of a story from said site.
|
||||
"""
|
||||
session = attr.ib()
|
||||
footnotes = attr.ib(factory=list, init=False)
|
||||
options = attr.ib(default=attr.Factory(
|
||||
session: object = field()
|
||||
footnotes: list = field(factory=list, init=False)
|
||||
options: dict = Factory(
|
||||
lambda site: site.get_default_options(),
|
||||
True
|
||||
))
|
||||
takes_self=True
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def site_key(cls):
|
||||
|
|
@ -288,17 +289,17 @@ class Site:
|
|||
return contents
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
@define(unsafe_hash=True, frozen=True)
|
||||
class SiteSpecificOption:
|
||||
"""Represents a site-specific option that can be configured.
|
||||
|
||||
Will be added to the CLI as a click.option -- many of these
|
||||
fields correspond to click.option arguments."""
|
||||
name = attr.ib()
|
||||
flag_pattern = attr.ib()
|
||||
type = attr.ib(default=None)
|
||||
help = attr.ib(default=None)
|
||||
default = attr.ib(default=None)
|
||||
name: str
|
||||
flag_pattern: str
|
||||
type: object = None
|
||||
default: bool = False
|
||||
help: str = None
|
||||
|
||||
def as_click_option(self):
|
||||
return click.option(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import logging
|
||||
import attr
|
||||
from attrs import define
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
|
|
@ -24,26 +24,23 @@ Example JSON:
|
|||
"""
|
||||
|
||||
|
||||
@attr.s
|
||||
@define
|
||||
class SiteDefinition:
|
||||
url = attr.ib()
|
||||
title = attr.ib()
|
||||
author = attr.ib()
|
||||
content_selector = attr.ib()
|
||||
url: str
|
||||
title: str
|
||||
author: str
|
||||
content_selector: str
|
||||
# If present, find something within `content` to use a chapter title; if not found, the link text to it will be used
|
||||
content_title_selector = attr.ib(default=False)
|
||||
content_title_selector: str = False
|
||||
# If present, find a specific element in the `content` to be the chapter text
|
||||
content_text_selector = attr.ib(default=False)
|
||||
content_text_selector: str = False
|
||||
# If present, it looks for chapters linked from `url`. If not, it assumes `url` points to a chapter.
|
||||
chapter_selector = attr.ib(default=False)
|
||||
chapter_selector: str = False
|
||||
# If present, use to find a link to the next content page (only used if not using chapter_selector)
|
||||
next_selector = attr.ib(default=False)
|
||||
next_selector: str = False
|
||||
# If present, use to filter out content that matches the selector
|
||||
filter_selector = attr.ib(default=False)
|
||||
cover_url = attr.ib(default='')
|
||||
|
||||
# If present, use to also download the images and embed them into the epub.
|
||||
image_selector = attr.ib(default=False)
|
||||
filter_selector: str = False
|
||||
cover_url: str = ''
|
||||
|
||||
|
||||
@register
|
||||
|
|
|
|||
Loading…
Reference in a new issue