Erster Stand der Hintergrundprozesse, die auf der Synology unter /volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins Web-Verzeichnis. Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot), zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat. Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py, gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte. Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein pip, sie muessen neben den Skripten liegen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
105 lines
4.1 KiB
Python
105 lines
4.1 KiB
Python
# Copyright (c) 2020, 2022, Oracle and/or its affiliates.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License, version 2.0, as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is also distributed with certain software (including
|
|
# but not limited to OpenSSL) that is licensed under separate terms,
|
|
# as designated in a particular file or component or in included license
|
|
# documentation. The authors of MySQL hereby grant you an
|
|
# additional permission to link the program and your derivative works
|
|
# with the separately licensed software that they have included with
|
|
# MySQL.
|
|
#
|
|
# Without limiting anything contained in the foregoing, this file,
|
|
# which is part of MySQL Connector/Python, is also subject to the
|
|
# Universal FOSS Exception, version 1.0, a copy of which can be found at
|
|
# http://oss.oracle.com/licenses/universal-foss-exception.
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
# See the GNU General Public License, version 2.0, for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
# mypy: disable-error-code="override,attr-defined"
|
|
|
|
"""Database Operations."""
|
|
|
|
from datetime import datetime, time
|
|
from typing import Optional
|
|
|
|
from django.conf import settings
|
|
from django.db.backends.mysql.operations import (
|
|
DatabaseOperations as MySQLDatabaseOperations,
|
|
)
|
|
from django.utils import timezone
|
|
|
|
try:
|
|
from _mysql_connector import datetime_to_mysql, time_to_mysql
|
|
except ImportError:
|
|
HAVE_CEXT = False
|
|
else:
|
|
HAVE_CEXT = True
|
|
|
|
|
|
class DatabaseOperations(MySQLDatabaseOperations):
|
|
"""Database Operations class."""
|
|
|
|
compiler_module = "mysql.connector.django.compiler"
|
|
|
|
def regex_lookup(self, lookup_type: str) -> str:
|
|
"""Return the string to use in a query when performing regular
|
|
expression lookup."""
|
|
if self.connection.mysql_version < (8, 0, 0):
|
|
if lookup_type == "regex":
|
|
return "%s REGEXP BINARY %s"
|
|
return "%s REGEXP %s"
|
|
|
|
match_option = "c" if lookup_type == "regex" else "i"
|
|
return f"REGEXP_LIKE(%s, %s, '{match_option}')"
|
|
|
|
def adapt_datetimefield_value(self, value: Optional[datetime]) -> Optional[bytes]:
|
|
"""Transform a datetime value to an object compatible with what is
|
|
expected by the backend driver for datetime columns."""
|
|
return self.value_to_db_datetime(value)
|
|
|
|
def value_to_db_datetime(self, value: Optional[datetime]) -> Optional[bytes]:
|
|
"""Convert value to MySQL DATETIME."""
|
|
ans: Optional[bytes] = None
|
|
if value is None:
|
|
return ans
|
|
# MySQL doesn't support tz-aware times
|
|
if timezone.is_aware(value):
|
|
if settings.USE_TZ:
|
|
value = value.astimezone(timezone.utc).replace(tzinfo=None)
|
|
else:
|
|
raise ValueError("MySQL backend does not support timezone-aware times")
|
|
if not self.connection.features.supports_microsecond_precision:
|
|
value = value.replace(microsecond=0)
|
|
if not self.connection.use_pure:
|
|
return datetime_to_mysql(value)
|
|
return self.connection.converter.to_mysql(value)
|
|
|
|
def adapt_timefield_value(self, value: Optional[time]) -> Optional[bytes]:
|
|
"""Transform a time value to an object compatible with what is expected
|
|
by the backend driver for time columns."""
|
|
return self.value_to_db_time(value)
|
|
|
|
def value_to_db_time(self, value: Optional[time]) -> Optional[bytes]:
|
|
"""Convert value to MySQL TIME."""
|
|
if value is None:
|
|
return None
|
|
|
|
# MySQL doesn't support tz-aware times
|
|
if timezone.is_aware(value):
|
|
raise ValueError("MySQL backend does not support timezone-aware times")
|
|
|
|
if not self.connection.use_pure:
|
|
return time_to_mysql(value)
|
|
return self.connection.converter.to_mysql(value)
|