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 

3 

4from typing import Any, ClassVar 

5 

6from icalendar.compatibility import Self 

7from icalendar.error import JCalParsingError 

8from icalendar.parser import Parameters 

9from icalendar.parser_tools import DEFAULT_ENCODING, to_unicode 

10 

11 

12class vOrg: 

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

14 

15 The ORG property specifies the organizational name and units associated with the vCard. 

16 

17 Its value is a structured type consisting of components separated by semicolons. 

18 The components are the organization name, followed by zero or more levels of organizational unit names: 

19 

20 .. code-block:: text 

21 

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

23 

24 Semicolons are field separators and are NOT escaped. 

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

26 

27 Examples: 

28 A property value consisting of an organizational name, 

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

30 

31 .. code-block:: text 

32 

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

34 

35 The same example in icalendar. 

36 

37 .. code-block:: pycon 

38 

39 >>> from icalendar.prop import vOrg 

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

41 >>> org.to_ical() 

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

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

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

45 """ 

46 

47 default_value: ClassVar[str] = "TEXT" 

48 params: Parameters 

49 fields: tuple[str, ...] 

50 

51 def __init__( 

52 self, 

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

54 /, 

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

56 ): 

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

58 

59 Parameters: 

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

61 vCard format string with semicolon-separated fields 

62 params: Optional property parameters 

63 """ 

64 if isinstance(fields, str): 

65 fields = self.from_ical(fields) 

66 if len(fields) < 1: 

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

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

69 self.params = Parameters(params) 

70 

71 def to_ical(self) -> bytes: 

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

73 from icalendar.prop.text import vText 

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

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

76 

77 @staticmethod 

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

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

80 

81 Parameters: 

82 ical: vCard format string with semicolon-separated fields 

83 

84 Returns: 

85 Tuple of field values with one or more fields 

86 """ 

87 from icalendar.parser import split_on_unescaped_semicolon 

88 

89 ical = to_unicode(ical) 

90 fields = split_on_unescaped_semicolon(ical) 

91 if len(fields) < 1: 

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

93 return tuple(fields) 

94 

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

96 """self == other""" 

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

98 

99 def __repr__(self) -> str: 

100 """String representation.""" 

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

102 

103 @property 

104 def name(self) -> str: 

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

106 return self.fields[0] 

107 

108 @property 

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

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

111 return self.fields[1:] 

112 

113 @property 

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

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

116 return self.fields 

117 

118 from icalendar.param import VALUE 

119 

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

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

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

123 result.extend(self.fields) 

124 return result 

125 

126 @classmethod 

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

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

129 

130 Parameters: 

131 jcal_property: The jCal property to parse. 

132 

133 Raises: 

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

135 """ 

136 JCalParsingError.validate_property(jcal_property, cls) 

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

138 raise JCalParsingError( 

139 f"ORG must have at least 4 elements (name, params, value_type, org name), " 

140 f"got {len(jcal_property)}" 

141 ) 

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

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

144 return cls( 

145 tuple(jcal_property[3:]), 

146 Parameters.from_jcal_property(jcal_property), 

147 ) 

148 

149 @classmethod 

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

151 """Examples of vOrg.""" 

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

153 

154__all__ = ["vOrg"]