Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

# -*- coding: UTF-8 -*- 

# Copyright 2013-2015 Luc Saffre 

# License: BSD (see file COPYING for details) 

 

"""Used by :class:`lino.utils.appy_pod.PrintLabelsAction` and 

:mod:`lino.modlib.contacts`. 

 

$ python setup.py test -s tests.UtilsTests.test_addressable 

 

 

""" 

 

from __future__ import print_function 

from builtins import object 

 

from lino.utils.xmlgen.html import E, lines2p 

 

 

class Addressable(object): 

    """Mixin to encapsulate the generating of "traditional" ("snail") mail 

    addresses. 

 

    It differentiates between the "person" and the "location" part of 

    an address.  For example:: 

     

        Mr. Luc Saffre     | person 

        Rumma & Ko OÜ      | person 

        Uus 1              | location 

        Vana-Vigala küla   | location 

        Vigala vald        | location 

        Estonia            | location 

 

    Usable subclasses must implement at least 

    :meth:`address_person_lines` and :meth:`address_location_lines`. 

 

    .. attribute:: address 

 

        A property which calls :meth:`get_address`. 

 

    .. attribute:: address_html 

 

        A property which calls :meth:`get_address_html`. 

 

    """ 

    def address_person_lines(self): 

        """Expected to yield one or more unicode strings, one for each line 

        of the person part. 

 

        """ 

        raise NotImplementedError() 

 

    def address_location_lines(self): 

        """Expected to yield one or more unicode strings, one for each line 

        of the location part. 

 

        """ 

        raise NotImplementedError() 

 

    def get_address_lines(self): 

        """Yields a series of strings, one for each line of the address.""" 

        for ln in self.address_person_lines(): 

            yield ln 

        for ln in self.address_location_lines(): 

            yield ln 

 

    def get_address(self, linesep="\n"): 

        """The plain text full postal address (person and location).  Lines 

        are separated by `linesep` which defaults to a newline. 

        """ 

        return linesep.join( 

            list(self.address_person_lines()) 

            + list(self.address_location_lines())) 

    address = property(get_address) 

 

    def get_address_html(self, *args, **kwargs): 

        """Returns the full postal address a a string containing html 

        markup of style:: 

         

            <p>line1<br/>line2...</p> 

 

        This returns always exactly one paragraph, even if the address 

        is empty (in which case the paragraph is empty): 

 

        >>> print(TestAddress().get_address_html()) 

        <p /> 

 

        Optional attributes for the enclosing `<p>` tag can be 

        specified as keyword arguments. Example: 

 

        >>> addr = TestAddress('line1', 'line2') 

        >>> print(addr.get_address_html(class_="Recipient")) 

        <p class="Recipient">line1<br />line2</p> 

           

        If `min_height` is specified, makes sure that the string 

        contains at least that many lines. Adds as many empty lines 

        (``<br/>``) as needed.  This is useful in a template which 

        wants to get a given height for every address. 

 

        >>> print(addr.get_address_html(min_height=5)) 

        <p>line1<br />line2<br /><br /><br /></p> 

 

        Any arguments are forwarded to :meth:`lines2p 

        <lino.utils.xmlgen.html.lines2p>` which is used to pack the address 

        lines into a paragraph (see there for more examples). 

 

        """ 

        lines = list(self.get_address_lines()) 

        return E.tostring(lines2p(lines, *args, **kwargs)) 

 

    address_html = property(get_address_html) 

 

    def has_address(self): 

        """ 

        >>> TestAddress('line1', 'line2').has_address() 

        True 

        >>> TestAddress().has_address() 

        False 

        """ 

        return len(list(self.address_location_lines())) > 0 

 

 

class TestAddress(Addressable): 

    """Used only for testing.""" 

    def __init__(self, *lines): 

        self.lines = lines 

 

    def address_person_lines(self): 

        return [] 

 

    def address_location_lines(self): 

        return self.lines