Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/prop/org.py: 49%

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

59 statements  

1"""The ORG property from :rfc:`6350`.""" 

2 

3from typing import Any, ClassVar 

4 

5from icalendar.compatibility import Self 

6from icalendar.error import JCalParsingError 

7from icalendar.parser import Parameters 

8from icalendar.parser_tools import DEFAULT_ENCODING, to_unicode 

9 

10 

11class vOrg: 

12 r"""vCard ORG (Organization) structured property per :rfc:`6350#section-6.6.4`. 

13 

14 The ORG property specifies the organizational name and units 

15 associated with the vCard. 

16 

17 Its value is a structured type consisting of components separated 

18 by semicolons. The components are the organization name, followed 

19 by zero or more levels of organizational unit names: 

20 

21 .. code-block:: text 

22 

23 organization-name; organizational-unit-1; organizational-unit-2; ... 

24 

25 Semicolons are field separators and are NOT escaped. 

26 Commas and backslashes within field values ARE escaped per :rfc:`6350`. 

27 

28 Examples: 

29 A property value consisting of an organizational name, 

30 organizational unit #1 name, and organizational unit #2 name. 

31 

32 .. code-block:: text 

33 

34 ORG:ABC\, Inc.;North American Division;Marketing 

35 

36 The same example in icalendar. 

37 

38 .. code-block:: pycon 

39 

40 >>> from icalendar.prop import vOrg 

41 >>> org = vOrg(("ABC, Inc.", "North American Division", "Marketing")) 

42 >>> org.to_ical() 

43 b'ABC\\, Inc.;North American Division;Marketing' 

44 >>> vOrg.from_ical(r"ABC\, Inc.;North American Division;Marketing") 

45 ('ABC, Inc.', 'North American Division', 'Marketing') 

46 """ 

47 

48 default_value: ClassVar[str] = "TEXT" 

49 params: Parameters 

50 fields: tuple[str, ...] 

51 

52 def __init__( 

53 self, 

54 fields: tuple[str, ...] | list[str] | str, 

55 /, 

56 params: dict[str, Any] | None = None, 

57 ): 

58 """Initialize ORG with variable fields or parse from vCard format string. 

59 

60 Parameters: 

61 fields: Either a tuple or list of one or more strings, or a 

62 vCard format string with semicolon-separated fields 

63 params: Optional property parameters 

64 """ 

65 if isinstance(fields, str): 

66 fields = self.from_ical(fields) 

67 if len(fields) < 1: 

68 raise ValueError("ORG must have at least 1 field (organization name)") 

69 self.fields = tuple(str(f) for f in fields) 

70 self.params = Parameters(params) 

71 

72 def to_ical(self) -> bytes: 

73 """Generate vCard format with semicolon-separated fields.""" 

74 from icalendar.prop.text import vText 

75 

76 parts = [vText(f).to_ical().decode(DEFAULT_ENCODING) for f in self.fields] 

77 return ";".join(parts).encode(DEFAULT_ENCODING) 

78 

79 @staticmethod 

80 def from_ical(ical: str | bytes) -> tuple[str, ...]: 

81 """Parse vCard ORG format into a tuple of fields. 

82 

83 Parameters: 

84 ical: vCard format string with semicolon-separated fields 

85 

86 Returns: 

87 Tuple of field values with one or more fields 

88 """ 

89 from icalendar.parser import split_on_unescaped_semicolon 

90 

91 ical = to_unicode(ical) 

92 fields = split_on_unescaped_semicolon(ical) 

93 if len(fields) < 1: 

94 raise ValueError(f"ORG must have at least 1 field: {ical}") 

95 return tuple(fields) 

96 

97 def __eq__(self, other: object) -> bool: 

98 """self == other""" 

99 return isinstance(other, vOrg) and self.fields == other.fields 

100 

101 def __repr__(self) -> str: 

102 """String representation.""" 

103 return f"{self.__class__.__name__}({self.fields}, params={self.params})" 

104 

105 @property 

106 def name(self) -> str: 

107 """The organization name (first field).""" 

108 return self.fields[0] 

109 

110 @property 

111 def units(self) -> tuple[str, ...]: 

112 """The organizational unit names (remaining fields after the name).""" 

113 return self.fields[1:] 

114 

115 @property 

116 def ical_value(self) -> tuple[str, ...]: 

117 """The organization fields as a tuple.""" 

118 return self.fields 

119 

120 from icalendar.param import VALUE 

121 

122 def to_jcal(self, name: str) -> list: 

123 """The jCal representation of this property according to :rfc:`7265`.""" 

124 result = [name, self.params.to_jcal(), self.VALUE.lower()] 

125 result.extend(self.fields) 

126 return result 

127 

128 @classmethod 

129 def from_jcal(cls, jcal_property: list) -> Self: 

130 """Parse jCal from :rfc:`7265`. 

131 

132 Parameters: 

133 jcal_property: The jCal property to parse. 

134 

135 Raises: 

136 ~error.JCalParsingError: If the provided jCal is invalid. 

137 """ 

138 JCalParsingError.validate_property(jcal_property, cls) 

139 if len(jcal_property) < 4: # name, params, value_type, at least 1 field 

140 raise JCalParsingError( 

141 "ORG must have at least 4 elements" 

142 " (name, params, value_type, org name)," 

143 f" got {len(jcal_property)}" 

144 ) 

145 for i, field in enumerate(jcal_property[3:], start=3): 

146 JCalParsingError.validate_value_type(field, str, cls, i) 

147 return cls( 

148 tuple(jcal_property[3:]), 

149 Parameters.from_jcal_property(jcal_property), 

150 ) 

151 

152 @classmethod 

153 def examples(cls) -> list[Self]: 

154 """Examples of vOrg.""" 

155 return [cls(("ABC Inc.", "North American Division", "Marketing"))] 

156 

157 

158__all__ = ["vOrg"]