refactor(api)!: Unifying log under 1 logger and removing debug parameter
So now you control the logging and the debugging from the shell through the logger with the name 'scrapling'
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
import sqlite3
|
||||
import threading
|
||||
from abc import ABC, abstractmethod
|
||||
@@ -9,7 +8,7 @@ from lxml import html
|
||||
from tldextract import extract as tld
|
||||
|
||||
from scrapling.core._types import Dict, Optional, Union
|
||||
from scrapling.core.utils import _StorageTools, cache
|
||||
from scrapling.core.utils import _StorageTools, log, lru_cache
|
||||
|
||||
|
||||
class StorageSystemMixin(ABC):
|
||||
@@ -20,7 +19,7 @@ class StorageSystemMixin(ABC):
|
||||
"""
|
||||
self.url = url
|
||||
|
||||
@cache(None, typed=True)
|
||||
@lru_cache(None, typed=True)
|
||||
def _get_base_url(self, default_value: str = 'default') -> str:
|
||||
if not self.url or type(self.url) is not str:
|
||||
return default_value
|
||||
@@ -52,7 +51,7 @@ class StorageSystemMixin(ABC):
|
||||
raise NotImplementedError('Storage system must implement `save` method')
|
||||
|
||||
@staticmethod
|
||||
@cache(None, typed=True)
|
||||
@lru_cache(None, typed=True)
|
||||
def _get_hash(identifier: str) -> str:
|
||||
"""If you want to hash identifier in your storage system, use this safer"""
|
||||
identifier = identifier.lower().strip()
|
||||
@@ -64,7 +63,7 @@ class StorageSystemMixin(ABC):
|
||||
return f"{hash_value}_{len(identifier)}" # Length to reduce collision chance
|
||||
|
||||
|
||||
@cache(None, typed=True)
|
||||
@lru_cache(None, typed=True)
|
||||
class SQLiteStorageSystem(StorageSystemMixin):
|
||||
"""The recommended system to use, it's race condition safe and thread safe.
|
||||
Mainly built so the library can run in threaded frameworks like scrapy or threaded tools
|
||||
@@ -86,7 +85,7 @@ class SQLiteStorageSystem(StorageSystemMixin):
|
||||
self.connection.execute("PRAGMA journal_mode=WAL")
|
||||
self.cursor = self.connection.cursor()
|
||||
self._setup_database()
|
||||
logging.debug(
|
||||
log.debug(
|
||||
f'Storage system loaded with arguments (storage_file="{storage_file}", url="{url}")'
|
||||
)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from cssselect.xpath import XPathExpr as OriginalXPathExpr
|
||||
from w3lib.html import HTML5_WHITESPACE
|
||||
|
||||
from scrapling.core._types import Any, Optional, Protocol, Self
|
||||
from scrapling.core.utils import cache
|
||||
from scrapling.core.utils import lru_cache
|
||||
|
||||
regex = f"[{HTML5_WHITESPACE}]+"
|
||||
replace_html5_whitespaces = re.compile(regex).sub
|
||||
@@ -139,6 +139,6 @@ class TranslatorMixin:
|
||||
|
||||
|
||||
class HTMLTranslator(TranslatorMixin, OriginalHTMLTranslator):
|
||||
@cache(maxsize=256)
|
||||
@lru_cache(maxsize=256)
|
||||
def css_to_xpath(self, css: str, prefix: str = "descendant-or-self::") -> str:
|
||||
return super().css_to_xpath(css, prefix)
|
||||
|
||||
+29
-28
@@ -9,18 +9,36 @@ from scrapling.core._types import Any, Dict, Iterable, Union
|
||||
|
||||
# Using cache on top of a class is brilliant way to achieve Singleton design pattern without much code
|
||||
# functools.cache is available on Python 3.9+ only so let's keep lru_cache
|
||||
from functools import lru_cache as cache # isort:skip
|
||||
|
||||
from functools import lru_cache # isort:skip
|
||||
|
||||
html_forbidden = {html.HtmlComment, }
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="[%(asctime)s] %(levelname)s: %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
handlers=[
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(1, typed=True)
|
||||
def setup_logger():
|
||||
"""Create and configure a logger with a standard format.
|
||||
|
||||
:returns: logging.Logger: Configured logger instance
|
||||
"""
|
||||
logger = logging.getLogger('scrapling')
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
fmt="[%(asctime)s] %(levelname)s: %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
# Add handler to logger (if not already added)
|
||||
if not logger.handlers:
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
log = setup_logger()
|
||||
|
||||
|
||||
def is_jsonable(content: Union[bytes, str]) -> bool:
|
||||
@@ -34,23 +52,6 @@ def is_jsonable(content: Union[bytes, str]) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
@cache(None, typed=True)
|
||||
def setup_basic_logging(level: str = 'debug'):
|
||||
levels = {
|
||||
'debug': logging.DEBUG,
|
||||
'info': logging.INFO,
|
||||
'warning': logging.WARNING,
|
||||
'error': logging.ERROR,
|
||||
'critical': logging.CRITICAL
|
||||
}
|
||||
formatter = logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s", "%Y-%m-%d %H:%M:%S")
|
||||
lvl = levels[level.lower()]
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(formatter)
|
||||
# Configure the root logger
|
||||
logging.basicConfig(level=lvl, handlers=[handler])
|
||||
|
||||
|
||||
def flatten(lst: Iterable):
|
||||
return list(chain.from_iterable(lst))
|
||||
|
||||
@@ -114,7 +115,7 @@ class _StorageTools:
|
||||
# return _impl
|
||||
|
||||
|
||||
@cache(None, typed=True)
|
||||
@lru_cache(None, typed=True)
|
||||
def clean_spaces(string):
|
||||
string = string.replace('\t', ' ')
|
||||
string = re.sub('[\n|\r]', '', string)
|
||||
|
||||
Reference in New Issue
Block a user