-
-class TextPlus(six.text_type):
- pass
-
-
-class DatePlus(date):
- pass
-
-
-# ==============
-# = Converters =
-# ==============
-@six.python_2_unicode_compatible
-@total_ordering
-class Person(object):
- """Single person with last name and a list of first names."""
- def __init__(self, last_name, *first_names):
- self.last_name = last_name
- self.first_names = first_names
-
- @classmethod
- def from_text(cls, text):
- parts = [token.strip() for token in text.split(',')]
- if len(parts) == 1:
- surname = parts[0]
- names = []
- elif len(parts) != 2:
- raise ValueError(
- "Invalid person name. "
- "There should be at most one comma: \"%s\"."
- % text.encode('utf-8')
- )
- else:
- surname = parts[0]
- if len(parts[1]) == 0:
- # there is no non-whitespace data after the comma
- raise ValueError(
- "Found a comma, but no names given: \"%s\" -> %r."
- % (text, parts)
- )
- names = parts[1].split()
- return cls(surname, *names)
-
- def readable(self):
- return u" ".join(self.first_names + (self.last_name,))
-
- def __eq__(self, right):
- return (self.last_name == right.last_name
- and self.first_names == right.first_names)
-
- def __lt__(self, other):
- return ((self.last_name, self.first_names)
- < (other.last_name, other.first_names))
-
- def __hash__(self):
- return hash((self.last_name, self.first_names))
-
- def __str__(self):
- if len(self.first_names) > 0:
- return '%s, %s' % (self.last_name, ' '.join(self.first_names))
- else:
- return self.last_name
-
- def __repr__(self):
- return 'Person(last_name=%r, first_names=*%r)' % (
- self.last_name, self.first_names
- )
-
-
-def as_date(text):
- """
- Dates for digitization of pictures. It seems we need the following:
- ranges: '1350-1450',
- centuries: "XVIII w.'
- half centuries/decades: '2 poł. XVIII w.', 'XVII w., l. 20'
- later-then: 'po 1450'
- circa 'ok. 1813-1814', 'ok.1876-ok.1886
- turn: 1893/1894
-
- For now we will translate this to some single date
- losing information of course.
- """
- try:
- # check out the "N. poł X w." syntax
- if isinstance(text, six.binary_type):
- text = text.decode("utf-8")
-
- century_format = (
- u"(?:([12]) *poł[.]? +)?([MCDXVI]+) *w[.,]*(?: *l[.]? *([0-9]+))?"
- )
- vague_format = u"(?:po *|ok. *)?([0-9]{4})(-[0-9]{2}-[0-9]{2})?"
-
- m = re.match(century_format, text)
- m2 = re.match(vague_format, text)
- if m:
- half = m.group(1)
- decade = m.group(3)
- century = roman_to_int(m.group(2))
- if half is not None:
- if decade is not None:
- raise ValueError(
- "Bad date format. "
- "Cannot specify both half and decade of century."
- )
- half = int(half)
- t = ((century*100 + (half-1)*50), 1, 1)
- else:
- decade = int(decade or 0)
- t = ((century*100 + decade), 1, 1)
- elif m2:
- year = m2.group(1)
- mon_day = m2.group(2)
- if mon_day:
- t = time.strptime(year + mon_day, "%Y-%m-%d")
- else:
- t = time.strptime(year, '%Y')
- else:
- raise ValueError
-
- return DatePlus(t[0], t[1], t[2])
- except ValueError:
- raise ValueError("Unrecognized date format. Try YYYY-MM-DD or YYYY.")
-
-
-def as_person(text):
- return Person.from_text(text)
-
-
-def as_unicode(text):
- if isinstance(text, six.text_type):
- return text
- else:
- return TextPlus(text.decode('utf-8'))