Coverage for aiocoap/numbers/optionnumbers.py: 93%
94 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-16 16:09 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-16 16:09 +0000
1# SPDX-FileCopyrightText: Christian Amsüss and the aiocoap contributors
2#
3# SPDX-License-Identifier: MIT
5"""Known values for CoAP option numbers
7The values defined in `OptionNumber` correspond to the IANA registry "CoRE
8Parameters", subregistries "CoAP Method Codes" and "CoAP Response Codes".
10The option numbers come with methods that can be used to evaluate their
11properties, see the `OptionNumber` class for details.
12"""
14from ..util import ExtensibleIntEnum
15from .. import optiontypes
17class OptionNumber(ExtensibleIntEnum):
18 """A CoAP option number.
20 As the option number contains information on whether the option is
21 critical, and whether it is safe-to-forward, those properties can be
22 queried using the `is_*` group of methods.
24 Note that whether an option may be repeated or not does not only depend on
25 the option, but also on the context, and is thus handled in the `Options`
26 object instead."""
27 IF_MATCH = 1
28 URI_HOST = 3
29 ETAG = 4
30 IF_NONE_MATCH = 5
31 OBSERVE = 6
32 URI_PORT = 7
33 LOCATION_PATH = 8
34 # The OBJECT_SECURITY name is to be deprecated when Python 3.8 support is
35 # dropped, and we can do that easily using a class property.
36 OSCORE = OBJECT_SECURITY = 9
37 URI_PATH = 11
38 CONTENT_FORMAT = 12
39 MAX_AGE = 14
40 URI_QUERY = 15
41 HOP_LIMIT = 16
42 ACCEPT = 17
43 Q_BLOCK1 = 19
44 LOCATION_QUERY = 20
45 EDHOC = 21
46 BLOCK2 = 23
47 BLOCK1 = 27
48 SIZE2 = 28
49 Q_BLOCK2 = 31
50 PROXY_URI = 35
51 PROXY_SCHEME = 39
52 SIZE1 = 60
53 ECHO = 252
54 NO_RESPONSE = 258
55 REQUEST_TAG = 292
57 # experimental for draft-amsuess-core-cachable-oscore
58 #
59 # Using the number suggested there (rather than a high one) as this is
60 # going to be used in overhead comparisons.
61 REQUEST_HASH = 548
63 def __add__(self, delta):
64 """Addition makes sense on these due to the delta encoding in CoAP
65 serialization"""
66 return type(self)(int(self) + delta)
68 def is_critical(self):
69 return self & 0x01 == 0x01
71 def is_elective(self):
72 return not self.is_critical()
74 def is_unsafe(self):
75 return self & 0x02 == 0x02
77 def is_safetoforward(self):
78 return not self.is_unsafe()
80 def is_nocachekey(self):
81 if self.is_unsafe():
82 raise ValueError("NoCacheKey is only meaningful for safe options")
83 return self & 0x1e == 0x1c
85 def is_cachekey(self):
86 return not self.is_nocachekey()
88 def _get_format(self):
89 if hasattr(self, "_format"):
90 return self._format
91 else:
92 return optiontypes.OpaqueOption
94 def _set_format(self, value):
95 self._format = value
97 format = property(_get_format, _set_format)
99 def create_option(self, decode=None, value=None):
100 """Return an Option element of the appropriate class from this option
101 number.
103 An initial value may be set using the decode or value options, and will
104 be fed to the resulting object's decode method or value property,
105 respectively."""
106 option = self.format(self)
107 if decode is not None:
108 option.decode(decode)
109 if value is not None:
110 option.value = value
111 return option
113 def _repr_html_(self):
114 import html
115 properties = f"{'critical' if self.is_critical() else 'elective'}, {'safe-to-forward' if self.is_safetoforward() else 'proxy unsafe'}"
116 if self.is_safetoforward():
117 properties += ", part of the cache key" if self.is_cachekey() else ", not part of the cache key"
118 if hasattr(self, "name"):
119 return f'<abbr title="option {int(self)}: {properties}">{html.escape(self.name)}</abbr>'
120 else:
121 return f'<abbr title="{properties}">Option {int(self)}</abbr>'
123# OpaqueOption is set on formats where it is known to be used even though it is
124# the default. This allows developers to rely on those interfaces to be stable
125# (or at least to be notified visibly in the release notes).
127# RFC 7252
129OptionNumber.IF_MATCH.format = optiontypes.OpaqueOption
130OptionNumber.URI_HOST.format = optiontypes.StringOption
131OptionNumber.ETAG.format = optiontypes.OpaqueOption
132OptionNumber.URI_PORT.format = optiontypes.UintOption
133OptionNumber.LOCATION_PATH.format = optiontypes.StringOption
134OptionNumber.URI_PATH.format = optiontypes.StringOption
135OptionNumber.CONTENT_FORMAT.format = optiontypes.ContentFormatOption
136OptionNumber.MAX_AGE.format = optiontypes.UintOption
137OptionNumber.URI_QUERY.format = optiontypes.StringOption
138OptionNumber.ACCEPT.format = optiontypes.ContentFormatOption
139OptionNumber.LOCATION_QUERY.format = optiontypes.StringOption
140OptionNumber.PROXY_URI.format = optiontypes.StringOption
141OptionNumber.PROXY_SCHEME.format = optiontypes.StringOption
142OptionNumber.SIZE1.format = optiontypes.UintOption
144# RFC 7959
146OptionNumber.BLOCK2.format = optiontypes.BlockOption
147OptionNumber.BLOCK1.format = optiontypes.BlockOption
148OptionNumber.SIZE2.format = optiontypes.UintOption
150# RFC 7641
152OptionNumber.OBSERVE.format = optiontypes.UintOption
154# RFC 7967
156OptionNumber.NO_RESPONSE.format = optiontypes.UintOption
158# RFC 8613
160OptionNumber.OSCORE.format = optiontypes.OpaqueOption
162# RFC 9175
164OptionNumber.ECHO.format = optiontypes.OpaqueOption
165OptionNumber.REQUEST_TAG.format = optiontypes.OpaqueOption
167# RFC 8768
169OptionNumber.HOP_LIMIT.format = optiontypes.UintOption
171# experimental for draft-amsuess-core-cachable-oscore
173OptionNumber.REQUEST_HASH.format = optiontypes.OpaqueOption