ó
'nD^c           @   sô   d  d l  Z d  d l m Z d  d l m Z d  d l m Z m Z d  d l	 m
 Z
 d  d l m Z m Z d  d l m Z d  d l m Z d  d l Z d	 Z e j j Z e j j Z d
 Z e j j Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ  d S(   iÿÿÿÿN(   t   version_info(   t   Element(   t   FamilyElementt   NotAnActualFamilyError(   t   FileElement(   t   IndividualElementt   NotAnActualIndividualError(   t   ObjectElement(   t   RootElementt   ALLt   PARENTSt   GedcomFormatViolationErrorc           B   s   e  Z RS(    (   t   __name__t
   __module__(    (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyR   -   s   t   Parserc           B   sã   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z e	 d „ Z
 e e	 d „ ƒ Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z e j j d „ Z d d „ Z d d „ Z d d „ Z e d „ Z d „  Z d „  Z RS(   s„  Parses and manipulates GEDCOM 5.5 format data

    For documentation of the GEDCOM 5.5 format, see:
    http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gctoc.htm

    This parser reads and parses a GEDCOM file.
    Elements may be accessed via:
      - a list (all elements, default order is same as in file)
      - a dict (only elements with pointers, which are the keys)
    c         C   s"   g  |  _  i  |  _ t ƒ  |  _ d S(   s    Initialize a GEDCOM data object.N(   t   _Parser__element_listt   _Parser__element_dictionaryR   t   _Parser__root_element(   t   self(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   __init__=   s    		c         C   s   g  |  _  i  |  _ d S(   sÞ   Empties the element list and dictionary to cause
        `get_element_list()` and `get_element_dictionary()` to return updated data

        The update gets deferred until each of the methods actually gets called.
        N(   R   R   (   R   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   invalidate_cacheC   s    	c         C   s=   |  j  s6 x* |  j ƒ  D] } |  j | |  j  ƒ q Wn  |  j  S(   s  Returns a list containing all elements from within the GEDCOM file

        By default elements are in the same order as they appeared in the file.

        This list gets generated on-the-fly, but gets cached. If the database
        was modified, you should call `invalidate_cache()` once to let this
        method return updated data.

        Consider using `get_root_element()` or `get_root_child_elements()` to access
        the hierarchical GEDCOM tree, unless you rarely modify the database.

        :rtype: list of Element
        (   R   t   get_root_child_elementst   _Parser__build_list(   R   t   element(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   get_element_listL   s    	c         C   s,   |  j  s% d „  |  j ƒ  Dƒ |  _  n  |  j  S(   sÔ  Returns a dictionary containing all elements, identified by a pointer, from within the GEDCOM file

        Only elements identified by a pointer are listed in the dictionary.
        The keys for the dictionary are the pointers.

        This dictionary gets generated on-the-fly, but gets cached. If the
        database was modified, you should call `invalidate_cache()` once to let
        this method return updated data.

        :rtype: dict of Element
        c         S   s+   i  |  ]! } | j  ƒ  r | | j  ƒ  “ q S(    (   t   get_pointer(   t   .0R   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pys
   <dictcomp>m   s   	 (   R   R   (   R   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   get_element_dictionary_   s    	c         C   s   |  j  S(   s°   Returns a virtual root element containing all logical records as children

        When printed, this element converts to an empty string.

        :rtype: RootElement
        (   R   (   R   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   get_root_elementr   s    c         C   s   |  j  ƒ  j ƒ  S(   s°   Returns a list of logical records in the GEDCOM file

        By default, elements are in the same order as they appeared in the file.

        :rtype: list of Element
        (   R   t   get_child_elements(   R   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyR   {   s    c         C   sw   |  j  ƒ  t ƒ  |  _ t | d ƒ } d } |  j ƒ  } x9 | D]1 } |  j | | j d ƒ | | ƒ } | d 7} q> Wd S(   s   Opens and parses a file, from the given file path, as GEDCOM 5.5 formatted data
        :type file_path: str
        :type strict: bool
        t   rbi   s	   utf-8-sigN(   R   R   R   t   openR   t   _Parser__parse_linet   decode(   R   t	   file_patht   strictt   gedcom_filet   line_numbert   last_elementt   line(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt
   parse_file„   s    
!c         C   sK  d } d } d } d } d } | | | | | }	 t  j |	 | ƒ }
 |
 d k r™| ru d |  d } t | ƒ ‚ qê| | | | } t  j | | ƒ }
 |
 d k	 rõ |
 j ƒ  } t | d ƒ } | d	 j d
 ƒ } | d } | d d	 } d } qêd } | | } t  j | | ƒ }
 |
 j ƒ  } | j ƒ  } | j ƒ  } d } | d d	 } | d	 } | t	 j
 j k rê| t	 j
 j k rê| d	 7} t	 j
 j } qênQ |
 j ƒ  } t | d ƒ } | d	 j d
 ƒ } | d } | d d	 } | d } | | j ƒ  d	 k r!d |  d d } t | ƒ ‚ n  | t	 j
 j k rTt | | | | | d t ƒ} n· | t	 j
 j k r‡t | | | | | d t ƒ} n„ | t	 j
 j k rºt | | | | | d t ƒ} nQ | t	 j
 j k rít | | | | | d t ƒ} n t | | | | | d t ƒ} | } x& | j ƒ  | d	 k r9| j ƒ  } qW| j | ƒ | S(   sT  Parse a line from a GEDCOM 5.5 formatted document

        Each line should have the following (bracketed items optional):
        level + ' ' + [pointer + ' ' +] tag + [' ' + line_value]

        :type line_number: int
        :type line: str
        :type last_element: Element
        :type strict: bool

        :rtype: Element
        s   ^(0|[1-9]+[0-9]*) s   (@[^@]+@ |)s   ([A-Za-z0-9_]+)s
   ( [^
]*|)s   ([
]{1,2})s.   Line %d of document violates GEDCOM format 5.5sJ   
See: https://chronoplexsoftware.com/gedcomvalidator/gedcom/gedcom-5.5.pdfi    i   t    i   i   s   
s	   ([^
]*|)i   s@   
Lines must be no more than one level higher than previous line.t
   multi_lineN(   t   regext   matcht   NoneR   t   groupst   intt   rstript	   get_levelt   get_tagt   gedcomt   tagst   GEDCOM_TAG_CONTINUEDt   GEDCOM_TAG_CONCATENATIONt   GEDCOM_TAG_INDIVIDUALR   t   Falset   GEDCOM_TAG_FAMILYR   t   GEDCOM_TAG_FILER   t   GEDCOM_TAG_OBJECTR   R   t   get_parent_elementt   add_child_element(   R%   R'   R&   R#   t   level_regext   pointer_regext	   tag_regext   value_regext   end_of_line_regext   gedcom_line_regext   regex_matcht   error_messaget   last_line_regext
   line_partst   levelt   pointert   tagt   valuet   crlft
   line_regext   cont_line_regexR   t   parent_element(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   __parse_line–   sp    
	

$


!!!!c         C   s8   | j  | ƒ x$ | j ƒ  D] } |  j | | ƒ q Wd S(   sŠ   Recursively add elements to a list containing elements
        :type element: Element
        :type element_list: list of Element
        N(   t   appendR   R   (   R   R   t   element_listt   child(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   __build_list  s    c   	      C   s  g  } t  | t ƒ s. t d t j j ƒ ‚ n  |  j | t j j ƒ } xÄ | D]¼ } x³ | j ƒ  D]¥ } | j	 ƒ  t j j
 k r` d } d } xb | j ƒ  D]T } | j	 ƒ  t j j k rÄ | j ƒ  } n  | j	 ƒ  t j j k r— | j ƒ  } q— q— W| j | | f ƒ q` q` WqM W| S(   s¦   Returns a list of marriages of an individual formatted as a tuple (`str` date, `str` place)
        :type individual: IndividualElement
        :rtype: tuple
        s-   Operation only valid for elements with %s tagt    (   t
   isinstanceR   R   R3   R4   R7   t   get_familiest   GEDCOM_TAG_FAMILY_SPOUSER   R2   t   GEDCOM_TAG_MARRIAGEt   GEDCOM_TAG_DATEt	   get_valuet   GEDCOM_TAG_PLACERQ   (	   R   t
   individualt	   marriagest   familiest   familyt   family_datat   datet   placet   marriage_data(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   get_marriages  s"    c         C   s   g  } t  | t ƒ s. t d t j j ƒ ‚ n  |  j | t j j ƒ } x³ | D]« } x¢ | j ƒ  D]” } | j	 ƒ  t j j
 k r` xs | j ƒ  D]b } | j	 ƒ  t j j k r‹ | j ƒ  j ƒ  d } y | j t | ƒ ƒ Wqí t k
 ré qí Xq‹ q‹ Wq` q` WqM W| S(   s‘   Returns a list of marriage years (as integers) for an individual
        :type individual: IndividualElement
        :rtype: list of int
        s-   Operation only valid for elements with %s tagiÿÿÿÿ(   RV   R   R   R3   R4   R7   RW   RX   R   R2   RY   RZ   R[   t   splitRQ   R/   t
   ValueError(   R   R]   t   datesR_   R`   RS   t   childOfChildRb   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   get_marriage_years%  s     c         C   sA   t  | t ƒ s( t d t j j ƒ ‚ n  |  j | ƒ } | | k S(   sÅ   Checks if one of the marriage years of an individual matches the supplied year. Year is an integer.
        :type individual: IndividualElement
        :type year: int
        :rtype: bool
        s-   Operation only valid for elements with %s tag(   RV   R   R   R3   R4   R7   Rj   (   R   R]   t   yeart   years(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   marriage_year_match?  s
    c         C   sl   t  | t ƒ s( t d t j j ƒ ‚ n  |  j | ƒ } x. | D]& } | | k o[ | k n r> t Sq> Wt S(   sÞ   Check if one of the marriage years of an individual is in a given range. Years are integers.
        :type individual: IndividualElement
        :type from_year: int
        :type to_year: int
        :rtype: bool
        s-   Operation only valid for elements with %s tag(	   RV   R   R   R3   R4   R7   Rj   t   TrueR8   (   R   R]   t	   from_yeart   to_yearRl   Rk   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   marriage_range_matchM  s    c         C   s¯   t  | t ƒ s( t d t j j ƒ ‚ n  g  } |  j ƒ  } xn | j ƒ  D]` } | j ƒ  | k o„ | j	 ƒ  | k o„ | | j	 ƒ  j
 ƒ  } | rG | j | | j	 ƒ  ƒ qG qG W| S(   sÓ  Return family elements listed for an individual

        family_type can be `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` (families where the individual is a spouse) or
        `gedcom.tags.GEDCOM_TAG_FAMILY_CHILD` (families where the individual is a child). If a value is not
        provided, `gedcom.tags.GEDCOM_TAG_FAMILY_SPOUSE` is default value.

        :type individual: IndividualElement
        :type family_type: str
        :rtype: list of FamilyElement
        s-   Operation only valid for elements with %s tag(   RV   R   R   R3   R4   R7   R   R   R2   R[   t	   is_familyRQ   (   R   R]   t   family_typeR_   t   element_dictionaryt   child_elementRr   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyRW   _  s    R	   c         C   sx   t  | t ƒ s( t d t j j ƒ ‚ n  |  j | | ƒ } g  } | j | ƒ x$ | D] } | j |  j | ƒ ƒ qT W| S(   sA  Return elements corresponding to ancestors of an individual

        Optional `ancestor_type`. Default "ALL" returns all ancestors, "NAT" can be
        used to specify only natural (genetic) ancestors.

        :type individual: IndividualElement
        :type ancestor_type: str
        :rtype: list of Element
        s-   Operation only valid for elements with %s tag(	   RV   R   R   R3   R4   R7   t   get_parentst   extendt   get_ancestors(   R   R]   t   ancestor_typet   parentst	   ancestorst   parent(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyRx   {  s    
c         C   sd  t  | t ƒ s( t d t j j ƒ ‚ n  g  } |  j | t j j ƒ } x| D]} | d k rFxú | j ƒ  D]Ó } | j	 ƒ  t j j
 k rl | j ƒ  | j ƒ  k rl xš | j ƒ  D]‰ } | j ƒ  d k r¯ | j	 ƒ  t j j k rþ | |  j | t j j ƒ 7} q8| j	 ƒ  t j j k r8| |  j | t j j ƒ 7} q8q¯ q¯ Wql ql WqM | |  j | d ƒ 7} qM W| S(   s?  Return elements corresponding to parents of an individual

        Optional parent_type. Default "ALL" returns all parents. "NAT" can be
        used to specify only natural (genetic) parents.

        :type individual: IndividualElement
        :type parent_type: str
        :rtype: list of IndividualElement
        s-   Operation only valid for elements with %s tagt   NATt   NaturalR
   (   RV   R   R   R3   R4   R7   RW   t   GEDCOM_TAG_FAMILY_CHILDR   R2   t   GEDCOM_TAG_CHILDR[   R   t   GEDCOM_PROGRAM_DEFINED_TAG_MRELt   get_family_memberst   GEDCOM_TAG_WIFEt   GEDCOM_PROGRAM_DEFINED_TAG_FRELt   GEDCOM_TAG_HUSBAND(   R   R]   t   parent_typeRz   R_   R`   t   family_memberRS   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyRv   “  s$    
0c         C   s½   t  | t ƒ r8 t  | t ƒ r8 t d t j j ƒ ‚ n  | sJ | g } n  | d j ƒ  | j ƒ  k rj | S|  j | d ƒ } x: | D]2 } |  j | | | | g ƒ } | d k	 rƒ | Sqƒ Wd S(   sG   Return path from descendant to ancestor
        :rtype: object
        s.   Operation only valid for elements with %s tag.iÿÿÿÿR}   N(
   RV   R   R   R3   R4   R7   R   Rv   t   find_path_to_ancestorR-   (   R   t
   descendantt   ancestort   pathRz   R|   t   potential_path(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyRˆ   ·  s    c         C   sƒ  t  | t ƒ s( t d t j j ƒ ‚ n  g  } |  j ƒ  } xB| j ƒ  D]4} | j ƒ  t j j	 k p’ | j ƒ  t j j
 k p’ | j ƒ  t j j k } | t k rÔ | j ƒ  t j j	 k pÎ | j ƒ  t j j
 k } nu | t k rû | j ƒ  t j j	 k } nN | t k r"| j ƒ  t j j
 k } n' | t k rI| j ƒ  t j j k } n  | rG | j ƒ  | k rG | j | | j ƒ  ƒ qG qG W| S(   s´  Return array of family members: individual, spouse, and children

        Optional argument `members_type` can be used to return specific subsets:

        "FAMILY_MEMBERS_TYPE_ALL": Default, return all members of the family
        "FAMILY_MEMBERS_TYPE_PARENTS": Return individuals with "HUSB" and "WIFE" tags (parents)
        "FAMILY_MEMBERS_TYPE_HUSBAND": Return individuals with "HUSB" tags (father)
        "FAMILY_MEMBERS_TYPE_WIFE": Return individuals with "WIFE" tags (mother)
        "FAMILY_MEMBERS_TYPE_CHILDREN": Return individuals with "CHIL" tags (children)

        :type family: FamilyElement
        :type members_type: str
        :rtype: list of IndividualElement
        s-   Operation only valid for element with %s tag.(   RV   R   R   R3   R4   R9   R   R   R2   R…   Rƒ   R€   t   FAMILY_MEMBERS_TYPE_PARENTSt   FAMILY_MEMBERS_TYPE_HUSBANDt   FAMILY_MEMBERS_TYPE_WIFEt   FAMILY_MEMBERS_TYPE_CHILDRENR[   RQ   (   R   R`   t   members_typet   family_membersRt   Ru   Rr   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyR‚   Î  s*    c         C   s!   d d l  m } |  j | ƒ d S(   s   Write GEDCOM data to stdoutiÿÿÿÿ(   t   stdoutN(   t   sysR“   t   save_gedcom(   R   R“   (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   print_gedcomü  s    c         C   sX   t  d d k r/ | j |  j ƒ  j t ƒ ƒ n% | j |  j ƒ  j t ƒ j d ƒ ƒ d S(   sA   Save GEDCOM data to a file
        :type open_file: file
        i    i   s	   utf-8-sigN(   R    t   writeR   t   to_gedcom_stringRn   t   encode(   R   t	   open_file(    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyR•     s    N(   R   R   t   __doc__R   R   R   R   R   R   Rn   R(   t   staticmethodR    R   Re   Rj   Rm   Rq   R3   R4   RX   RW   Rx   Rv   R-   Rˆ   t   FAMILY_MEMBERS_TYPE_ALLR‚   R–   R•   (    (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyR   1   s,   
									j					$.	(!   t   reR+   R”   R    t   gedcom.element.elementR   t   gedcom.element.familyR   R   t   gedcom.element.fileR   t   gedcom.element.individualR   R   t   gedcom.element.objectR   t   gedcom.element.rootR   t   gedcom.tagsR3   R   R4   R€   R   R…   RŽ   R   Rƒ   R   t	   ExceptionR   t   objectR   (    (    (    sT   /var/www/genealogy.alanbeam.net/app/env/lib/python3.5/site-packages/gedcom/parser.pyt   <module>   s   