mirror of
https://github.com/bspeice/elektricity
synced 2024-12-21 15:38:11 -05:00
Refactoring work to make this a real program
This commit is contained in:
parent
5853c86a2d
commit
fcc280b96c
@ -13,23 +13,7 @@
|
|||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="Python 3.5.1 (C:\Users\Bradlee Speice\Anaconda3\python.exe)" project-jdk-type="Python SDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="Python 3.5.1 (C:\Users\Bradlee Speice\Anaconda3\python.exe)" project-jdk-type="Python SDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
<component name="masterDetails">
|
|
||||||
<states>
|
|
||||||
<state key="ProjectJDKs.UI">
|
|
||||||
<settings>
|
|
||||||
<last-edited>Python 3.5.1 (C:\Users\Bradlee Speice\Anaconda3\python.exe)</last-edited>
|
|
||||||
<splitter-proportions>
|
|
||||||
<option name="proportions">
|
|
||||||
<list>
|
|
||||||
<option value="0.2" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</splitter-proportions>
|
|
||||||
</settings>
|
|
||||||
</state>
|
|
||||||
</states>
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
@ -1,12 +1,15 @@
|
|||||||
# Format: (all args are passed to __init__ as kwargs
|
# Format (all args are passed to __init__ as kwargs:
|
||||||
#
|
#
|
||||||
# <mountpoint>:
|
# <mountpoint>:
|
||||||
# class: <feed_class>
|
# class: <feed_class>
|
||||||
# args:
|
# args:
|
||||||
# key: value
|
# key: value
|
||||||
subfactory-show:
|
server:
|
||||||
package: bassdrive
|
port: 10000
|
||||||
class: BassdriveFeed
|
|
||||||
args:
|
podcasts:
|
||||||
url: http://archives.bassdrivearchive.com/1%20-%20Monday/Subfactory%20Show%20-%20DJ%20Spim/
|
subfactory-show:
|
||||||
logo: http://www.bassdrive.com/img/radio_schedule_entries/image/original/subfactory-web-add-56.jpg
|
class: podcasters.BassdriveFeed
|
||||||
|
args:
|
||||||
|
url: http://archives.bassdrivearchive.com/1%20-%20Monday/Subfactory%20Show%20-%20DJ%20Spim/
|
||||||
|
logo: http://www.bassdrive.com/img/radio_schedule_entries/image/original/subfactory-web-add-56.jpg
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
"""
|
|
||||||
Given a configuration file, set up everything needed to kick
|
|
||||||
off the server.
|
|
||||||
"""
|
|
||||||
from importlib import import_module
|
|
||||||
import yaml
|
|
||||||
from pyramid.config import Configurator
|
|
||||||
from os.path import expanduser, join
|
|
||||||
|
|
||||||
# Needed for import_module call
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import modules
|
|
||||||
|
|
||||||
|
|
||||||
def build_configuration(conf=None) -> Configurator:
|
|
||||||
if conf is None:
|
|
||||||
conf = join(expanduser('~'), '.repodrc')
|
|
||||||
|
|
||||||
with open(conf) as conf_file:
|
|
||||||
conf_dict = yaml.load(conf_file)
|
|
||||||
server_conf = Configurator()
|
|
||||||
for mountpoint, feed in conf_dict.items():
|
|
||||||
feed_package = import_module('modules.' + feed['package'])
|
|
||||||
feed_class = getattr(feed_package, feed['class'])
|
|
||||||
feed_instance = feed_class(**feed['args'])
|
|
||||||
|
|
||||||
server_conf.add_route(mountpoint, '/' + mountpoint + '/')
|
|
||||||
server_conf.add_view(feed_instance.view, route_name=mountpoint)
|
|
||||||
|
|
||||||
return server_conf
|
|
@ -1,10 +0,0 @@
|
|||||||
from wsgiref.simple_server import make_server
|
|
||||||
from conf_parser import build_configuration
|
|
||||||
|
|
||||||
def start_server():
|
|
||||||
app = build_configuration().make_wsgi_app()
|
|
||||||
server = make_server('0.0.0.0', 8080, app)
|
|
||||||
server.serve_forever()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
start_server()
|
|
38
src/conf_parser.py
Normal file
38
src/conf_parser.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""
|
||||||
|
Given a configuration file, set up everything needed to kick
|
||||||
|
off the server.
|
||||||
|
"""
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from pyramid.config import Configurator
|
||||||
|
|
||||||
|
|
||||||
|
def build_configurator(podcasts: dict) -> Configurator:
|
||||||
|
server_conf = Configurator()
|
||||||
|
for mountpoint, feed in podcasts:
|
||||||
|
package, class_name = feed['class'].rsplit('.', 1)
|
||||||
|
feed_package = import_module(package)
|
||||||
|
feed_class = getattr(feed_package, class_name)
|
||||||
|
feed_instance = feed_class(**feed['args'])
|
||||||
|
|
||||||
|
server_conf.add_route(mountpoint, '/' + mountpoint + '/')
|
||||||
|
server_conf.add_view(feed_instance.view, route_name=mountpoint)
|
||||||
|
|
||||||
|
|
||||||
|
def build_configuration_text(file_str: str) -> (dict, Configurator):
|
||||||
|
conf_dict = yaml.load(file_str)
|
||||||
|
|
||||||
|
server_opts = conf_dict.get('server', None)
|
||||||
|
podcasts = build_configurator(conf_dict['podcasts'])
|
||||||
|
return server_opts, podcasts
|
||||||
|
|
||||||
|
|
||||||
|
def build_configuration(file_name) -> (dict, Configurator):
|
||||||
|
try:
|
||||||
|
with open(file_name) as conf_file:
|
||||||
|
return build_configuration_text(conf_file.read())
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("Could not locate configuration file " +
|
||||||
|
"(does {} exist?)".format(file_name))
|
||||||
|
raise
|
@ -11,6 +11,7 @@ class BasePodcast():
|
|||||||
"Return a list of all episodes, in descending date order"
|
"Return a list of all episodes, in descending date order"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
def view(self, request):
|
def view(self, request):
|
||||||
fg = self.build_feed()
|
fg = self.build_feed()
|
||||||
response = Response(fg.rss_str(pretty=True))
|
response = Response(fg.rss_str(pretty=True))
|
@ -1,22 +1,26 @@
|
|||||||
"""
|
"""
|
||||||
Podcast provider for the Bassdrive Archives
|
Podcast provider for the Bassdrive Archives
|
||||||
"""
|
"""
|
||||||
|
from datetime import datetime
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from feedgen.feed import FeedGenerator
|
from feedgen.feed import FeedGenerator
|
||||||
|
|
||||||
from podcast import BasePodcast
|
|
||||||
from datetime import datetime
|
|
||||||
from pytz import UTC
|
from pytz import UTC
|
||||||
|
|
||||||
|
from podcasters.base import BasePodcast
|
||||||
|
|
||||||
|
|
||||||
class BassdriveParser(HTMLParser):
|
class BassdriveParser(HTMLParser):
|
||||||
|
def error(self, message):
|
||||||
|
return super().error(message)
|
||||||
|
|
||||||
record_link_text = False
|
record_link_text = False
|
||||||
link_url = ''
|
link_url = ''
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
# noinspection PyArgumentList
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.links = []
|
self.links = []
|
||||||
|
|
||||||
@ -62,7 +66,6 @@ class BassdriveFeed(BasePodcast):
|
|||||||
|
|
||||||
# And turn them into something usable
|
# And turn them into something usable
|
||||||
fg = FeedGenerator()
|
fg = FeedGenerator()
|
||||||
#fg.load_extension('podcast')
|
|
||||||
fg.id(self.url)
|
fg.id(self.url)
|
||||||
fg.title(self.title)
|
fg.title(self.title)
|
||||||
fg.description(self.title)
|
fg.description(self.title)
|
||||||
@ -79,8 +82,8 @@ class BassdriveFeed(BasePodcast):
|
|||||||
fe.enclosure(self.url + link[1], 0, 'audio/mpeg')
|
fe.enclosure(self.url + link[1], 0, 'audio/mpeg')
|
||||||
|
|
||||||
# Bassdrive always uses date strings of
|
# Bassdrive always uses date strings of
|
||||||
# [yyyy.mm.dd] with 0 padding, so that
|
# [yyyy.mm.dd] with 0 padding on days and months,
|
||||||
# makes our lives easy
|
# so that makes our lives easy
|
||||||
date_start = link[0].find('[')
|
date_start = link[0].find('[')
|
||||||
date_str = link[0][date_start:date_start+12]
|
date_str = link[0][date_start:date_start+12]
|
||||||
published = datetime.strptime(date_str, '[%Y.%m.%d]')
|
published = datetime.strptime(date_str, '[%Y.%m.%d]')
|
38
src/server.py
Normal file
38
src/server.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import argparse
|
||||||
|
from wsgiref.simple_server import make_server
|
||||||
|
from conf_parser import build_configuration
|
||||||
|
from os.path import expanduser, join
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
def start_server(cmd_args: dict):
|
||||||
|
try:
|
||||||
|
server_conf, configurator = build_configuration(cmd_args.configuration)
|
||||||
|
app = configurator.make_wsgi_app()
|
||||||
|
server = make_server(cmd_args.host, cmd_args.port, app)
|
||||||
|
|
||||||
|
server.serve_forever()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("Unable to find configuration file. Does {} exist?"
|
||||||
|
.format(cmd_args.configuration))
|
||||||
|
except AttributeError:
|
||||||
|
print("Unable to parse configuration file. Is {} a valid YML file?"
|
||||||
|
.format(cmd_args.configuration))
|
||||||
|
except KeyError:
|
||||||
|
print('Unable to parse configuration file. Is there a `podcasts`'
|
||||||
|
'section?')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
default_rc = join(expanduser('~'), '.repodrc')
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--verbose', help='Run server in verbose mode')
|
||||||
|
parser.add_argument('--port', type=int, default=10000,
|
||||||
|
help='Port to use when starting the server')
|
||||||
|
parser.add_argument('--host', type=str, default='0.0.0.0',
|
||||||
|
help='Host address to start the server')
|
||||||
|
parser.add_argument('--configuration', type=str, default=default_rc,
|
||||||
|
help='Configuration file to start the server')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
start_server(args)
|
0
src/tests/__init__.py
Normal file
0
src/tests/__init__.py
Normal file
12
src/tests/test_build_configurator.py
Normal file
12
src/tests/test_build_configurator.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
import conf_parser
|
||||||
|
|
||||||
|
|
||||||
|
class TestBuild_configurator(TestCase):
|
||||||
|
def test_build_configurator(self):
|
||||||
|
try:
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
conf_parser.build_configurator(None)
|
||||||
|
self.fail("Must have dictionary to set up configurator")
|
||||||
|
except TypeError:
|
||||||
|
pass
|
Loading…
Reference in New Issue
Block a user