diff --git a/plex-posters/README.rst b/plex-posters/README.rst
index 61ef802..1ba9e66 100644
--- a/plex-posters/README.rst
+++ b/plex-posters/README.rst
@@ -1,3 +1,4 @@
-# plex_posters
+plex_posters
+============
A script to pull the top 10 hottest posters from /r/moviepostersporn
diff --git a/plex-posters/__dev/sphinx.txt b/plex-posters/__dev/sphinx.txt
new file mode 100644
index 0000000..09763b7
--- /dev/null
+++ b/plex-posters/__dev/sphinx.txt
@@ -0,0 +1,160 @@
+poetry add --dev sphinx
+poetry add --dev sphinx_rtd_theme
+
+
+Numpy docstrings: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
+
+
+Parameters - passed to the __init__
+
+Attributes - anything set in the class (e.g self.value is an attribute)
+
+Arguments - anything passed to a method
+
+
+References:
+
+reference classes in docstrings with
+:class:`~module.submodule.Class`
+
+ (one of "module", "class", "exception", "function", "method", "attribute") ?
+
+:py:mod:
+ Reference a module; a dotted name may be used. This should also be used for package names.
+:py:func:
+ Reference a Python function; dotted names may be used. The role text needs not include trailing parentheses to enhance readability; they will be added automatically by Sphinx if the add_function_parentheses config value is True (the default).
+:py:data:
+ Reference a module-level variable.
+:py:const:
+ Reference a “defined” constant. This may be a Python variable that is not intended to be changed.
+:py:class:
+ Reference a class; a dotted name may be used.
+:py:meth:
+ Reference a method of an object. The role text can include the type name and the method name; if it occurs within the description of a type, the type name can be omitted. A dotted name may be used.
+:py:attr:
+ Reference a data attribute of an object.
+:py:exc:
+ Reference an exception. A dotted name may be used.
+:py:obj:
+ Reference an object of unspecified type. Useful e.g. as the default_role.
+
+
+
+Misc
+ .. seealso:: blabla
+ .. warnings also:: blabla
+ .. note:: blabla
+ .. todo:: blabla
+
+
+
+sphinx-quickstart
+sphinx-apidoc -o source ../src/plex_posters
+
+sphinx-apidoc --ext-autodoc --separate --module-first -o source/modules ../src/plex_posters
+
+
+ls -l | awk '{print $7}'
+
+to get a list to add to toc
+
+
+Replace
+
+plex\_posters.config.config module
+==================================
+
+with
+
+.. include:: ../global.rst
+
+Config :modname:`plex_posters.config`
+------------------------------------
+
+for each rst in the /modules dir to set the formatting and title properly
+
+
+
+Handling the toctree with submodules:
+
+If you want the submodules link to appear in the toctree:
+
+1. module with a submodules as the main:
+
+Your toctree should just contain a link to the base module, all the submodules will automatially be filled under the submodule header:
+
+toc.rst:
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Overview
+ :titlesonly:
+
+ introduction
+ configuration
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Modules
+ :titlesonly:
+
+ modules/plex_posters.rst
+
+
+all other submodules should include the submodules and toctree as normal
+
+eg. config.rst:
+.. include:: ../global.rst
+
+Config :modname:`plex_posters.config`
+-------------------------------------------
+
+.. automodule:: plex_posters.config
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+
+ plex_posters.config.config
+
+
+2. If you dont want the submodule layout, and would rather link to each submodule directly
+
+Remove the
+
+
+Submodules
+----------
+
+.. toctree::
+
+ plex_posters.config.config
+
+from each of the module *rst files. Including the main module.
+
+Refer to each module you want referenced in the toc.rst explicitly
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Overview
+ :titlesonly:
+
+ introduction
+ configuration
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Modules
+ :titlesonly:
+
+ modules/plex_posters.rst
+ modules/plex_posters.config.config.rst
+ modules/plex_posters.lib.rst
+
+
+
+
diff --git a/plex-posters/docs/Makefile b/plex-posters/docs/Makefile
new file mode 100644
index 0000000..d0c3cbf
--- /dev/null
+++ b/plex-posters/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/plex-posters/docs/make.bat b/plex-posters/docs/make.bat
new file mode 100644
index 0000000..6247f7e
--- /dev/null
+++ b/plex-posters/docs/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/plex-posters/docs/plex_posters/index.html b/plex-posters/docs/plex_posters/index.html
deleted file mode 100644
index 810c9c7..0000000
--- a/plex-posters/docs/plex_posters/index.html
+++ /dev/null
@@ -1,373 +0,0 @@
-
-
-
-
-
-
-plex_posters API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Expand source code
-
-from __future__ import annotations
-from .__version__ import __version__
-from .lib import export
-from typing import Type, TypeVar
-import praw
-import requests
-
-__all__ = []
-
-T_movie_poster_porn_scraper = TypeVar(
- 'T_movie_poster_porn_scraper', bound="movie_poster_porn_scraper"
-)
-
-
-@export
-class movie_poster_porn_scraper(object):
-
- """Poster scraper
-
- Attributes
- ----------
- reddit_instance : praw.Reddit
- A praw instance connected to Reddit
- """
-
- def __init__(self, instance: praw.Reddit) -> None:
- """
- Parameters
- ----------
- instance : praw.Reddit
- A praw instance connected to Reddit
- """
- super().__init__()
- self.reddit_instance = instance
-
- @classmethod
- def create_instance(
- cls: Type(T_movie_poster_porn_scraper),
- client_id: str,
- client_secret: str,
- user_agent: str,
- ) -> T_movie_poster_porn_scraper:
- """Connect to reddit
-
- Parameters
- ----------
- client_id : str
- a valid client id
- client_secret : str
- the secret key for the client
- user_agent : str
- a user agent
- """
- reddit_instance = praw.Reddit(
- client_id=client_id,
- client_secret=client_secret,
- user_agent=user_agent,
- )
-
- return cls(reddit_instance)
-
- def get_hot_posters(
- self: T_movie_poster_porn_scraper,
- ) -> T_movie_poster_porn_scraper:
- """
- """
- self._poster_urls = {}
- for post in self.reddit_instance.subreddit('MoviePosterPorn').hot(
- limit=10
- ):
- print(post.title)
- print(post.url)
- # print(dir(post))
- # self._poster_urls.append(post.url)
- self._poster_urls[post.title] = post.url
- print(self._poster_urls)
- return self
-
- def get_posters(self: T_movie_poster_porn_scraper):
- """download the posters
-
- Returns
- -------
- self
- """
- for title, url in self._poster_urls.items():
- r = requests.get(url)
- with open('posters/' + title + '.jpg', 'wb') as p:
- p.write(r.content)
- return self
-
-
-
-
-
-
-
-
-
-class movie_poster_porn_scraper
-( instance)
-
-
-Poster scraper
-Attributes
-
-reddit_instance : praw.Reddit
-A praw instance connected to Reddit
-
-Parameters
-
-instance : praw.Reddit
-A praw instance connected to Reddit
-
-
-
-Expand source code
-
-class movie_poster_porn_scraper(object):
-
- """Poster scraper
-
- Attributes
- ----------
- reddit_instance : praw.Reddit
- A praw instance connected to Reddit
- """
-
- def __init__(self, instance: praw.Reddit) -> None:
- """
- Parameters
- ----------
- instance : praw.Reddit
- A praw instance connected to Reddit
- """
- super().__init__()
- self.reddit_instance = instance
-
- @classmethod
- def create_instance(
- cls: Type(T_movie_poster_porn_scraper),
- client_id: str,
- client_secret: str,
- user_agent: str,
- ) -> T_movie_poster_porn_scraper:
- """Connect to reddit
-
- Parameters
- ----------
- client_id : str
- a valid client id
- client_secret : str
- the secret key for the client
- user_agent : str
- a user agent
- """
- reddit_instance = praw.Reddit(
- client_id=client_id,
- client_secret=client_secret,
- user_agent=user_agent,
- )
-
- return cls(reddit_instance)
-
- def get_hot_posters(
- self: T_movie_poster_porn_scraper,
- ) -> T_movie_poster_porn_scraper:
- """
- """
- self._poster_urls = {}
- for post in self.reddit_instance.subreddit('MoviePosterPorn').hot(
- limit=10
- ):
- print(post.title)
- print(post.url)
- # print(dir(post))
- # self._poster_urls.append(post.url)
- self._poster_urls[post.title] = post.url
- print(self._poster_urls)
- return self
-
- def get_posters(self: T_movie_poster_porn_scraper):
- """download the posters
-
- Returns
- -------
- self
- """
- for title, url in self._poster_urls.items():
- r = requests.get(url)
- with open('posters/' + title + '.jpg', 'wb') as p:
- p.write(r.content)
- return self
-
-Static methods
-
-
-def create_instance (client_id, client_secret, user_agent)
-
-
-Connect to reddit
-Parameters
-
-client_id : str
-a valid client id
-client_secret : str
-the secret key for the client
-user_agent : str
-a user agent
-
-
-
-Expand source code
-
-@classmethod
-def create_instance(
- cls: Type(T_movie_poster_porn_scraper),
- client_id: str,
- client_secret: str,
- user_agent: str,
-) -> T_movie_poster_porn_scraper:
- """Connect to reddit
-
- Parameters
- ----------
- client_id : str
- a valid client id
- client_secret : str
- the secret key for the client
- user_agent : str
- a user agent
- """
- reddit_instance = praw.Reddit(
- client_id=client_id,
- client_secret=client_secret,
- user_agent=user_agent,
- )
-
- return cls(reddit_instance)
-
-
-
-Methods
-
-
-def get_hot_posters (self)
-
-
-
-
-
-Expand source code
-
-def get_hot_posters(
- self: T_movie_poster_porn_scraper,
-) -> T_movie_poster_porn_scraper:
- """
- """
- self._poster_urls = {}
- for post in self.reddit_instance.subreddit('MoviePosterPorn').hot(
- limit=10
- ):
- print(post.title)
- print(post.url)
- # print(dir(post))
- # self._poster_urls.append(post.url)
- self._poster_urls[post.title] = post.url
- print(self._poster_urls)
- return self
-
-
-
-def get_posters (self)
-
-
-download the posters
-Returns
-
-self
-
-
-
-
-Expand source code
-
-def get_posters(self: T_movie_poster_porn_scraper):
- """download the posters
-
- Returns
- -------
- self
- """
- for title, url in self._poster_urls.items():
- r = requests.get(url)
- with open('posters/' + title + '.jpg', 'wb') as p:
- p.write(r.content)
- return self
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/plex-posters/docs/plex_posters/lib/index.html b/plex-posters/docs/plex_posters/lib/index.html
deleted file mode 100644
index ef5f3ce..0000000
--- a/plex-posters/docs/plex_posters/lib/index.html
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-plex_posters.lib API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-Module plex_posters.lib
-
-
-
-
-Expand source code
-
-import sys
-
-
-def export(fn):
- mod = sys.modules[fn.__module__]
- if hasattr(mod, '__all__'):
- mod.__all__.append(fn.__name__)
- else:
- mod.__all__ = [fn.__name__]
- return fn
-
-
-
-
-
-
-
-
-def export (fn)
-
-
-
-
-
-Expand source code
-
-def export(fn):
- mod = sys.modules[fn.__module__]
- if hasattr(mod, '__all__'):
- mod.__all__.append(fn.__name__)
- else:
- mod.__all__ = [fn.__name__]
- return fn
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/plex-posters/docs/source/_static/custom.css b/plex-posters/docs/source/_static/custom.css
new file mode 100644
index 0000000..a4c3e5d
--- /dev/null
+++ b/plex-posters/docs/source/_static/custom.css
@@ -0,0 +1,31 @@
+@import url("css/theme.css");
+
+.modname {
+ font-size: 0.8em;
+ opacity: 0.4;
+}
+.modname::before {
+ content: '- ';
+}
+.title {
+ font-weight: bold;
+ font-size: 1.2em;
+ background-color: #eee;
+ display: block;
+ padding: 1px 5px;
+ border-left: 2px solid #ddd;
+}
+
+.wy-menu-vertical header, .wy-menu-vertical p.caption{
+ color: ##466A54;;
+}
+
+.wy-side-nav-search{
+ background-color: #0E6458;
+}
+
+.rst-content dl:not(.docutils) dt{
+ background: #F2E7D3;
+ color: #499265;
+ border-top: solid 3px #87CB7C;
+}
diff --git a/plex-posters/docs/source/changelog.rst b/plex-posters/docs/source/changelog.rst
new file mode 100644
index 0000000..1f38ff8
--- /dev/null
+++ b/plex-posters/docs/source/changelog.rst
@@ -0,0 +1,7 @@
+Version history
+================
+
+0.1.0 (28/11/19)
+----------------
+
+- Initial release.
diff --git a/plex-posters/docs/source/conf.py b/plex-posters/docs/source/conf.py
new file mode 100644
index 0000000..bf59060
--- /dev/null
+++ b/plex-posters/docs/source/conf.py
@@ -0,0 +1,94 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+import plex_posters
+from plex_posters.__version__ import __version__ as version
+import sphinx_rtd_theme
+
+# -- Project information -----------------------------------------------------
+
+project = 'plex_posters'
+copyright = '2019, Daniel Tomlinson'
+author = 'Daniel Tomlinson'
+
+# The full version, including alpha/beta/rc tags
+release = version
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.viewcode',
+ 'sphinx.ext.napoleon',
+ 'sphinx.ext.todo',
+]
+
+# -- Napoleon Settings -----------------------------------------------------
+napoleon_google_docstring = False
+napoleon_numpy_docstring = True
+napoleon_include_init_with_doc = True
+napoleon_include_private_with_doc = False
+napoleon_include_special_with_doc = False
+napoleon_use_admonition_for_examples = False
+napoleon_use_admonition_for_notes = False
+napoleon_use_admonition_for_references = False
+napoleon_use_ivar = True
+napoleon_use_param = True
+napoleon_use_rtype = True
+napoleon_use_keyword = True
+autodoc_member_order = 'bysource'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The master toctree document.
+master_doc = 'index'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = "sphinx_rtd_theme"
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+
+html_theme = "sphinx_rtd_theme"
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_static_path = ['_static']
+html_context = {'css_files': ['_static/custom.css']}
+html_theme_options = {
+ 'collapse_navigation': True,
+ 'display_version': True,
+ #'navigation_depth': 3,
+}
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# Enable todo
+todo_include_todos = True
diff --git a/plex-posters/docs/source/configuration.rst b/plex-posters/docs/source/configuration.rst
new file mode 100644
index 0000000..972dd83
--- /dev/null
+++ b/plex-posters/docs/source/configuration.rst
@@ -0,0 +1,4 @@
+Configuration
+=============
+
+.. todo:: fill in configuration options
diff --git a/plex-posters/docs/source/global.rst b/plex-posters/docs/source/global.rst
new file mode 100644
index 0000000..b117004
--- /dev/null
+++ b/plex-posters/docs/source/global.rst
@@ -0,0 +1,5 @@
+.. role:: modname
+ :class: modname
+
+.. role:: title
+ :class: title
diff --git a/plex-posters/docs/source/index.rst b/plex-posters/docs/source/index.rst
new file mode 100644
index 0000000..176e544
--- /dev/null
+++ b/plex-posters/docs/source/index.rst
@@ -0,0 +1,3 @@
+Table of Contents
+=================
+.. include:: toc.rst
diff --git a/plex-posters/docs/source/introduction.rst b/plex-posters/docs/source/introduction.rst
new file mode 100644
index 0000000..a6210d3
--- /dev/null
+++ b/plex-posters/docs/source/introduction.rst
@@ -0,0 +1 @@
+.. include:: ../../README.rst
diff --git a/plex-posters/docs/source/modules/modules.rst b/plex-posters/docs/source/modules/modules.rst
new file mode 100644
index 0000000..29b37f1
--- /dev/null
+++ b/plex-posters/docs/source/modules/modules.rst
@@ -0,0 +1,7 @@
+plex_posters
+============
+
+.. toctree::
+ :maxdepth: 4
+
+ plex_posters
diff --git a/plex-posters/docs/source/modules/plex_posters.config.config.rst b/plex-posters/docs/source/modules/plex_posters.config.config.rst
new file mode 100644
index 0000000..6416827
--- /dev/null
+++ b/plex-posters/docs/source/modules/plex_posters.config.config.rst
@@ -0,0 +1,9 @@
+.. include:: ../global.rst
+
+Config :modname:`plex_posters.config.config`
+---------------------------------------------
+
+.. automodule:: plex_posters.config.config
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/plex-posters/docs/source/modules/plex_posters.config.rst b/plex-posters/docs/source/modules/plex_posters.config.rst
new file mode 100644
index 0000000..7203b86
--- /dev/null
+++ b/plex-posters/docs/source/modules/plex_posters.config.rst
@@ -0,0 +1,16 @@
+.. include:: ../global.rst
+
+Config :modname:`plex_posters.config`
+-------------------------------------
+
+.. automodule:: plex_posters.config
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+
+ plex_posters.config.config
diff --git a/plex-posters/docs/source/modules/plex_posters.lib.rst b/plex-posters/docs/source/modules/plex_posters.lib.rst
new file mode 100644
index 0000000..5f7a951
--- /dev/null
+++ b/plex-posters/docs/source/modules/plex_posters.lib.rst
@@ -0,0 +1,9 @@
+.. include:: ../global.rst
+
+Lib :modname:`plex_posters.lib`
+------------------------------------
+
+.. automodule:: plex_posters.lib
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/plex-posters/docs/source/modules/plex_posters.rst b/plex-posters/docs/source/modules/plex_posters.rst
new file mode 100644
index 0000000..86184c7
--- /dev/null
+++ b/plex-posters/docs/source/modules/plex_posters.rst
@@ -0,0 +1,17 @@
+.. include:: ../global.rst
+
+plex_posters :modname:`plex_posters`
+------------------------------------
+
+.. automodule:: plex_posters
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+ plex_posters.config
+ plex_posters.lib
diff --git a/plex-posters/docs/source/toc.rst b/plex-posters/docs/source/toc.rst
new file mode 100644
index 0000000..9a24667
--- /dev/null
+++ b/plex-posters/docs/source/toc.rst
@@ -0,0 +1,24 @@
+.. toctree::
+ :maxdepth: 1
+ :caption: Overview
+ :titlesonly:
+
+ introduction
+ configuration
+ changelog
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Modules
+ :titlesonly:
+
+ modules/plex_posters.rst
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Submodules
+ :titlesonly:
+
+ modules/plex_posters.config.config.rst
+ modules/plex_posters.lib.rst
+
diff --git a/plex-posters/poetry.lock b/plex-posters/poetry.lock
index 0c699d1..430b451 100644
--- a/plex-posters/poetry.lock
+++ b/plex-posters/poetry.lock
@@ -1,3 +1,11 @@
+[[package]]
+category = "dev"
+description = "A configurable sidebar-enabled Sphinx theme"
+name = "alabaster"
+optional = false
+python-versions = "*"
+version = "0.7.12"
+
[[package]]
category = "dev"
description = "Atomic file writes."
@@ -20,6 +28,17 @@ dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.int
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
+[[package]]
+category = "dev"
+description = "Internationalization utilities"
+name = "babel"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.7.0"
+
+[package.dependencies]
+pytz = ">=2015.7"
+
[[package]]
category = "main"
description = "Python package for providing Mozilla's CA Bundle."
@@ -45,6 +64,14 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.4.1"
+[[package]]
+category = "dev"
+description = "Docutils -- Python Documentation Utilities"
+name = "docutils"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "0.15.2"
+
[[package]]
category = "main"
description = "Internationalized Domain Names in Applications (IDNA)"
@@ -53,6 +80,36 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.8"
+[[package]]
+category = "dev"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+name = "imagesize"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.1.0"
+
+[[package]]
+category = "dev"
+description = "A very fast and expressive template engine."
+name = "jinja2"
+optional = false
+python-versions = "*"
+version = "2.10.3"
+
+[package.dependencies]
+MarkupSafe = ">=0.23"
+
+[package.extras]
+i18n = ["Babel (>=0.8)"]
+
+[[package]]
+category = "dev"
+description = "Safely add untrusted strings to HTML/XML markup."
+name = "markupsafe"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.1.1"
+
[[package]]
category = "dev"
description = "More routines for operating on iterables, beyond itertools"
@@ -85,6 +142,18 @@ optional = false
python-versions = "*"
version = "0.4.3"
+[[package]]
+category = "dev"
+description = "Core utilities for Python packages"
+name = "packaging"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "19.2"
+
+[package.dependencies]
+pyparsing = ">=2.0.2"
+six = "*"
+
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
@@ -151,6 +220,14 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "2.4.2"
+[[package]]
+category = "dev"
+description = "Python parsing module"
+name = "pyparsing"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "2.4.5"
+
[[package]]
category = "dev"
description = "pytest: simple powerful testing with Python"
@@ -169,6 +246,14 @@ py = ">=1.5.0"
setuptools = "*"
six = ">=1.10.0"
+[[package]]
+category = "dev"
+description = "World timezone definitions, modern and historical"
+name = "pytz"
+optional = false
+python-versions = "*"
+version = "2019.3"
+
[[package]]
category = "main"
description = "Python HTTP for Humans."
@@ -195,6 +280,122 @@ optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "1.13.0"
+[[package]]
+category = "dev"
+description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms."
+name = "snowballstemmer"
+optional = false
+python-versions = "*"
+version = "2.0.0"
+
+[[package]]
+category = "dev"
+description = "Python documentation generator"
+name = "sphinx"
+optional = false
+python-versions = ">=3.5"
+version = "2.2.1"
+
+[package.dependencies]
+Jinja2 = ">=2.3"
+Pygments = ">=2.0"
+alabaster = ">=0.7,<0.8"
+babel = ">=1.3,<2.0 || >2.0"
+colorama = ">=0.3.5"
+docutils = ">=0.12"
+imagesize = "*"
+packaging = "*"
+requests = ">=2.5.0"
+setuptools = "*"
+snowballstemmer = ">=1.1"
+sphinxcontrib-applehelp = "*"
+sphinxcontrib-devhelp = "*"
+sphinxcontrib-htmlhelp = "*"
+sphinxcontrib-jsmath = "*"
+sphinxcontrib-qthelp = "*"
+sphinxcontrib-serializinghtml = "*"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+test = ["pytest", "pytest-cov", "html5lib", "flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.740)", "docutils-stubs"]
+
+[[package]]
+category = "dev"
+description = "Read the Docs theme for Sphinx"
+name = "sphinx-rtd-theme"
+optional = false
+python-versions = "*"
+version = "0.4.3"
+
+[package.dependencies]
+sphinx = "*"
+
+[[package]]
+category = "dev"
+description = ""
+name = "sphinxcontrib-applehelp"
+optional = false
+python-versions = "*"
+version = "1.0.1"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+category = "dev"
+description = ""
+name = "sphinxcontrib-devhelp"
+optional = false
+python-versions = "*"
+version = "1.0.1"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+category = "dev"
+description = ""
+name = "sphinxcontrib-htmlhelp"
+optional = false
+python-versions = "*"
+version = "1.0.2"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy", "html5lib"]
+
+[[package]]
+category = "dev"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+name = "sphinxcontrib-jsmath"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.1"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+category = "dev"
+description = ""
+name = "sphinxcontrib-qthelp"
+optional = false
+python-versions = "*"
+version = "1.0.2"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+category = "dev"
+description = ""
+name = "sphinxcontrib-serializinghtml"
+optional = false
+python-versions = "*"
+version = "1.1.3"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
[[package]]
category = "main"
description = "Python Library for Tom's Obvious, Minimal Language"
@@ -263,28 +464,46 @@ version = "0.56.0"
six = "*"
[metadata]
-content-hash = "535a624cacbbf26a39bef9870a9f37106b05293cfd93a0b05be181cab1f57628"
+content-hash = "8f2035c47db0ff77df15941d995000a73e7873006e556bbbd0a7de4f0a9620e3"
python-versions = "^3.8"
[metadata.hashes]
+alabaster = ["446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"]
atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"]
attrs = ["08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"]
+babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"]
certifi = ["e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", "fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"]
chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
+docutils = ["6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", "9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", "a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"]
idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
+imagesize = ["3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"]
+jinja2 = ["74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", "9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"]
+markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"]
more-itertools = ["409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", "92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"]
mypy = ["1521c186a3d200c399bd5573c828ea2db1362af7209b2adb1bb8532cea2fb36f", "31a046ab040a84a0fc38bc93694876398e62bc9f35eca8ccbf6418b7297f4c00", "3b1a411909c84b2ae9b8283b58b48541654b918e8513c20a400bb946aa9111ae", "48c8bc99380575deb39f5d3400ebb6a8a1cb5cc669bbba4d3bb30f904e0a0e7d", "540c9caa57a22d0d5d3c69047cc9dd0094d49782603eb03069821b41f9e970e9", "672e418425d957e276c291930a3921b4a6413204f53fe7c37cad7bc57b9a3391", "6ed3b9b3fdc7193ea7aca6f3c20549b377a56f28769783a8f27191903a54170f", "9371290aa2cad5ad133e4cdc43892778efd13293406f7340b9ffe99d5ec7c1d9", "ace6ac1d0f87d4072f05b5468a084a45b4eda970e4d26704f201e06d47ab2990", "b428f883d2b3fe1d052c630642cc6afddd07d5cd7873da948644508be3b9d4a7", "d5bf0e6ec8ba346a2cf35cb55bf4adfddbc6b6576fcc9e10863daa523e418dbb", "d7574e283f83c08501607586b3167728c58e8442947e027d2d4c7dcd6d82f453", "dc889c84241a857c263a2b1cd1121507db7d5b5f5e87e77147097230f374d10b", "f4748697b349f373002656bf32fede706a0e713d67bfdcf04edf39b1f61d46eb"]
mypy-extensions = ["090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", "2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"]
+packaging = ["28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47", "d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108"]
pluggy = ["15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"]
praw = ["2e5c98e49fe60e5308255ed147b670d350f98281f84f582df30f87de727b6de2", "cb8f85541ad4c6b10214ef9639acccfb5fed7ffee977be169b85357d2d2ea6d9"]
prawcore = ["25dd14bf121bc0ad2ffc78e2322d9a01a516017105a5596cc21bb1e9a928b40c", "ab5558efb438aa73fc66c4178bfc809194dea3ce2addf4dec873de7e2fd2824e"]
pudb = ["e8f0ea01b134d802872184b05bffc82af29a1eb2f9374a277434b932d68f58dc"]
py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"]
pygments = ["71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"]
+pyparsing = ["20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f", "4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a"]
pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"]
+pytz = ["1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", "b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"]
requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"]
six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"]
+snowballstemmer = ["209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", "df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"]
+sphinx = ["31088dfb95359384b1005619827eaee3056243798c62724fd3fa4b84ee4d71bd", "52286a0b9d7caa31efee301ec4300dbdab23c3b05da1c9024b4e84896fb73d79"]
+sphinx-rtd-theme = ["00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4", "728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"]
+sphinxcontrib-applehelp = ["edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897", "fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"]
+sphinxcontrib-devhelp = ["6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34", "9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"]
+sphinxcontrib-htmlhelp = ["4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422", "d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"]
+sphinxcontrib-jsmath = ["2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", "a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"]
+sphinxcontrib-qthelp = ["513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20", "79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"]
+sphinxcontrib-serializinghtml = ["c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227", "db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"]
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
typed-ast = ["1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", "18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", "262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", "2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", "354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", "48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", "4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", "630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", "66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", "71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", "7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", "838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", "95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", "bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", "cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", "d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", "d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", "d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", "fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", "ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"]
typing-extensions = ["091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2", "910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d", "cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"]
diff --git a/plex-posters/poetry.lock.bak b/plex-posters/poetry.lock.bak
deleted file mode 100644
index 3c5eaf3..0000000
--- a/plex-posters/poetry.lock.bak
+++ /dev/null
@@ -1,189 +0,0 @@
-[[package]]
-category = "dev"
-description = "Atomic file writes."
-name = "atomicwrites"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.3.0"
-
-[[package]]
-category = "dev"
-description = "Classes Without Boilerplate"
-name = "attrs"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "19.3.0"
-
-[[package]]
-category = "main"
-description = "Python package for providing Mozilla's CA Bundle."
-name = "certifi"
-optional = false
-python-versions = "*"
-version = "2019.9.11"
-
-[[package]]
-category = "main"
-description = "Universal encoding detector for Python 2 and 3"
-name = "chardet"
-optional = false
-python-versions = "*"
-version = "3.0.4"
-
-[[package]]
-category = "dev"
-description = "Cross-platform colored terminal text."
-marker = "sys_platform == \"win32\""
-name = "colorama"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.4.1"
-
-[[package]]
-category = "main"
-description = "Internationalized Domain Names in Applications (IDNA)"
-name = "idna"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.8"
-
-[[package]]
-category = "dev"
-description = "More routines for operating on iterables, beyond itertools"
-name = "more-itertools"
-optional = false
-python-versions = ">=3.4"
-version = "7.2.0"
-
-[[package]]
-category = "dev"
-description = "plugin and hook calling mechanisms for python"
-name = "pluggy"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.13.0"
-
-[[package]]
-category = "main"
-description = "PRAW, an acronym for `Python Reddit API Wrapper`, is a python package that allows for simple access to reddit's API."
-name = "praw"
-optional = false
-python-versions = ">=3.4"
-version = "6.4.0"
-
-[package.dependencies]
-prawcore = ">=1.0.1,<2.0"
-update-checker = ">=0.16"
-websocket-client = ">=0.54.0"
-
-[[package]]
-category = "main"
-description = "Low-level communication layer for PRAW 4+."
-name = "prawcore"
-optional = false
-python-versions = "*"
-version = "1.0.1"
-
-[package.dependencies]
-requests = ">=2.6.0,<3.0"
-
-[[package]]
-category = "dev"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-name = "py"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.8.0"
-
-[[package]]
-category = "dev"
-description = "pytest: simple powerful testing with Python"
-name = "pytest"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "3.10.1"
-
-[package.dependencies]
-atomicwrites = ">=1.0"
-attrs = ">=17.4.0"
-colorama = "*"
-more-itertools = ">=4.0.0"
-pluggy = ">=0.7"
-py = ">=1.5.0"
-setuptools = "*"
-six = ">=1.10.0"
-
-[[package]]
-category = "main"
-description = "Python HTTP for Humans."
-name = "requests"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "2.22.0"
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-chardet = ">=3.0.2,<3.1.0"
-idna = ">=2.5,<2.9"
-urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
-
-[[package]]
-category = "main"
-description = "Python 2 and 3 compatibility utilities"
-name = "six"
-optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*"
-version = "1.13.0"
-
-[[package]]
-category = "main"
-description = "A python module that will check for package updates."
-name = "update-checker"
-optional = false
-python-versions = "*"
-version = "0.16"
-
-[package.dependencies]
-requests = ">=2.3.0"
-
-[[package]]
-category = "main"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-name = "urllib3"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
-version = "1.25.7"
-
-[[package]]
-category = "main"
-description = "WebSocket client for Python. hybi13 is supported."
-name = "websocket-client"
-optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.56.0"
-
-[package.dependencies]
-six = "*"
-
-[metadata]
-content-hash = "3b87e030e8047911ca71f9edde0e547018b1282a3122c53430c0d966bb3d4ffd"
-python-versions = "^3.8"
-
-[metadata.hashes]
-atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"]
-attrs = ["08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"]
-certifi = ["e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", "fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"]
-chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
-colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
-idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
-more-itertools = ["409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", "92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"]
-pluggy = ["0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", "fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34"]
-praw = ["2e5c98e49fe60e5308255ed147b670d350f98281f84f582df30f87de727b6de2", "cb8f85541ad4c6b10214ef9639acccfb5fed7ffee977be169b85357d2d2ea6d9"]
-prawcore = ["25dd14bf121bc0ad2ffc78e2322d9a01a516017105a5596cc21bb1e9a928b40c", "ab5558efb438aa73fc66c4178bfc809194dea3ce2addf4dec873de7e2fd2824e"]
-py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"]
-pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"]
-requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"]
-six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"]
-update-checker = ["59cfad7f9a0ee99f95f1dfc60f55bf184937bcab46a7270341c2c33695572453", "70e39446fccf77b21192cf7a8214051fa93a636dc3b5c8b602b589d100a168b8"]
-urllib3 = ["a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", "f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"]
-websocket-client = ["1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9", "1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a"]
diff --git a/plex-posters/pyproject.toml b/plex-posters/pyproject.toml
index b7daa39..385041b 100644
--- a/plex-posters/pyproject.toml
+++ b/plex-posters/pyproject.toml
@@ -13,6 +13,8 @@ toml = "^0.10.0"
pytest = "^3.0"
mypy = "^0.740.0"
pudb = "^2019.2"
+sphinx = "^2.2"
+sphinx_rtd_theme = "^0.4.3"
[build-system]
requires = ["poetry>=0.12"]
diff --git a/plex-posters/requirements.txt b/plex-posters/requirements.txt
new file mode 100644
index 0000000..515e8d2
--- /dev/null
+++ b/plex-posters/requirements.txt
@@ -0,0 +1,34 @@
+certifi==2019.9.11 \
+ --hash=sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50 \
+ --hash=sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef
+chardet==3.0.4 \
+ --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \
+ --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691
+idna==2.8 \
+ --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \
+ --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
+praw==6.4.0 \
+ --hash=sha256:2e5c98e49fe60e5308255ed147b670d350f98281f84f582df30f87de727b6de2 \
+ --hash=sha256:cb8f85541ad4c6b10214ef9639acccfb5fed7ffee977be169b85357d2d2ea6d9
+prawcore==1.0.1 \
+ --hash=sha256:25dd14bf121bc0ad2ffc78e2322d9a01a516017105a5596cc21bb1e9a928b40c \
+ --hash=sha256:ab5558efb438aa73fc66c4178bfc809194dea3ce2addf4dec873de7e2fd2824e
+requests==2.22.0 \
+ --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \
+ --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31
+six==1.13.0 \
+ --hash=sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd \
+ --hash=sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66
+toml==0.10.0 \
+ --hash=sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c \
+ --hash=sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e \
+ --hash=sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3
+update-checker==0.16 \
+ --hash=sha256:59cfad7f9a0ee99f95f1dfc60f55bf184937bcab46a7270341c2c33695572453 \
+ --hash=sha256:70e39446fccf77b21192cf7a8214051fa93a636dc3b5c8b602b589d100a168b8
+urllib3==1.25.7 \
+ --hash=sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293 \
+ --hash=sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745
+websocket-client==0.56.0 \
+ --hash=sha256:1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9 \
+ --hash=sha256:1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a
diff --git a/plex-posters/setup.py b/plex-posters/setup.py
new file mode 100644
index 0000000..412128b
--- /dev/null
+++ b/plex-posters/setup.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+from distutils.core import setup
+
+package_dir = \
+{'': 'src'}
+
+packages = \
+['plex_posters',
+ 'plex_posters.__dev',
+ 'plex_posters.config',
+ 'plex_posters.lib']
+
+package_data = \
+{'': ['*'],
+ 'plex_posters': ['.mypy_cache/3.8/*',
+ '.mypy_cache/3.8/collections/*',
+ '.mypy_cache/3.8/email/*',
+ '.mypy_cache/3.8/http/*',
+ '.mypy_cache/3.8/importlib/*',
+ '.mypy_cache/3.8/logging/*',
+ '.mypy_cache/3.8/os/*',
+ '.mypy_cache/3.8/requests/*',
+ '.mypy_cache/3.8/requests/packages/*',
+ '.mypy_cache/3.8/requests/packages/urllib3/*',
+ '.mypy_cache/3.8/requests/packages/urllib3/packages/*',
+ '.mypy_cache/3.8/requests/packages/urllib3/packages/ssl_match_hostname/*',
+ '.mypy_cache/3.8/requests/packages/urllib3/util/*',
+ '.mypy_cache/3.8/urllib/*',
+ 'test/*']}
+
+install_requires = \
+['praw>=6.4,<7.0', 'toml>=0.10.0,<0.11.0']
+
+setup_kwargs = {
+ 'name': 'plex-posters',
+ 'version': '0.1.4',
+ 'description': '',
+ 'long_description': None,
+ 'author': 'dtomlinson',
+ 'author_email': 'dtomlinson@panaetius.co.uk',
+ 'url': None,
+ 'package_dir': package_dir,
+ 'packages': packages,
+ 'package_data': package_data,
+ 'install_requires': install_requires,
+ 'python_requires': '>=3.8,<4.0',
+}
+
+
+setup(**setup_kwargs)
diff --git a/plex-posters/src/plex_posters/__header__.py b/plex-posters/src/plex_posters/__header__.py
new file mode 100644
index 0000000..5f83435
--- /dev/null
+++ b/plex-posters/src/plex_posters/__header__.py
@@ -0,0 +1 @@
+__header__ = 'PLEX_POSTERS'
diff --git a/plex-posters/src/plex_posters/__init__.py b/plex-posters/src/plex_posters/__init__.py
index 41c801e..6e8beba 100644
--- a/plex-posters/src/plex_posters/__init__.py
+++ b/plex-posters/src/plex_posters/__init__.py
@@ -1,35 +1,44 @@
-from plex_posters.config import plexPosterConfig
+from __future__ import annotations
+from .config.config import Config
+from .library import set_config
+from .__header__ import __header__
import logging
-
-__header__ = 'plex_posters'
-
+from logging.handlers import RotatingFileHandler
+import os
+import sys
# Load User Defined Config
-DEFAULT_CONFIG_PATH = os.path.expanduser('~/.config/plexapi/config.ini')
-CONFIG_PATH = os.environ.get('PLEXAPI_CONFIG_PATH', DEFAULT_CONFIG_PATH)
-_config = plexPosterConfig(CONFIG_PATH)
-
+DEFAULT_CONFIG_PATH = f'~/.config/{__header__.lower()}'
+CONFIG_PATH = os.environ.get(f'{__header__}_CONFIG_PATH', DEFAULT_CONFIG_PATH)
+CONFIG = Config(CONFIG_PATH)
# Logging Configuration
-log = logging.getLogger(__header__)
-logfile = CONFIG.get('log.path')
-logformat = CONFIG.get(
- 'log.format',
- '%(asctime)s %(module)12s:%(lineno)-4s %(levelname)-9s %(message)s',
+logger = logging.getLogger(__header__)
+set_config(CONFIG, 'logging.path')
+set_config(
+ CONFIG,
+ 'logging.format',
+ '%(asctime)s - %(module)s:%(lineno)s - %(levelname)s - %(message)s',
)
-loglevel = CONFIG.get('log.level', 'INFO').upper()
-loghandler = logging.NullHandler()
+set_config(CONFIG, 'logging.level', 'INFO')
+loghandler_sys = logging.StreamHandler(sys.stdout)
-if logfile: # pragma: no cover
- logbackups = CONFIG.get('log.backup_count', 3, int)
- logbytes = CONFIG.get('log.rotate_bytes', 512000, int)
- loghandler = RotatingFileHandler(
- os.path.expanduser(logfile), 'a', logbytes, logbackups
+if CONFIG.logging_path:
+ set_config(CONFIG, 'logging.backup_count', 3, int)
+ set_config(CONFIG, 'logging.rotate_bytes', 512000, int)
+ loghandler_file = RotatingFileHandler(
+ os.path.expanduser(CONFIG.logging_path),
+ 'a',
+ CONFIG.logging_rotate_bytes,
+ CONFIG.logging_backup_count
)
+ loghandler_file.setFormatter(logging.Formatter(CONFIG.logging_format))
+ logger.addHandler(loghandler_file)
-loghandler.setFormatter(logging.Formatter(logformat))
-log.addHandler(loghandler)
-log.setLevel(loglevel)
-logfilter = SecretsFilter()
-if CONFIG.get('log.show_secrets', '').lower() != 'true':
- log.addFilter(logfilter)
+loghandler_sys.setFormatter(logging.Formatter(CONFIG.logging_format))
+logger.addHandler(loghandler_sys)
+logger.setLevel(CONFIG.logging_level)
+
+for msg in CONFIG.deferred_messages:
+ logger.info(msg)
+CONFIG.reset_log()
diff --git a/plex-posters/src/plex_posters/__pycache__/__init__.cpython-38.pyc b/plex-posters/src/plex_posters/__pycache__/__init__.cpython-38.pyc
index 4bd21f8..f2d9abd 100644
Binary files a/plex-posters/src/plex_posters/__pycache__/__init__.cpython-38.pyc and b/plex-posters/src/plex_posters/__pycache__/__init__.cpython-38.pyc differ
diff --git a/plex-posters/src/plex_posters/config/__init__.py b/plex-posters/src/plex_posters/config/__init__.py
index 530dad7..e69de29 100644
--- a/plex-posters/src/plex_posters/config/__init__.py
+++ b/plex-posters/src/plex_posters/config/__init__.py
@@ -1,95 +0,0 @@
-from plex_posters.lib import export
-from plex_posters import __header__ as header
-from typing import Union
-import os
-import toml
-
-__all__ = []
-__section__ = 'CONFIG'
-
-
-@export
-class plexPosterConfig:
-
- """Handles the config options for the module
-
- Attributes
- ----------
- config_file : dict
- Contains the config options. See `plexPosterConfig.read_config()`
- for the data structure.
- """
-
- def __init__(self, path: str) -> None:
- self.config_file = self.read_config(path)
- self.module_name = header.lower()
-
- @staticmethod
- def read_config(path: str) -> Union[dict, None]:
-
- """Reads the toml config file from `path` if it exists.
-
- Parameters
- ----------
- path : str
- Path to config file.
-
- Returns
- -------
- Union[dict, None]
- Returns a dict if the file is found else returns nothing.
-
- The dict contains a key for each header. Each key contains a
- dictionary containing a key, value pair for each config under
- that header.
-
- Example:
-
- [plexposters]
-
- [plexposters.foo]
- foo = bar
-
- Returns a dict: {'plexposters' : {foo: {'foo': 'bar'}}}
- """
-
- path += 'config.toml' if path[-1] == '/' else '/config.toml'
-
- try:
- with open(path, 'r+') as config_file:
- config_file = toml.load(config_file)
- return config_file
- except FileNotFoundError:
- pass
-
- def get(self, key: str, default: str = None, cast: callable = None):
- env_key = f"{header}_{key.upper().replace('.', '_')}"
- print(self.config_file)
- try:
- section, name = key.lower().split('.')
- value = self.config_file[self.module_name][section][name]
- print(f'{env_key} found in config.toml')
- return cast(value) if cast else value
- except KeyError:
- print(f'{env_key} not found in config.toml')
- value = os.environ.get(env_key)
- if value is not None:
- print(f'{env_key} found in an environment variable')
- else:
- print(f'{env_key} not found in an environment variable.')
- value = default
- print(f'{env_key} set to default {default}')
- return cast(value) if cast else value
-
-
-inst = plexPosterConfig(
- os.path.expanduser('~/.config/plex-posters/')
-)
-
-# print(inst.config_file, '\n')
-
-# print(f"{os.environ.get('VIRTUAL_ENV')=}")
-
-PLEX_USERNAME = inst.get(f'plex.password', 'smile')
-
-print(f'{PLEX_USERNAME=}')
diff --git a/plex-posters/src/plex_posters/config/config.py b/plex-posters/src/plex_posters/config/config.py
new file mode 100644
index 0000000..b5c2ca9
--- /dev/null
+++ b/plex-posters/src/plex_posters/config/config.py
@@ -0,0 +1,145 @@
+from plex_posters.library import export
+from plex_posters.__header__ import __header__ as header
+from typing import Callable, Union
+import os
+import toml
+
+__all__ = []
+
+
+@export
+class Config:
+
+ """Handles the config options for the module and stores config variables
+ to be shared.
+
+ Attributes
+ ----------
+ config_file : dict
+ Contains the config options. See :meth:`~plex_posters.config.config.Config.read_config`
+ for the data structure.
+ deferred_messages : list
+ A list containing the messages to be logged once the logger has been
+ instantiated.
+ module_name : str
+ A string representing the module name. This is added in front of all
+ envrionment variables and is the title of the `config.toml`.
+ """
+
+ def __init__(self, path: str) -> None:
+ """
+ Parameters
+ ----------
+ path : str
+ Path to config file
+ """
+ self.config_file = self.read_config(path)
+ self.module_name = header.lower()
+ self.deferred_messages = []
+
+ def read_config(self, path: str) -> Union[dict, None]:
+
+ """Reads the toml config file from `path` if it exists.
+
+ Parameters
+ ----------
+ path : str
+ Path to config file. Should not contain `config.toml`
+
+ Example: `path = '~/.config/plex_posters'`
+
+ Returns
+ -------
+ Union[dict, None]
+ Returns a dict if the file is found else returns nothing.
+
+ The dict contains a key for each header. Each key corresponds to a
+ dictionary containing a key, value pair for each config under
+ that header.
+
+ Example:
+
+ [plex_posters]
+
+ [plex_posters.foo]
+ foo = bar
+
+ Returns a dict: {'plex_posters' : {foo: {'foo': 'bar'}}}
+ """
+
+ path += 'config.toml' if path[-1] == '/' else '/config.toml'
+ path = os.path.expanduser(path)
+
+ try:
+ with open(path, 'r+') as config_file:
+ config_file = toml.load(config_file)
+ return config_file
+ except FileNotFoundError:
+ try:
+ self.defer_log(f'Config file not found at {config_file}')
+ except UnboundLocalError:
+ pass
+ pass
+
+ def get(
+ self, key: str, default: str = None, cast: Callable = None
+ ) -> Union[str, None]:
+ """Retrives the config variable from either the `config.toml` or an
+ environment variable. Will default to the default value if it is
+ provided.
+
+ Parameters
+ ----------
+ key : str
+ Key to the configuration variable. Should be in the form
+ `module.variable` which will be converted to `module_variable`.
+ default : str, optional
+ The default value if nothing is found.
+ cast : Callable, optional
+ The type of the variable. E.g `int` or `float`. Should reference
+ the type object and not as string.
+
+ Returns
+ -------
+ Any
+ Will return the config variable if found, or the default.
+ """
+ env_key = f"{header}_{key.upper().replace('.', '_')}"
+ # self.defer_log(self.config_file)
+ try:
+ # look in the config.toml
+ section, name = key.lower().split('.')
+ value = self.config_file[self.module_name][section][name]
+ self.defer_log(f'{env_key} found in config.toml')
+ return cast(value) if cast else value
+ except KeyError:
+ self.defer_log(f'{env_key} not found in config.toml')
+ except TypeError:
+ pass
+ # look for an environment variable
+ value = os.environ.get(env_key)
+ if value is not None:
+ self.defer_log(f'{env_key} found in an environment variable')
+ else:
+ # fall back to default
+ self.defer_log(f'{env_key} not found in an environment variable.')
+ value = default
+ self.defer_log(f'{env_key} set to default {default}')
+ return cast(value) if cast else value
+
+ def defer_log(self, msg: str) -> None:
+ """Populates a list `Config.deferred_messages` with all the events to
+ be passed to the logger later if required.
+
+ Parameters
+ ----------
+ msg : str
+ The message to be logged.
+ """
+ self.deferred_messages.append(msg)
+
+ def reset_log(self) -> None:
+ """Empties the list `Config.deferred_messages`.
+ """
+ del self.deferred_messages
+ self.deferred_messages = []
diff --git a/plex-posters/src/plex_posters/lib/__init__.py b/plex-posters/src/plex_posters/lib/__init__.py
deleted file mode 100644
index 83aa23c..0000000
--- a/plex-posters/src/plex_posters/lib/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import sys
-
-
-def export(fn: callable) -> callable:
- mod = sys.modules[fn.__module__]
- if hasattr(mod, '__all__'):
- mod.__all__.append(fn.__name__)
- else:
- mod.__all__ = [fn.__name__]
- return fn
diff --git a/plex-posters/src/plex_posters/lib/__pycache__/__init__.cpython-38.pyc b/plex-posters/src/plex_posters/lib/__pycache__/__init__.cpython-38.pyc
deleted file mode 100644
index 03d14b0..0000000
Binary files a/plex-posters/src/plex_posters/lib/__pycache__/__init__.cpython-38.pyc and /dev/null differ
diff --git a/plex-posters/src/plex_posters/library/__init__.py b/plex-posters/src/plex_posters/library/__init__.py
new file mode 100644
index 0000000..82f6d7c
--- /dev/null
+++ b/plex-posters/src/plex_posters/library/__init__.py
@@ -0,0 +1,37 @@
+import sys
+from typing import Any, TypeVar, Type
+
+
+config_inst_t = TypeVar('config_inst_t', bound='config.config.Config')
+
+
+def export(fn: callable) -> callable:
+ mod = sys.modules[fn.__module__]
+ if hasattr(mod, '__all__'):
+ mod.__all__.append(fn.__name__)
+ else:
+ mod.__all__ = [fn.__name__]
+ return fn
+
+
+def set_config(
+ config_inst: Type[config_inst_t],
+ key: str,
+ default: str = None,
+ cast: Any = None,
+) -> None:
+ """Sets the config variable on the instance of a class.
+
+ Parameters
+ ----------
+ config_inst : Type[config_inst_t]
+ Instance of the config class.
+ key : str
+ The key referencing the config variable.
+ default : str, optional
+ The default value.
+ cast : Any, optional
+ The type of the variable.
+ """
+ config_var = key.lower().replace('.', '_')
+ setattr(config_inst, config_var, config_inst.get(key, default, cast))
diff --git a/plex-posters/src/plex_posters/test/test.py b/plex-posters/src/plex_posters/test/test.py
new file mode 100644
index 0000000..bb095f4
--- /dev/null
+++ b/plex-posters/src/plex_posters/test/test.py
@@ -0,0 +1,3 @@
+from plex_posters import CONFIG
+
+print(CONFIG)
diff --git a/plex-posters/tests/config.toml b/plex-posters/tests/config.toml
new file mode 100644
index 0000000..e69de29
diff --git a/plex-posters/tests/test-config.py b/plex-posters/tests/test-config.py
new file mode 100644
index 0000000..1e7faf0
--- /dev/null
+++ b/plex-posters/tests/test-config.py
@@ -0,0 +1,3 @@
+from plex_posters import CONFIG
+
+print(f'{CONFIG.logging_path=}')