Support extras and stay slim on initial install

See https://git.vvvvvvaria.org/decentral1se/xbotlib/issues/7.
This commit is contained in:
Luke Murphy 2021-01-23 23:56:07 +01:00
parent 745a561409
commit 998667c839
No known key found for this signature in database
GPG Key ID: 5E2EF5A63E3718CC
5 changed files with 59 additions and 19 deletions

View File

@ -7,6 +7,7 @@
- Document `return` statement semantics ([#6](https://git.vvvvvvaria.org/decentral1se/xbotlib/issues/6))
- Make file system the first-class storage option ([#3](https://git.vvvvvvaria.org/decentral1se/xbotlib/issues/3))
- Note support for open formats when serving the web ([#5](https://git.vvvvvvaria.org/decentral1se/xbotlib/issues/5))
- Support extras for optional dependencies ([#7](https://git.vvvvvvaria.org/decentral1se/xbotlib/issues/7))
# xbotlib 0.14.1 (2021-01-21)

View File

@ -278,7 +278,8 @@ $ cat mybot.json
For more advanced use cases, `xbotlib` also supports [Redis](https://redis.io/)
as a storage back-end. You'll need to configure this (e.g. `--storage redis`)
as the default uses the filesystem approach mentioned above. The same `self.db`
will then be passed as a Redis connection object.
will then be passed as a Redis connection object. You will also need to install
additional dependencies using `pip install xbotlib[redis]`.
### Loading Plugins
@ -294,6 +295,12 @@ See [here](https://slixmpp.readthedocs.io/xeps.html) for the list of supported p
### Serving HTTP
Firstly, you'll need to install additional dependencies.
```bash
$ pip install xbotlib[web]
```
Your bot will run a web server if you configure it to do so. Use the `--serve`
option on the command-line, the `serve = True` configuration option or the
`XBOT_SERVE=True` environment variable.

26
poetry.lock generated
View File

@ -15,7 +15,7 @@ name = "aiohttp"
version = "3.7.3"
description = "Async http client/server framework (asyncio)"
category = "main"
optional = false
optional = true
python-versions = ">=3.6"
[package.dependencies]
@ -43,7 +43,7 @@ name = "async-timeout"
version = "3.0.1"
description = "Timeout context manager for asyncio programs"
category = "main"
optional = false
optional = true
python-versions = ">=3.5.3"
[[package]]
@ -96,7 +96,7 @@ name = "chardet"
version = "3.0.4"
description = "Universal encoding detector for Python 2 and 3"
category = "main"
optional = false
optional = true
python-versions = "*"
[[package]]
@ -137,7 +137,7 @@ name = "idna"
version = "3.1"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
optional = true
python-versions = ">=3.4"
[[package]]
@ -145,7 +145,7 @@ name = "idna-ssl"
version = "1.1.0"
description = "Patch ssl.match_hostname for Unicode(idna) domains support"
category = "main"
optional = false
optional = true
python-versions = "*"
[package.dependencies]
@ -185,7 +185,7 @@ name = "jinja2"
version = "2.11.2"
description = "A very fast and expressive template engine."
category = "main"
optional = false
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[package.dependencies]
@ -199,7 +199,7 @@ name = "markupsafe"
version = "1.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
optional = true
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
[[package]]
@ -215,7 +215,7 @@ name = "multidict"
version = "5.1.0"
description = "multidict implementation"
category = "main"
optional = false
optional = true
python-versions = ">=3.6"
[[package]]
@ -288,7 +288,7 @@ name = "redis"
version = "3.5.3"
description = "Python client for Redis key-value store"
category = "main"
optional = false
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[package.extras]
@ -356,7 +356,7 @@ name = "yarl"
version = "1.6.3"
description = "Yet another URL library"
category = "main"
optional = false
optional = true
python-versions = ">=3.6"
[package.dependencies]
@ -376,10 +376,14 @@ python-versions = ">=3.6"
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
[extras]
redis = ["redis"]
web = ["aiohttp", "Jinja2"]
[metadata]
lock-version = "1.1"
python-versions = "^3.6"
content-hash = "0578ed3f31fcb6ea0b170b1afe2950a047bcd3eae5c0200982f2fd61abcb9307"
content-hash = "4d10b4f1e9f193be431e27f13f861f033a4c59e89258be4b40399b54f574c691"
[metadata.files]
aiodns = [

View File

@ -17,15 +17,19 @@ keywords = []
python = "^3.6"
slixmpp = "^1.6.0"
humanize = "^3.2.0"
redis = "^3.5.3"
Jinja2 = "^2.11.2"
aiohttp = "^3.7.3"
redis = {version = "^3.5.3", optional = true}
aiohttp = {version = "^3.7.3", optional = true}
Jinja2 = {version = "^2.11.2", optional = true}
[tool.poetry.dev-dependencies]
black = "^19.10b0"
flake8 = "^3.8.3"
isort = "^5.0.2"
[tool.poetry.extras]
redis = ["redis"]
web = ["aiohttp", "jinja2"]
[tool.black]
line-length = 80
target-version = ["py38"]

View File

@ -14,10 +14,7 @@ from os.path import exists
from pathlib import Path
from sys import exit, stdout
from aiohttp.web import Application, Response, get, run_app
from humanize import naturaldelta
from jinja2 import Environment, FileSystemLoader
from redis import Redis
from slixmpp import ClientXMPP
@ -434,8 +431,8 @@ class Bot(ClientXMPP):
self.rooms = rooms
self.no_auto_join = no_auto_join
self.port = port
self.template = self.load_template(template)
self.serve = serve
self.template = self.load_template(template) if self.serve else None
self.storage = storage
self.storage_file = Path(storage_file).absolute()
@ -444,6 +441,13 @@ class Bot(ClientXMPP):
if not exists(Path(template).absolute()):
return None
try:
from jinja2 import Environment, FileSystemLoader
except ModuleNotFoundError:
print("Missing required dependency: jinja2")
print("Have you tried `pip install xbotlib[web]`")
exit(1)
try:
loader = FileSystemLoader(searchpath="./")
env = Environment(loader=loader)
@ -578,12 +582,18 @@ class Bot(ClientXMPP):
exit(1)
else:
try:
from redis import Redis
self.db = Redis.from_url(self.redis_url, decode_responses=True)
return self.log.info("Successfully connected to Redis storage")
except ValueError as exception:
message = f"Failed to connect to Redis storage: {exception}"
self.log.info(message)
exit(1)
except ModuleNotFoundError:
print("missing required dependency using Redis")
print("Have you tried `pip install xbotlib[redis]`")
exit(1)
def run(self):
"""Run the bot."""
@ -628,6 +638,13 @@ class Bot(ClientXMPP):
async def default_serve(self, request):
"""Default placeholder text for HTML serving."""
try:
from aiohttp.web import Response
except ModuleNotFoundError:
print("Missing required dependency: aiohttp")
print("Have you tried `pip install xbotlib[web]`")
exit(1)
return Response(text=f"{self.nick} is alive and well")
def reply(self, text, to=None, room=None):
@ -673,4 +690,11 @@ class Bot(ClientXMPP):
def respond(self, response, content_type="text/html"):
"""Send this response back with the web server."""
try:
from aiohttp.web import Response
except ModuleNotFoundError:
print("Missing required dependency: aiohttp")
print("Have you tried `pip install xbotlib[web]`")
exit(1)
return Response(text=response, content_type=content_type)