Skip to content

Commit 8a0eb65

Browse files
committed
Simplify utilities and core write logic
1 parent 1a31167 commit 8a0eb65

File tree

3 files changed

+41
-71
lines changed

3 files changed

+41
-71
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ python-hosts
55

66
This is a python library for managing a hosts file.
77
It enables you to add and remove entries, or import them from a file or URL.
8+
Utility functions have been streamlined for easier maintenance.
89
It remains compatible with Python 2.7 as well as modern Python 3 releases.
910

1011
Documentation

python_hosts/hosts.py

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -196,50 +196,38 @@ def write(self, path=None, mode='w'):
196196
:param path: override the write path
197197
:return: Dictionary containing counts
198198
"""
199-
written_count = 0
200-
comments_written = 0
201-
blanks_written = 0
202-
ipv4_entries_written = 0
203-
ipv6_entries_written = 0
204-
if path:
205-
output_file_path = path
206-
else:
207-
output_file_path = self.path
199+
200+
counters = {
201+
'total_written': 0,
202+
'comments_written': 0,
203+
'blanks_written': 0,
204+
'ipv4_entries_written': 0,
205+
'ipv6_entries_written': 0,
206+
}
207+
output_file_path = path if path else self.path
208208
try:
209209
with open(output_file_path, mode) as hosts_file:
210-
for written_count, line in enumerate(self.entries):
211-
if line.entry_type == 'comment':
212-
hosts_file.write(line.comment + "\n")
213-
comments_written += 1
214-
if line.entry_type == 'blank':
210+
for entry in self.entries:
211+
if entry.entry_type == 'comment':
212+
hosts_file.write(entry.comment + "\n")
213+
counters['comments_written'] += 1
214+
elif entry.entry_type == 'blank':
215215
hosts_file.write("\n")
216-
blanks_written += 1
217-
if line.entry_type == 'ipv4':
218-
hosts_file.write(
219-
"{0}\t{1}{2}\n".format(
220-
line.address,
221-
' '.join(line.names),
222-
" # " + line.comment if line.comment else ""
223-
)
224-
)
225-
ipv4_entries_written += 1
226-
if line.entry_type == 'ipv6':
216+
counters['blanks_written'] += 1
217+
else:
227218
hosts_file.write(
228219
"{0}\t{1}{2}\n".format(
229-
line.address,
230-
' '.join(line.names),
231-
" # " + line.comment if line.comment else ""
220+
entry.address,
221+
' '.join(entry.names),
222+
" # " + entry.comment if entry.comment else "",
232223
)
233224
)
234-
ipv6_entries_written += 1
225+
key = 'ipv6_entries_written' if entry.entry_type == 'ipv6' else 'ipv4_entries_written'
226+
counters[key] += 1
227+
counters['total_written'] += 1
235228
except Exception:
236229
raise UnableToWriteHosts()
237-
return {'total_written': written_count + 1,
238-
'comments_written': comments_written,
239-
'blanks_written': blanks_written,
240-
'ipv4_entries_written': ipv4_entries_written,
241-
'ipv6_entries_written': ipv6_entries_written}
242-
230+
return counters
243231
@staticmethod
244232
def get_hosts_by_url(url=None):
245233
"""
@@ -264,8 +252,10 @@ def exists(self, address=None, names=None, comment=None):
264252
if self.find_all_matching(address=address, name=name, comment=comment):
265253
return True
266254

267-
return any(entry.entry_type == 'comment' and entry.comment == comment
268-
for entry in self.entries)
255+
if comment:
256+
return any(entry.entry_type == 'comment' and entry.comment == comment
257+
for entry in self.entries)
258+
return False
269259

270260
def remove_all_matching(self, address=None, name=None, comment=None):
271261
"""

python_hosts/utils.py

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,34 @@
99

1010

1111
def is_ipv4(entry):
12-
"""
13-
Check if the string provided is a valid ipv4 address
14-
:param entry: A string representation of an IP address
15-
:return: True if valid, False if invalid
16-
"""
12+
"""Return ``True`` if ``entry`` is a valid IPv4 address."""
1713
try:
18-
if socket.inet_aton(entry):
19-
return True
14+
socket.inet_aton(entry)
2015
except socket.error:
2116
return False
17+
return True
2218

2319

2420
def is_ipv6(entry):
25-
"""
26-
Check if the string provided is a valid ipv6 address
27-
:param entry: A string representation of an IP address
28-
:return: True if valid, False if invalid
29-
"""
21+
"""Return ``True`` if ``entry`` is a valid IPv6 address."""
3022
try:
31-
if socket.inet_pton(socket.AF_INET6, entry):
32-
return True
23+
socket.inet_pton(socket.AF_INET6, entry)
3324
except socket.error:
3425
return False
26+
return True
3527

3628

3729
def valid_hostnames(hostname_list):
38-
"""
39-
Check if the supplied list of strings are valid hostnames
40-
:param hostname_list: A list of strings
41-
:return: True if the strings are valid hostnames, False if not
42-
"""
43-
for entry in hostname_list:
44-
if len(entry) > 255:
45-
return False
46-
allowed = re.compile(r'(?!-)[A-Z\d-]{1,63}(?<!-)$', re.IGNORECASE)
47-
if not all(allowed.match(x) for x in entry.split(".")):
48-
return False
49-
return True
30+
"""Return ``True`` if all items in ``hostname_list`` are valid hostnames."""
31+
allowed = re.compile(r'(?!-)[A-Z\d-]{1,63}(?<!-)$', re.IGNORECASE)
32+
return all(len(entry) <= 255 and
33+
all(allowed.match(x) for x in entry.split('.'))
34+
for entry in hostname_list)
5035

5136

5237
def is_readable(path=None):
53-
"""
54-
Test if the supplied filesystem path can be read
55-
:param path: A filesystem path
56-
:return: True if the path is a file that can be read. Otherwise, False
57-
"""
58-
if os.path.isfile(path) and os.access(path, os.R_OK):
59-
return True
60-
return False
38+
"""Return ``True`` if ``path`` exists and is readable."""
39+
return os.path.isfile(path) and os.access(path, os.R_OK)
6140

6241

6342
def dedupe_list(seq):

0 commit comments

Comments
 (0)