Some prelim work on builder api.
[librarian.git] / src / librarian / meta / types / person.py
1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
3 #
4 from functools import total_ordering
5 from .base import MetaValue
6
7
8 @total_ordering
9 class Person(MetaValue):
10     """Single person with last name and a list of first names."""
11     def __init__(self, last_name, *first_names):
12         self.last_name = last_name
13         self.first_names = first_names
14
15     @classmethod
16     def from_text(cls, text):
17         parts = [token.strip() for token in text.split(',')]
18         if len(parts) == 1:
19             surname = parts[0]
20             names = []
21         elif len(parts) != 2:
22             raise ValueError(
23                 "Invalid person name. "
24                 "There should be at most one comma: \"%s\"."
25                 % text.encode('utf-8')
26             )
27         else:
28             surname = parts[0]
29             if len(parts[1]) == 0:
30                 # there is no non-whitespace data after the comma
31                 raise ValueError(
32                     "Found a comma, but no names given: \"%s\" -> %r."
33                     % (text, parts)
34                 )
35             names = parts[1].split()
36         return cls(surname, *names)
37
38     def readable(self):
39         return " ".join(self.first_names + (self.last_name,))
40
41     def __eq__(self, right):
42         return (self.last_name == right.last_name
43                 and self.first_names == right.first_names)
44
45     def __lt__(self, other):
46         return ((self.last_name, self.first_names)
47                 < (other.last_name, other.first_names))
48
49     def __hash__(self):
50         return hash((self.last_name, self.first_names))
51
52     def __str__(self):
53         if len(self.first_names) > 0:
54             return '%s, %s' % (self.last_name, ' '.join(self.first_names))
55         else:
56             return self.last_name
57
58     def __repr__(self):
59         return 'Person(last_name=%r, first_names=*%r)' % (
60             self.last_name, self.first_names
61         )