Skip to content

Commit

Permalink
Add usage docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Saluev committed Jan 5, 2024
1 parent 7af93cc commit 844f69c
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 4 deletions.
28 changes: 28 additions & 0 deletions docs/features/mongodb_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# MongoDB integration

To run Suppgram with MongoDB, you'll have to install optional dependencies:
```shell
python -m pip install "suppgram[mongodb]"
```

Then you can configure the integration by database URI. Examples:

```shell
# All-in-one CLI + MongoDB (insecure)
python -m suppgram.cli.all_in_one \
--mongodb-uri mongodb://user:password@host:27017/database \
...

# All-in-one CLI + MongoDB (secret in environment variable)
export MONGODB_URI=mongodb://user:password@host:27017/database
python -m suppgram.cli.all_in_one ...

# All-in-one CLI + MongoDB (secret in file)
echo "mongodb://user:password@host:27017/database" > /secrets/mongodb_uri
python -m suppgram.cli.all_in_one \
--mongodb-uri-file /secrets/mongodb_uri \
...
```

Suppgram will create collections with names starting with `suppgram_`, so you may use
a preexisting database instead of creating a separate one.
39 changes: 39 additions & 0 deletions docs/features/sql_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# PostgreSQL/SQLite integration

Suppgram ships with support for arbitrary persistent storage supported by SQLAlchemy,
including PostgreSQL, SQLite and [numerous other databases](https://docs.sqlalchemy.org/en/20/dialects/).
However, note that unit tests are only run for PostgreSQL (latest) and SQLite.

To run Suppgram with SQLAlchemy, you'll have to install optional dependencies:
```shell
python -m pip install "suppgram[sqlalchemy]"
```
This pack of dependencies includes asynchronous drivers for PostgreSQL and SQLite.
For other databases, additional packages may be required.

Then you can configure the integration the same way SQLAlchemy is normally configured —
by database URI. Examples:
```shell
# All-in-one CLI + SQLite
python -m suppgram.cli.all_in_one \
--sqlalchemy-uri sqlite+aiosqlite:///path/to/file.db \
...

# All-in-one CLI + PostgreSQL (insecure)
python -m suppgram.cli.all_in_one \
--sqlalchemy-uri postgresql+asyncpg://user:password@host:5432/database \
...

# All-in-one CLI + PostgreSQL (secret in environment variable)
export SQLALCHEMY_URI=postgresql+asyncpg://user:password@host:5432/database
python -m suppgram.cli.all_in_one ...

# All-in-one CLI + PostgreSQL (secret in file)
echo "postgresql+asyncpg://user:password@host:5432/database" > /secrets/postgres_uri
python -m suppgram.cli.all_in_one \
--sqlalchemy-uri-file /secrets/postgres_uri \
...
```

Suppgram will create tables with names starting with `suppgram_`, so you may use
a preexisting database instead of creating a separate one.
8 changes: 7 additions & 1 deletion docs/usage/all_in_one_cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ Options:
--sqlalchemy-uri TEXT SQLAlchemy connection URI. Alternatively,
environment variable SQLALCHEMY_URI may be
used
--sqlalchemy-uri-file FILE Path to file storing SQLAlchemy connection
URI. Alternatively, environment variable
SQLALCHEMY_URI may be used
--mongodb-uri TEXT MongoDB connection URI. Alternatively,
environment variable MONGODB_URI may be used
--mongodb-uri-file FILE Path to file storing MongoDB connection URI.
Alternatively, environment variable
MONGODB_URI may be used
--mongodb-database TEXT MongoDB database name. If not specified,
will connect to the default database
specified in the URI
Expand Down Expand Up @@ -53,7 +59,7 @@ Options:
essageConverter]
--help Show this message and exit.
```
It is recommended to prefer environment variables over command line arguments
It is recommended to prefer environment variables or files over command line arguments
for sensitive data, e.g. for SQLAlchemy URI if it contains username and/or password.

Details on particular integrations (SQLAlchemy, MongoDB, Telegram, PubNub, ...) are
Expand Down
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ nav:
- 'All-in-one CLI': usage/all_in_one_cli.md
- Builder: usage/builder.md
- 'Customizing texts': usage/customizing_texts.md
- Features:
- 'PostgreSQL/SQLite integration': features/sql_integration.md
- 'MongoDB integration': features/mongodb_integration.md
- Development:
- 'Contribution guide': development/contribution_guide.md
- 'Architecture overview': development/architecture_overview.md
Expand Down
7 changes: 7 additions & 0 deletions suppgram/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import sys

print(
"Error: 'suppgram' package is not directly runnable. Did you mean 'suppgram.cli.all_in_one'?",
file=sys.stderr,
)
sys.exit(1)
37 changes: 35 additions & 2 deletions suppgram/cli/all_in_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,25 @@
default=None,
help="SQLAlchemy connection URI. Alternatively, environment variable SQLALCHEMY_URI may be used",
)
@click.option(
"--sqlalchemy-uri-file",
default=None,
type=click.Path(exists=True, dir_okay=False),
help="Path to file storing SQLAlchemy connection URI. "
"Alternatively, environment variable SQLALCHEMY_URI may be used",
)
@click.option(
"--mongodb-uri",
envvar="MONGODB_URI",
default=None,
help="MongoDB connection URI. Alternatively, environment variable MONGODB_URI may be used",
)
@click.option(
"--mongodb-uri-file",
default=None,
type=click.Path(exists=True, dir_okay=False),
help="Path to file storing MongoDB connection URI. Alternatively, environment variable MONGODB_URI may be used",
)
@click.option(
"--mongodb-database",
"mongodb_database_name",
Expand Down Expand Up @@ -99,7 +112,9 @@
def run_all_in_one(
loglevel: str,
sqlalchemy_uri: Optional[str],
sqlalchemy_uri_file: Optional[str],
mongodb_uri: Optional[str],
mongodb_uri_file: Optional[str],
mongodb_database_name: Optional[str],
texts_class_path: str,
telegram_customer_bot_token_file: Optional[str],
Expand Down Expand Up @@ -140,6 +155,15 @@ def run_all_in_one(

builder = Builder()

if sqlalchemy_uri_file:
if sqlalchemy_uri:
raise UsageError(
"both --sqlalchemy-uri (or SQLALCHEMY_URI environment variable) "
"and --sqlalchemy-uri-file are specified; unclear which URI to use."
)

sqlalchemy_uri = _read_secret_from_file(sqlalchemy_uri_file)

try:
if sqlalchemy_uri:
builder = builder.with_sqlalchemy_storage(sqlalchemy_uri)
Expand All @@ -149,6 +173,15 @@ def run_all_in_one(
"Make sure that necessary dependencies are installed:\n\n pip install suppgram[sqlalchemy]\n"
) from exc

if mongodb_uri_file:
if mongodb_uri:
raise UsageError(
"both --mongodb-uri (or MONGODB_URI environment variable) "
"and --mongodb-uri-file are specified; unclear which URI to use."
)

mongodb_uri = _read_secret_from_file(mongodb_uri_file)

try:
if mongodb_uri is not None:
builder = builder.with_mongodb_storage(mongodb_uri, mongodb_database_name)
Expand Down Expand Up @@ -209,11 +242,11 @@ def run_all_in_one(
builder.build()
except NoStorageSpecified as exc:
raise UsageError(
"No storage specified. Consider specifying --sqlalchemy-uri or --mongodb-uri parameters."
"no storage specified. Consider specifying --sqlalchemy-uri or --mongodb-uri parameters."
) from exc
except NoFrontendSpecified as exc:
raise UsageError(
"No frontend specified. In this configuration the application is not going to do anything.\n"
"no frontend specified. In this configuration the application is not going to do anything.\n"
"Consider specifying --telegram-*, --pubnub-* or --customer-shell parameters."
) from exc

Expand Down
2 changes: 1 addition & 1 deletion suppgram/storages/sqlalchemy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def make_workplace_filter(self, identification: WorkplaceIdentification) -> Colu
if identification.telegram_user_id is not None:
return (
(workplace_model.telegram_bot_id == identification.telegram_bot_id)
& (workplace_model.agent_id == self.agent_model.id)
& (workplace_model.agent_id == agent_model.id)
& (agent_model.telegram_user_id == identification.telegram_user_id)
)
raise WorkplaceEmptyIdentification(identification)
Expand Down

0 comments on commit 844f69c

Please sign in to comment.