Skip to content
Open
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
36 changes: 22 additions & 14 deletions cloudinit/distros/parsers/hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,58 @@
# This file is part of cloud-init. See LICENSE file for license information.

from io import StringIO
from typing import List, Optional, Set, Tuple

from cloudinit.distros.parsers import chop_comment

# A single parsed line: its type ("blank", "all_comment" or "hostname") and the
# string components that make it up.
_ParsedLine = Tuple[str, List[str]]


# Parser that knows how to work with /etc/hostname format
class HostnameConf:
def __init__(self, text):
def __init__(self, text: str) -> None:
self._text = text
self._contents = None
self._contents: Optional[List[_ParsedLine]] = None

def parse(self):
def parse(self) -> None:
if self._contents is None:
self._contents = self._parse(self._text)

def __str__(self):
def __str__(self) -> str:
self.parse()
contents = StringIO()
assert self._contents is not None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this technically is a form of type narrowing, it results in an exception when the assertion is fails.

out = StringIO()
for line_type, components in self._contents:
if line_type == "blank":
contents.write("%s\n" % (components[0]))
out.write("%s\n" % (components[0]))
elif line_type == "all_comment":
contents.write("%s\n" % (components[0]))
out.write("%s\n" % (components[0]))
elif line_type == "hostname":
(hostname, tail) = components
contents.write("%s%s\n" % (hostname, tail))
out.write("%s%s\n" % (hostname, tail))
# Ensure trailing newline
contents = contents.getvalue()
contents = out.getvalue()
if not contents.endswith("\n"):
contents += "\n"
return contents

@property
def hostname(self):
def hostname(self) -> Optional[str]:
self.parse()
assert self._contents is not None
for line_type, components in self._contents:
if line_type == "hostname":
return components[0]
return None

def set_hostname(self, your_hostname):
def set_hostname(self, your_hostname: str) -> None:
your_hostname = your_hostname.strip()
if not your_hostname:
return
self.parse()
assert self._contents is not None
replaced = False
for line_type, components in self._contents:
if line_type == "hostname":
Expand All @@ -57,9 +65,9 @@ def set_hostname(self, your_hostname):
if not replaced:
self._contents.append(("hostname", [str(your_hostname), ""]))

def _parse(self, contents):
entries = []
hostnames_found = set()
def _parse(self, contents: str) -> List[_ParsedLine]:
entries: List[_ParsedLine] = []
hostnames_found: Set[str] = set()
for line in contents.splitlines():
if not len(line.strip()):
entries.append(("blank", [line]))
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ module = [
"cloudinit.distros.azurelinux",
"cloudinit.distros.bsd",
"cloudinit.distros.opensuse",
"cloudinit.distros.parsers.hostname",
"cloudinit.distros.parsers.resolv_conf",
"cloudinit.distros.ug_util",
"cloudinit.helpers",
Expand Down
Loading