Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up a number of small issues and improve error checking #205

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion xword_dl/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .xword_dl import *

34 changes: 15 additions & 19 deletions xword_dl/downloader/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import glob
import importlib
import inspect
import os
import sys
import pkgutil
from typing import Type

# This code runs through the modules in its directory and imports the ones
# that end in .py (but that aren't __init__.py). It then adds any classes
# from those modules to its own namespace.
from .basedownloader import BaseDownloader as __bd

modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))
modules = [os.path.basename(f)[:-3] for f in modules if os.path.isfile(f) and not f.endswith('__init__.py')]
def __get_subclasses[T](cls: Type[T]) -> list[Type[T]]:
"""Recursively returns a list of subclasses of `cls` in imported namespaces."""
return [cls] + [
r_cls
for s_cls in cls.__subclasses__()
for r_cls in __get_subclasses(s_cls)
]

for mod in modules:
mdl = importlib.import_module('.' + mod, package=__name__)
if '__all__' in mdl.__dict__:
names = mdl.__dict__['__all__']
else:
names = [x for x in mdl.__dict__ if not x.startswith('_')
and inspect.isclass(mdl.__dict__[x])]

globals().update({k: getattr(mdl, k) for k in names})
globals().pop(mod)
def get_plugins():
"""Returns all plugins available in the downloader package."""
for _, mod, _ in pkgutil.walk_packages(__path__):
importlib.import_module(f".{mod}", package=__name__)
return __get_subclasses(__bd)
27 changes: 14 additions & 13 deletions xword_dl/downloader/amuniversaldownloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import json
import sys
import time
import urllib
import xml

import puz
Expand All @@ -20,6 +19,9 @@ def __init__(self, **kwargs):
self.url_blob = None

def find_by_date(self, dt):
if self.url_blob is None:
raise XWordDLException("Blob URL was not set by AMUniversal subclass.")

self.date = dt

url_format = dt.strftime('%Y-%m-%d')
Expand Down Expand Up @@ -53,22 +55,21 @@ def process_clues(self, clue_list):

return clue_list

def parse_xword(self, xword_data):
def parse_xword(self, xw_data):
fetched = {}
for field in ['Title', 'Author', 'Editor', 'Copryight']:
fetched[field] = urllib.parse.unquote(
xword_data.get(field, '')).strip()
fetched[field] = unquote(xw_data.get(field, '')).strip()

puzzle = puz.Puzzle()
puzzle.title = fetched.get('Title', '')
puzzle.author = ''.join([fetched.get('Author', ''),
' / Ed. ',
fetched.get('Editor', '')])
puzzle.copyright = fetched.get('Copyright', '')
puzzle.width = int(xword_data.get('Width'))
puzzle.height = int(xword_data.get('Height'))
puzzle.width = int(xw_data.get('Width'))
puzzle.height = int(xw_data.get('Height'))

solution = xword_data.get('AllAnswer').replace('-', '.')
solution = xw_data.get('AllAnswer').replace('-', '.')

puzzle.solution = solution

Expand All @@ -80,8 +81,8 @@ def parse_xword(self, xword_data):
fill += '-'
puzzle.fill = fill

across_clues = xword_data['AcrossClue'].splitlines()
down_clues = self.process_clues(xword_data['DownClue'].splitlines())
across_clues = xw_data['AcrossClue'].splitlines()
down_clues = self.process_clues(xw_data['DownClue'].splitlines())

clues_list = across_clues + down_clues

Expand Down Expand Up @@ -130,7 +131,7 @@ def find_by_date(self, dt):
try:
res = requests.head(url)
res.raise_for_status()
except:
except requests.HTTPError:
raise XWordDLException('Unable to find puzzle for date provided.')

return url
Expand Down Expand Up @@ -160,10 +161,10 @@ def fetch_data(self, solver_url):

return xw_data

def parse_xword(self, xword_data):
def parse_xword(self, xw_data):
try:
xw = xmltodict.parse(xword_data).get('crossword')
except xml.parsers.expat.ExpatError:
xw = xmltodict.parse(xw_data)['crossword']
except (xml.parsers.expat.ExpatError, KeyError):
raise XWordDLException('Puzzle data malformed, cannot parse.')

puzzle = puz.Puzzle()
Expand Down
Loading
Loading