Coverage for aiocoap / util / linkformat.py: 100%
19 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 12:28 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 12:28 +0000
1# SPDX-FileCopyrightText: Christian Amsüss and the aiocoap contributors
2#
3# SPDX-License-Identifier: MIT
5"""This module contains in-place modifications to the LinkHeader module to
6satisfy RFC6690 constraints.
8It is a general nursery for what aiocoap needs of link-format management before
9any of this is split out into its own package.
10"""
12from .vendored import link_header
15class LinkFormat(link_header.LinkHeader):
16 """Variation of the now vendered-in link_header package.
18 This accounts for the RFC6690 constraint (not present in RFC5899) that
19 there be no space after commas or semicolons.
21 >>> str(LinkFormat([Link("/parent/", rel="up"), Link("/parent/here/child")]))
22 '</parent/>;rel="up",</parent/here/child>'
23 """
25 def __str__(self):
26 return ",".join(str(link) for link in self.links)
29class Link(link_header.Link):
30 # This is copy-pasted from the link_header module's code, just replacing
31 # the '; ' with ';'.
32 #
33 # Original copyright Michael Burrows <mjb@asplake.co.uk>, distributed under
34 # the BSD license
35 def __str__(self):
36 def str_pair(key, value):
37 if value is None:
38 return key
39 # workaround to accommodate copper
40 # elif RE_ONLY_TOKEN.match(value) or key.endswith('*'):
41 # return '%s=%s' % (key, value)
42 else:
43 return '%s="%s"' % (key, value.replace('"', r"\""))
45 return ";".join(
46 ["<%s>" % self.href]
47 + [str_pair(key, value) for key, value in self.attr_pairs]
48 )
51def parse(linkformat: str | bytes) -> LinkFormat:
52 """Parses RFC6690 links.
54 Unlike the (now vendored-in) link_header package's parsing, this
56 - accepts either bytes or strings; the former are decoded as UTF-8
57 - produces types that, in their serialization, account for differences between RFC6690 and RFC5899
59 >>> parse(b"</hell\\xc3\\xb6>")
60 LinkHeader([Link('/hellö')])
61 >>> parse("</hellö>")
62 LinkHeader([Link('/hellö')])
63 """
64 if isinstance(linkformat, bytes):
65 linkformat = linkformat.decode("utf-8")
66 data = link_header.parse(linkformat)
67 data.__class__ = LinkFormat
68 for link in data.links:
69 link.__class__ = Link
70 return data