Skip to content

Fix log #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 12 additions & 64 deletions src/cript/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ class API:
"""

# dictates whether the user wants to see terminal log statements or not
_verbose: bool = True
logger: logging.Logger = None # type: ignore
_logger: logging.Logger = None # type: ignore

_host: str = ""
_api_token: str = ""
Expand All @@ -77,7 +76,7 @@ class API:
# trunk-ignore-end(cspell)

@beartype
def __init__(self, host: Union[str, None] = None, api_token: Union[str, None] = None, storage_token: Union[str, None] = None, config_file_path: Union[str, Path] = ""):
def __init__(self, host: Union[str, None] = None, api_token: Union[str, None] = None, storage_token: Union[str, None] = None, config_file_path: Union[str, Path] = "", default_log_level=logging.INFO):
"""
Initialize CRIPT API client with host and token.
Additionally, you can use a config.json file and specify the file path.
Expand Down Expand Up @@ -220,8 +219,8 @@ def __init__(self, host: Union[str, None] = None, api_token: Union[str, None] =
self._check_initial_host_connection()

# set a logger instance to use for the class logs
self._set_logger()
self._db_schema = DataSchema(self.host)
self._init_logger(default_log_level)
self._db_schema = DataSchema(self.host, self.logger)

def __str__(self) -> str:
"""
Expand All @@ -244,15 +243,15 @@ def __str__(self) -> str:
"""
return f"CRIPT API Client - Host URL: '{self.host}'"

def _set_logger(self, verbose: bool = True) -> None:
def _init_logger(self, log_level=logging.INFO) -> None:
"""
Prepare and configure the logger for the API class.

This function creates and configures a logger instance associated with the current module (class).

Parameters
----------
verbose: bool default True
log_level: logging.LEVEL default logging.INFO
set if you want `cript.API` to give logs to console or not

Returns
Expand All @@ -263,11 +262,7 @@ def _set_logger(self, verbose: bool = True) -> None:
# Create a logger instance associated with the current module
logger = logging.getLogger(__name__)

# Set the logger's level based on the verbose flag
if verbose:
logger.setLevel(logging.INFO) # Display INFO logs
else:
logger.setLevel(logging.CRITICAL) # Display no logs
logger.setLevel(log_level)

# Create a console handler
console_handler = logging.StreamHandler()
Expand All @@ -282,58 +277,11 @@ def _set_logger(self, verbose: bool = True) -> None:
logger.addHandler(console_handler)

# set logger for the class
self.logger = logger
self._logger = logger

@property
def verbose(self) -> bool:
"""
A boolean flag that controls whether verbose logging is enabled or not.

When `verbose` is set to `True`, the class will provide additional detailed logging
to the terminal. This can be useful for debugging and understanding the internal
workings of the class.

```bash
INFO: Validating Project graph...
```

When `verbose` is set to `False`, the class will only provide essential logging information,
making the terminal output less cluttered and more user-friendly.

Examples
--------
>>> import cript
>>> with cript.API(
... host="https://api.criptapp.org/",
... api_token=os.getenv("CRIPT_TOKEN"),
... storage_token=os.getenv("CRIPT_STORAGE_TOKEN")
... ) as api:
... # turn off the terminal logs
... api.verbose = False

Returns
-------
bool
verbose boolean value
"""
return self._verbose

@verbose.setter
def verbose(self, new_verbose_value: bool) -> None:
"""
sets the verbose value and then sets a new logger for the class

Parameters
----------
new_verbose_value: bool
new verbose value to turn the logging ON or OFF

Returns
-------
None
"""
self._verbose = new_verbose_value
self._set_logger(verbose=new_verbose_value)
def logger(self):
return self._logger

@beartype
def _prepare_host(self, host: str) -> str:
Expand Down Expand Up @@ -932,7 +880,7 @@ def delete(self, node) -> None:

Notes
-----
After the node has been successfully deleted, a log is written to the terminal if `cript.API.verbose = True`
After the node has been successfully deleted, a log is written to the terminal

```bash
INFO: Deleted 'Material' with UUID of '80bfc642-157e-4692-a547-97c470725397' from CRIPT API.
Expand Down Expand Up @@ -1010,7 +958,7 @@ def delete_node_by_uuid(self, node_type: str, node_uuid: str) -> None:

Notes
-----
After the node has been successfully deleted, a log is written to the terminal if `cript.API.verbose = True`
After the node has been successfully deleted, a log is written

```bash
INFO: Deleted 'Material' with UUID of '80bfc642-157e-4692-a547-97c470725397' from CRIPT API.
Expand Down
14 changes: 9 additions & 5 deletions src/cript/api/data_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
import logging
from typing import Union

import jsonschema
Expand All @@ -21,6 +20,7 @@ class DataSchema:

_vocabulary: dict = {}
_db_schema: dict = {}
_logger = None
# Advanced User Tip: Disabling Node Validation
# For experienced users, deactivating node validation during creation can be a time-saver.
# Note that the complete node graph will still undergo validation before being saved to the back end.
Expand All @@ -45,13 +45,15 @@ def _get_db_schema(self, host: str) -> dict:
return self._db_schema

# fetch db_schema from API
logging.info(f"Loading node validation schema from {host}/schema/")
if self._logger:
self._logger.info(f"Loading node validation schema from {host}/schema/")
# fetch db schema from API
response: requests.Response = requests.get(url=f"{host}/schema/", timeout=_API_TIMEOUT)

# raise error if not HTTP 200
response.raise_for_status()
logging.info(f"Loading node validation schema from {host}/schema/ was successful.")
if self._logger:
self._logger.info(f"Loading node validation schema from {host}/schema/ was successful.")

# if no error, take the JSON from the API response
response_dict: dict = response.json()
Expand All @@ -61,7 +63,7 @@ def _get_db_schema(self, host: str) -> dict:

return db_schema

def __init__(self, host: str):
def __init__(self, host: str, logger=None):
"""
Initialize DataSchema class with a full hostname to fetch the node validation schema.

Expand All @@ -75,6 +77,7 @@ def __init__(self, host: str):

self._db_schema = self._get_db_schema(host)
self._vocabulary = self._get_vocab(host)
self._logger = logger

def _get_vocab(self, host: str) -> dict:
"""
Expand Down Expand Up @@ -244,7 +247,8 @@ def is_node_schema_valid(self, node_json: str, is_patch: bool = False, force_val
else:
log_message += " (Can be disabled by setting `cript.API.skip_validation = True`.)"

logging.info(log_message)
if self._logger:
self._logger.info(log_message)

# set the schema to test against http POST or PATCH of DB Schema
schema_http_method: str
Expand Down