1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-06 21:32:21 +01:00

Merge remote-tracking branch 'upstream/dev' into protosize_object

This commit is contained in:
J. Nick Koston
2025-07-27 18:46:54 -10:00
38 changed files with 1027 additions and 188 deletions

View File

@@ -562,11 +562,16 @@ class StringType(TypeInfo):
@property
def public_content(self) -> list[str]:
content: list[str] = []
# Add std::string storage if message needs decoding
if self._needs_decode:
# Check if no_zero_copy option is set
no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False)
# Add std::string storage if message needs decoding OR if no_zero_copy is set
if self._needs_decode or no_zero_copy:
content.append(f"std::string {self.field_name}{{}};")
if self._needs_encode:
# Only add StringRef if encoding is needed AND no_zero_copy is not set
if self._needs_encode and not no_zero_copy:
content.extend(
[
# Add StringRef field if message needs encoding
@@ -581,13 +586,28 @@ class StringType(TypeInfo):
@property
def encode_content(self) -> str:
return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);"
# Check if no_zero_copy option is set
no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False)
if no_zero_copy:
# Use the std::string directly
return f"buffer.encode_string({self.number}, this->{self.field_name});"
else:
# Use the StringRef
return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);"
def dump(self, name):
# Check if no_zero_copy option is set
no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False)
# If name is 'it', this is a repeated field element - always use string
if name == "it":
return "append_quoted_string(out, StringRef(it));"
# If no_zero_copy is set, always use std::string
if no_zero_copy:
return f'out.append("\'").append(this->{self.field_name}).append("\'");'
# For SOURCE_CLIENT only, always use std::string
if not self._needs_encode:
return f'out.append("\'").append(this->{self.field_name}).append("\'");'
@@ -607,6 +627,13 @@ class StringType(TypeInfo):
@property
def dump_content(self) -> str:
# Check if no_zero_copy option is set
no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False)
# If no_zero_copy is set, always use std::string
if no_zero_copy:
return f'dump_field(out, "{self.name}", this->{self.field_name});'
# For SOURCE_CLIENT only, use std::string
if not self._needs_encode:
return f'dump_field(out, "{self.name}", this->{self.field_name});'
@@ -622,8 +649,17 @@ class StringType(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
# For SOURCE_CLIENT only messages, use the string field directly
if not self._needs_encode:
# Check if no_zero_copy option is set
no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False)
# For SOURCE_CLIENT only messages or no_zero_copy, use the string field directly
if not self._needs_encode or no_zero_copy:
# For no_zero_copy, we need to use .size() on the string
if no_zero_copy and name != "it":
field_id_size = self.calculate_field_id_size()
return (
f"size.add_length({field_id_size}, this->{self.field_name}.size());"
)
return self._get_simple_size_calculation(name, force, "add_length")
# Check if this is being called from a repeated field context

View File

@@ -197,7 +197,7 @@ def lint_content_find_check(find, only_first=False, **kwargs):
find_ = find(fname, content)
errs = []
for line, col in find_all(content, find_):
err = func(fname)
err = func(fname, line, col, content)
errs.append((line + 1, col + 1, err))
if only_first:
break
@@ -264,12 +264,12 @@ def lint_executable_bit(fname):
"esphome/dashboard/static/ext-searchbox.js",
],
)
def lint_tabs(fname):
def lint_tabs(fname, line, col, content):
return "File contains tab character. Please convert tabs to spaces."
@lint_content_find_check("\r", only_first=True)
def lint_newline(fname):
def lint_newline(fname, line, col, content):
return "File contains Windows newline. Please set your editor to Unix newline mode."
@@ -512,7 +512,7 @@ def relative_cpp_search_text(fname, content):
@lint_content_find_check(relative_cpp_search_text, include=["esphome/components/*.cpp"])
def lint_relative_cpp_import(fname):
def lint_relative_cpp_import(fname, line, col, content):
return (
"Component contains absolute import - Components must always use "
"relative imports.\n"
@@ -529,6 +529,20 @@ def relative_py_search_text(fname, content):
return f"esphome.components.{integration}"
def convert_path_to_relative(abspath, current):
"""Convert an absolute path to a relative import path."""
if abspath == current:
return "."
absparts = abspath.split(".")
curparts = current.split(".")
uplen = len(curparts)
while absparts and curparts and absparts[0] == curparts[0]:
absparts.pop(0)
curparts.pop(0)
uplen -= 1
return "." * uplen + ".".join(absparts)
@lint_content_find_check(
relative_py_search_text,
include=["esphome/components/*.py"],
@@ -537,14 +551,19 @@ def relative_py_search_text(fname, content):
"esphome/components/web_server/__init__.py",
],
)
def lint_relative_py_import(fname):
def lint_relative_py_import(fname, line, col, content):
import_line = content.splitlines()[line]
abspath = import_line[col:].split(" ")[0]
current = fname.removesuffix(".py").replace(os.path.sep, ".")
replacement = convert_path_to_relative(abspath, current)
newline = import_line.replace(abspath, replacement)
return (
"Component contains absolute import - Components must always use "
"relative imports within the integration.\n"
"Change:\n"
' from esphome.components.abc import abc_ns"\n'
f" {import_line}\n"
"to:\n"
" from . import abc_ns\n\n"
f" {newline}\n"
)
@@ -588,7 +607,7 @@ def lint_namespace(fname, content):
@lint_content_find_check('"esphome.h"', include=cpp_include, exclude=["tests/custom.h"])
def lint_esphome_h(fname):
def lint_esphome_h(fname, line, col, content):
return (
"File contains reference to 'esphome.h' - This file is "
"auto-generated and should only be used for *custom* "
@@ -679,7 +698,7 @@ def lint_trailing_whitespace(fname, match):
"tests/custom.h",
],
)
def lint_log_in_header(fname):
def lint_log_in_header(fname, line, col, content):
return (
"Found reference to ESP_LOG in header file. Using ESP_LOG* in header files "
"is currently not possible - please move the definition to a source file (.cpp)"

View File

@@ -6,7 +6,7 @@ set -e
cd "$(dirname "$0")/.."
if [ ! -n "$VIRTUAL_ENV" ]; then
if [ -x "$(command -v uv)" ]; then
uv venv venv
uv venv --seed venv
else
python3 -m venv venv
fi