Memory usage - small improvement by tidying up module imports

This commit is contained in:
dgtlmoon
2026-09-01 16:50:58 +02:00
parent 143a0f116f
commit e765588089
6 changed files with 15 additions and 13 deletions
@@ -1,7 +1,6 @@
import re
import pluggy
from price_parser import Price
from loguru import logger
from flask_babel import lazy_gettext as _l
@@ -70,6 +69,7 @@ def register_field_choices():
@hookimpl
def add_data(current_watch_uuid, application_datastruct, ephemeral_data):
from price_parser import Price
res = {}
if 'text' in ephemeral_data:
res['page_filtered_text'] = ephemeral_data['text']
+2 -2
View File
@@ -696,14 +696,14 @@ class ValidateCSSJSONXPATHInput(object):
raise ValidationError("XPath not permitted in this field!")
from lxml import etree, html
import elementpath
from changedetectionio.html_tools import SafeXPath3Parser, lxml_guard, lxml_html_parser
from changedetectionio.html_tools import get_safe_xpath3_parser, lxml_guard, lxml_html_parser
line = line.replace('xpath:', '')
try:
# Runs on a Flask request thread - must share the worker's lxml lock.
with lxml_guard():
tree = html.fromstring("<html></html>", parser=lxml_html_parser())
elementpath.select(tree, line.strip(), parser=SafeXPath3Parser)
elementpath.select(tree, line.strip(), parser=get_safe_xpath3_parser())
except elementpath.ElementPathError as e:
message = field.gettext('\'%(expression)s\' is not a valid XPath expression. (%(error)s)')
raise ValidationError(message % {'expression': line, 'error': str(e)})
+3 -5
View File
@@ -164,7 +164,8 @@ _DEFAULT_UNSAFE_XPATH3_FUNCTIONS = [
]
def _build_safe_xpath3_parser():
@lru_cache(maxsize=1)
def get_safe_xpath3_parser():
"""Return an XPath3Parser subclass with filesystem/environment access functions removed.
XPath 3.0 includes functions that can read arbitrary files or environment variables:
@@ -196,9 +197,6 @@ def _build_safe_xpath3_parser():
return SafeXPath3Parser
# Module-level singleton — built once, reused everywhere.
SafeXPath3Parser = _build_safe_xpath3_parser()
# Doesn't look like python supports forward slash auto enclosure in re.findall
# So convert it to inline flag "(?i)foobar" type configuration
@lru_cache(maxsize=100)
@@ -386,7 +384,7 @@ def xpath_filter(xpath_filter, html_content, append_pretty_line_formatting=False
# This allows //title to match elements in the default namespace
namespaces[''] = tree.nsmap[None]
r = elementpath.select(tree, xpath_filter.strip(), namespaces=namespaces, parser=SafeXPath3Parser)
r = elementpath.select(tree, xpath_filter.strip(), namespaces=namespaces, parser=get_safe_xpath3_parser())
#@note: //title/text() now works with default namespaces (fixed by registering '' prefix)
#@note: //title/text() wont work where <title>CDATA.. (use cdata_in_document_to_text first)
@@ -80,7 +80,6 @@ Note:
This extension uses the Arrow library for timezone-aware datetime handling.
All timezone names should be valid IANA timezone identifiers (e.g., 'America/New_York').
"""
import arrow
from jinja2 import nodes
from jinja2.ext import Extension
@@ -125,6 +124,7 @@ class TimeExtension(Extension):
_datetime('UTC', '+', 'hours=2,minutes=30', '%Y-%m-%d %H:%M:%S')
# Returns current time + 2.5 hours
"""
import arrow
# Use default timezone if none specified
if not timezone or timezone == '':
timezone = self.environment.default_timezone
@@ -162,6 +162,7 @@ class TimeExtension(Extension):
_now('America/New_York', '%Y-%m-%d %H:%M:%S')
# Returns current time in New York timezone
"""
import arrow
# Use default timezone if none specified
if not timezone or timezone == '':
timezone = self.environment.default_timezone
+5 -3
View File
@@ -1,11 +1,8 @@
import time
import re
import apprise
from apprise import NotifyFormat
from loguru import logger
from urllib.parse import urlparse
from .apprise_plugin.assets import apprise_asset, APPRISE_AVATAR_URL
from .email_helpers import as_monospaced_html_email
from ..diff import HTML_REMOVED_STYLE, REMOVED_PLACEMARKER_OPEN, REMOVED_PLACEMARKER_CLOSED, ADDED_PLACEMARKER_OPEN, HTML_ADDED_STYLE, \
ADDED_PLACEMARKER_CLOSED, CHANGED_INTO_PLACEMARKER_OPEN, CHANGED_INTO_PLACEMARKER_CLOSED, CHANGED_PLACEMARKER_OPEN, \
@@ -64,6 +61,7 @@ def notification_format_align_with_apprise(n_format : str):
:param n_format:
:return:
"""
from apprise import NotifyFormat
if not n_format:
return NotifyFormat.TEXT.value
@@ -208,6 +206,7 @@ def replace_placemarkers_in_text(text, url, requested_output_format):
def apply_service_tweaks(url, n_body, n_title, requested_output_format):
from .apprise_plugin.assets import APPRISE_AVATAR_URL
logger.debug(f"Applying markup in '{requested_output_format}' mode")
# Re 323 - Limit discord length to their 2000 char limit total or it wont send.
@@ -305,6 +304,9 @@ def apply_service_tweaks(url, n_body, n_title, requested_output_format):
def process_notification(n_object: NotificationContextData, datastore):
import apprise
from apprise import NotifyFormat
from .apprise_plugin.assets import apprise_asset
from changedetectionio.jinja2_custom import render as jinja_render
from . import USE_SYSTEM_DEFAULT_NOTIFICATION_FORMAT_FOR_WATCH, default_notification_format, valid_notification_formats
# be sure its registered
+2 -1
View File
@@ -1,6 +1,5 @@
from functools import lru_cache
import arrow
from enum import IntEnum
@@ -32,6 +31,7 @@ def am_i_inside_time(
Returns:
bool: True if the current time is within the time range, False otherwise.
"""
import arrow
# Parse the target day of the week
try:
target_weekday = Weekday[day_of_week.capitalize()]
@@ -91,6 +91,7 @@ def is_within_schedule(time_schedule_limit, default_tz="UTC"):
Returns:
bool: True if current time is within the schedule, False otherwise.
"""
import arrow
if time_schedule_limit and time_schedule_limit.get('enabled'):
# Get the timezone the time schedule is in, so we know what day it is there
tz_name = time_schedule_limit.get('timezone')