403Webshell
Server IP : 217.160.0.244  /  Your IP : 216.73.217.138
Web Server : Apache
System : Linux infong-eu155 4.4.400-icpu-108 #2 SMP Wed Feb 11 11:51:01 UTC 2026 x86_64
User : u100174116 ( 6746176)
PHP Version : 8.5.10
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /lib/python3/dist-packages/breezy/__pycache__/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /lib/python3/dist-packages/breezy/__pycache__/graph.cpython-313.pyc
�

p��g*��X�SSKJrJrJrJr SSKJr Sr"SS5r"SS5r	"SS	5r
"S
S5r"SS
5r"SS5r
"SS5r"SS5rSrSr"SS5r/SQrSSKJr g!\a"r\R0"\5 SSKJr SrCgSrCff=f)�)�debug�errors�osutils�trace)�revision�c�*�\rSrSrSrSrSrSrSrg)�DictParentsProvider�.z%A parents provider for Graph objects.c��Xlg�N��ancestry)�selfrs  �./usr/lib/python3/dist-packages/breezy/graph.py�__init__�DictParentsProvider.__init__1s�� �
�c�8�SRUR5$)NzDictParentsProvider({!r}))�formatr�rs r�__repr__�DictParentsProvider.__repr__4s��*�1�1�$�-�-�@�@rc�^�URnUVs0sHo3U;dM
X2U_M sn$s snf�z*See StackedParentsProvider.get_parent_map.r)r�keysr�ks    r�get_parent_map�"DictParentsProvider.get_parent_map<s/���=�=��(,�>��1�X�
���A�;���>�>��>s�	*�	*rN�	�__name__�
__module__�__qualname__�__firstlineno__�__doc__rrr�__static_attributes__�rrr
r
.s��/�!�A�?rr
c�*�\rSrSrSrSrSrSrSrg)�StackedParentsProvider�Bz�A parents provider which stacks (or unions) multiple providers.

The providers are queries in the order of the provided parent_providers.
c��Xlgr
��_parent_providers)r�parent_providerss  rr�StackedParentsProvider.__init__Hs��!1�rc�b�SRURRUR5$�Nz{}({!r}))r�	__class__r!r-rs rr�StackedParentsProvider.__repr__Ks%��� � ����!8�!8�$�:P�:P�Q�Qrc��0n[U5nURHHn[USS5nUcMU"U5nURU5 UR	U5 U(aMH O U(dU$URHAnURU5nURU5 UR	U5 U(aM@ U$ U$![Ra M^f=f)a�Get a mapping of keys => parents.

A dictionary is returned with an entry for each key present in this
source. If this source doesn't have information about a key, it should
not include an entry.

[NULL_REVISION] is used as the parent of the first user-committed
revision.  Its parent list is empty.

:param keys: An iterable returning keys to check (eg revision_ids)
:return: A dictionary mapping each key to its parents
�get_cached_parent_mapN)�setr-�getattr�update�difference_updaterr�UnsupportedOperation)rr�found�	remaining�parents_provider�
get_cached�	new_founds       rr�%StackedParentsProvider.get_parent_mapNs�������I�	�
!%� 6� 6�� �!1�3J�D�Q�J��!��"�9�-�I��L�L��#��'�'�	�2��9��!7���L� $� 6� 6��
�,�;�;�I�F�	�
�L�L��#��'�'�	�2��9����!7����
�.�.�
��
�s�?C�C�Cr,Nr r'rrr)r)Bs���
2�R�'rr)c�P�\rSrSrSrS
SjrSrSSjrSrSr	S	r
S
rSrSr
g)�CachingParentsProvider�xa~A parents provider which will cache the revision => parents as a dict.

This is useful for providers which have an expensive look up.

Either a ParentsProvider or a get_parent_map-like callback may be
supplied.  If it provides extra un-asked-for parents, they will be cached,
but filtered out of get_parent_map.

The cache is enabled by default, but may be disabled and re-enabled.
Nc��XlUcURRUlOX lSUlUR	S5 g)z�Constructor.

:param parent_provider: The ParentProvider to use.  It or
    get_parent_map must be supplied.
:param get_parent_map: The get_parent_map callback to use.  It or
    parent_provider must be supplied.
NT)�_real_providerr�_get_parent_map�_cache�enable_cache)r�parent_providerrs   rr�CachingParentsProvider.__init__�s?��.���!�#'�#6�#6�#E�#E�D� �#1� �������$�rc�b�SRURRUR5$r1)rr2r!rErs rr�CachingParentsProvider.__repr__�s%��� � ����!8�!8�$�:M�:M�N�Nrc�l�URb[S5e0UlXl[5Ulg)z
Enable cache.Nz#Cache enabled when already enabled.)rG�AssertionError�
_cache_missesr6�missing_keys)r�cache_missess  rrH�#CachingParentsProvider.enable_cache�s/���;�;�"� �!F�G�G����)���E��rc�>�SUlSUl[5Ulg)zDisable and clear the cache.N)rGrOr6rPrs r�
disable_cache�$CachingParentsProvider.disable_cache�s�����!����E��rc�H�URcg[UR5$)z(Return any cached get_parent_map values.N)rG�dictrs r�get_cached_map�%CachingParentsProvider.get_cached_map�s���;�;����D�K�K� � rc�h�URnUc0$UVs0sHo3U;dM
X2U_M sn$s snf)z�Return items from the cache.

This returns the same info as get_parent_map, but explicitly does not
invoke the supplied ParentsProvider to search for uncached values.
)rG)rr�cache�keys    rr5�,CachingParentsProvider.get_cached_parent_map�s;�������=��I�+/�@�4�C�%�<���3�Z��4�@�@��@s�	/�	/c��URnUcURU5nO�UVs1sHo3U;dM
UiM nnURUR5 U(aTURU5nUR	U5 UR
(a!UHnX5;dM
UR
U5 M 0nUHnURU5nUcMXvU'M U$s snfr)rGrFr9rPr8rO�note_missing_key�get)rrr[r\�needed_revisions�
parent_map�result�values        rr�%CachingParentsProvider.get_parent_map�s��������=��(�(��.�E�/3�H�t��%�7G��t��H��.�.�t�/@�/@�A��!�1�1�2B�C�
����Z�(��%�%�/���0� �1�1�#�6� 0����C��I�I�c�N�E�� �#�s����
�� Is
�	C�Cc�^�UR(aURRU5 gg)zNote that key is a missing key.N)rOrP�add)rr\s  rr_�'CachingParentsProvider.note_missing_key�s$��������!�!�#�&�r)rGrOrFrErP)NN)T)r!r"r#r$r%rrrHrTrXr5rr_r&r'rrrBrBxs1��	� � O�"�"�!�	A��.'rrBc�*�\rSrSrSrSrSrSrSrg)� CallableToParentsProviderAdapter��z�A parents provider that adapts any callable to the parents provider API.

i.e. it accepts calls to self.get_parent_map and relays them to the
callable it was constructed with.
c��Xlgr
��callable)r�
a_callables  rr�)CallableToParentsProviderAdapter.__init__�s��"�
rc�b�SRURRUR5$r1)rr2r!rnrs rr�)CallableToParentsProviderAdapter.__repr__�s#��� � ����!8�!8�$�-�-�H�Hrc�$�URU5$r
rm)rrs  rr�/CallableToParentsProviderAdapter.get_parent_map�s���}�}�T�"�"rrmNr r'rrrjrj�s���#�I�#rrjc���\rSrSrSrSrSrSrSrSr	Sr
S	rS
rSr
SrS
rSrSrSrSrSrSrSrSrSrSrSrS#SjrSrS$SjrSrSrSr S r!S!r"S"r#g)%�Graph��z�Provide incremental access to revision graphs.

This is the generic implementation; it is intended to be subclassed to
specialize it for other repository types.
c��[USS5bURUl[USS5bURUlXlg)ahConstruct a Graph that uses several graphs as its input.

This should not normally be invoked directly, because there may be
specialized implementations for particular repository types.  See
Repository.get_graph().

:param parents_provider: An object providing a get_parent_map call
    conforming to the behavior of
    StackedParentsProvider.get_parent_map.
�get_parentsNr)r7ryr�_parents_provider)rr=s  rr�Graph.__init__�sG���#�]�D�9�E�/�;�;�D���#�%5�t�<�H�"2�"A�"A�D��!1�rc�8�SRUR5$)NzGraph({!r}))rrzrs rr�Graph.__repr__�s���#�#�D�$:�$:�;�;rc�L�URU5up#nURU5$)a
Determine the lowest common ancestors of the provided revisions.

A lowest common ancestor is a common ancestor none of whose
descendants are common ancestors.  In graphs, unlike trees, there may
be multiple lowest common ancestors.

This algorithm has two phases.  Phase 1 identifies border ancestors,
and phase 2 filters border ancestors to determine lowest common
ancestors.

In phase 1, border ancestors are identified, using a breadth-first
search starting at the bottom of the graph.  Searches are stopped
whenever a node or one of its descendants is determined to be common

In phase 2, the border ancestors are filtered to find the least
common ancestors.  This is done by searching the ancestries of each
border ancestor.

Phase 2 is perfomed on the principle that a border ancestor that is
not an ancestor of any other border ancestor is a least common
ancestor.

Searches are stopped when they find a node that is determined to be a
common ancestor of all border ancestors, because this shows that it
cannot be a descendant of any border ancestor.

The scaling of this operation should be proportional to:

1. The number of uncommon ancestors
2. The number of border ancestors
3. The length of the shortest path between a border ancestor and an
   ancestor of all border ancestors.
)�_find_border_ancestors�heads)r�	revisions�
border_common�common�sidess     r�find_lca�Graph.find_lca�s+��D(,�'B�'B�9�'M�$�
�u��z�z�-�(�(rc���URX/5up4nURXE5 USRnUSRnURU5URU54$)z5Determine the graph difference between two revisions.�r)r�_search_for_extra_common�seen�
difference)r�
left_revision�right_revision�borderr��	searchers�left�rights        r�find_difference�Graph.find_difference'sj��$(�$?�$?�
�+�%
�!��	�	
�%�%�f�8���|� � ���!��!�!������&��(8�(8��(>�?�?rc��URURX55n[[U55nUR	U/5n[U5 UR$)z:Find descendants of old_key that are ancestors of new_key.)�
get_child_map�_find_descendant_ancestorsrvr
�_make_breadth_first_searcher�listr�)r�old_key�new_key�	child_map�graph�searchers      r�find_descendants�Graph.find_descendants1sU���&�&��+�+�G�=�
�	��)�)�4�5���5�5�w�i�@���X���}�}�rc�^�URU/5nURU/5nUH_nURRU5nURU5 UR	UR55nURU5 Ma URR
UR5$)z=Find ancestors of new_key that may be descendants of old_key.)r�r��intersection�stop_searching_any�find_seen_ancestors�stepr�)rr�r��stop�descendantsr��old_stop�	seen_stops        rr�� Graph._find_descendant_ancestors;s����0�0�'��;���7�7��	�B��$�I��y�y�-�-�i�8�H��*�*�8�4�#�7�7��	�	��D�I��*�*�9�5�	%�
���*�*�4�9�9�5�5rc���URRU5n0n[UR55H/upEUH$nUR	U/5RU5 M& M1 U$)z�Get a mapping from parents to children of the specified keys.

This is simply the inversion of get_parent_map.  Only supplied keys
will be discovered as children.
:return: a dict of key:child_list for keys.
)rzr�sorted�items�
setdefault�append)rrrb�parent_child�child�parents�parents       rr��Graph.get_child_mapFsf���+�+�:�:�4�@�
���$�Z�%5�%5�%7�8�N�E�!���'�'���3�:�:�5�A�"�9��rc��[U5nUnSn[RnSX6'[U5n0nXC;a�XXU'US-
nU1n	U	R	U5 URU	5n
U
R
US5nU(d[R"X5eUSn/nUHTn
U
R
U
S5nU(dMUSnX=S-
nX�;a	X�U-s $X�;aM?X�U'URU5 MV UnXC;aM�X4U-$)a[Find the left-hand distance to the NULL_REVISION.

(This can also be considered the revno of a branch at
target_revision_id.)

:param target_revision_id: A revision_id which we would like to know
    the revno for.
:param known_revision_ids: [(revision_id, revno)] A list of known
    revno, revision_id tuples. We'll use this to seed the search.
r�rN)
rW�
_mod_revision�
NULL_REVISIONr�r8rr`r�GhostRevisionsHaveNoRevnor�)r�target_revision_id�known_revision_ids�known_revnos�cur_tip�	num_stepsr��searching_known_tips�unknown_searched�	to_searchrbr��next_known_tips�revision_id�next�
next_revnos                r�find_distance_to_null�Graph.find_distance_to_nullTs6���.�/��$���	�%�3�3�
�&'��#�#�L�1�����)�(1�W�%���N�I� �	�I����1�2��,�,�Y�7�J� �n�n�W�d�3�G���6�6�7I�S�S��a�j�G� �O�3��$�.�.��d�;�����q�z��)�6��:�
��+�%��(>�>�>��'��%/�T�"��&�&�t�,� 4�$3� �1�)�8�$�y�0�0rc��/n/nUH%nURX@RXB545 M' UHnURUS45 M [	U5$![Ra URU5 Mxf=f)z�Find the distance to null for all the keys in keys.

:param keys: keys to lookup.
:return: A dict key->distance for all of keys.
���)r�r�rr�rW)rrr��ghostsr\s     r�find_lefthand_distances�Graph.find_lefthand_distances�s��������C�
#��#�#��4�4�S�G�H����C�����b�	�*���L�!�!��	�3�3�
#��
�
�c�"�
#�s�!A�%B�?Bc��X;a
[5$URU/U5up4URRUR5nU(dU$UR	XSU5upgURX6Xt5 URUR5nS[R;a*[R"S[U5[U55 U$)a"Find the unique ancestors for a revision versus others.

This returns the ancestry of unique_revision, excluding all revisions
in the ancestry of common_revisions. If unique_revision is in the
ancestry, then the empty set will be returned.

:param unique_revision: The revision_id whose ancestry we are
    interested in.
    (XXX: Would this API be better if we allowed multiple revisions on
    to be searched here?)
:param common_revisions: Revision_ids of ancestries to exclude.
:return: A set of revisions in the ancestry of unique_revision
r�z%Found %d truly unique nodes out of %d)r6�_find_initial_unique_nodesr�r��_make_unique_searchers�_refine_unique_nodesr�debug_flagsr�mutter�len)	r�unique_revision�common_revisions�unique_searcher�common_searcher�unique_nodes�all_unique_searcher�unique_tip_searchers�true_unique_nodess	         r�find_unique_ancestors�Graph.find_unique_ancestors�s����.��5�L�*,0�+J�+J�
��/�,
�(��'�+�+�6�6��7K�7K�L�����6:�6Q�6Q��?�7
�3�	�	
�!�!��2F�	
�)�3�3�O�4H�4H�I���e�'�'�'��L�L�7��%�&��L�!�
�
!� rc�L�URU5n[U5 URU5nUR(a�[UR	55n[UR	55nURUR5nURURUR55 U(aSURU5nURURU55 URU5 URU5 UR(aM�X44$)z�Steps 1-3 of find_unique_ancestors.

Find the maximal set of unique nodes. Some of these might actually
still be common, but we are sure that there are no other unique nodes.

:return: (unique_searcher, common_searcher)
)r�r��_next_queryr6r�r�r�r8r�r��start_searching)	r�unique_revisionsr�r�r��next_unique_nodes�next_common_nodes�unique_are_common_nodes�	ancestorss	         rr�� Graph._find_initial_unique_nodes�s	���;�;�<L�M��	
�_���;�;�<L�M���)�)� #�O�$8�$8�$:� ;�� #�O�$8�$8�$:� ;��'8�&D�&D��$�$�'�#�
$�*�*�!�.�.��/C�/C�D�
�'�+�?�?�@W�X�	�
� � ��!D�!D�Y�!O�P��2�2�9�=��/�/�	�:�)�)�)�)�,�/�/rc
��URXRU55n[U5S:Xa/nURU5nO�/nUHmnURU/5nUR	URU55 URU5n	XylU	R5 URU	5 Mo SnUH8n	Uc[U	R5nMURU	R5nM: URU5n
U(agU
R5 URURU55nSnUH/n	U[U	RU	RU555-
nM1 S[R;a?[R "S[U5[U5W[U5[W55 X�4$)z�Create a searcher for all the unique search tips (step 4).

As a side effect, the common_searcher will stop searching any nodes
that are ancestors of the unique searcher tips.

:return: (all_unique_searcher, unique_tip_searchers)
rNr�r�zuFor %d unique nodes, created %d + 1 unique searchers (%d stopped search tips, %d common ancestors (%d stopped common))�_remove_simple_descendantsrr�r�r8r��_labelr�r�r6r�r�r�rr�rr�)
rr�r�r��unique_tipsr��ancestor_all_unique�tip�revs_to_searchr�r��stopped_common�
total_stoppeds
             rr��Graph._make_unique_searcherss����5�5��-�-�l�;�
���{��q� �#%� �"1�"E�"E�k�"R��#%� �"��!0�!D�!D�c�U�!K���%�%�#�7�7��G�� �<�<�^�L��"%���
�
��$�+�+�H�5�#�#'��0��&�.�*-�h�m�m�*<�'�*=�*J�*J� �
�
�+�'�	1�#�?�?�@S�T���
 �$�$�&�-�?�?��3�3�4G�H��N��M�0�����/�/� �4�4�5H�I��"��
�1��e�'�'�'��L�L�'��L�!��(�)���'�(��N�#�	
�#�8�8rc��[UR55n[5nUH�n[UR55nURURU55 URURU55 UH)nX�LaM	URURU55 M+ UR	U5 URU5 M� XE4$)zStep all the searchers.)r6r�r8r�r�)	rr�r�r��newly_seen_common�newly_seen_uniquer�r��alt_searchers	         r�!_step_unique_and_common_searchers�'Graph._step_unique_and_common_searchersEs��� �� 4� 4� 6�7���E��,�H��x�}�}��'�D��K�K��;�;�D�A�B��K�K��;�;�D�A�B� 4���+�����L�<�<�T�B�C�!5�
�$�$�T�*��$�$�T�*�-�!�3�3rc��UR5nUHnURUR5 M  URUR5 U(a�[R"5nUR5nUR
U5 S[R;aX[R"5U-
n	[R"SU	[U5[UR5UR5 U$)z�Find nodes that are common to all unique_tip_searchers.

If it is time, step the all_unique_searcher, and add its nodes to the
result.
r�zKall_unique_searcher step() took %.3fsfor %d nodes (%d total), iteration: %s)
�copy�intersection_updater�r�perf_counterr�r8rr�rr�r��_iterations)
rr�r�r��step_all_unique�common_to_all_unique_nodesr��tstart�nodes�tdeltas
          r� _find_nodes_common_to_all_unique�&Graph._find_nodes_common_to_all_uniqueWs���&7�%;�%;�%=�"�,�H�&�:�:�8�=�=�I�-�"�6�6�7J�7O�7O�P���)�)�+�F�'�,�,�.�E�&�-�-�e�4��%�+�+�+� �-�-�/�&�8�����=����J��+�0�0�1�'�3�3�
�*�)rc	��0nUH�nURU5n[UR5nU(dNS[R;a8[
R"SURUR[U55 M|M~Xc;aU/X6'M�X6RU5 M� /nUR5H�n[U5S:XaURUS5 M(USn	USSH(nU	RRUR5 M* S[R;aH[
R"S[U5[U	R5[U	R55 URU	5 M� U$)a/Combine searchers that are searching the same tips.

When two searchers are searching the same tips, we can stop one of the
searchers. We also know that the maximal set of common ancestors is the
intersection of the two original searchers.

:return: A list of searchers that are searching unique nodes.
r�z@Unique searcher %s was stopped. (%s iterations) %d nodes stoppedrr�NzQCombining %d searchers into a single searcher searching %d nodes with %d ancestry)r��	frozensetr�rr�rr�r�r�r�r��valuesr�r�)
rr�r��unique_search_tipsr��stopped�will_search_set�next_unique_searchersr��
next_searchers
          r�_collapse_unique_searchers� Graph._collapse_unique_searcherszs_�� ��,�H��1�1�2L�M�G�'��(<�(<�=�O�"��e�/�/�/��L�L�<� ��� �,�,��G���0�!�:�7?�j�"�3�"�3�:�:�8�D�!-�&!#��+�2�2�4�I��9�~��"�%�,�,�Y�q�\�:�!*�!��
� )�!�"�
�H�!�&�&�:�:�8�=�=�I�!.��e�/�/�/��L�L�'��I���M�5�5�6��M�.�.�/�
�&�,�,�]�;�+5�,%�$rc��SnUR(Ga:URXCU5upgURUUUUS:H5nUS-[-nU(a*UR	UR
R
U55 U(aBURURU55 URU5 UR	U5 URX85n	[U5[U	5:waIS[R;a5[R"S[U5[U	5UR 5 U	nUR(aGM9gg)zvSteps 5-8 of find_unique_ancestors.

This function returns when common_searcher has stopped searching for
more nodes.
r�rr�z4Collapsed %d unique searchers => %d at %s iterationsN)r�r�r��STEP_UNIQUE_SEARCHER_EVERYr�r�r�r8r�r�r	r�rr�rr�r�)
rr�r�r�r��step_all_unique_counterr�r�r�rs
          rr��Graph._refine_unique_nodes�sO��#$���)�)�)��6�6�#�?��
3�
�*.�)N�)N�$�#�!�'�1�,�	*�&�(�!�+�*�'+�#�!� �2�2�'�,�,�9�9�:K�L��*�*�1�1�#�7�7�8R�S��$�3�3�4N�O��2�2�3M�N�$(�$C�$C�$�%�!��'�(�C�0E�,F�F��e�/�/�/��L�L�N��0�1��1�2�+�7�7�	�$9� �a�)�)�)rc�P�0nURU5Hup4UcM
XBU'M U$)z�Get a map of key:parent_list for revisions.

This implementation delegates to get_parents, for old parent_providers
that do not supply get_parent_map.
)ry)rr�rc�revr�s     rr�Graph.get_parent_map�s4���� �,�,�Y�7�L�C��"�%�s��8��
rc��[X5$r
)�_BreadthFirstSearcher)rr�s  rr��"Graph._make_breadth_first_searchers
��$�Y�5�5rc���SU;a[R"SU5e[5nUVs/sHo0RU/5PM nn[5n[5nUH-nUR	5nU(dMURU5 M/ [5n	UHXn
X�;aU	R
U
5 MUHnX�R;dM M4 UR
U
5 U	R
U
5 MZ U	(aTUH#nU	RURU	55 M% UHnURU	5 M URU	5 [5nUH0n[UR5nX�;dMUR
U5 M2 [U5S:XaCUR5n
U
RU5nU(a[SR!X55eOGM�XRU4$s snf)aFind common ancestors with at least one uncommon descendant.

Border ancestors are identified using a breadth-first
search starting at the bottom of the graph.  Searches are stopped
whenever a node or one of its descendants is determined to be common.

This will scale with the number of uncommon ancestors.

As well as the border ancestors, a set of seen common ancestors and a
list of sets of seen ancestors for each input revision is returned.
This allows calculation of graph difference from the results of this
operation.
NrzmSomehow we ended up converging without actually marking them as in common.
Start_nodes: {}
uncommon_nodes: {})r�InvalidRevisionIdr6r�r�r8rgr�r�r�rr�r��popr�rNr)rr��common_ancestors�rr��border_ancestors�
newly_seenr��
new_ancestors�
new_commonr�unique_search_setsrr��uncommon_nodess               rr�Graph._find_border_ancestorss����9���*�*�4��6�6��5��EN�O�Y��6�6��s�;�Y�	�O��5�����J�%�� (�
�
��
� �=��%�%�m�4�&���J�&���/��N�N�8�,�� )�H��}�}�4��!*�%�(�(��2��N�N�8�,�'�� )�H��%�%�h�&B�&B�:�&N�O�!*� )�H��,�,�Z�8�!*� �'�'�
�3�"%���%��"+�H�,@�,@�"A��"�<�&�*�*�?�;�	&��%�&�!�+�*�.�.�0��!&�!1�!1�2B�!C��!�(�/�06�v�i�/P����e�f �9�<�<��mPs�G-c���[U5n[RU;a7UR[R5 U(d[R1$[	U5S:aU$UVs0sHo3URU/5_M nn[
U5nUR5Hn[U5 M UR/5n[	U5S:�GaM[5n[U5 [U5H#n	XYnUR[U55 M% [5n
UH�nX�;aURU5 XK	X�;aX[	X�R;a-U1nUR5HnURU5 M M^UR5HnX�R;dM M� U
RU5 UR5H&nUR!U/5n
URU
5 M( M� UR#U
5 [	U5S:�aGMMU$s snf![a GNKf=f![a GMRf=f![a XY	GMff=f)aReturn the heads from amongst keys.

This is done by searching the ancestries of each key.  Any key that is
reachable from another key is not returned; all the others are.

This operation scales with the relative depth between any two keys. If
any two keys are completely disconnected all ancestry of both sides
will be retrieved.

:param keys: An iterable of keys.
:return: A set of the heads. Note that as a set there is no ordering
    information. Callers will need to filter their input to create
    order if they need it.
�r�)r6r�r��remover�r�rWrr��
StopIterationr��KeyErrorr8r�r�rgr�r�)rr�candidate_heads�cr��active_searchersr��
common_walkerr��	candidater�ancestor�ancestor_set�seen_ancestorss              rr��Graph.headsNsK���d�)���&�&�/�9��"�"�=�#>�#>�?�"�%�3�3�4�4����!�#�"�"�HW�X��1��9�9�1�#�>�>��	�X��	�?��(�/�/�1�H���N�2��9�9�"�=�
��"�#�a�'���I�
��]�#�"�"2�3�	��/�:�H���$�$�T�(�^�4�4���J�%���.�#�*�*�8�4�!�+��3�,�6��1�1�1�%-�:�L�$-�$4�$4�$6�� �3�3�L�A�%7�%.�$4�$4�$6��#�=�=�8�!�%7�#���x�0�(1�(8�(8�(:�H�-5�-I�-I�8�*�-U�N�$�7�7��G�);�/&�4
�)�)�*�5�c�"�#�a�'�d���}Y��"!�
��
�� ���	��%��(�3���s<�,H'�#H,�=H=�I�,
H:�9H:�=
I�I�I �I c�h�[U5S:Xa[U5$[U5nU/n/n[5nU(a�U(a�UR5nUR	U5 Xs;aUURU5 UR
U5 [U5S:Xa"URUR55 U$M�URU/5RUS5nU(dM�[U5H*n	X�;aURU	5 UR	U	5 M, U(a	U(aM�U$)z�Find the order that each revision was merged into tip.

This basically just walks backwards with a stack, and walks left-first
until it finds a node to stop.
rN)
r�r�r6rrgr�r#rr`�reversed)
r�tip_revision_id�lca_revision_ids�looking_for�stackr;r�r��
parent_ids�	parent_ids
          r�find_merge_order�Graph.find_merge_order�s
���� �A�%��(�)�)��*�+��!�!�����u�����9�9�;�D��H�H�T�N��"����T�"��"�"�4�(��{�#�q�(��L�L����!2�3��"��!��,�,�d�V�4�8�8��t�D�J���%�j�1�	��(��L�L��+�����#�2����2�rc�t�URX5nURU5nSnUHnXc;aUs $UnM g)a�Find the first lefthand ancestor of tip_key that merged merged_key.

We do this by first finding the descendants of merged_key, then
walking through the lefthand ancestry of tip_key until we find a key
that doesn't descend from merged_key.  Its child is the key that
merged merged_key.

:return: The first lefthand ancestor of tip_key to merge merged_key.
    merged_key if it is a lefthand ancestor of tip_key.
    None if no ancestor of tip_key merged merged_key.
N)r��iter_lefthand_ancestry)r�
merged_key�tip_keyr��candidate_iterator�last_candidater*s       r�find_lefthand_merger�Graph.find_lefthand_merger�sE���+�+�J�@��!�8�8��A����+�I��+�%�%�&�N�,rc���X/nSnUS-
nUR"U6n[U5S:XaUR5nU(aXu4$U$[U5S:Xa[R"X5eUnMh)a2Find a unique LCA.

Find lowest common ancestors.  If there is no unique  common
ancestor, find the lowest common ancestors of those ancestors.

Iteration stops when a unique lowest common ancestor is found.
The graph origin is necessarily a unique lowest common ancestor.

Note that None is not an acceptable substitute for NULL_REVISION.
in the input for this method.

:param count_steps: If True, the return value will be a tuple of
    (unique_lca, steps) where steps is the number of times that
    find_lca was run.  If False, only unique_lca is returned.
r�r)r�r�rr�NoCommonAncestor)rr�r��count_stepsr��steps�lcarcs        r�find_unique_lca�Graph.find_unique_lca�sw�� #�3�	�����Q�J�E��-�-��+�C��3�x�1�}�������!�=�(�!�M��3�x�1�}��-�-�m�L�L��I�rc#�h^# �[U5n[5mU(a�TRU5 URU5n[5nUR5H%nUv� URU4SjUS55 M' UR	U5nUH	nUS4v� M UnU(aM�gg7f)a�Iterate the ancestry of this revision.

:param revision_ids: Nodes to start the search
:return: Yield tuples mapping a revision_id to its parents for the
    ancestry of revision_id.
    Ghosts will be returned with None as their parents, and nodes
    with no parents will have NULL_REVISION as their only parent. (As
    defined by get_parent_map.)
    There will also be a node for (NULL_REVISION, ())
c3�6># �UHoT;dM
Uv� M g7fr
r')�.0�p�	processeds  �r�	<genexpr>�&Graph.iter_ancestry.<locals>.<genexpr>s����#M�w�!�9�:L�A�A�w�s�	�	rN)r6r8rr�r�)	r�revision_ids�pending�next_map�next_pending�itemr��ghostrLs	        @r�
iter_ancestry�Graph.iter_ancestrys������l�#���E�	�����W�%��*�*�7�3�H��5�L� ���(���
��#�#�#M�t�A�w�#M�M�)��'�'��1�F����d�m�#� �"�G��g�s�B+B2�0B2Nc#�^^# �UcSnUmUU4SjnTU;agU"T5nTv� [U5S:XagUSmM*7f)Nr'c�>�TRRU/5U$![a [R"TT5ef=fr
)rzrr%r�RevisionNotPresent)r\�next_keyrs ��rry�1Graph.iter_lefthand_ancestry.<locals>.get_parents%sK���
@��-�-�<�<�c�U�C�C�H�H���
@��/�/��$�?�?�
@�s	�"�"Ar�)r�)r�	start_key�	stop_keysryr�rZs`    @rr:�Graph.iter_lefthand_ancestry sX�������I���	@���9�$��!�(�+�G��N��7�|�q� ��"�1�:���s�:>c�n�SSKJn URURU55nUR	5$)z�Iterate through the input revisions in topological order.

This sorting only ensures that parents come before their children.
An ancestor may sort after a descendant if the relationship is not
visible in the supplied list of revisions.
r�)�tsort)�breezyr`�
TopoSorterr�iter_topo_order)rr�r`�sorters    rrc�Graph.iter_topo_order5s1��	!��!�!�$�"5�"5�i�"@�A���%�%�'�'rc�.�U1URX/5:H$)z�Determine whether a revision is an ancestor of another.

We answer this using heads() as heads() has the logic to perform the
smallest number of parent lookups to determine the ancestral
relationship between N revisions.
)r�)r�candidate_ancestor�candidate_descendants   r�is_ancestor�Graph.is_ancestorAs%��%�%����
�6�*
�
�	
rc��USL=(d URX5=(a USL=(d URX!5$)z�Determine whether a revision is between two others.

returns true if and only if:
lower_bound_revid <= revid <= upper_bound_revid
N)ri)r�revid�lower_bound_revid�upper_bound_revids    r�
is_between�Graph.is_betweenLsA��
��%�S��)9�)9�%�)S�X� �D�(�V�D�,<�,<�=N�,V�	Xrc��[U5S:wa[S5eUnUSnUSnURRUR5nU(dg[U5nUR	X`RU55n[U5n/n	UHen
X�R;aUnOUnUR
U
/5nU(dU
/nURU5n
U
R5 U	RU
5 Mg SnU	H8n
Uc[U
R5nMURU
R5nM: [R"SUU5 [5nUH"n
URU
R55 M$ [5nU	H"n
URU
R55 M$ [5nUH0nU	Hn
UU
R;dM M URU5 M2 U(auUH#n
URU
R
U55 M% UHn
U
R!U5 M URU5nU(aUHn
U
R#U5 M U(a�U	H#n
URU
R
U55 M% UH#n
URU
R
U55 M% U	Hn
U
R!U5 M UHn
U
R#U5 M URU5 /n[5nU	HBn
[%U
R&5nUU;dM URU5 URU
5 MD Un	UHn
U
R&(dM O gGM4)aMake sure that unique nodes are genuinely unique.

After _find_border_ancestors, all nodes marked "common" are indeed
common. Some of the nodes considered unique are not, due to history
shortcuts stopping the searches early.

We know that we have searched enough when all common search tips are
descended from all unique (uncommon) nodes because we know that a node
cannot be an ancestor of its own ancestor.

:param common: A set of common nodes
:param searchers: The searchers returned from _find_border_ancestors
:return: None
r"z/Algorithm not yet implemented for > 2 searchersr�rNz3Started %d unique searchers for %d unique revisions)r��NotImplementedErrorr��symmetric_differencer�rr�r�r�r�r6r�rr�r8rgr�r�rr�)rr�r��common_searchers�
left_searcher�right_searcher�unique�total_unique�
simple_unique�unique_searchersr��parent_searcherr�r�r�r�r��new_common_uniquer�stop_searching_commonrrrs                       rr��Graph._search_for_extra_commonVs[��<�y�>�Q��%�&W�X�X�$��!�!��
�"�1����#�#�8�8��9L�9L�M�����6�{���0�0��9L�9L�V�9T�U���F��
���!�K��0�0�0�"/��"0��,�@�@�+��O�N�!�"-����8�8��H�H��M�M�O��#�#�H�-�"�"#��(�H�"�*�&)�(�-�-�&8�#�&9�&F�&F�x�}�}�&U�#�	)�	���A���	
�� #���,��!�(�(�����9�-� #���,��!�(�(�����9�-� #���-�� 0�H��x�}�}�4��!1�&�)�)�(�3�.�!�!1�H�%�,�,� �4�4�5F�G��!1�!1�H��,�,�->�?�!1�
)<�(H�(H�%�)�%�)�$4�� �3�3�4I�J�%5� � 0�H�%�,�,� �4�4�5F�G��!1�!1�H�%�,�,� �4�4�5F�G��!1�!1�H��,�,�->�?�!1� 0�H��/�/�0A�B�!1�#�*�*�+<�=�)+�%�%(�U�"� 0�H�&/��0D�0D�&E�O�&�.@�@�+�.�.��?�-�4�4�X�>�
!1�$9� �,���'�'�'��-�
�]rc��UR5nUR5H,upEUcM
UHnXa;dM
URU5  M* M. U$)a&Remove revisions which are children of other ones in the set.

This doesn't do any graph searching, it just checks the immediate
parent_map to find if there are any children which can be removed.

:param revisions: A set of revision_ids
:return: A set of revision_ids with the children removed
)r�r��discard)rr�rb�simple_ancestorsrr5r6s       rr�� Graph._remove_simple_descendants�s]��%�>�>�+��(%/�$4�$4�$6� �H��!��'�	��)�%�,�,�X�6��(�%7� �r)rzrry)Fr
)$r!r"r#r$r%rrr�r�r�r�r�r�r�r�r�r�r�r�r	r�rr�rr�r7r?rFrUr:rcriror�r�r&r'rrrvrv�s����2�"<�&)�P@��	6��21�h"�*:!�x%0�NC9�J4�$!*�F8%�t@9�D
�6�G=�RU�n-�^'�(�>#�2&�*
(�	
�X�W�r& rrvc�$�\rSrSrSrSrSrSrg)�
HeadsCacheiz)A cache of results for graph heads calls.c��Xl0Ulgr
�r��_heads�rr�s  rr�HeadsCache.__init__����
���rc���[U5n[URU5$![a7 URRU5nX RU'[U5s$f=f)a`Return the heads of keys.

This matches the API of Graph.heads(), specifically the return value is
a set which can be mutated, and ordering of the input is not preserved
in the output.

:see also: Graph.heads.
:param keys: The keys to calculate heads for.
:return: A set containing the heads, which may be mutated without
    affecting future lookups.
)rr6r�r%r�r��rrr�s   rr��HeadsCache.headss_������	��t�{�{�4�(�)�)���	��J�J�$�$�T�*�E� %�K�K����u�:��	�s�%�>A&�%A&�r�r�N)r!r"r#r$r%rr�r&r'rrr�r�s��3��rr�c�*�\rSrSrSrSrSrSrSrg)�FrozenHeadsCachei4z;Cache heads() calls, assuming the caller won't modify them.c��Xl0Ulgr
r�r�s  rr�FrozenHeadsCache.__init__7r�rc��[U5nURU$![a7 [URR	U55nX RU'Us$f=f)z�Return the heads of keys.

Similar to Graph.heads(). The main difference is that the return value
is a frozen set which cannot be mutated.

:see also: Graph.heads.
:param keys: The keys to calculate heads for.
:return: A frozenset containing the heads.
)rr�r%r�r�r�s   rr��FrozenHeadsCache.heads;sZ������	��;�;�t�$�$���	��d�j�j�.�.�t�4�5�E� %�K�K����L�	�s��>A�Ac�F�[U5UR[U5'g)zStore a known value.N)rr�r�s   rr[�FrozenHeadsCache.cacheMs��'0��'7����I�d�O�$rr�N)	r!r"r#r$r%rr�r[r&r'rrr�r�4s��E���$8rr�c�d�\rSrSrSrSrSrSrSrSr	\	r
SrS	rS
r
SrSrS
rSrSrg)riRz�Parallel search breadth-first the ancestry of revisions.

This class implements the iterator protocol, but additionally
1. provides a set of seen ancestors, and
2. allows some ancestries to be unsearched, via stop_searching_any
c��SUl[U5Ul[5Ul[UR5Ul[5UlX lSUl[5Ul[5Ul	0Ul
g)Nr��next_with_ghosts)r�r6r�r��
_started_keys�
_stopped_keysrz�
_returning�_current_present�_current_ghosts�_current_parents)rr�r=s   rr�_BreadthFirstSearcher.__init__Zse������y�>����E��	� ��!1�!1�2��� �U���!1��,��� #����"�u��� "��rc���UR(aSnOSnSRU[UR55nSURSUS[UR5<S3$)N�	searching�startingz{}={!r}z!_BreadthFirstSearcher(iterations=z, z, seen=�))r�rr�r�r�)r�prefix�searchs   rr�_BreadthFirstSearcher.__repr__fsc����� �F��F��!�!�&�$�t�/?�/?�*@�A��2�4�3C�3C�2D�B�v�h�g�VZ�[_�[d�[d�Ve�Uh�hi�j�jrc�X�URS:XaKURUR5upp4URR	U5 URU5nOURnURRU5nURRU5nURXg4$)zfGet the current state of this searcher.

:return: Tuple with started keys, excludes and included keys
r�)	r��	_do_queryr�r�r9�unionr�r�r�)rr;r�r�r��
next_query�excludes�
included_keyss        r�	get_state�_BreadthFirstSearcher.get_statens���
�?�?�f�$�,0�>�>�$�:J�:J�+K�(�E�4�
�I�I�'�'��-����F�+�J��)�)�J��%�%�+�+�J�7���	�	�,�,�X�6�
��!�!�8�:�:rc�:�[U5$![a gf=f)Nr')r�r$rs rr��_BreadthFirstSearcher.step�s#��	���:����	��	�s�

�
�c�$�URS:waSUlU=RS-
slOUR5 [UR5S:Xa
[5eURRUR5 UR$)aReturn the next ancestors of this revision.

Ancestors are returned in the order they are seen in a breadth-first
traversal.  No ancestor will be returned more than once. Ancestors are
returned before their parentage is queried, so ghosts and missing
revisions (including the start revisions) are included in the result.
This can save a round trip in LCA style calculation by allowing
convergence to be detected without reading the data for the revision
the convergence occurs on.

:return: A set of revision_ids.
r�rr�)r�r��_advancer�r�r$r�r8rs r�__next__�_BreadthFirstSearcher.__next__�sr���?�?�f�$�$�D�O�����!���M�M�O��t��� �A�%��/�!�	
�	�	����)�)�*����rc���URS:waSUlUR5 [UR5S:Xa
[	5eUR5 UR
UR4$)a}Return the next found ancestors, with ghosts split out.

Ancestors are returned in the order they are seen in a breadth-first
traversal.  No ancestor will be returned more than once. Ancestors are
returned only after asking for their parents, which allows us to detect
which revisions are ghosts and which are not.

:return: A tuple with (present ancestors, ghost ancestors) sets.
r�r�)r�r�r�r�r$r�r�rs rr��&_BreadthFirstSearcher.next_with_ghosts�s\���?�?�0�0�0�D�O��M�M�O��t��� �A�%��/�!��
�
���$�$�d�&:�&:�:�:rc���U=RS-
slURUR5upp4XlX lX0lX@lURRU5 g)z�Advance the search.

Updates self.seen, self._next_query, self._current_present,
self._current_ghosts, self._current_parents and self._iterations.
rN)r�r�r�r�r�r�r�r8)rr;r�r�r�s     rr��_BreadthFirstSearcher._advance�s\��	
���A���'+�~�~�d�6F�6F�'G�$��t� %��%���� '��	
���!�!�&�)rc�x�[5n[5nURnURU5 URR	U5nURU5 UR5H=upgUcM
UVs/sHo�U;dM
UPM n	nU	(dM,URU	5 M? X-
n
X*X54$s snf)z�Query for revisions.

Adds revisions to the seen set.

:param revisions: Revisions to query.
:return: A tuple: (set(found_revisions), set(ghost_revisions),
   set(parents_of_found_revisions), dict(found_revisions:parents)).
)r6r�r8rzrr�)rr��found_revisions�parents_of_foundr�rb�_rev_idr�rK�new_found_parents�ghost_revisionss           rr��_BreadthFirstSearcher._do_query�s����%���5���y�y�����I���+�+�:�:�9�E�
����z�*� *� 0� 0� 2��G����,3� E�G�q��}��G�� E� � �!�'�'�(9�:�!3�$�5���1A�M�M��
!Fs�<	B7�	B7c��U$r
r'rs r�__iter__�_BreadthFirstSearcher.__iter__�s���rc��URn[U5RU5n[U5nURS:Xa
URnOSnURU5 URRnU(aU"U5n/nUR5Hn	URU	5 M URU5RU5n
URU
5 U
RU5 U
nU(aMU$)z�Find ancestors of these revisions that have already been seen.

This function generally makes the assumption that querying for the
parents of a node that has already been queried is reasonably cheap.
(eg, not a round trip to a remote host).
r�r')r�r6r�r�r�r9rzrr�extendr�r8)rr��all_seenrPr-�not_searched_yetrrb�all_parentsr5rRs           rr��)_BreadthFirstSearcher.find_seen_ancestors�s����9�9���i�.�-�-�h�7���W����?�?�f�$� $�/�/��!���!�!�"2�3��/�/�>�>���'��0�J��K�)�/�/�1�
��"�"�:�.�2�#�0�0��=�H�H��X�L��!�!�,�/��*�*�+;�<�"�G��g��rc���[U5nURS:Xa=URRU5nURR	U5UlGO?UR
RU5nUR
URRU55nUR
RU5 URRU5 0nUH.nURUHnXd;aSXF'XF==S-
ss'M M0 URR5HnUHnXF==S-ss'M M [5nUR5Hup�U
S:XdM
URU	5 M  URRU5 URR!U5 URR!U5 U$![a M�f=f)a�Remove any of the specified revisions from the search list.

None of the specified revisions are required to be present in the
search list.

It is okay to call stop_searching_any() for revisions which were seen
in previous iterations. It is the callers responsibility to call
find_seen_ancestors() to make sure that current search tips that are
ancestors of those revisions are also stopped.  All explicitly stopped
revisions will be excluded from the search result's get_keys(), though.
r�r�r)rr�r�r�r�r�r�r�r9r�rr%r6r�rgr�r8)rr�r�stopped_present�stop_rev_referencesrr6r��stop_parents�rev_id�refss           rr��(_BreadthFirstSearcher.stop_searching_anys����i�(�	��?�?�f�$��&�&�3�3�I�>�G�#�/�/�:�:�9�E�D��"�3�3�@�@��K�O�%�+�+��$�$�1�1�)�<��G�
�!�!�3�3�G�<�� � �2�2�7�;�#%��&��!%�!6�!6�s�!;�I� �;�9:�+�6�'�2�a�7�2�"<�'� �0�0�7�7�9��!(�I��+�6�!�;�6�")�:��5�L� 3� 9� 9� ;����1�9� �$�$�V�,�!<�
���.�.�|�<����!�!�'�*����!�!�)�,����$����s�-G�
G�Gc�N�[U5nURRU5 URUR5nUR
S:Xa7URRU5 URRU5 gURU5up4pVURRU5 URRU5 URRU5 URRU5 URRU5 X44$)a/Add revisions to the search.

The parents of revisions will be returned from the next call to next()
or next_with_ghosts(). If next_with_ghosts was the most recently used
next* call then the return value is the result of looking up the
ghost/not ghost status of revisions. (A tuple (present, ghosted)).
r�N)rr�r8r�r�r�r�r�r�r�r�r�)rr��
new_revisions�revsr��queryr�s       rr��%_BreadthFirstSearcher.start_searchingAs����i�(�	����!�!�)�,�!�,�,�T�Y�Y�7�
��?�?�f�$����#�#�M�2��I�I���]�+�,0�>�>�)�+D�(�D�%����%�%�f�-��!�!�(�(��.�� � �'�'��/����#�#�E�*��!�!�(�(��1��<�r)
r�r�r�r�r�rzr�r�r�r�N)r!r"r#r$r%rrr�r�r�r�r�r�r�r�r�r�r�r&r'rrrrRsN���
#�k�;�,� �4�D�;�&*� N�8�$�L1�f rrc�z�0nUR5H$up#UHnXA;aU4X'MXU4-X'M M& U$)zDGiven a map from child => parents, create a map of parent=>children.)r�)rbr�r�r�rKs     r�invert_parent_mapr�ZsO���I�$�*�*�,����A��!� %�x�	��(�|�u�h�6�	���-��rc��0nUR5HAup#URU/5 UH$nURU/5RU5 M& MC [5n[	U5nUH�nXgn[U5S:XdMXSn[U5S:waM0Xn	[U	5S:waMEUR
U	SS5n
[U
5S:waMkX6U	S'X�US'Xg	X	URU5 M� U$)aCollapse regions of the graph that are 'linear'.

For example::

  A:[B], B:[C]

can be collapsed by removing B and getting::

  A:[C]

:param parent_map: A dictionary mapping children to their parents
:return: Another dictionary with 'linear' chains collapsed
rr�N)r�r�r�r6rWr�r`rg)rb�childrenr�r�rK�removedrc�node�parent_children�
node_children�
child_parentss           r�collapse_linear_regionsr�is��N�H�$�*�*�,������E�2�&��A�����2�&�-�-�e�4��-�
�e�G�
�*�
�F����,���w�<�1��&�q�z�2�O��?�#�q�(��$�N�M��=�!�Q�&��"�J�J�}�Q�'7��>�M��=�!�Q�&��(/�=��#�$�#0�W�Q�Z� ������K�K���)�,�Mrc�6�\rSrSrSrSrSrSrSrSr	Sr
g	)
�GraphThunkIdsToKeysi�z7Forwards calls about 'ids' to be about keys internally.c��Xlgr
��_graphr�s  rr�GraphThunkIdsToKeys.__init__�s���rc�d�URR5Vs/sHuoPM sn$s snfr
)r��	topo_sort)rrs  rr��GraphThunkIdsToKeys.topo_sort�s+��"�k�k�3�3�5�6�5�d�q��5�6�6��6s�
-c��UVs/sHo"4PM nnURRU5nUVs1sHoUSiM	 sn$s snfs snf)zSee Graph.heads().r�)r�r�)r�ids�i�as_keys�	head_keys�hs      rr��GraphThunkIdsToKeys.heads�sI��!$�%��A�4���%��K�K�%�%�g�.�	�'�(�i��!��i�(�(��&��(s
�A�Ac�x�URRU45nUHnURSUlM U$)Nr�)r��
merge_sortr\)r�tip_revisionr�r�s    rr��GraphThunkIdsToKeys.merge_sort�s6�����&�&���7���D��x�x��{�D�H���rc�j�URRU4UVs/sHo34PM sn5 gs snfr
)r��add_node)rrr�rKs    rr��GraphThunkIdsToKeys.add_node�s*�������h�[��*A��A�4��*A�B��*As�0
r�N)r!r"r#r$r%rr�r�r�r�r&r'rrr�r��s��A��7�)��Crr�)r�r�r�r�r�r�r�)�
KnownGraphN)�rrrrrr�rr
r)rBrjrvr�r�rr�r�r��	_counters�_known_graph_pyxr��ImportError�e�failed_to_load_extension�_known_graph_pyr'rr�<module>r�s���$,�+�'���2?�?�(3�3�lX'�X'�v#�#�"q �q �h!��88�8�<E �E �P�E�PC�C�2
"�	�,�,���,��$�$�Q�'�+�+��,�s�:B�B)�B$�$B)

Youez - 2016 - github.com/yon3zu
LinuXploit