Current File : //usr/lib/python3/dist-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc
�

/�g���&�ddlZddlmZddlZddlZddlmZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZ	ddlZddlZddlZddlZddlZddlZ	ddlZddlZddlmZddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/e
j`e1�Z2e
jfd�Z4e
jfd�Z5e
jfd	�Z6e
jfd
�Z7e
jfd�Z8e
jfd�Z9e
jfd
�Z:e
jfd�Z;d�Z<d�Z=d�Z>d�Z?d�Z@did�ZAd�ZBd�ZCd�ZDej�d��ZFej�d��ZGej�djd��ZHGd�deI�ZJd�ZKGd�deI�ZLd �ZMGd!�d"eI�ZNe
jfd#e
j��ZPd$�ZQdkd%�ZRd&�ZSd'�ZTd(�ZUd)�ZVd*�ZWe
jfd+e
j��ZYe
jfd,�ZZdkd-�Z[e
jfd.�Z\d/�Z]d0�Z^d1�Z_d2Z`d3�Zad4�ZbGd5�d6eI�ZcGd7�d8eI�ZdGd9�d:eI�Zed;Zfdld<�Zgd=�Zhd>ZiGd?�d@eI�Zje
jfdA�Zke
jfdB�Zle
jfdC�ZmdD�ZdE�Zner6ddFlmoZpmqZqmrZrGdG�dHe$j��ZsGdI�dJep�ZoGdK�dLeoe&�ZtGdM�dNe%j��ZuerGdO�dPe%j��ZvGdQ�dRe%j��ZwdS�ZxGdT�dUeI�ZyGdV�dWey�ZzGdX�dYey�Z{GdZ�d[e'�Z|Gd\�d]eI�Z}d^�Z~Gd_�d`eI�Zda�Z�db�Z�dc�Z�dddedfdg�Z�dh�Z�y#e$rdZY��EwxYw#e$rddlZY��<wxYw)m�N)�deque)�iglob�)�DistlibException)�string_types�	text_type�shutil�	raw_input�StringIO�cache_from_source�urlopen�urljoin�httplib�	xmlrpclib�HTTPHandler�BaseConfigurator�valid_ident�	Container�configparser�URLError�ZipFile�fsdecode�unquote�urlparsez^([\w\.-]+)\s*z^([\w\.*+-]+)\s*z^(<=?|>=?|={2,3}|[~!]=)\s*z*^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*z^or\b\s*z	^and\b\s*z(\S+)\s*z(([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)c�@�����d����fd���fd���fd���|�S)ae
    Parse a marker string and return a dictionary containing a marker expression.

    The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in
    the expression grammar, or strings. A string contained in quotes is to be
    interpreted as a literal string, and a string not contained in quotes is a
    variable (such as os_name).
    c��tj|�}|r*|j�d}||j�d}||fS|st	d��|d}|dvrt	d|z��dj|d�}|dd}|g}|r�|d|k(rn�|d|k(r|j
|�|dd}nZtj|�}|st	d|z��|j
|j�d�||j�d}|r��dj|�}t	d|z��|j
|�dj|�}|ddj�}||fS)	Nrzunexpected end of inputz'"zinvalid expression: %s�rzerror in string literal: %szunterminated string: %s)
�
IDENTIFIER�match�groups�end�SyntaxError�replace�append�STRING_CHUNK�join�lstrip)�	remaining�m�result�q�oq�parts�ss       �:/usr/lib/python3/dist-packages/pip/_vendor/distlib/util.py�
marker_varz parse_marker.<locals>.marker_varBs{�����Y�'����X�X�Z��]�F�!�!�%�%�'�(�+�I�<�y� � �;��7�8�8��!��A���~�!�":�Y�"F�G�G����q�"�%�B�!�!�"�
�I��C�E���Q�<�1�$���q�\�R�'��L�L��$� )�!�"�
�I�$�*�*�9�5�A��)�*G�*3�+4�5�5��L�L�����A��/� )�!�%�%�'�(� 3�I���G�G�E�N��!�";�a�"?�@�@��L�L��O��W�W�U�^�F�!�!�"�
�,�,�.�I��y� � �c�t��|rQ|ddk(rI�|ddj��\}}|ddk7rtd|z��|ddj�}||fS�|�\}}|rRtj|�}|sn:|j	�d}||j�d}�|�\}}|||d�}|r�R|}||fS)Nr�(r�)�unterminated parenthesis: %s��op�lhs�rhs)r'r"�	MARKER_OPrr r!)r(r*r8r)r7r9�markerr0s      ��r/�marker_exprz!parse_marker.<locals>.marker_exprgs������1���,� &�y���}�';�';�'=� >��F�I���|�s�"�!�"@�9�"L�M�M�!�!�"�
�,�,�.�I��y� � �(�	�2�N�C����O�O�I�.�����X�X�Z��]��%�a�e�e�g�h�/�	�!+�I�!6���Y���C�8����F��y� � r1c����|�\}}|rCtj|�}|s	||fS||j�d}�|�\}}d||d�}|r�C||fS)N�andr6)�ANDrr!)r(r8r)r9r<s    �r/�
marker_andz parse_marker.<locals>.marker_andzss���$�Y�/���Y���	�	�)�$�A����I�~��"�!�%�%�'�(�+�I�(��3�N�C���s�3�7�C�
��I�~�r1c����|�\}}|rCtj|�}|s	||fS||j�d}�|�\}}d||d�}|r�C||fS)N�orr6)�ORrr!)r(r8r)r9r@s    �r/r;zparse_marker.<locals>.marker�ss���#�I�.���Y������#�A����I�~��"�!�%�%�'�(�+�I�'�	�2�N�C���c�#�6�C�
��I�~�r1�)�
marker_stringr;r@r<r0s @@@@r/�parse_markerrF8s%���#!�J!�&	�	��-� � r1c	���|j�}|r|jd�rytj|�}|st	d|z��|j�d}||j
�d}dx}x}x}}|r�|ddk(r�|jdd�}|dkrt	d|z��|d|}	||dzdj�}g}|	r�tj|	�}|st	d	|	z��|j|j�d�|	|j
�d}	|	sn,|	dd
k7rt	d|	z��|	ddj�}	|	r��|sd}|�r�|ddk(r�|ddj�}tj|�}|st	d
|z��|j�d}t|�}
|
jr|
jst	d|z��||j
�dj�}n�d�}|ddk7r||�\}}n�|jdd�}|dkrt	d|z��|d|}	||dzdj�}tj|	�r||	�\}}nntj|	�}|st	d|	z��|j�d}
|	|j
�dj�}	|	rt	d|	z��d|
fg}|r7|ddk7rt	d|z��|ddj�}t!|�\}}|r|ddk7rt	d|z��|s|}n'|�ddj#|D�cgc]}d|z��	c}���}t%||||||��Scc}w)z�
    Parse a requirement passed in as a string. Return a Container
    whose attributes contain the various parts of the requirement.
    �#Nzname expected: %sr�[�]rzunterminated extra: %szmalformed extra: %s�,zcomma expected in extras: %s�@zinvalid URI: %szInvalid URL: %sc���tj|�}d}|r�g}	|j�d}||j�d}tj|�}|std|z��|j�d}|j
||f�||j�d}|r|ddk7rn<|ddj�}|sn&tj|�}|std|z����|sd}||fS)z|
                Return a list of operator, version tuples if any are
                specified, else None.
                Nrzinvalid version: %srKr�invalid constraint: %s)�
COMPARE_OPrr r!�VERSION_IDENTIFIERr"r$r')�
ver_remainingr)�versionsr7�vs     r/�get_versionsz'parse_requirement.<locals>.get_versions�s��
�$�$�]�3�����!�H���X�X�Z��]��(5�a�e�e�g�h�(?�
�.�4�4�]�C�� �"-�.C�.;�/<�#=�=��H�H�J�q�M�� ����Q��0�(5�a�e�e�g�h�(?�
�,�
�a�0@�C�0G�!�(5�a�b�(9�(@�(@�(B�
� -�!�&�,�,�]�;�� �"-�.F�.;�/<�#=�=�'�*$�#'����.�.r1r3r4r5rNz~=�;zinvalid requirement: %szunexpected trailing data: %s� �, z%s %s)�name�extras�constraintsr;�url�requirement)�strip�
startswithrrr"r r!�findr'r$�	NON_SPACEr�scheme�netlocrOrPrFr&r)�reqr(r)�distnamerY�	mark_exprrR�uri�ir.�trT�_rS�rs�cons                r/�parse_requirementrl�s���
�	�	��I��	�,�,�S�1������#�A���-�	�9�:�:��x�x�z�!�}�H��!�%�%�'�(�#�I�*.�.�F�.�Y�.��C��Y�q�\�S�(��N�N�3��"���q�5��6��B�C�C��a��N���a�!�e�f�%�,�,�.�	����� � ��#�A��!�"7�!�";�<�<��M�M�!�(�(�*�Q�-�(��!�%�%�'�(��A�����t�s�{�!�"@�1�"D�E�E��!�"�����A����F���Q�<�3��!�!�"�
�,�,�.�I����	�*�A��!�"3�i�"?�@�@��(�(�*�Q�-�C���
�A�
�H�H����!�"3�c�"9�:�:�!�!�%�%�'�(�+�2�2�4�I� 
/�D��|�s�"�&2�9�&=�#��)��N�N�3��*���q�5�%�&D�&/�'0�1�1��a��N��%�a�!�e�f�-�4�4�6�	��#�#�A�&�".�q�/�K�H�a�*�0�0��3�A��)�*B�Q�*F�G�G����
�1�
�A��!�%�%�'�(��*�*�,�A��)�*B�Q�*F�G�G�!%�q�	�{�H���Q�<�3���7�)�C�D�D��a�b�M�(�(�*�	�+�I�6��	�9��Y�q�\�S�(��8�9�D�E�E��
�� �$�)�)�&.�/�s�W�s�]�/�#1�2���(�"�!)�%��!#�%�%��
0s�
M0c��d�}i}|D]�\}}}tjj||�}t|�D]�}tjj||�}	t|	�D]m}
|||
�}|�|j	|d��!|||
�}|jtjjd�jd�}
|
dz|z||<�o����|S)z%Find destinations for resources filesc�
�|jtjjd�}|jtjjd�}|j	|�sJ�|t|�dj
d�S�N�/)r#�os�path�sepr^�lenr')�rootrrs  r/�get_rel_pathz)get_resources_dests.<locals>.get_rel_paths`���|�|�B�G�G�K�K��-���|�|�B�G�G�K�K��-�����t�$�$�$��C��I�J��&�&�s�+�+r1Nrp)rqrrr&r�popr#rs�rstrip)�resources_root�rulesrv�destinations�base�suffix�dest�prefix�abs_base�abs_glob�abs_path�
resource_file�rel_path�rel_dests              r/�get_resources_destsr�s���,��L�#�L���f�d������n�d�3���f�
�		L�H��w�w�|�|�H�f�5�H�!�(�O�
L�� ,�^�X� F�
��<� �$�$�]�D�9�+�H�h�?�H�#�|�|�B�G�G�K�K��=�D�D�S�I�H�2:�S�.�8�2K�L��/�
L�		L�L��r1c��ttd�rd}|Stjttdtj�k7}|S)N�real_prefixT�base_prefix)�hasattr�sysr�getattr�r*s r/�in_venvr�2s:���s�M�"����M����w�s�M�3�:�:�F�F���Mr1c�\�tj}t|t�st	|�}|S�N)r��
executable�
isinstancerrr�s r/�get_executabler�<s&���^�^�F��f�i�(��&�!���Mr1c�|�|}	t|�}|}|s|r|}|r$|dj�}||vr	|S|rd|||fz}�:)Nrz	%c: %s
%s)r
�lower)�prompt�
allowed_chars�error_prompt�default�pr.�cs       r/�proceedr�Nsa���A�
��a�L�����W��A���!��
�
��A��M�!��
�H�� �A�|�V�#<�<��r1c�r�t|t�r|j�}i}|D]}||vs�||||<�|Sr�)r�r�split)�d�keysr*�keys    r/�extract_by_keyr�^sF���$��%��z�z�|��
�F��!���!�8��C�&�F�3�K�!��Mr1c�H�tjddk\rtjd�|�}|j	�}t|�}	t
j|�}|ddd}|j�D]8\}}|j�D] \}}|�d|��}t|�}	|	�J�|	||<�"�:|S#t$r|jdd�YnwxYwd�}
tj�}	|
||�nR#tj$r<|j�t!j"|�}t|�}|
||�YnwxYwi}|j%�D]=}ix||<}|j|�D] \}
}|
�d|��}t|�}	|	�J�|	||
<�"�?|S)	Nr��utf-8�
extensionszpython.exports�exports� = c�b�t|d�r|j|�y|j|�y)N�	read_file)r�r��readfp)�cp�streams  r/�read_streamz!read_exports.<locals>.read_stream|s$���2�{�#��L�L�� ��I�I�f�r1)r��version_info�codecs�	getreader�readr�json�load�items�get_export_entry�	Exception�seekr�ConfigParser�MissingSectionHeaderError�close�textwrap�dedent�sections)r��data�jdatar*�group�entries�krSr.�entryr�r�r�rX�values               r/�read_exportsr�hs���
�����a��*��!�!�'�*�6�2���;�;�=�D�
�d�^�F���	�	�&�!���|�$�%5�6�y�A��$�l�l�n�	#�N�E�7��
�
��
#���1�!"�A�&��(��+���(�(�(�"���
�	
#�	#��
�������A�q�����
�	"�	"�	$�B� ��B�����1�1� ��������t�$���$����B���	 ���F��{�{�}�"�� "�"��s��g��8�8�C�=�	"�K�D�%�!�5�)�A�$�Q�'�E��$�$�$�!�G�D�M�	"�"��Ms&�A,B;�;C�C�4	C>�>AE
�E
c�(�tjddk\rtjd�|�}t	j
�}|j
�D]�\}}|j|�|j�D]�}|j�
|j}n|j�d|j��}|jr!|�ddj|j��d�}|j||j|�����|j|�y)Nrr�r��:z [rWrJ)r�r�r��	getwriterrr�r��add_section�valuesr}r�flagsr&�setrX�write)r�r�r�r�rSr�r.s       r/�
write_exportsr��s���
�����a��*��!�!�'�*�6�2��	�	"�	"�	$�B��
�
��
%���1�
���q���X�X�Z�	%�E��|�|�#��L�L��$�|�|�U�\�\�:���{�{�!"�D�I�I�e�k�k�$:�;���F�F�1�e�j�j�!�$�	%�
%��H�H�V�r1c#�K�tj�}	|��tj|�y#tj|�wxYw�wr�)�tempfile�mkdtempr	�rmtree)�tds r/�tempdirr��s6����	�	�	�	�B�����
�
�b����
�
�b��s�A�2�A�A	�	Ac#��K�tj�}	tj|�d��tj|�y#tj|�wxYw�wr�)rq�getcwd�chdir)r��cwds  r/r�r��s:����
�)�)�+�C��
�����
�
����
������
���A!�A�A!�A�A!c#��K�tj�}	tj|�d��tj|�y#tj|�wxYw�wr�)�socket�getdefaulttimeout�setdefaulttimeout)�seconds�ctos  r/�socket_timeoutr��sF����
�
"�
"�
$�C�&�� � ��)�
�� � ��%��� � ��%�r�c��eZdZd�Zdd�Zy)�cached_propertyc��||_yr�)�func)�selfr�s  r/�__init__zcached_property.__init__�s	����	r1Nc��|�|S|j|�}tj||jj|�|Sr�)r��object�__setattr__�__name__)r��obj�clsr�s    r/�__get__zcached_property.__get__�s:���;��K��	�	�#������3��	�	� 2� 2�E�:��r1r�)r��
__module__�__qualname__r�r�rDr1r/r�r��s���
r1r�c��tjdk(r|S|s|S|ddk(rtd|z��|ddk(rtd|z��|jd�}tj|vr2|jtj�tj|vr�2|stjStjj|�S)a�Return 'pathname' as a name that will work on the native filesystem.

    The path is split on '/' and put back together again using the current
    directory separator.  Needed because filenames in the setup script are
    always supplied in Unix style, and have to be converted to the local
    convention before we can actually use them in the filesystem.  Raises
    ValueError on non-Unix-ish systems if 'pathname' either starts or
    ends with a slash.
    rprzpath '%s' cannot be absolute���zpath '%s' cannot end with '/')rqrs�
ValueErrorr��curdir�removerrr&)�pathname�pathss  r/�convert_pathr��s���
�v�v��}��������{�c���7�(�B�C�C���|�s���8�8�C�D�D��N�N�3��E�
�)�)�u�
�
���R�Y�Y��
�)�)�u�
���y�y��
�7�7�<�<���r1c�|�eZdZdd�Zd�Zd�Zd�Zdd�Zdd�Zd�Z	d	�Z
d
�Zd�Zd�Z
				dd
�Zd�Zd�Zd�Zd�Zy)�FileOperatorc�P�||_t�|_|j�yr�)�dry_runr��ensured�_init_record)r�r�s  r/r�zFileOperator.__init__�s������u������r1c�N�d|_t�|_t�|_y�NF)�recordr��
files_written�dirs_created�r�s r/r�zFileOperator._init_record�s����� �U����E��r1c�T�|jr|jj|�yyr�)rr�add)r�rrs  r/�record_as_writtenzFileOperator.record_as_written�s"���;�;����"�"�4�(�r1c�T�tjj|�s+tdtjj	|�z��tjj|�sytj
|�jtj
|�jkDS)a�Tell if the target is newer than the source.

        Returns true if 'source' exists and is more recently modified than
        'target', or if 'source' exists and 'target' doesn't.

        Returns false if both exist and 'target' is the same age or younger
        than 'source'. Raise PackagingFileError if 'source' does not exist.

        Note that this test is not very accurate: files created in the same
        second will have the same "age".
        zfile '%r' does not existT)rqrr�existsr�abspath�stat�st_mtime)r��source�targets   r/�newerzFileOperator.newerss���w�w�~�~�f�%�"�#=�#%�7�7�?�?�6�#:�$;�<�
<��w�w�~�~�f�%���w�w�v��'�'�"�'�'�&�/�*B�*B�B�Br1c���|jtjj|��tjd||�|js�d}|rhtjj|�rd|z}nCtjj|�r$tjj|�sd|z}|rt|dz��tj||�|j|�y)z8Copy a file respecting dry-run and force flags.
        zCopying %s to %sNz%s is a symlinkz%s is a non-regular filez which would be overwritten)�
ensure_dirrqrr�dirname�logger�infor��islinkr	�isfiler�r	�copyfiler)r��infile�outfile�check�msgs     r/�	copy_filezFileOperator.copy_files���	
���������0�1����&���8��|�|��C���7�7�>�>�'�*�+�g�5�C��W�W�^�^�G�,�R�W�W�^�^�G�5L�4�w�>�C�� ��'D�!D�E�E��O�O�F�G�,����w�'r1Nc���tjj|�rJ�|jtjj	|��t
j
d||�|jsN|�
t|d�}ntj|d|��}	tj||�|j�|j|�y#|j�wxYw)NzCopying stream %s to %s�wb�w��encoding)rqrr�isdirrrrrr��openr�r	�copyfileobjr�r)r��instreamrr!�	outstreams     r/�copy_streamzFileOperator.copy_stream's����7�7�=�=��)�)�)����������0�1����-�x��A��|�|��� ��$�/�	�"�K�K���x�H�	�
"��"�"�8�Y�7����!����w�'�����!�s�C�C%c�f�|jtjj|��|jsZtjj|�rtj|�t|d�5}|j|�ddd�|j|�y#1swY�xYw)Nr)
rrqrrrr�r	r�r#r�r)r�rrr��fs    r/�write_binary_filezFileOperator.write_binary_file6sw�����������-�.��|�|��w�w�~�~�d�#��	�	�$���d�D�!�
�Q�����
�
����t�$�
�
�s�;B'�'B0c�F�|j||j|��yr�)r*�encode)r�rrr�r!s    r/�write_text_filezFileOperator.write_text_file?s�����t�T�[�[��%:�;r1c�r�tjdk(s&tjdk(r�tjdk(r}|D]w}|jrtjd|��&tj|�j|z|z}tjd||�tj||��yyyy)N�posix�javazchanging mode of %szchanging mode of %s to %o)	rqrX�_namer�rrr�st_mode�chmod)r��bits�mask�filesr)�modes      r/�set_modezFileOperator.set_modeBs���
�7�7�g��"�'�'�V�"3����G�8K��
&���<�<��K�K� 5�q�9��G�G�A�J�.�.��5��=�D��K�K� ;�Q��E��H�H�Q��%�

&�9L�"3r1c�(�|jdd|�S)Nimi�)r8)r.r)s  r/�<lambda>zFileOperator.<lambda>Ns��q�z�z�%���'C�r1c��tjj|�}||jvr�tjj	|�s�|jj|�tjj
|�\}}|j|�tjd|z�|jstj|�|jr|jj|�yyyy)NzCreating %s)rqrrr
r�r	rr�rrrr��mkdirrr)r�rrr�r)s    r/rzFileOperator.ensure_dirPs����w�w���t�$���t�|�|�#�B�G�G�N�N�4�,@��L�L���T�"��7�7�=�=��&�D�A�q��O�O�A���K�K�
��,�-��<�<�������{�{��!�!�%�%�d�+��-A�#r1c��t||�}tjd||�|js�|s|j	||�r&|sd}n!|j|�sJ�|t
|�d}i}|r-ttd�rtjj|d<tj||dfi|��|j|�|S)NzByte-compiling %s to %s�PycInvalidationMode�invalidation_modeT)
rrrr�rr^rtr��
py_compiler>�CHECKED_HASH�compiler)	r�rr�optimize�forcer�hashed_invalidation�dpath�diagpath�compile_kwargss	         r/�byte_compilezFileOperator.byte_compile\s���"�$�H��5�����-�t�U�;��|�|���
�
�4��/��#�H��?�?�6�2�2�2�#�C��K�L�1�H��N�"�w�z�/D�(F�,6�+I�+I�+V�+V��'�)����t�U�H�d�
1�!/�
1����u�%��r1c���tjj|��rAtjj|�r�tjj	|�sot
j
d|�|jstj|�|jr+||jvr|jj|�yyytjj	|�rd}nd}t
j
d||�|jstj|�|jr+||jvr|jj|�yyyy)NzRemoving directory tree at %s�link�filezRemoving %s %s)rqrrr	r"rr�debugr�r	r�rrr�r)r�rrr.s   r/�ensure_removedzFileOperator.ensure_removedus���
�7�7�>�>�$���w�w�}�}�T�"�2�7�7�>�>�$�+?����<�d�C��|�|��M�M�$�'��;�;��t�0�0�0��)�)�0�0��6�1���7�7�>�>�$�'��A��A����-�q�$�7��|�|��I�I�d�O��;�;��t�1�1�1��*�*�1�1�$�7�2��! r1c���d}|srtjj|�r'tj|tj�}	|Stjj|�}||k(r	|S|}|s�r|Sr)rqrrr	�access�W_OKr)r�rrr*�parents    r/�is_writablezFileOperator.is_writable�sn������w�w�~�~�d�#����4����1���
�
�	�W�W�_�_�T�*�F���~���
��D���
r1c�r�|jsJ�|j|jf}|j�|S)zV
        Commit recorded changes, turn off recording, return
        changes.
        )rrrr�)r�r*s  r/�commitzFileOperator.commit�s7��
�{�{��{��#�#�T�%6�%6�6�������
r1c���|js�t|j�D]7}tjj|�s�#tj|��9t|jd��}|D]n}tj|�}|r@|dgk(sJ�tjj||d�}tj|�tj|��p|j�y)NT)�reverse�__pycache__r)
r��listrrqrrr	r��sortedr�listdirr&�rmdirr�)r�r)�dirsr��flist�sds      r/�rollbackzFileOperator.rollback�s����|�|��$�,�,�-�
!���7�7�>�>�!�$��I�I�a�L�
!��$�+�+�T�:�D��
���
�
�1�
��� �]�O�3�3�3������a��q��2�B��H�H�R�L������

�	
���r1�F�Tr�)FFNF)r�r�r�r�r�rrrr'r*r-r8�set_executable_moderrIrNrSrUr`rDr1r/r�r��se���
"�
)�C�((�"
(�%�<�
&�D��
,�$� � �).��28�*
��r1r�c���|tjvrtj|}nt|�}|�|}|S|jd�}t	||jd��}|D]}t	||�}�|S)N�.r)r��modules�
__import__r�r�rw)�module_name�dotted_path�modr*r-r�s      r/�resolverk�s~���c�k�k�!��k�k�+�&����%�������M�	�!�!�#�&����e�i�i��l�+���	(�A��V�Q�'�F�	(��Mr1c�F�eZdZd�Zed��Zd�Zd�ZejZ	y)�ExportEntryc�<�||_||_||_||_yr��rXrr}r�)r�rXrr}r�s     r/r�zExportEntry.__init__�s����	���������
r1c�B�t|j|j�Sr�)rkrr}rs r/r�zExportEntry.value�s���t�{�{�D�K�K�0�0r1c	�p�d|j�d|j�d|j�d|j�d�	S)Nz
<ExportEntry r�r�rV�>rors r/�__repr__zExportEntry.__repr__�s(��04�	�	�4�;�;�04���T�Z�Z�I�	Ir1c��t|t�sd}|S|j|jk(xrO|j|jk(xr4|j|jk(xr|j
|j
k(}|Sr)r�rmrXrr}r�)r��otherr*s   r/�__eq__zExportEntry.__eq__�st���%��-��F�
�
��i�i�5�:�:�-�4�$�+�+����2M�4��+�+����5�4��*�*����3�
��
r1N)
r�r�r�r�r�r�rsrvr��__hash__rDr1r/rmrm�s1����1��1�I�����Hr1rmz�(?P<name>([^\[]\S*))
                      \s*=\s*(?P<callable>(\w+)([:\.]\w+)*)
                      \s*(\[\s*(?P<flags>[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
                      c���tj|�}|sd}d|vsd|vrtd|z��|S|j�}|d}|d}|j	d�}|dk(r|d}}n'|dk7rtd|z��|jd�\}}|d	}	|	�d|vsd|vrtd|z��g}	n,|	jd
�D�
cgc]}
|
j
���}	}
t||||	�}|Scc}
w)NrIrJzInvalid specification '%s'rX�callabler�rrr�rK)�ENTRY_RE�searchr�	groupdict�countr�r]rm)�
specificationr)r*r�rXrr�colonsrr}r�r)s           r/r�r��s.�����
�&�A�����-��3�-�#7�"�$*�,9�$:�;�
;�.�M�)
�K�K�M����y����}�����C����Q�;�!�4�F�F���{�&�(.�0=�(>�?�?�!�Z�Z��_�N�F�F��'�
���=��m�#�s�m�';�&�(.�0=�(>�?�?��E�(-���C�(8�9�1�Q�W�W�Y�9�E�9��T�6�6�5�9���M��:s�C*c��|�d}tjdk(r2dtjvr tjj	d�}ntjjd�}tjj
|�r=tj|tj�}|s/tjd|�n	tj|�d}|s*tj�}tjd|�tjj||�S#t$rtjd|d�	�d
}Y�qwxYw)a�
    Return the default base location for distlib caches. If the directory does
    not exist, it is created. Use the suffix provided for the base directory,
    and default to '.distlib' if it isn't provided.

    On Windows, if LOCALAPPDATA is defined in the environment, then it is
    assumed to be a directory, and will be the parent directory of the result.
    On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home
    directory - using os.expanduser('~') - will be the parent directory of
    the result.

    The result is just the directory '.distlib' in the parent directory as
    determined above, or with the name specified with ``suffix``.
    z.distlib�nt�LOCALAPPDATAz
$localappdata�~z(Directory exists but is not writable: %sTzUnable to create %s)�exc_infoFz#Default location unusable, using %s)rqrX�environrr�
expandvars�
expanduserr"rPrQr�warning�makedirs�OSErrorr�r�r&)r}r*�usables   r/�get_cache_baser�s����~���	�w�w�$��>�R�Z�Z�7����#�#�O�4�����#�#�C�(��
�w�w�}�}�V�����6�2�7�7�+����N�N�E�v�N�	��K�K����F���!�!�#�����<�f�E�
�7�7�<�<���'�'��
�	��N�N�0�&�4�N�H��F�	�s�D)�)#E�Ec��tjjtjj|��\}}|r|j	dd�}|j	tj
d�}||zdzS)a
    Convert an absolute path to a directory name for use in a cache.

    The algorithm used is:

    #. On Windows, any ``':'`` in the drive is replaced with ``'---'``.
    #. Any occurrence of ``os.sep`` is replaced with ``'--'``.
    #. ``'.cache'`` is appended.
    r�z---z--z.cache)rqrr�
splitdriver
r#rs)rrr�r�s   r/�path_to_cache_dirr�-s_���7�7���b�g�g�o�o�d�3�4�D�A�q��
�I�I�c�5�!��	�	�	�"�&�&�$��A��q�5�8��r1c�2�|jd�s|dzS|Sro)�endswith)r.s r/�ensure_slashr�>s���:�:�c�?��3�w���Hr1c��dx}}d|vr1|jdd�\}}d|vr|}n|jdd�\}}|rt|�}|rt|�}|||fS)NrLrr�)�rsplitr�r)rb�username�passwordrs    r/�parse_credentialsr�Dsp����H�x�
�f�}����s�A�.�����f���H�!'���c�1�!5��H�h���8�$����8�$���X�v�%�%r1c�Z�tjd�}tj|�|S)N�)rq�umaskr�s r/�get_process_umaskr�Ss ��
�X�X�d�^�F��H�H�V���Mr1c�d�d}d}t|�D]\}}t|t�r�d}n|�J�|S)NTF)�	enumerater�r)�seqr*rgr.s    r/�is_string_sequencer�YsF��
�F��A��#�����1��!�\�*��F���
�=��=��Mr1z3([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-([a-z0-9_.+-]+)z
-py(\d\.?\d?)c��d}d}t|�jdd�}tj|�}|r$|j	d�}|d|j�}|rft
|�t
|�dzkDrLtjtj|�dz|�}|r|j�}|d|||dzd|f}|�:tj|�}|r#|j	d�|j	d�|f}|S)zw
    Extract name, version, python version from a filename (no extension)

    Return name, version, pyver or None
    NrV�-rz\br�)rr#�PYTHON_VERSIONr{r��startrt�rer�escaper!�PROJECT_NAME_AND_VERSION)�filename�project_namer*�pyverr)�ns      r/�split_filenamer�js����F��E��x� �(�(��c�2�H����h�'�A������
���J�Q�W�W�Y�'����H�
��L�(9�A�(=�=��H�H�R�Y�Y�|�,�u�4�h�?�������A��b�q�\�8�A��E�F�#3�U�:�F�
�~�$�*�*�8�4����W�W�Q�Z������U�2�F��Mr1z-(?P<name>[\w .-]+)\s*\(\s*(?P<ver>[^\s)]+)\)$c��tj|�}|std|z��|j�}|dj	�j�|dfS)z�
    A utility method used to get name and version from a string.

    From e.g. a Provides-Dist value.

    :param p: A value in a form 'foo (1.0)'
    :return: The name and version as a tuple.
    z$Ill-formed name/version string: '%s'rX�ver)�NAME_VERSION_RErrr|r]r�)r�r)r�s   r/�parse_name_and_versionr��sV��	���a� �A���G�!�K�L�L�	���
�A��V�9�?�?��"�"�$�a��h�.�.r1c��t�}t|xsg�}t|xsg�}d|vr|jd�||z}|D]�}|dk(r|j|��|jd�r8|dd}||vrtjd|z�||vs�Q|j|��c||vrtjd|z�|j|���|S)N�*r�rzundeclared extra: %s)r�r�rr^rr�)�	requested�	availabler*�r�unwanteds     r/�
get_extrasr��s���
�U�F��I�O��$�I��I�O��$�I�
�i��������)���
�����8��J�J�q�M�
�\�\�#�
����u�H��y�(����5��@�A��6�!��
�
�h�'��	�!����5��9�:��J�J�q�M���Mr1c�t�i}	t|�}|j�}|jd�}|jd�stjd|�|St
jd�|�}tj|�}	|S#t$r"}tjd||�Yd}~|Sd}~wwxYw)NzContent-Typezapplication/jsonz(Unexpected response for JSON request: %sr�z&Failed to get external data for %s: %s)r
r�getr^rrMr�r�r�r�r��	exception)r[r*�resp�headers�ct�reader�es       r/�_get_external_datar��s���
�F�K��s�|���)�)�+��
�[�[��
(���}�}�/�0��L�L�C�R�H��M�
/�V�%�%�g�.�t�4�F��Y�Y�v�&�F��M���K����A�3��J�J��M��K�s�AB�0B�	B7�B2�2B7z'https://www.red-dove.com/pypi/projects/c�n�|dj��d|�d�}tt|�}t|�}|S)Nrrpz
/project.json��upperr�_external_data_base_urlr�)rXr[r*s   r/�get_project_datar��s2��"&�q�'�-�-�/�4�
8�C�
�)�3�
/�C�
��
$�F��Mr1c�p�|dj��d|�d|�d�}tt|�}t|�S)Nrrpz	/package-z.jsonr�)rX�versionr[s   r/�get_package_datar��s0��%)�!�W�]�]�_�d�G�
D�C�
�)�3�
/�C��c�"�"r1c�"�eZdZdZd�Zd�Zd�Zy)�Cachez�
    A class implementing a cache for resources that need to live in the file system
    e.g. shared libraries. This class was moved from resources to here because it
    could be used by other modules, e.g. the wheel module.
    c�d�tjj|�stj|�tj|�j
dzdk7rtjd|�tjjtjj|��|_
y)zu
        Initialise an instance.

        :param base: The base directory where the cache should be located.
        �?rzDirectory '%s' is not privateN)rqrrr"r�rr2rr�r
�normpathr|)r�r|s  r/r�zCache.__init__�sm���w�w�}�}�T�"��K�K����G�G�D�M�!�!�D�(�Q�.��N�N�<�d�C��G�G�O�O�B�G�G�$4�$4�T�$:�;��	r1c��t|�S)zN
        Converts a resource prefix to a directory name in the cache.
        )r�)r�rs  r/�
prefix_to_dirzCache.prefix_to_dir�s��!��(�(r1c��g}tj|j�D]�}tjj	|j|�}	tjj|�stjj
|�rtj|�n4tjj|�rtj|���|S#t$r|j|�Y��wxYw)z"
        Clear the cache.
        )
rqr[r|rrr&rrr�r"r	r�r�r$)r��not_removed�fns   r/�clearzCache.clear�s������*�*�T�Y�Y�'�	'�B������d�i�i��,�B�
'��7�7�>�>�"�%�������);��I�I�b�M��W�W�]�]�2�&��M�M�"�%��
	'�����
'��"�"�2�&�
'�s�BC�C9�8C9N)r�r�r��__doc__r�r�r�rDr1r/r�r��s���<�)�r1r�c�0�eZdZdZd�Zdd�Zd�Zd�Zd�Zy)	�
EventMixinz1
    A very simple publish/subscribe system.
    c��i|_yr�)�_subscribersrs r/r�zEventMixin.__init__
s
����r1c��|j}||vrt|g�||<y||}|r|j|�y|j|�y)a`
        Add a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be added (and called when the
                           event is published).
        :param append: Whether to append or prepend the subscriber to an
                       existing subscriber list for the event.
        N)r�rr$�
appendleft)r��event�
subscriberr$�subs�sqs      r/rzEventMixin.add
sK��� � ��������-�D��K��e��B���	�	�*�%��
�
�j�)r1c�h�|j}||vrtd|z��||j|�y)z�
        Remove a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be removed.
        zNo subscribers: %rN)r�r�r�)r�r�r�r�s    r/r�zEventMixin.remove!s:��� � ������1�E�9�:�:��U����:�&r1c�L�t|jj|d��S)z�
        Return an iterator for the subscribers for an event.
        :param event: The event to return subscribers for.
        rD)�iterr�r�)r�r�s  r/�get_subscriberszEventMixin.get_subscribers-s"��
�D�%�%�)�)�%��4�5�5r1c���g}|j|�D] }	||g|��i|��}|j	|��"tjd||||�|S#t$rtjd�d}Y�PwxYw)a^
        Publish a event and return a list of values returned by its
        subscribers.

        :param event: The event to publish.
        :param args: The positional arguments to pass to the event's
                     subscribers.
        :param kwargs: The keyword arguments to pass to the event's
                       subscribers.
        z"Exception during event publicationNz/publish %s: args = %s, kwargs = %s, result = %s)r�r�rr�r$rM)r�r��args�kwargsr*r�r�s       r/�publishzEventMixin.publish4s������.�.�u�5�	!�J�
�"�5�:�4�:�6�:��
�M�M�%� �
	!�	���F���6�6�	+��
��
�
�� � �!E�F���
�s�A� A5�4A5Nrb)	r�r�r�r�r�rr�r�r�rDr1r/r�r�s ����*�(
'�6�r1r�c�X�eZdZd�Zd�Zdd�Zd�Zd�Zd�Zd�Z	e
d��Ze
d	��Zy
)�	Sequencerc�>�i|_i|_t�|_yr�)�_preds�_succsr��_nodesrs r/r�zSequencer.__init__Qs���������e��r1c�:�|jj|�yr�)r�r)r��nodes  r/�add_nodezSequencer.add_nodeVs��������r1c�8�||jvr|jj|�|r�t|jj	|d��D]}|j||��t|j
j	|d��D]}|j||��t
|jj��D]\}}|r�	|j|=�t
|j
j��D]\}}|r�	|j
|=�yy)NrD)r�r�r�r�r�r�rYr�)r�r��edgesr�r.r�rSs       r/�remove_nodezSequencer.remove_nodeYs����4�;�;���K�K���t�$���������r�2�3�
%�����A�t�$�
%��������r�2�3�
%�����D�!�$�
%��T�[�[�.�.�0�1�
'���1�����A��
'��T�[�[�.�.�0�1�
'���1�����A��
'�r1c���||k7sJ�|jj|t��j|�|jj|t��j|�yr�)r��
setdefaultr�rr�)r��pred�succs   r/rz
Sequencer.addisP���t�|��|������t�S�U�+�/�/��5������t�S�U�+�/�/��5r1c��||k7sJ�	|j|}|j|}	|j	|�|j	|�y#t$rtd|z��wxYw#t$rt|�d|����wxYw)Nz%r not a successor of anythingz not a successor of )r�r��KeyErrorr�r�)r�r�r��preds�succss     r/r�zSequencer.removens����t�|��|�	F��K�K��%�E��K�K��%�E�	H��L�L����L�L����	�	F��=��D�E�E�	F��
�	H��4��F�G�G�	H�s�A�"A&�A#�&Bc�^�||jvxs||jvxs||jvSr�)r�r�r�)r��steps  r/�is_stepzSequencer.is_step{s4������#�'�t�t�{�{�':�'��4�;�;�&�	(r1c��|j|�std|z��g}g}t�}|j|�|r�|j	d�}||vr(||k7rr|j|�|j|�nO|j
|�|j|�|jj|d�}|j|�|r��t|�S)NzUnknown: %rrrD)r�r�r�r$rwr�rr�r��extend�reversed)r��finalr*�todo�seenr�r�s       r/�	get_stepszSequencer.get_stepss����|�|�E�"��]�U�2�3�3������u�����E����8�8�A�;�D��t�|��5�=��M�M�$�'��M�M�$�'�������
�
�d�#�������b�1�����E�"�� ���r1c���������dg�g�i�i�g�|j��������fd���D]}|�vs��|���S)Nrc����d�|<�d�|<�dxxdz
cc<�
j|�	�|}|D]>}|�vr�|�t�|�|��|<�%|�
vs�*t�|�|��|<�@�|�|k(rHg}	�
j�}|j|�||k(rn�(t	|�}�	j|�yy#t$rg}Y��wxYw�Nrr)r$r��minrw�tuple)r��
successors�	successor�connected_component�	component�graph�index�
index_counter�lowlinksr*�stack�
strongconnects     �������r/rz3Sequencer.strong_connections.<locals>.strongconnect�s ���'��*�E�$�K�*�1�-�H�T�N��!���!���L�L���
 �"�4�[�
�(�
K�	��H�,�!�)�,�%(��$���)�9L�%M�H�T�N��%�'�&)��$���y�9I�%J�H�T�N�
K���~��t��,�&(�#�� %�	�	��I�'�.�.�y�9� �D�(��	�
"�"5�6�	��
�
�i�(�-���
 ��
�
 �s�C
�
C�C)r�)	r�r�r
rrrr*rrs	  @@@@@@@r/�strong_connectionszSequencer.strong_connections�s\�����
�������������!	)�!	)�F�	$�D��8�#��d�#�	$��
r1c	��dg}|jD]0}|j|}|D]}|jd|�d|�d����2|jD]}|jd|z��|jd�dj|�S)Nzdigraph G {z  z -> rUz  %s;�}�
)r�r$r�r&)r�r*r�r�r�r�s      r/�dotz
Sequencer.dot�s�������K�K�	<�D��K�K��%�E��
<���
�
�t�T�:�;�
<�	<��K�K�	*�D��M�M�'�D�.�)�	*��
�
�c���y�y�� � r1Nra)
r�r�r�r�r�r�rr�r�r�propertyrrrDr1r/r�r�OsO���
�'� 6�
H�(� �2�1��1�f�	!��	!r1r�)�.tar.gz�.tar.bz2�.tar�.zip�.tgz�.tbz�.whlc�p�����fd�}tjj���t���d}|�d|j	d�rd}nP|j	d�rd}d}n:|j	d�rd}d	}n$|j	d
�rd}d}ntd
|z��	|dk(r.t
|d�}|rW|j�}|D]
}||��n7tj|�}|r|j�}|D]
}||��|dk7rftjddkrP|j�D]=}	t|	jt �r�|	jj#d�|	_�?d�}
|
|_|j'��|r|j)�yy#|r|j)�wwxYw)Nc�,��t|t�s|jd�}tjjtjj
�|��}|j��r|�tjk7rtd|z��y)Nr�zpath outside destination: %r)
r�r�decoderqrrr
r&r^rsr�)rrr��dest_dir�plens  ��r/�
check_pathzunarchive.<locals>.check_path�sm����$�	�*��;�;�w�'�D��G�G�O�O�B�G�G�L�L��4�8�9���|�|�H�%��4��B�F�F�):��;�a�?�@�@�*;r1)rr�zip)rr�tgzzr:gz)rr�tbzzr:bz2r�tarr�zUnknown format for %rrr�r�c��	tj||�S#tj$r}tt	|���d}~wwxYw)z9Run tarfile.tar_filter, but raise the expected ValueErrorN)�tarfile�
tar_filter�FilterErrorr��str)�memberrr�excs   r/�extraction_filterz$unarchive.<locals>.extraction_filters?��
+��)�)�&�$�7�7���&�&�
+� ��S��*�*��
+�s��A�?�A)rqrrr
rtr�r�r�namelistr+r#�getnamesr�r��
getmembersr�rXrr"r1�
extractallr�)�archive_filenamer#�formatrr%�archiver7�namesrX�tarinfor1r$s `         @r/�	unarchiver;�s����A��w�w���x�(�H��x�=�D��G�
�~��$�$�%5�6��F�
�
&�
&�':�
;��F��D�
�
&�
&�';�
<��F��D�
�
&�
&�v�
.��F��D��4�7G�G�H�H�'��U�?��.��4�G���(�(�*��!�%�D��t�$�%��l�l�#3�T�:�G���(�(�*��!�%�D��t�$�%��U�?�s�/�/��2�Q�6�
#�-�-�/�
@��!�'�,�,�	�:�#*�<�<�#6�#6�w�#?�G�L�
@�	+�%6��!����8�$���M�M�O���7��M�M�O��s�B2F �=F � F5c��tj�}t|�}t|d�5}t	j
|�D]d\}}}|D]Y}tjj||�}||d}	tjj|	|�}
|j||
��[�f	ddd�|S#1swY|SxYw)z*zip a directory tree into a BytesIO objectrN)	�io�BytesIOrtrrq�walkrrr&r�)�	directoryr*�dlen�zfrur]r6rX�full�relr~s           r/�zip_dirrE%s���
�Z�Z�\�F��y�>�D�	���	�%��!#����!3�	%��D�$���
%���w�w�|�|�D�$�/���4�5�k���w�w�|�|�C��.������t�$�	
%�	%�%��M�%��M�s�A=B4�4B>)r�K�M�G�T�Pc�v�eZdZdZd
d�Zd�Zd�Zd�Zd�Ze	d��Z
e	d��Zd	�Ze	d
��Z
e	d��Zy)�Progress�UNKNOWNc�j�|�||k\sJ�|x|_|_||_d|_d|_d|_y)NrF)r�cur�max�started�elapsed�done)r��minval�maxvals   r/r�zProgress.__init__=s>���~��6�!1�1�1�$�$���4�8������������	r1c���|j|ksJ�|j�||jksJ�||_tj�}|j�||_y||jz
|_yr�)rrPrO�timerQrR)r��curval�nows   r/�updatezProgress.updateEsb���x�x�6�!�!�!��x�x��6�T�X�X�#5�5�5�����i�i�k���<�<���D�L�����-�D�Lr1c�N�|dk\sJ�|j|j|z�y)Nr)rZrO)r��incrs  r/�	incrementzProgress.incrementOs"���q�y��y����D�H�H�t�O�$r1c�<�|j|j�|Sr�)rZrrs r/r�zProgress.startSs�����D�H�H���r1c�`�|j�|j|j�d|_y�NT)rPrZrSrs r/�stopz
Progress.stopWs#���8�8���K�K����!���	r1c�J�|j�|jS|jSr�)rP�unknownrs r/�maximumzProgress.maximum\s��#�x�x�/�t�|�|�=�T�X�X�=r1c��|jrd}|S|j�d}|Sd|j|jz
z|j|jz
z}d|z}|S)Nz100 %z ?? %gY@z%3d %%)rSrPrOr)r�r*rSs   r/�
percentagezProgress.percentage`sf���9�9��F��
��X�X�
��F��
�����D�H�H�,�-����D�H�H�1D�E�A���\�F��
r1c��|dkr|j�|j|jk(rd}|Stjdtj
|��}|S)Nrz??:??:??z%H:%M:%S)rPrOrrW�strftime�gmtime)r��durationr*s   r/�format_durationzProgress.format_durationksM����M�t�x�x�/�4�8�8�t�x�x�3G��F�
�
��]�]�:�t�{�{�8�/D�E�F��
r1c�|�|jrd}|j}n�d}|j�d}n{|jdk(s|j|jk(rd}nPt|j|jz
�}||j|jz
z}|dz
|jz}|�d|j
|���S)N�DonezETA r�rrz: )rSrRrPrOr�floatrk)r�rrhs   r/�ETAzProgress.ETAts����9�9��F����A��F��x�x��������"�t�x�x�4�8�8�';����$�(�(�T�X�X�-�.���T�X�X����(�(����U�d�l�l�*��!�4�#7�#7��#:�;�;r1c��|jdk(rd}n&|j|jz
|jz}tD]}|dkrn|dz}�d|fzS)Nrgi�g@�@z%d %sB/s)rRrOr�UNITS)r�r*�units   r/�speedzProgress.speed�sb���<�<�1���F��h�h����)�T�\�\�9�F��	�D���}���f��F�	��V�T�N�*�*r1N)r�d)r�r�r�rcr�rZr]r�rarrdrfrkrorsrDr1r/rLrL:su���G��.�%���
�>��>�������<��<�$�	+��	+r1rLz\{([^}]*)\}z[^/\\,{]\*\*|\*\*[^/\\,}]z^[^{]*\}|\{[^}]*$c��tj|�rd}t||z��tj|�rd}t||z��t	|�S)zAExtended globbing function that supports ** and {opt1,opt2,opt3}.z7invalid glob %r: recursive glob "**" must be used alonez2invalid glob %r: mismatching set marker '{' or '}')�_CHECK_RECURSIVE_GLOBr{r��_CHECK_MISMATCH_SET�_iglob)�	path_globrs  r/rr�sQ���#�#�I�.�K����y��)�)��!�!�)�,�F����y��)�)��)��r1c#�K�tj|d�}t|�dkDrXt|�dk(sJ|��|\}}}|jd�D](}tdj	|||f��D]}|����*yd|vrt|�D]}|���y|jdd�\}}|dk(rd}|dk(rd}n"|j
d�}|j
d	�}tj|�D]W\}}}	tjj|�}ttjj	||��D]}
|
����Yy�w)
Nrr�rKrz**rer�rp�\)�	RICH_GLOBr�rtrxr&�	std_iglobr'rqr?rrr�)ry�rich_path_globrr�r}�itemrr�radical�dirr6r�s           r/rxrx�sP�����_�_�Y��2�N�
�>��Q���>�"�a�'�7��7�'�,����V��I�I�c�N�	�D��r�w�w���f�'=�>�?�
���
�
�	��y� �!�)�,�
���
�
�(�o�o�d�A�6�O�F�G���|����"�}���"�.�.��-��!�.�.��.��$&�G�G�F�O�
� ��c�5��w�w�'�'��-�� ������d�G�!<�=��B��H��
�s�EE)�HTTPSHandler�match_hostname�CertificateErrorc��eZdZdZdZd�Zy)�HTTPSConnectionNTc�,�tj|j|jf|j�}t|dd�r||_|j�tjtj�}ttd�r#|xjtjzc_t|dd�r&|j|j|j �i}|j"rQtj$|_|j)|j"��ttdd�r|j|d<|j*|fi|��|_|j"r]|j,rP	t/|jj1�|j�t2j5d|j�yyy#t6$rE|jj9tj:�|jj=��wxYw)	N�_tunnel_hostF�OP_NO_SSLv2�	cert_file)�cafile�HAS_SNI�server_hostnamezHost verified: %s)r��create_connection�host�port�timeoutr��sock�_tunnel�ssl�
SSLContext�PROTOCOL_SSLv23r��optionsr��load_cert_chainr��key_file�ca_certs�
CERT_REQUIRED�verify_mode�load_verify_locations�wrap_socket�check_domainr��getpeercertrrMr��shutdown�	SHUT_RDWRr�)r�r��contextr�s    r/�connectzHTTPSConnection.connect�s~���+�+�T�Y�Y��	�	�,B�,0�L�L�:�D��t�^�U�3� ��	������n�n�S�%8�%8�9�G��s�M�*����3�?�?�2���t�[�$�/��'�'�����
�
�F��F��}�}�&)�&7�&7��#��-�-�T�]�]�-�C��3�	�5�1�04�	�	�F�,�-�+��+�+�D�;�F�;�D�I��}�}��!2�!2��"�4�9�9�#8�#8�#:�D�I�I�F��L�L�!4�d�i�i�@�"3�}��(���I�I�&�&�v�'7�'7�8��I�I�O�O�%���s�4AG�AH)r�r�r�r�r�r�rDr1r/r�r��s������	r1r�c� �eZdZdd�Zd�Zd�Zy)r�c�J�tj|�||_||_yr�)�BaseHTTPSHandlerr�r�r�)r�r�r�s   r/r�zHTTPSHandler.__init__�s���%�%�d�+�$�D�M� ,�D�r1c�x�t|i|��}|jr"|j|_|j|_|S)a
            This is called to create a connection instance. Normally you'd
            pass a connection class to do_open, but it doesn't actually check for
            a class, and just expects a callable. As long as we behave just as a
            constructor would have, we should be OK. If it ever changes so that
            we *must* pass a class, we'll create an UnsafeHTTPSConnection class
            which just sets check_domain to False in the class definition, and
            choose which one to pass to do_open.
            )r�r�r�)r�r�r�r*s    r/�_conn_makerzHTTPSHandler._conn_maker�s8��%�d�5�f�5�F��}�}�"&�-�-���&*�&7�&7��#��Mr1c��	|j|j|�S#t$r5}dt|j�vrtd|jz���d}~wwxYw)Nzcertificate verify failedz*Unable to verify server certificate for %s)�do_openr�rr.�reasonr�r�)r�rcr�s   r/�
https_openzHTTPSHandler.https_opensa��
��|�|�D�$4�$4�c�:�:���
�.�#�a�h�h�-�?�*�!�#&�8�8�,�-�-���

�s��	A�0A�ANrb)r�r�r�r�r�r�rDr1r/r�r��s��	-�
	� 		r1r�c��eZdZd�Zy)�HTTPSOnlyHandlerc��td|z��)NzAUnexpected HTTP request on what should be a secure connection: %s)r)r�rcs  r/�	http_openzHTTPSOnlyHandler.http_opens���!�#&�'�(�
(r1N)r�r�r�r�rDr1r/r�r�s��	(r1r�c��eZdZdd�Zd�Zy)�	Transportc�R�||_tjj||�yr�)r�rr�r��r�r��use_datetimes   r/r�zTransport.__init__&s��������$�$�T�<�8r1c���|j|�\}}}|jr||jdk7r#||_|tj|�f|_|jdSr)�
get_host_info�_connection�_extra_headersr�HTTPConnection)r�r��h�eh�x509s     r/�make_connectionzTransport.make_connection*sd���(�(��.���2�t����4�4�+;�+;�A�+>�#>�"$�D��#�W�%;�%;�A�%>�>�D������"�"r1N�r�r�r�r�r�r�rDr1r/r�r�$s��9�#r1r�c��eZdZdd�Zd�Zy)�
SafeTransportc�R�||_tjj||�yr�)r�rr�r�r�s   r/r�zSafeTransport.__init__6s��"�D�L��#�#�,�,�T�<�@r1c��|j|�\}}}|si}|j|d<|jr||jdk7r%||_|t	j
|dfi|��f|_|jdS)Nr�rr)r�r�r�r�rr�)r�r�r�r�r�s     r/r�zSafeTransport.make_connection:s��� �.�.�t�4�M�A�r�6���� $���F�9���#�#�t�t�/?�/?��/B�'B�&(��#�#'��)@�)@��t�*'�%�*'�$'�� ��#�#�A�&�&r1Nr�r�rDr1r/r�r�4s
��	A�		'r1r�c��eZdZd�Zy)�ServerProxyc��|jdd�x|_}|�Ht|�d}|jdd�}|dk(rt}nt
}|||��x|d<}||_tjj||fi|��y)Nr�rr��https)r��	transport)
rwr�rr�r�r�r�rr�r�)r�rfr�r�rar��tclsrhs        r/r�zServerProxy.__init__Hs���!'���I�t�!<�<���w����c�]�1�%�F�!�:�:�n�a�8�L��� �$�� ��&*�7��&N�N�F�;��!��D�N����&�&�t�S�;�F�;r1N)r�r�r�r�rDr1r/r�r�Fs��<r1r�c�h�tjddkr|dz
}n
d|d<d|d<t||fi|��S)Nrr��br�newliner�r!)r�r�r#)r�r7r�s   r/�	_csv_openr�_sF��
�����Q��������y��%��z����D�#�F�#�#r1c�H�eZdZed�ed�ed�d�Zd�Zd�Zy)�CSVBaserK�"r)�	delimiter�	quotechar�lineterminatorc��|Sr�rDrs r/�	__enter__zCSVBase.__enter__q����r1c�8�|jj�yr�)r�r�)r�r�s  r/�__exit__zCSVBase.__exit__ts�������r1N)r�r�r�r.�defaultsr�r�rDr1r/r�r�js(����X���X��d�)��H��r1r�c�"�eZdZd�Zd�Zd�ZeZy)�	CSVReaderc��d|vr>|d}tjddk\rtjd�|�}||_nt|dd�|_t
j|jfi|j��|_y)Nr�rr�r�rrr�)	r�r�r�r�r�r��csvr�r�)r�r�r�s   r/r�zCSVReader.__init__zst���v���H�%�F�����"�a�'�2��)�)�'�2�6�:�� �D�K�#�F�6�N�C�8�D�K��j�j����>��
�
�>��r1c��|Sr�rDrs r/�__iter__zCSVReader.__iter__�r�r1c���t|j�}tjddkr8t	|�D]*\}}t|t�r�|jd�||<�,|S�Nrr�r�)�nextr�r�r�r�r�rr")r�r*rgrs    r/r�zCSVReader.next�s^���d�k�k�"�����A���"�$�V�,�
5���4�!�$�	�2� $���G� 4�F�1�I�
5��
r1N)r�r�r�r�r�r��__next__rDr1r/r�r�xs��	?����Hr1r�c��eZdZd�Zd�Zy)�	CSVWriterc��t|d�|_tj|jfi|j��|_y)Nr)r�r�r��writerr�)r�r�r�s   r/r�zCSVWriter.__init__�s-����C�(����j�j����>��
�
�>��r1c���tjddkr=g}|D]4}t|t�r|j	d�}|j|��6|}|jj|�yr�)r�r�r�rr,r$r��writerow)r��rowr�rs    r/r�zCSVWriter.writerow�se�����A���"��A��
���d�I�.��;�;�w�/�D������
��C������S�!r1N)r�r�r�r�r�rDr1r/r�r��s��?�"r1r�c�`��eZdZeej
�Zded<d�fd�	Zd�Zd�Zd�Z	�xZ
S)�Configurator�inc_convert�incc�f��tt|�|�|xstj�|_yr�)�superr�r�rqr�r|)r��configr|�	__class__s   �r/r�zConfigurator.__init__�s$���
�l�D�*�6�2��'�B�I�I�K��	r1c�������fd��|jd�}t|�s�j|�}|jdd�}|jdd�}|rt|D�cgc]
}�|���c}�}|D�cgc]}t	|�s�|�||�f��}}t|�}||i|��}	|r+|j
�D]\}
}t|	|
�|���|	Scc}wcc}w)Nc�.��t|ttf�r't|�|D�cgc]
}�|���c}�}|St|t�r0d|vr�j|�}|Si}|D]}�||�||<�|S�j
|�}|Scc}w�N�())r�rYr�type�dict�configure_custom�convert)�orgr*r�r�r�s    ��r/r�z.Configurator.configure_custom.<locals>.convert�s�����!�d�E�]�+� ��a��a�!8��'�!�*�!8�9���M��A�t�$��1�9�!�2�2�1�5�F��M� �F��2��$+�A�a�D�M��q�	�2��M����a����M��"9s�Br�rez[]rD)rwryrkrrr�r��setattr)
r�r�r��propsr�r�r�r�r�r*r�rSr�s
`           @r/r�zConfigurator.configure_custom�s����	�
�J�J�t�����{����Q��A��
�
�3��%���z�z�$��#����d�3��'�!�*�3�4�D�28�K�Q�K��N�!�W�V�A�Y�'�(�K��K��e����D�#�F�#������
�
/���1����7�1�:�.�
/��
��4��Ks�%C#�?C(�C(c��|j|}t|t�r$d|vr |j|�x|j|<}|Sr�)r�r�r�r�)r�r�r*s   r/�__getitem__zConfigurator.__getitem__�sC�����S�!���f�d�#����(,�(=�(=�f�(E�E�D�K�K���v��
r1c��tjj|�s*tjj|j|�}tj|dd��5}tj|�}ddd�|S#1swYSxYw)z*Default converter for the inc:// protocol.r�r�r N)	rqrr�isabsr&r|r�r#r�r�)r�r�r)r*s    r/r�zConfigurator.inc_convert�sc���w�w�}�}�U�#��G�G�L�L����E�2�E�
�[�[���g�
6�	"�!��Y�Y�q�\�F�	"��
�	"��
�s�"B�Br�)r�r�r�r�r�value_convertersr�r�rr��
__classcell__)r�s@r/r�r��s5����,�=�=�>��+��U��(��@�r1r�c�$�eZdZdZdd�Zd�Zd�Zy)�SubprocessMixinzC
    Mixin for running subprocesses and capturing their output
    Nc� �||_||_yr�)�verbose�progress)r�r	r
s   r/r�zSubprocessMixin.__init__�s����� ��
r1c�r�|j}|j}	|j�}|sn{|�
|||�nn|s tjjd�n.tjj|j
d��tjj���|j�y)z�
        Read lines from a subprocess' output stream and either pass to a progress
        callable (if specified) or write progress information to sys.stderr.
        Nrer�)	r
r	�readliner��stderrr�r"�flushr�)r�r�r�r
r	r.s      r/r�zSubprocessMixin.reader�s���
�=�=���,�,������!�A����#���G�$���J�J�$�$�S�)��J�J�$�$�Q�X�X�g�%6�7��
�
� � �"��	���r1c�Z�tj|ftjtjd�|��}tj|j
|jdf��}|j�tj|j
|jdf��}|j�|j�|j�|j�|j�|jdd�|S|jrtjjd�|S)N)�stdoutr
r)rr�r
zdone.�mainzdone.
)�
subprocess�Popen�PIPE�	threading�Threadr�rr�r
�waitr&r
r	r�r�)r��cmdr�r��t1�t2s      r/�run_commandzSubprocessMixin.run_command�s������S�
'�$.�O�O�$.�O�O�
'� &�
'���
�
�T�[�[����(�7K�
L��
���
�
�
�
�T�[�[����(�7K�
L��
���
�	����
���	�
���	��=�=�$��M�M�'�6�*����\�\��J�J���Y�'��r1)FN)r�r�r�r�r�r�rrDr1r/rr�s���!��*r1rc�L�tjdd|�j�S)z,Normalize a python package name a la PEP 503z[-_.]+r�)r��subr�)rXs r/�normalize_namers ���6�6�(�C��&�,�,�.�.r1c�(�eZdZdZdZdd�Zd�Zd�Zy)�
PyPIRCFilezhttps://upload.pypi.org/legacy/�pypiNc��|�=tjjtjjd�d�}||_||_y)Nr�z.pypirc)rqrrr&r�r�r[)r�r�r[s   r/r�zPyPIRCFile.__init__(s8��
�:������b�g�g�0�0��5�y�A�B���
���r1c��i}tjj|j��r�|jxs|j
}t
j�}|j|j�|j�}d|v�r|jdd�}|jd�D�cgc]%}|j�dk7r|j���'}}|gk(r	d|vr�dg}|S|D]�}d|i}|j|d�|d<d|j
fd	|jfd
fD]2\}}	|j||�r|j||�||<�.|	||<�4|dk(r ||j
dfvr|j
|d<��|d|k7s��|d|k7s��i}��|Sd|vred}|j|d�r|j|d�}n|j
}|j|d�|j|d�|||jd
�}|Scc}w)N�	distutilsz
index-serversrrr!�serverr��
repository�realm)r�Nzserver-loginr�)r�r�r&r%r')rqrrr	r�r[�DEFAULT_REPOSITORYr�RawConfigParserr�r�r�r�r]�
DEFAULT_REALM�
has_option)
r�r*r&r�r��
index_serversr%�_serversr�r�s
          r/r�zPyPIRCFile.read.s8����
�7�7�>�>�$�-�-�(����<�T�%<�%<�J�!�1�1�3�F��K�K��
�
�&����(�H��h�&� &�
�
�;�� H�
�1>�1D�1D�T�1J��'-��|�|�~��+��L�L�N�����r�>���)�$*�8��N�
�K#+�(��"*�F�!3��-3�Z�Z��
�-K��z�*�/;�.2�.E�.E�.G�.5�t�7I�7I�-J�-?�-A�6�L�C�� &�0�0���=�.4�j�j���.E��s��.5��s��6�#�f�,��$(�$;�$;�V�#D�2E�37�3J�3J�F�<�0�$�X�.�*�<�"(��"6�*�"D�%'�F�-(�J�
� �8�+�'���$�$�V�\�:�!'���F�L�!A�J�!%�!8�!8�J� &�
�
�6�:� >� &�
�
�6�:� >�",�$�!�/�/����
��]s�0*Hc�Z�tj�}|j}|j|�|j	d�s|jd�|j
dd|�|j
dd|�t|d�5}|j|�ddd�y#1swYyxYw)Nr!r�r�r)	rr)r�r��has_sectionr�r�r#r�)r�r�r�r�r�r)s      r/rZzPyPIRCFile.updatejs����-�-�/��
�]�]�����B���!�!�&�)����v�&��
�
�6�:�x�0��
�
�6�:�x�0�
�"�c�]�	�a��L�L��O�	�	�	�s�B!�!B*�NN)r�r�r�r(r*r�r�rZrDr1r/r r #s��:���M��:�x
r1r c�J�t|j��j�S)zG
    Read the PyPI access configuration as supported by distutils.
    )r[)r r[r��rs r/�_load_pypircr3ws���%�)�)�$�)�)�+�+r1c�`�t�j|j|j�yr�)r rZr�r�r2s r/�
_store_pypircr5~s���L���������7r1c��tjdk(rsdtjj	�vrydtjj	�vrydtjj	�vrytj
SdtjvrtjdStjd	k7sttd
�stj
Stj�\}}}}}|j	�jdd�}|jd
d�jdd�}|dddk(r|�d|��S|dddk(rB|ddk\r�d}dt|d�dz
|ddfz}ddd�}|d|tjzz
}n�|dddk(r
ddlm
}|�S|dd d!k(rJd!}tjd"tj �}|j#|�}|rJ|j%�}n9|dd d#k(r1ddl}		dd$lm}
|	j/|
j1�|||�\}}}|�d|�d|��S#t,$rddl}
Y�?wxYw)%a�Return a string that identifies the current platform.  This is used mainly to
    distinguish platform-specific build directories and platform-specific built
    distributions.  Typically includes the OS name and version and the
    architecture (as supplied by 'os.uname()'), although the exact information
    included depends on the OS; eg. on Linux, the kernel version isn't
    particularly important.

    Examples of returned values:
       linux-i586
       linux-alpha (?)
       solaris-2.6-sun4u

    Windows will return one of:
       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
       win32 (all others - specifically, sys.platform is returned)

    For other non-POSIX platforms, currently just returns 'sys.platform'.

    r��amd64�	win-amd64z(arm)�	win-arm32z(arm64)z	win-arm64�_PYTHON_HOST_PLATFORMr/�unamerprrVrir�N��linux�sunosr�5�solarisz%d.%sr���32bit�64bit)i���l����z.%s�aix)�aix_platform��cygwinz[\d.]+�darwin)�	sysconfig)rqrXr�r�r��platformr�r�r;r#�int�maxsize�_aix_supportrEr�rB�ASCIIrr��_osx_supportr$rI�ImportError�get_platform_osx�get_config_vars)�osnamer��releaser��machine�bitnessrE�rel_rer)rOrIs           r/�get_host_platformrX�s3��(
�w�w�$���c�k�k�'�'�)�)���c�k�k�'�'�)�)������)�)�+�+���|�|���"�*�*�,��z�z�1�2�2�	�w�w�'����W�!5��|�|��13���
�-�V�T�7�G�W��\�\�^�
#�
#�C��
,�F��o�o�c�3�'�/�/��S�9�G�
�b�q�z�W��!�'�*�*�	����w�	��1�:����F���W�Q�Z��1�!4�g�a�b�k� B�B�G�$+��I�G��u�w�s�{�{�3�3�3�G�	����u�	�-��~��	����x�	������I�r�x�x�0���L�L��!����g�g�i�G�	����x�	��	�+�$0�#@�#@��%�%�'���'�$C� ���� ��'�2�2���	��	�s�H>�>
I�
I�win32r8r9)�x86�x64�armc��tjdk7r
t�Stjj	d�}|t
vr
t�St
|S)Nr��VSCMD_ARG_TGT_ARCH)rqrXrXr�r��_TARGET_TO_PLAT)�cross_compilation_targets r/�get_platformra�sG��	�w�w�$�� �"�"�!�z�z�~�~�.B�C����6� �"�"��3�4�4r1r0)�r�r`)�r��collectionsr�
contextlibr��globrr}r=r��loggingrqr@r�r�r�rPrr�r+r�r�r�dummy_threadingrWrr�compatrrr	r
rrr
rrrrrrrrrrrrr�	getLoggerr�rrBrrPrOr:rCr?r`r%rFrlr�r�r�r�r�r�r��contextmanagerr�r�r�r�r�r�r�rkrm�VERBOSErzr�r�r�r�r�r�r��Ir�r�r�r�r�r�r�r�r�r�r�r�r��ARCHIVE_EXTENSIONSr;rErqrLr|rvrwrxr�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr r3r5rXr_rarDr1r/�<module>rns+��
���
�#�	���	��	�
����
����(����(�(�(�(�(�(�
��	�	�8�	$���R�Z�Z�)�
*�
��R�Z�Z� 3�4��
�R�Z�Z�5�
6�
��B�J�J�D�E�	��R�Z�Z�����b�j�j�����B�J�J�{�#�	��r�z�z�E�F��X!�vB%�J�4��$

� �,�^�&���������������&��&�
�f�
�  �6~�6�~�B��&��8�2�:�:���:�:�	'���>&(�R�"
�&���&�2�:�:���t�t�������,�-���4�"�*�*�9�:��
/� �8�*D���#�)�F�)�XD��D�TG!��G!�\��A�H�$	&��W+�v�W+�|
�B�J�J�~�&�	�"��
�
�#?�@�� �b�j�j�!5�6����8�+�+� �'�1�1� �D �'� �V(�<��(�#�	�#�#�#��'�	�/�/�'�$<�)�'�'�<�2$��f�����6"��"�,5�#�5�p.�f�.�b/�"Q��Q�h,�8�Q3�j�����5��a>��
�C����(�'�(�s#�M5�N�5N�?N�	N�N
¿Qué es la limpieza dental de perros? - Clínica veterinaria


Es la eliminación del sarro y la placa adherida a la superficie de los dientes mediante un equipo de ultrasonidos que garantiza la integridad de las piezas dentales a la vez que elimina en profundidad cualquier resto de suciedad.

A continuación se procede al pulido de los dientes mediante una fresa especial que elimina la placa bacteriana y devuelve a los dientes el aspecto sano que deben tener.

Una vez terminado todo el proceso, se mantiene al perro en observación hasta que se despierta de la anestesia, bajo la atenta supervisión de un veterinario.

¿Cada cuánto tiempo tengo que hacerle una limpieza dental a mi perro?

A partir de cierta edad, los perros pueden necesitar una limpieza dental anual o bianual. Depende de cada caso. En líneas generales, puede decirse que los perros de razas pequeñas suelen acumular más sarro y suelen necesitar una atención mayor en cuanto a higiene dental.


Riesgos de una mala higiene


Los riesgos más evidentes de una mala higiene dental en los perros son los siguientes:

  • Cuando la acumulación de sarro no se trata, se puede producir una inflamación y retracción de las encías que puede descalzar el diente y provocar caídas.
  • Mal aliento (halitosis).
  • Sarro perros
  • Puede ir a más
  • Las bacterias de la placa pueden trasladarse a través del torrente circulatorio a órganos vitales como el corazón ocasionando problemas de endocarditis en las válvulas. Las bacterias pueden incluso acantonarse en huesos (La osteomielitis es la infección ósea, tanto cortical como medular) provocando mucho dolor y una artritis séptica).

¿Cómo se forma el sarro?

El sarro es la calcificación de la placa dental. Los restos de alimentos, junto con las bacterias presentes en la boca, van a formar la placa bacteriana o placa dental. Si la placa no se retira, al mezclarse con la saliva y los minerales presentes en ella, reaccionará formando una costra. La placa se calcifica y se forma el sarro.

El sarro, cuando se forma, es de color blanquecino pero a medida que pasa el tiempo se va poniendo amarillo y luego marrón.

Síntomas de una pobre higiene dental
La señal más obvia de una mala salud dental canina es el mal aliento.

Sin embargo, a veces no es tan fácil de detectar
Y hay perros que no se dejan abrir la boca por su dueño. Por ejemplo…

Recientemente nos trajeron a la clínica a un perro que parpadeaba de un ojo y decía su dueño que le picaba un lado de la cara. Tenía molestias y dificultad para comer, lo que había llevado a sus dueños a comprarle comida blanda (que suele ser un poco más cara y llevar más contenido en grasa) durante medio año. Después de una exploración oftalmológica, nos dimos cuenta de que el ojo tenía una úlcera en la córnea probablemente de rascarse . Además, el canto lateral del ojo estaba inflamado. Tenía lo que en humanos llamamos flemón pero como era un perro de pelo largo, no se le notaba a simple vista. Al abrirle la boca nos llamó la atención el ver una muela llena de sarro. Le realizamos una radiografía y encontramos una fístula que llegaba hasta la parte inferior del ojo.

Le tuvimos que extraer la muela. Tras esto, el ojo se curó completamente con unos colirios y una lentilla protectora de úlcera. Afortunadamente, la úlcera no profundizó y no perforó el ojo. Ahora el perro come perfectamente a pesar de haber perdido una muela.

¿Cómo mantener la higiene dental de tu perro?
Hay varias maneras de prevenir problemas derivados de la salud dental de tu perro.

Limpiezas de dientes en casa
Es recomendable limpiar los dientes de tu perro semanal o diariamente si se puede. Existe una gran variedad de productos que se pueden utilizar:

Pastas de dientes.
Cepillos de dientes o dedales para el dedo índice, que hacen más fácil la limpieza.
Colutorios para echar en agua de bebida o directamente sobre el diente en líquido o en spray.

En la Clínica Tus Veterinarios enseñamos a nuestros clientes a tomar el hábito de limpiar los dientes de sus perros desde que son cachorros. Esto responde a nuestro compromiso con la prevención de enfermedades caninas.

Hoy en día tenemos muchos clientes que limpian los dientes todos los días a su mascota, y como resultado, se ahorran el dinero de hacer limpiezas dentales profesionales y consiguen una mejor salud de su perro.


Limpiezas dentales profesionales de perros y gatos

Recomendamos hacer una limpieza dental especializada anualmente. La realizamos con un aparato de ultrasonidos que utiliza agua para quitar el sarro. Después, procedemos a pulir los dientes con un cepillo de alta velocidad y una pasta especial. Hacemos esto para proteger el esmalte.

La frecuencia de limpiezas dentales necesaria varía mucho entre razas. En general, las razas grandes tienen buena calidad de esmalte, por lo que no necesitan hacerlo tan a menudo e incluso pueden pasarse la vida sin requerir una limpieza. Sin embargo, razas pequeñas como el Yorkshire o el Maltés, deben hacérselas todos los años desde cachorros si se quiere conservar sus piezas dentales.

Otro factor fundamental es la calidad del pienso. Algunas marcas han diseñado croquetas que limpian la superficie del diente y de la muela al masticarse.

Ultrasonido para perros

¿Se necesita anestesia para las limpiezas dentales de perros y gatos?

La limpieza dental en perros no es una técnica que pueda practicarse sin anestesia general , aunque hay veces que los propietarios no quieren anestesiar y si tiene poco sarro y el perro es muy bueno se puede intentar…… , pero no se va a poder pulir ni acceder a todas la zona de la boca …. Además los limpiadores dentales van a irrigar agua y hay riesgo de aspiración a vías respiratorias si no se realiza una anestesia correcta con intubación traqueal . En resumen , sin anestesia no se va hacer una correcta limpieza dental.

Tampoco sirve la sedación ya que necesitamos que el animal esté totalmente quieto, y el veterinario tenga un acceso completo a todas sus piezas dentales y encías.

Alimentos para la limpieza dental

Hay que tener cierto cuidado a la hora de comprar determinados alimentos porque no todos son saludables. Algunos tienen demasiado contenido graso, que en exceso puede causar problemas cardiovasculares y obesidad.

Los mejores alimentos para los dientes son aquellos que están elaborados por empresas farmacéuticas y llevan componentes químicos con tratamientos específicos para el diente del perro. Esto implica no solo limpieza a través de la acción mecánica de morder sino también un tratamiento antibacteriano para prevenir el sarro.

Conclusión

Si eres como la mayoría de dueños, por falta de tiempo , es probable que no estés prestando la suficiente atención a la limpieza dental de tu perro. Por eso te animamos a que comiences a limpiar los dientes de tu perro y consideres atender a su higiene bucal con frecuencia.

Estas simples medidas pueden conllevar a que tu perro tenga una vida más larga y mucho más saludable.

Si te resulta imposible introducir un cepillo de dientes a tu perro en la boca, pásate con él por clínica Tus Veterinarios y te explicamos cómo hacerlo.

Necesitas hacer una limpieza dental profesional a tu mascota?
Llámanos al 622575274 o contacta con nosotros

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¡Hola!