Skip to content

Commit

Permalink
Improve docstrings.
Browse files Browse the repository at this point in the history
- Fix typos.
- Fix broken links.
- Improve readability.
  • Loading branch information
pkhalaj committed May 24, 2024
1 parent 78c7816 commit 929543a
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 60 deletions.
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Welcome to Pytroll documentation!
Pytroll-db Documentation
===========================================

.. toctree::
Expand Down
2 changes: 1 addition & 1 deletion trolldb/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""trolldb package."""
"""The database interface of the Pytroll package."""
2 changes: 1 addition & 1 deletion trolldb/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
For more information and documentation, please refer to the following sub-packages and modules:
- :obj:`trolldb.api.routes`: The package which defines the API routes.
- :obj:`trollddb.api.api`: The module which defines the API server and how it is run via the given configuration.
- :obj:`trolldb.api.api`: The module which defines the API server and how it is run via the given configuration.
"""
10 changes: 5 additions & 5 deletions trolldb/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
title="pytroll-db",
summary="The database API of Pytroll",
description=
"The API allows you to perform CRUD operations as well as querying the database"
"The API allows you to perform CRUD operations as well as querying the database"
"At the moment only MongoDB is supported. It is based on the following Python packages"
"\n * **PyMongo** (https://github.com/mongodb/mongo-python-driver)"
"\n * **motor** (https://github.com/mongodb/motor)",
Expand All @@ -43,7 +43,7 @@
url="https://www.gnu.org/licenses/gpl-3.0.en.html"
)
)
"""These will appear int the auto-generated documentation and are passed to the ``FastAPI`` class as keyword args."""
"""These will appear in the auto-generated documentation and are passed to the ``FastAPI`` class as keyword args."""


@validate_call
Expand All @@ -65,8 +65,8 @@ def run_server(config: Union[AppConfig, FilePath], **kwargs) -> None:
`FastAPI class <https://fastapi.tiangolo.com/reference/fastapi/#fastapi.FastAPI>`_ and are directly passed
to it. These keyword arguments will be first concatenated with the configurations of the API server which
are read from the ``config`` argument. The keyword arguments which are passed explicitly to the function
take precedence over ``config``. Finally, ``API_INFO``, which are hard-coded information for the API server,
will be concatenated and takes precedence over all.
take precedence over ``config``. Finally, :obj:`API_INFO`, which are hard-coded information for the API
server, will be concatenated and takes precedence over all.
Raises:
ValidationError:
Expand All @@ -75,7 +75,7 @@ def run_server(config: Union[AppConfig, FilePath], **kwargs) -> None:
Example:
.. code-block:: python
from api.api import run_server
from trolldb.api.api import run_server
if __name__ == "__main__":
run_server("config.yaml")
"""
Expand Down
2 changes: 1 addition & 1 deletion trolldb/api/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""routes package."""
"""The routes package of the API."""

from .router import api_router

Expand Down
18 changes: 5 additions & 13 deletions trolldb/config/config.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
"""The module which handles parsing and validating the config (YAML) file.
The validation is performed using `Pydantic <https://docs.pydantic.dev/latest/>`_.
Note:
Functions in this module are decorated with
`pydantic.validate_call <https://docs.pydantic.dev/latest/api/validate_call/#pydantic.validate_call_decorator.validate_call>`_
so that their arguments can be validated using the corresponding type hints, when calling the function at runtime.
"""

import errno
Expand All @@ -32,7 +27,7 @@ def id_must_be_valid(id_like_string: str) -> ObjectId:
The string to be converted to an ObjectId.
Returns:
The ObjectId object if successfully.
The ObjectId object if successful.
Raises:
ValueError:
Expand All @@ -46,7 +41,7 @@ def id_must_be_valid(id_like_string: str) -> ObjectId:


MongoObjectId = Annotated[str, AfterValidator(id_must_be_valid)]
"""Type hint validator for object IDs."""
"""The type hint validator for object IDs."""


class MongoDocument(BaseModel):
Expand All @@ -60,7 +55,7 @@ class APIServerConfig(NamedTuple):
Note:
The attributes herein are a subset of the keyword arguments accepted by
`FastAPI class <https://fastapi.tiangolo.com/reference/fastapi/#fastapi.FastAPI>`_ and are directly passed
to the FastAPI class.
to the FastAPI class. Consult :func:`trolldb.api.api.run_server` on how these configurations are treated.
"""

url: AnyUrl
Expand All @@ -79,7 +74,7 @@ class DatabaseConfig(NamedTuple):
"""

url: MongoDsn
"""The URL of the MongoDB server excluding the port part, e.g. ``"mongodb://localhost:27017"``"""
"""The URL of the MongoDB server including the port part, e.g. ``"mongodb://localhost:27017"``"""

timeout: Timeout
"""The timeout in seconds (non-negative float), after which an exception is raised if a connection with the
Expand All @@ -95,7 +90,7 @@ class DatabaseConfig(NamedTuple):


class AppConfig(BaseModel):
"""A model to hold all the configurations of the application including both the API server and the database.
"""A model to hold all the configurations of the application, i.e. the API server, the database, and the subscriber.
This will be used by Pydantic to validate the parsed YAML file.
"""
Expand All @@ -121,9 +116,6 @@ def parse_config_yaml_file(filename: FilePath) -> AppConfig:
ValidationError:
If the successfully parsed file fails the validation, i.e. its schema or the content does not conform to
:class:`AppConfig`.
ValidationError:
If the function is not called with arguments of valid type.
"""
logger.info("Attempt to parse the YAML file ...")
with open(filename, "r") as file:
Expand Down
12 changes: 6 additions & 6 deletions trolldb/database/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


class Client(ResponsesErrorGroup):
"""Client error responses, e.g. if something goes wrong with initialization or closing the client."""
"""Database client error responses, e.g. if something goes wrong with initialization or closing the client."""
CloseNotAllowedError = ResponseError({
status.HTTP_405_METHOD_NOT_ALLOWED:
"Calling `close()` on a client which has not been initialized is not allowed!"
Expand All @@ -37,25 +37,25 @@ class Client(ResponsesErrorGroup):

ConnectionError = ResponseError({
status.HTTP_400_BAD_REQUEST:
"Could not connect to the database with URL."
"Could not connect to the database with the given URL."
})


class Collections(ResponsesErrorGroup):
"""Collections error responses, e.g. if a requested collection cannot be found."""
"""Collections error responses, e.g. if the requested collection cannot be found."""
NotFoundError = ResponseError({
status.HTTP_404_NOT_FOUND:
"Could not find the given collection name inside the specified database."
})

WrongTypeError = ResponseError({
status.HTTP_422_UNPROCESSABLE_ENTITY:
"Both the Database and collection name must be `None` if one of them is `None`."
"Both the database and collection name must be `None` if either one is `None`."
})


class Databases(ResponsesErrorGroup):
"""Databases error responses, e.g. if a requested database cannot be found."""
"""Databases error responses, e.g. if the requested database cannot be found."""
NotFoundError = ResponseError({
status.HTTP_404_NOT_FOUND:
"Could not find the given database name."
Expand All @@ -68,7 +68,7 @@ class Databases(ResponsesErrorGroup):


class Documents(ResponsesErrorGroup):
"""Documents error responses, e.g. if a requested document cannot be found."""
"""Documents error responses, e.g. if the requested document cannot be found."""
NotFound = ResponseError({
status.HTTP_404_NOT_FOUND:
"Could not find any document with the given object id."
Expand Down
17 changes: 11 additions & 6 deletions trolldb/database/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async def get_id(doc: CoroutineDocument) -> str:
Note:
The rationale behind this method is as follows. In MongoDB, each document has a unique ID which is of type
:class:`~bson.objectid.ObjectId`. This is not suitable for purposes when a simple string is needed, hence
:class:`bson.objectid.ObjectId`. This is not suitable for purposes when a simple string is needed, hence
the need for this method.
Args:
Expand Down Expand Up @@ -84,7 +84,7 @@ async def get_ids(docs: Union[AsyncIOMotorCommandCursor, AsyncIOMotorCursor]) ->
class MongoDB:
"""A wrapper class around the `motor async driver <https://www.mongodb.com/docs/drivers/motor/>`_ for Mongo DB.
It includes convenience methods tailored to our specific needs. As such, the :func:`~MongoDB.initialize()`` method
It includes convenience methods tailored to our specific needs. As such, the :func:`~MongoDB.initialize()` method
returns a coroutine which needs to be awaited.
Note:
Expand Down Expand Up @@ -117,16 +117,20 @@ async def initialize(cls, database_config: DatabaseConfig):
Args:
database_config:
A named tuple which includes the database configurations.
An object of type :class:`~trolldb.config.config.DatabaseConfig` which includes the database
configurations.
Warning:
The timeout is given in seconds in the configurations, while the MongoDB uses milliseconds.
Returns:
On success ``None``.
Raises:
SystemExit(errno.EIO):
If connection is not established (``ConnectionFailure``)
If connection is not established, i.e. ``ConnectionFailure``.
SystemExit(errno.EIO):
If the attempt times out (``ServerSelectionTimeoutError``)
If the attempt times out, i.e. ``ServerSelectionTimeoutError``.
SystemExit(errno.EIO):
If one attempts reinitializing the class with new (different) database configurations without calling
:func:`~close()` first.
Expand All @@ -135,7 +139,8 @@ async def initialize(cls, database_config: DatabaseConfig):
configurations still exist and are different from the new ones which have been just provided.
SystemExit(errno.ENODATA):
If either ``database_config.main_database`` or ``database_config.main_collection`` does not exist.
If either ``database_config.main_database_name`` or ``database_config.main_collection_name`` does not
exist.
"""
logger.info("Attempt to initialize the MongoDB client ...")
logger.info("Checking the database configs ...")
Expand Down
2 changes: 1 addition & 1 deletion trolldb/database/piplines.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Pipelines(list):
Each item in the list is a dictionary with its key being the literal string ``"$match"`` and its corresponding value
being of type :class:`PipelineBooleanDict`. The ``"$match"`` key is what actually triggers the matching operation in
the MongoDB aggregation pipeline. The condition against which the matching will be performed is given by the value
which is a simply a boolean pipeline dictionary which has a hierarchical structure.
which is a simply a boolean pipeline dictionary and has a hierarchical structure.
Example:
.. code-block:: python
Expand Down
18 changes: 11 additions & 7 deletions trolldb/errors/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ def _listify(item: str | list[str]) -> list[str]:
.. code-block:: python
# The following evaluate to True
__listify("test") == ["test"]
__listify(["a", "b"]) = ["a", "b"]
__listify([]) == []
_listify("test") == ["test"]
_listify(["a", "b"]) = ["a", "b"]
_listify([]) == []
"""
return item if isinstance(item, list) else [item]

Expand Down Expand Up @@ -76,8 +76,7 @@ class ResponseError(Exception):
error_b = ResponseError({404: "Not Found"})
errors = error_a | error_b
# When used in a FastAPI response descriptor,
# the following string will be generated for errors
# When used in a FastAPI response descriptor, the following string is generated
"Bad Request |OR| Not Found"
"""

Expand All @@ -101,7 +100,7 @@ def __init__(self, args_dict: OrderedDict[StatusCode, str | list[str]] | dict) -
error_b = ResponseError({404: "Not Found"})
errors = error_a | error_b
errors_a_or_b = ResponseError({400: "Bad Request", 404: "Not Found"})
errors_list = ResponseError({404: ["Not Found", "Still Not Found"]})
errors_list = ResponseError({404: ["Not Found", "Yet Not Found"]})
"""
self.__dict: OrderedDict = OrderedDict(args_dict)
self.extra_information: dict | None = None
Expand Down Expand Up @@ -188,7 +187,7 @@ def get_error_details(
Args:
extra_information (Optional, default ``None``):
More information (if any) that wants to be added to the message string.
More information (if any) that needs to be added to the message string.
status_code (Optional, default ``None``):
The status code to retrieve. This is useful when there are several error items in the internal
dictionary. In case of ``None``, the internal dictionary must include a single entry, otherwise an error
Expand Down Expand Up @@ -233,6 +232,11 @@ def sys_exit_log(
def fastapi_descriptor(self) -> dict[StatusCode, dict[str, str]]:
"""Gets the FastAPI descriptor (dictionary) of the error items stored in :obj:`ResponseError.__dict`.
Note:
Consult the FastAPI documentation for
`additional responses <https://fastapi.tiangolo.com/advanced/additional-responses/>`_ to see why and how
descriptors are used.
Example:
.. code-block:: python
Expand Down
2 changes: 1 addition & 1 deletion trolldb/test_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""This package provide tools to test the database and api packages."""
"""This package provides tools to test the database and api packages."""
2 changes: 1 addition & 1 deletion trolldb/test_utils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def make_test_app_config(subscriber_address: Optional[FilePath] = None) -> dict:
config will be an empty dictionary.
Returns:
A dictionary which resembles an object of type :obj:`AppConfig`.
A dictionary which resembles an object of type :obj:`~trolldb.config.config.AppConfig`.
"""
app_config = dict(
api_server=dict(
Expand Down
Loading

0 comments on commit 929543a

Please sign in to comment.