Coverage for aiocoap/numbers/codes.py: 99%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

74 statements  

1# This file is part of the Python aiocoap library project. 

2# 

3# Copyright (c) 2012-2014 Maciej Wasilak <http://sixpinetrees.blogspot.com/>, 

4# 2013-2014 Christian Amsüss <c.amsuess@energyharvesting.at> 

5# 

6# aiocoap is free software, this file is published under the MIT license as 

7# described in the accompanying LICENSE file. 

8 

9"""List of known values for the CoAP "Code" field. 

10 

11The values in this module correspond to the IANA registry "`CoRE Parameters`_", 

12subregistries "CoAP Method Codes" and "CoAP Response Codes". 

13 

14The codes come with methods that can be used to get their rough meaning, see 

15the :class:`Code` class for details. 

16 

17.. _`CoRE Parameters`: https://www.iana.org/assignments/core-parameters/core-parameters.xhtml 

18""" 

19 

20from ..util import ExtensibleIntEnum 

21 

22class Code(ExtensibleIntEnum): 

23 """Value for the CoAP "Code" field. 

24 

25 As the number range for the code values is separated, the rough meaning of 

26 a code can be determined using the :meth:`is_request`, :meth:`is_response` and 

27 :meth:`is_successful` methods.""" 

28 

29 EMPTY = 0 

30 GET = 1 

31 POST = 2 

32 PUT = 3 

33 DELETE = 4 

34 FETCH = 5 

35 PATCH = 6 

36 iPATCH = 7 

37 CREATED = 65 

38 DELETED = 66 

39 VALID = 67 

40 CHANGED = 68 

41 CONTENT = 69 

42 CONTINUE = 95 

43 BAD_REQUEST = 128 

44 UNAUTHORIZED = 129 

45 BAD_OPTION = 130 

46 FORBIDDEN = 131 

47 NOT_FOUND = 132 

48 METHOD_NOT_ALLOWED = 133 

49 NOT_ACCEPTABLE = 134 

50 REQUEST_ENTITY_INCOMPLETE = 136 

51 CONFLICT = (4 << 5) + 9 

52 PRECONDITION_FAILED = 140 

53 REQUEST_ENTITY_TOO_LARGE = 141 

54 UNSUPPORTED_CONTENT_FORMAT = 143 

55 UNSUPPORTED_MEDIA_TYPE = UNSUPPORTED_CONTENT_FORMAT # deprecated alias 

56 UNPROCESSABLE_ENTITY = (4 << 5) + 22 

57 INTERNAL_SERVER_ERROR = 160 

58 NOT_IMPLEMENTED = 161 

59 BAD_GATEWAY = 162 

60 SERVICE_UNAVAILABLE = 163 

61 GATEWAY_TIMEOUT = 164 

62 PROXYING_NOT_SUPPORTED = 165 

63 

64 CSM = 225 

65 PING = 226 

66 PONG = 227 

67 RELEASE = 228 

68 ABORT = 229 

69 

70 def is_request(self): 

71 """True if the code is in the request code range""" 

72 return True if (self >= 1 and self < 32) else False 

73 

74 

75 def is_response(self): 

76 """True if the code is in the response code range""" 

77 return True if (self >= 64 and self < 192) else False 

78 

79 def is_signalling(self): 

80 return True if self >= 224 else False 

81 

82 

83 def is_successful(self): 

84 """True if the code is in the successful subrange of the response code range""" 

85 return True if (self >= 64 and self < 96) else False 

86 

87 def can_have_payload(self): 

88 """True if a message with that code can carry a payload. This is not 

89 checked for strictly, but used as an indicator.""" 

90 return self.is_response() or self in (self.POST, self.PUT, self.FETCH, self.PATCH, self.iPATCH) 

91 

92 @property 

93 def class_(self): 

94 """The class of a code (distinguishing whether it's successful, a 

95 request or a response error or more). 

96 

97 >>> Code.CONTENT 

98 <Successful Response Code 69 "2.05 Content"> 

99 >>> Code.CONTENT.class_ 

100 2 

101 >>> Code.BAD_GATEWAY 

102 <Response Code 162 "5.02 Bad Gateway"> 

103 >>> Code.BAD_GATEWAY.class_ 

104 5 

105 """ 

106 return self >> 5 

107 

108 @property 

109 def dotted(self): 

110 """The numeric value three-decimal-digits (c.dd) form""" 

111 return "%d.%02d"%divmod(self, 32) 

112 

113 @property 

114 def name_printable(self): 

115 """The name of the code in human-readable form""" 

116 return self.name.replace('_', ' ').title() 

117 

118 def __str__(self): 

119 if self.is_request() or self is self.EMPTY: 

120 return self.name 

121 elif self.is_response() or self.is_signalling(): 

122 return "%s %s"%(self.dotted, self.name_printable) 

123 else: 

124 return "%d"%self 

125 

126 def __repr__(self): 

127 """ 

128 >>> Code.GET 

129 <Request Code 1 "GET"> 

130 >>> Code.CONTENT 

131 <Successful Response Code 69 "2.05 Content"> 

132 >>> Code.BAD_GATEWAY 

133 <Response Code 162 "5.02 Bad Gateway"> 

134 >>> Code(32) 

135 <Code 32 "32"> 

136 """ 

137 return '<%s%sCode %d "%s">'%("Successful " if self.is_successful() else "", "Request " if self.is_request() else "Response " if self.is_response() else "", self, self) 

138 

139 name = property(lambda self: self._name if hasattr(self, "_name") else "(unknown)", lambda self, value: setattr(self, "_name", value), doc="The constant name of the code (equals name_printable readable in all-caps and with underscores)") 

140 

141for k in vars(Code): 

142 if isinstance(getattr(Code, k), Code): 

143 locals()[k] = getattr(Code, k) 

144 

145__all__ = ['Code'] + [k for (k,v) in locals().items() if isinstance(v, Code)]