otlp-arrow-library 0.6.4

Cross-platform Rust library for receiving OTLP messages via gRPC and writing to Arrow IPC files
Documentation
�

�7&i������dZddlZddlZddlZddlZddlZddlZddlmZddl	m
Z
mZmZddl
mZddlmZmZddlmZmZGd�d	�Zd
edefd�Zd
�Zedk(re�yy)a�
Fetch all comments from a GitHub Pull Request.

This script retrieves all types of comments from a PR:
- Issue comments (general PR comments)
- Review comments (comments on code)
- Review body comments (top-level review comments)

Usage:
    python fetch_pr_comments.py <owner> <repo> <pr_number> [--token TOKEN] [--status STATUS]
    python fetch_pr_comments.py <pr_url> [--token TOKEN] [--status STATUS]

Examples:
    python fetch_pr_comments.py pixie79 otlp-rust-service 123
    python fetch_pr_comments.py https://github.com/pixie79/otlp-rust-service/pull/123
    python fetch_pr_comments.py pixie79 otlp-rust-service 123 --token ghp_xxxxx
    python fetch_pr_comments.py pixie79 otlp-rust-service 123 --status open
    python fetch_pr_comments.py pixie79 otlp-rust-service 123 --status all

Environment Variables:
    GITHUB_TOKEN - GitHub personal access token (optional, can use --token instead)
�N)�datetime)�Dict�List�Optional)�urlparse)�Request�urlopen)�	HTTPError�URLErrorc
�B�eZdZdZddededeefd�Zd deded	eefd
�Zde	defd
�Z
de	deefd�Zde	deefd�Z
de	deefd�Zde	deefd�Zde	defd�Zd!de	dedefd�Zde	de	dededef
d�Zed"dededefd��Zdd	edeefd�Zd	efd�Zd	efd�Zy)#�GitHubPRCommentsz*Fetch comments from a GitHub Pull Request.N�owner�repo�tokenc���||_||_|xstjd�|_d|_ddd�|_|jrd|j��|jd<yy)	a
        Initialize GitHub API client.

        Args:
            owner: Repository owner (username or organization)
            repo: Repository name
            token: GitHub personal access token (optional, uses GITHUB_TOKEN env var if not provided)
        �GITHUB_TOKENzhttps://api.github.comzapplication/vnd.github.v3+json�PR-Comments-Fetcher)�Accept�
User-Agentztoken �
AuthorizationN)rr�os�getenvr�base_url�headers)�selfrrrs    �scripts/fetch_pr_comments.py�__init__zGitHubPRComments.__init__)sd����
���	��7�b�i�i��7��
�0��
�6�/�
����:�:�.4�T�Z�Z�L�,A�D�L�L��)���endpoint�method�datac�P�|dk(�r�|j�|��}|r$tj|�jd�nd}t	|||j
d��}	t
|�5}|j�}t|j
�}	|dk(r2tdtj��tjd��n|d	k(r1td
tj��tjd�n�|dk(rVtdtj��d
|	vr!td|	d
��tj��tjd�nt|dvrptd|��tj��|j�jd�}
td|
��tj��tjd�|j�jd�}tj|�cddd�Sg}
d}d}	|j�|�d|�d|��}t	||j
��}	t
|�5}|j�}t|j
�}	|dk(r1tdtj��tjd�n�|d	k(r1tdtj��tjd�n�|dk(rVtdtj��d
|	vr!td|	d
��tj��tjd�n8|dk7r3td|��tj��tjd�|j�jd�}tj|�}|s	ddd�|
S|
j+|�t-|�|kr	ddd�|
S|dz
}ddd����#1swYnxYw���#t $r�}td|j"�d|j$��tj��t'|d�r|j�jd�nd}
td|
��tj��tjd�Yd}~���d}~wt($rH}td|j$��tj��tjd�Yd}~���d}~wwxYw#1swY��xYw#t $rU}td|j"�d|j$��tj��tjd�Yd}~��qd}~wt($rH}td|j$��tj��tjd�Yd}~���d}~wwxYw)a�
        Make a request to GitHub API and handle pagination (for GET) or single request (for POST).

        Args:
            endpoint: API endpoint (relative to base_url)
            method: HTTP method (GET or POST)
            data: Optional data to send in POST request body

        Returns:
            List of all items from paginated response (GET) or single Dict response (POST)
        �POST�utf-8N�r!rr i�z6Error: Authentication failed. Check your GitHub token.��file�i�z8Error: Not found. Check owner/repo/PR number/comment ID.i�z,Error: Rate limit exceeded or access denied.zX-RateLimit-RemainingzRate limit remaining: )�����Error: HTTP z
Response: �: �read�z(Error: Failed to connect to GitHub API: �dz?page=z
&per_page=�rz-Error: Not found. Check owner/repo/PR number.r)� - �Error: )r�json_lib�dumps�encoderrr	�getcode�dict�print�sys�stderr�exitr-�decode�loadsr
�code�reason�hasattrr�extend�len)rrr r!�url�req_data�req�response�status_coder�
error_body�
response_data�e�	all_items�page�per_page�itemss                 r�
_make_requestzGitHubPRComments._make_request=sf���V���]�]�O�H�:�.�C�?C�x�~�~�d�+�2�2�7�;��H��#�H�d�l�l�6�R�C�
��S�\�X�"*�"2�"2�"4�K�"�8�#3�#3�4�G�"�c�)��V�]`�]g�]g�h������$��+�� X�`c�`j�`j�k������$��+��L�SV�S]�S]�^�2�g�=�!�$:�7�CZ�;[�:\�"]�dg�dn�dn�o������$�J�6���[�M�:����L�%-�]�]�_�%;�%;�G�%D�
��
�:�,�7�c�j�j�I������$,�M�M�O�$:�$:�7�$C�M�#�>�>�-�8�-"�\�B�	�������]�]�O�H�:�V�D�6��H�:�N�C��#�t�|�|�4�C�&
��S�\�X�"*�"2�"2�"4�K�"�8�#3�#3�4�G�"�c�)��V�]`�]g�]g�h������$��+�� M�UX�U_�U_�`������$��+��L�SV�S]�S]�^�2�g�=�!�$:�7�CZ�;[�:\�"]�dg�dn�dn�o������$��+���[�M�:����L������#�=�=�?�1�1�'�:�D�$�N�N�4�0�E� ��/"�N���$�$�U�+��5�z�H�,��;"�N���A�I�D�?"��K"�\��\��.�
���Q�V�V�H�B�q�x�x�j�9��
�
�K�9@��F�9K�Q�V�V�X�_�_�W�5�QS�
��
�:�,�/�c�j�j�A���������
��@����
�K�RU�R\�R\�]��������
��"�\��@�
���Q�V�V�H�C����z�:����L���������
������z�*����<��������
�s��O0�$FO"�9	O0�8S8�ES+�S8�) S+�	S8�S+�S8�"O+�'O0�0	S(�9BR�S(� =S#�#S(�+S5�0S8�8	V%�A
U�V%�=V � V%�	pr_number�returnc�>�d|j�d|j�d|��}|j�|��}t||j��}	t|�5}|j
�dk7rAtd|j
���tj��tjd�|j�jd	�}tj|�cd
d
d
�S#1swYy
xYw#t$rT}td|j �d|j"��tj��tjd�Yd
}~y
d
}~wt$$rG}td|j"��tj��tjd�Yd
}~y
d
}~wwxYw)
z�
        Get basic PR information.

        Args:
            pr_number: Pull request number

        Returns:
            PR information dictionary
        �/repos/�/�/pulls/r0r)r+r&r(r$Nr1r2)rrrrrr	r6r8r9r:r;r-r<r3r=r
r>r?r)rrPrrCrErFr!rJs        r�get_pr_infozGitHubPRComments.get_pr_info�s+���T�Z�Z�L��$�)�)��G�I�;�G�������z�*���c�4�<�<�0��	������#�#�%��,��L��)9�)9�);�(<�=�C�J�J�O��H�H�Q�K��}�}��-�-�g�6���~�~�d�+������	��L������A�H�H�:�6�S�Z�Z�H��H�H�Q�K�K���	��G�A�H�H�:�&�S�Z�Z�8��H�H�Q�K�K��	�sD�C1�BC%�	C1�%C.�*C1�.C1�1	F�:A
E	�	F�=F�Fc�d�d|j�d|j�d|�d�}|j|�S)z�
        Get all issue comments (general PR comments).

        Args:
            pr_number: Pull request number

        Returns:
            List of issue comments
        rSrT�/issues/�	/comments�rrrO�rrPrs   r�get_issue_commentsz#GitHubPRComments.get_issue_comments�s7���T�Z�Z�L��$�)�)��H�Y�K�y�Q���!�!�(�+�+rc�h�d|j�d|j�d|�d�}|j|�}|S)z�
        Get all review comments (comments on code).

        Args:
            pr_number: Pull request number

        Returns:
            List of review comments
        rSrTrUrYrZ)rrPr�commentss    r�get_review_commentsz$GitHubPRComments.get_review_comments�s=���T�Z�Z�L��$�)�)��G�I�;�i�P���%�%�h�/���rc��gS)a�
        Get conversation status for review comments.
        
        Note: GitHub's REST API doesn't directly expose conversation resolved status.
        This method would need to use GraphQL API or check conversations endpoint.
        
        Args:
            pr_number: Pull request number
            
        Returns:
            List of conversation statuses (if available)
        �)rrPs  r�get_conversationsz"GitHubPRComments.get_conversations�s	�� �	rc�d�d|j�d|j�d|�d�}|j|�S)z�
        Get all reviews (including review body comments).

        Args:
            pr_number: Pull request number

        Returns:
            List of reviews
        rSrTrUz/reviewsrZr[s   r�get_reviewszGitHubPRComments.get_reviews�s7���T�Z�Z�L��$�)�)��G�I�;�h�O���!�!�(�+�+rc�,�|js%tdtj��t	�S	d}d}|j
|j|d�}tj||d��jd�}ddd	d
|j��d�}t|||d�
�}t|�5}|j�dk7ra|j�jd�}	td|j��d|	��tj��t	�cddd�Stj|j�jd��}
d|
vrItdtj|
dd����tj��t	�cddd�St	�}|
j!di�j!di�j!di�j!di�j!dg�}t#|�}
d}|D]j}|j!dd�}|s�|dz
}|j!di�j!dg�}|D]'}|j!d �}|s�|j%|��)�l|
dkDr/td!|
�d"|�d#t#|��d$�tj��ntd%tj��|cddd�S#1swYyxYw#t&$r2}td&|��tj��t	�cYd}~Sd}~wwxYw)'a
        Get set of resolved review comment IDs using GraphQL API.
        
        Args:
            pr_number: Pull request number
            
        Returns:
            Set of resolved comment IDs (empty set if GraphQL not available or error)
        zVWarning: No GitHub token provided. Cannot check resolved status. Showing all comments.r&zhttps://api.github.com/graphqlaA
            query($owner: String!, $repo: String!, $prNumber: Int!) {
              repository(owner: $owner, name: $repo) {
                pullRequest(number: $prNumber) {
                  reviewThreads(first: 100) {
                    nodes {
                      isResolved
                      comments(first: 100) {
                        nodes {
                          id
                          databaseId
                        }
                      }
                    }
                  }
                }
              }
            }
            )rr�prNumber)�query�	variablesr$zapplication/jsonrzBearer )rzContent-Typerrr#r%r)zGraphQL API returned status r,N�errorszGraphQL API errors: ���indentr!�
repository�pullRequest�
reviewThreads�nodesr�
isResolvedFr(r^�
databaseIdzFound z review threads, z resolved, z resolved commentszCWarning: No review threads found via GraphQL. Showing all comments.z6Warning: Could not fetch resolved status via GraphQL: )rr8r9r:�setrrr3r4r5rr	r6r-r<r=�getrB�add�	Exception)rrP�graphql_urlrgrh�payload�graphql_headersrErFrHr!�resolved_ids�threads�
total_threads�resolved_threads�thread�is_resolvedr^�comment�
comment_idrJs                     r�_get_resolved_comment_idsz*GitHubPRComments._get_resolved_comment_ids�s����z�z��j�qt�q{�q{�|��5�L�P	�:�K��E�*����	�	�%��I��n�n�u�9�%M�N�U�U�V]�^�G�-� 2�3�#*�4�:�:�,�!7�	�O����'��	�C������#�#�%��,�!)����!7�!7��!@�J��8��9I�9I�9K�8L�B�z�l�[�be�bl�bl�m��5�	�� �~�~�h�m�m�o�&<�&<�W�&E�F���t�#��0�����X��WX�1Y�0Z�[�be�bl�bl�m��5��� #�u���(�(�6�2�.�2�2�<��D�H�H��XZ�[�_�_�`o�qs�t�x�x�zA�CE�F�� #�G��
�#$� �%�F�"(�*�*�\�5�"A�K�"�(�A�-�(�#)�:�:�j�"�#=�#A�#A�'�2�#N��'/�G�)0���\�)B�J�)� ,� 0� 0�� <�	(0�&�!�1�$��F�=�/�1B�CS�BT�T_�`c�dp�`q�_r�sE�F�MP�MW�MW�X��_�gj�gq�gq�r�#�A����B�	��J�1�#�N�UX�U_�U_�`��5�L��	�sd�A3K�&A+K�	K�A5K�	K�BK�?K�A%K�	K�K�K�K�	L�!'L�L�L�statusc�2�td|�d�tj��|j|�}|j	|�}|j|�}|j
|�}|dk7r�|j|�}g}|D]N}	|	jd�}
|r|
|vnd}|dk(r|s|j|	��5|dk(s�;|s�>|j|	��P|}|dk(rtd	tj��n |dk(rtd
tj��||||d�S)a6
        Fetch all comments from a PR.

        Args:
            pr_number: Pull request number
            status: Filter by comment status - "open" (default, unresolved), "resolved", or "all"

        Returns:
            Dictionary containing PR info and all types of comments (filtered by status)
        zFetching comments for PR #�...r&�all�idF�open�resolvedz4Filtering to show only open (unresolved) comments...z+Filtering to show only resolved comments...)�pr_info�issue_comments�review_comments�reviews)
r8r9r:rVr\r_rdr�rt�append)rrPr�r�r�r�r��resolved_comment_ids�filtered_review_commentsr�r�rs            r�fetch_all_commentsz#GitHubPRComments.fetch_all_comments_s$��	�*�9�+�S�9��
�
�K��"�"�9�-���0�0��;���2�2�9�=���"�"�9�-��
�U�?�#'�#A�#A�)�#L� �')�$�*��$�[�[��.�
�DX�j�,@�@�^c���V�#�K�,�3�3�G�<��z�)�k�,�3�3�G�<�+�7�O�����L�TW�T^�T^�_��:�%��C�3�:�:�V��,�.��	
�	
rr��comment_type�
reply_bodyc	��|js0tdtj��tjd�|dk(r=d|j
�d|j�d|�d|�d	�	}d
|i}|j|d|��}|S|d
k(r;d|j
�d|j�d|�d�}||d�}|j|d|��}|S|dk(rUtdtj��d|j
�d|j�d|�d�}d
|i}|j|d|��}|Std|��tj��tjd�y)ah
        Reply to a comment on a PR.

        Args:
            pr_number: Pull request number
            comment_id: ID of the comment to reply to
            comment_type: Type of comment ("issue", "review_comment", or "review")
            reply_body: Text of the reply

        Returns:
            Dictionary containing the created reply comment
        z3Error: GitHub token is required for posting repliesr&r(�review_commentrSrTrUz
/comments/z/replies�bodyr#)r r!�issuerXrY)r��in_reply_to�reviewzQWarning: Reviews cannot be directly replied to. Posting as issue comment instead.zError: Unknown comment type: N)rr8r9r:r;rrrO)rrPr�r�r�rr!�results        r�reply_to_commentz!GitHubPRComments.reply_to_comment�sX���z�z��G�c�j�j�Y��H�H�Q�K��+�+� �����A�d�i�i�[��	�{�*�U_�T`�`h�i�H��J�'�D��'�'���d�'�K�F��M�
�W�
$�!�����A�d�i�i�[����9�U�H�&�z�B�D��'�'���d�'�K�F��M�
�X�
%�
�c��Z�Z�
�!�����A�d�i�i�[����9�U�H��J�'�D��'�'���d�'�K�F��M��1�,��@�s�z�z�R��H�H�Q�Krr�c���|jdi�}t|t�r|jdd�n
t|�}|jdd�}|jdd�}|�d}|r8	t	j
|j
dd��}|jd	�}nd
}|dk(r�|jdd
�}|jdd�}	|jd�}
|jd�}|jdd�}|jd�}
|jd�}d|�d|�d�}|d|��z
}|	r	|d|	�d�z
}|
r|
|	k7r	|d|
�d�z
}|r	|d|�d�z
}|dz
}|
r	|d|
�d�z
}|r	|d|�d�z
}|r	|d|�d�z
}|r
|d |�d�z
}nU|d!z
}nO|d"k(r0|jd#d$�}d%|�d&|�d'|�d�}|r
|d(|�d�z
}n |d)z
}nd*|�d|�d�}|r
|d|�d�z
}n|d!z
}|dzd+zdzS#t$r|}Y��VwxYw),z�
        Format a comment for display.

        Args:
            comment: Comment dictionary from API
            comment_type: Type of comment (issue, review, review_comment)

        Returns:
            Formatted string
        �user�login�Unknown�
created_atr.r��Zz+00:00z%Y-%m-%d %H:%M:%S UTCzUnknown dater��pathzUnknown file�line�?�
original_line�
start_line�	diff_hunk�in_reply_to_id�pull_request_review_idz[Review Comment] z on �
zFile: z (line �)z (original line z
 (start line zReply to comment ID: zReview ID: z
Code Context:
z

Comment:
z
(No comment text)
r��state�unknownz	[Review] z (z) on z
Review Body:
z
(No review body)
z
[Comment] zP--------------------------------------------------------------------------------)	rt�
isinstancer7�strr�
fromisoformat�replace�strftime�
ValueError)r�r�r��
user_loginr�r��dt�date_strr�r�r�r�r�r�r�r�r�s                 r�format_commentzGitHubPRComments.format_comment�s����{�{�6�2�&��5?��d�5K�T�X�X�g�y�1�QT�UY�QZ�
��[�[��r�2�
��{�{�6�2�&���<��D��
&��+�+�J�,>�,>�s�H�,M�N���;�;�'>�?��&�H��+�+��;�;�v�~�6�D��;�;�v�s�+�D�#�K�K��8�M� ���\�2�J����K��4�I�$�[�[�)9�:�N�%,�[�[�1I�%J�"�(���D��
�"�E�F���t�f�o�%�F���G�D�6��+�+����$�!6��,�]�O�1�=�=����M�*��Q�7�7���d�N�F���1�.�1A��D�D��%��K�(>�'?�r�B�B����-�i�[��;�;����L���b�1�1���1�1��
�X�
%��K�K���3�E� ���B�u�g�U�8�*�B�G�F���,�T�F�"�5�5���0�0��!�*��T�(��2�>�F���B�t�f�B�-�'���1�1����}�x�'�$�.�.��g�
&�%��
&�s�+6G,�,G;�:G;�output_filec��ddl}|d}|d}|d}|d}|rt|ddd	�
�}ntj}	t	j
|�}	|	j
gd��|	j
|d|d
t|dt�r|ddnd|d|d|dg�|	j
g�|r�|	j
gd��|D]�}
|	j
d|
jdd�t|
jd�t�r"|
jdi�jdd�nd|
jdd�|
jdd�jdd�jdd�|
jdd�g���|	j
g�|�r|	j
gd��|D]�}
|	j
d|
jdd�t|
jd�t�r"|
jdi�jdd�nd|
jdd�|
jdd�|
jdd�|
jdd�jdd�jdd�|
jdd�g���|	j
g�|r�|	j
gd��|D]�}|	j
d |jdd�t|jd�t�r"|jdi�jdd�nd|jdd�|jd!�xs|jdd�|jdd�jdd�jdd�|jdd�g���|r2|r/|j�td"|��tj�#�yyy#|r2|r/|j�td"|��tj�#�wwwxYw)$z�
        Print comments in CSV format.

        Args:
            data: Dictionary containing PR info and comments
            output_file: Optional file path to write CSV to (default: stdout)
        rNr�r�r�r��wr.r$)�newline�encoding)z	PR NumberzPR Title�Author�State�
Created At�URL�number�titler�r�r�r�r��html_url)�Comment Type�IDr�r��Bodyr��
issue_commentr�r�r�� �
)r�r�r�r��File�Liner�r�r�r�r�)r�r�r�r�r�r�r�r��submitted_atzCSV exported to r&)�ior�r9�stdout�csv�writer�writerowr�r7rtr��closer8r:)rr!r�r�r�r�r�r��outputr�r�r�s            r�print_csv_viewzGitHubPRComments.print_csv_views���	��y�/���.�/���0�1���y�/����+�s�B��I�F��Z�Z�F�=	I��Z�Z��'�F�
�O�O�]�^��O�O���!��� �,6�w�v���,M�����(�S\��� ���%��
�#�
�
�
�O�O�B������ ]�^�-�G��O�O�'����D�"�-�KU�V]�Va�Va�bh�Vi�ko�Kp����F�B�/�3�3�G�Y�G�v����L�"�5����F�B�/�7�7��c�B�J�J�4�QS�T����J��3�
%�� .�����#����� m�n�.�G��O�O�(����D�"�-�KU�V]�Va�Va�bh�Vi�ko�Kp����F�B�/�3�3�G�Y�G�v����L�"�5����F�B�/����F�B�/����F�B�/�7�7��c�B�J�J�4�QS�T����J��3�	%�	� /�����#����� f�g�%�F��O�O� ��
�
�4��,�JT�U[�U_�U_�`f�Ug�im�Jn��
�
�6�2�.�2�2�7�I�F�t}��
�
�7�B�/��
�
�>�2�R�f�j�j��r�6R��
�
�6�2�.�6�6�t�S�A�I�I�$�PR�S��
�
�:�r�2�%��&��v������(��
�6�S�Z�Z�H� &�{��{�v������(��
�6�S�Z�Z�H� &�{�s�MO�6Pc
��|d}|d}|d}|d}tdd���td|d�d	|d
���td|dd
�d|d�d|d���td|d���td�d��d;dtdtdtfd�}|�r&tdd���tdt|��d��td��tdd�ddd�dd d�dd!d"���td��|D]�}t|j	d#d$��}t|j	d�t�r"|j	di�j	d
d%�nd%}	|j	d�r|j	dd&�d'd(nd%}
||j	d)d&�d*�}t|d�d|	d�d|
d�d|d"�����td�d��|�rItdd���td+t|��d��td��tdd�ddd�dd,d-�dd.d/�dd!d0��	�td��|D]�}t|j	d#d$��}t|j	d�t�r"|j	di�j	d
d%�nd%}	|j	d1d%�}t|�d2kDrd3|d4d'z}t|j	d5d6��}
||j	d)d&�d7�}t|d�d|	d�d|d-�d|
d/�d|d0��	���td�d��t|�t|�z}td��td8t|��d9t|��d:|���td�d��y')<z�
        Print comments in a formatted table view.

        Args:
            data: Dictionary containing PR info and comments
        r�r�r�r�r�zd====================================================================================================�PR #r�r,r��Author: r�r�z
 | State: r�z | Created: r��URL: r��text�max_lenrQc��|sy|jdd�jdd�}t|�|kDr|d|dz
dzS|S)Nr.r�r�r��r�)r�rB)r�r�s  r�truncatez3GitHubPRComments.print_table_view.<locals>.truncatessL�����<�<��c�*�2�2�4��<�D��4�y�7�"��L�W�q�[�)�E�1�1��Kru,────────────────────────────────────────────────────────────────────────────────────────────────────�ISSUE COMMENTS (� total)r�z<12r�r�z<20�Date�Commentz<48r�zN/Ar�r.N�r��0z!REVIEW COMMENTS - Code Comments (r�z<35r�z<8z<25r��!r�i����r�r��z	SUMMARY: z Issue Comments | z Review Comments | Total: )�<)r8r��intrBrtr�r7)rr!r�r�r�r�r�r�r�r��createdr�r�r��totals               r�print_table_viewz!GitHubPRComments.print_table_view_s����y�/���.�/���0�1���y�/��	��9�+���
��W�X�&�'�r�'�'�*:�);�<�=�
������1�2�*�W�W�=M�<N�l�[b�co�[p�Zq�r�s�
��g�j�)�*�+�,�
���2���	�3�	��	�c�	���B�{�m�$�%��$�S��%8�$9��A�B��[�M�#��T�#�J�a���~�Q�v�c�l�!�I�c�?�K�L��[�M�#�)�� ����T�5�!9�:�
�JT�U\�U`�U`�ag�Uh�jn�Jo�w�{�{�6�2�.�2�2�7�I�F�u~��@G���L�@Y�'�+�+�l�B�7���<�_h������F�B� 7��<����C�(��$�s��1�W�S�M��4��*�M�N�*�
�[�M��$�%���B�{�m�$�%��5�c�/�6J�5K�7�S�T��[�M�#��T�#�J�a���~�Q�v�c�l�!�F�2�;�a�	�RU��W�X��[�M�#�*�� ����T�5�!9�:�
�JT�U\�U`�U`�ag�Uh�jn�Jo�w�{�{�6�2�.�2�2�7�I�F�u~���{�{�6�9�5���t�9�r�>� �4���:�-�D��7�;�;�v�s�3�4������F�B� 7��<����C�(��$�s��1�T�#�J�a��R�y��$�s��T�U�+�
�[�M��$�%��N�#�c�/�&:�:��
����
�	�#�n�-�.�.@��_�AU�@V�Vp�qv�pw�x�y�
���2��rc��|d}tdd���td|d�d|d���td|d	d
���td|d���td
|d���td|d���td�d��|d}|rVtdd���tdt|��d��td�d��|D]}t|j|d���|d}|rVtdd���tdt|��d��td�d��|D]}t|j|d���|d}|rVtdd���tdt|��d��td�d��|D]}t|j|d���t|�t|�zt|�z}tdd���td�td��tdt|����tdt|����tdt|����td|���td�d��y )!z�
        Print all comments in a readable format.

        Args:
            data: Dictionary containing PR info and comments
        r�r�zP================================================================================r�r�r,r�r�r�r�zState: r�z	Created: r�r�r�r�r�r�r�r�z!REVIEW COMMENTS (Code Comments) (r�r�z	REVIEWS (r��SUMMARYzIssue Comments: zReview Comments: z	Reviews: zTotal: N)r8rBr�)	rr!r�r�r�r�r�r�r�s	         r�print_all_commentsz#GitHubPRComments.print_all_comments�sb���y�/��
��8�*�o��
��W�X�&�'�r�'�'�*:�);�<�=�
������1�2�3�4�
����(�)�*�+�
�	�'�,�/�0�1�2�
��g�j�)�*�+�,�
��
�"�o���.�/����B�x�j�/�"��$�S��%8�$9��A�B��X�J�b�/�"�)���d�)�)�'�7�;�<�*��0�1����B�x�j�/�"��5�c�/�6J�5K�7�S�T��X�J�b�/�"�*���d�)�)�'�3C�D�E�+��y�/����B�x�j�/�"��I�c�'�l�^�7�3�4��X�J�b�/�"�!���d�)�)�&�(�;�<�"��N�#�c�/�&:�:�S��\�I��
��8�*�o��
���
��
��
� ��^�!4� 5�6�7�
�!�#�o�"6�!7�8�9�
�	�#�g�,��(�)�
���w�� �
��
�"�o�r)N)�GETN)r�)r�)�__name__�
__module__�__qualname__�__doc__r�rrrrOr�rVrr\r_rbrdrsr�r�r��staticmethodr�r�r�r�rarrr
r
&s���4�B�c�B��B�X�c�]�B�(d�c�d�3�d�h�t�n�d�L�S��T��8,�C�,�D��J�,��S��T�$�Z��&�3��4��:��$,�S�,�T�$�Z�,�_�3�_�3�_�B.
�C�.
��.
�$�.
�`-��-�*-�-�=@�-�NQ�-�	
�-�^�K/��K/�C�K/��K/��K/�ZQI�4�QI�h�s�m�QI�fA �T�A �F4�t�4rr
rCrQc���d}tj||�}|rA|j�d|j�dt|j�d�fSt	d|����)z�
    Parse a GitHub PR URL to extract owner, repo, and PR number.

    Args:
        url: GitHub PR URL

    Returns:
        Tuple of (owner, repo, pr_number)
    z&github\.com/([^/]+)/([^/]+)/pull/(\d+)rr(rjzInvalid PR URL format: )�re�search�groupsr�r�)rC�pattern�matchs   r�parse_pr_urlr��sb��8�G��I�I�g�s�#�E���|�|�~�a� �%�,�,�.��"3�S������9J�5K�K�K�
�.�s�e�4�
5�5rc��tjdtjt��}|j	ddd��|j	ddd��|j	d	dt
d
��|j	dd
��|j	ddd��|j	ddd��|j	ddddd��|j	dt
dd��|j	dgd�d �!�|j	d"t
dd#��|j	d$d%��|j	d&d'��|j	d(gd)�d*d+�,�|j
�}|js%|j�tjd-�|jjd.�r	t|j�\}}}n||j r|j"s@td2tj�0�|j�tjd-�|j}|j }|j"}t%|j&�3�}|j(�r�|j*s0td4tj�0�tjd-�|j,s<|j.s0td5tj�0�tjd-�|j&s0td6tj�0�tjd-�|j,}|j.r1t1|j.d7d8�9�5}|j3�}d1d1d1�|j5|j(|j*|�}	td:�td;|	j7d<����td=|	j7d>����tjd?�|j8�r|j*s0td@tj�0�tjd-�|j;|j8|j*�}
|
s>tdA|j8�dB�tj�0�tjd-�|j<r!tt?j@|
dC�D��n;dEdFdGd�}t|jC|
|j7|j*dE���tjd?�|jE|jF�H�}|j<�r�|dIdJ|dIdKtI|dIdLtJ�r|dIdLdMndN|dIdO|dIdP|dId>dQ�|dRD�
cgc]�}
|
j7d<�tI|
j7dL�tJ�r"|
j7dLi�j7dMdN�ndN|
j7dP�|
j7dSd�|
j7d>�dT����c}
|dUD�
cgc]�}
|
j7d<�tI|
j7dL�tJ�r"|
j7dLi�j7dMdN�ndN|
j7dP�|
j7dV�|
j7dW�|
j7dSd�|
j7dX�|
j7d>�dY����c}
|dZD�cgc]�}|j7d<�tI|j7dL�tJ�r"|j7dLi�j7dMdN�ndN|j7dO�|j7dP�|j7dSd�|j7d>�d[����c}d\�tM|dR�tM|dU�tM|dZ�tM|dR�tM|dU�ztM|dZ�zd]�d^�}tt?j@|dC�D��y1|jN�-|jNr|jNnd1}|jQ||�y1|jRr|jU|�y1|jW|�y1#t$r>}td/|��tj�0�tjd-�Yd1}~��td1}~wwxYw#1swY��XxYwcc}
wcc}
wcc}w)_zMain entry point.z-Fetch all comments from a GitHub Pull Request)�description�formatter_class�epilog�owner_or_urlr�z.Repository owner (username/org) or full PR URL)�nargs�helprzGRepository name (required if owner is provided, not if URL is provided)rPzMPull request number (required if owner/repo provided, not if URL is provided))r�typerz--tokenz:GitHub personal access token (or set GITHUB_TOKEN env var))rz--json�
store_truez)Output as JSON (useful for AI/automation))�actionrz--tablez9Output as formatted table (default: detailed text format)z--csvr.�FILEz?Output as CSV (optionally specify output file, default: stdout))r�const�metavarrz--detail�
COMMENT_IDz(Get details for a specific comment by ID)rrrz--comment-type)r�r�r�zHComment type for --detail or --reply (required with --detail or --reply))�choicesrz--replyz!Reply to a specific comment by IDz--reply-bodyz'Reply body text (required with --reply)z--reply-body-filez=File containing reply body text (alternative to --reply-body)z--status)r�r�r�r�z�Filter comments by status: 'open' (default, unresolved comments), 'resolved', or 'all' (all comments). Note: Requires --token for status filtering to work.)r	�defaultrr(�httpr2r&NzCError: Must provide both repo and pr_number when using owner format)rz.Error: --comment-type is required with --replyzAError: --reply-body or --reply-body-file is required with --replyz&Error: --token is required for --reply�rr$)r�zReply posted successfully!zComment ID: r�r�r�rz/Error: --comment-type is required with --detailzError: Comment z
 not foundrjrkr�r�r�)r�r�r�r�r�r�r�r�r�)r�r��authorr�r�rCr�r�)r�r�r�r�rCr�r�r�r�)r�r�r�r�r�r�r�rCr�)r�r�r�r�r�rC)r�r�r�)�total_issue_comments�total_review_comments�
total_reviews�total_comments)�prr^�summary),�argparse�ArgumentParser�RawDescriptionHelpFormatterr��add_argumentr��
parse_argsr��
print_helpr9r;�
startswithr�r�r8r:rrPr
r�replyr�r��reply_body_filer�r-r�rt�detail�get_comment_by_id�jsonr3r4r�r�r�r�r7rBr�r��tabler�r�)�parser�argsrrrPrJ�clientr��fr�r��comment_type_mapr!�cr�json_outputr�s                 r�mainr(�s���
�
$�
$�C� �<�<���F�
�����
=���
�����
V���
�����
�
\�	������
I��������
8���
�����
H���
�������
N�������
��
7�	������5�
W���
����
��
0�	������
6�������
L�������+��k�	������D����������������#�#�F�+�	�%1�$�2C�2C�%D�"�E�4��
�y�y�����W�^a�^h�^h�i������H�H�Q�K��!�!���y�y���N�N�	��e�T����
<�F��z�z�� � ��B����T��H�H�Q�K����t�';�';��U�\_�\f�\f�g��H�H�Q�K��z�z��:����L��H�H�Q�K��_�_�
�����d�*�*�C�'�B�a��V�V�X�
�C��(�(��D�J�J��@Q�@Q�S]�^��
�*�,�
��V�Z�Z��-�.�/�0�
��f�j�j��,�-�.�/�������{�{�� � ��C�#�*�*�U��H�H�Q�K��*�*�4�;�;��8I�8I�J����O�D�K�K�=�
�;�#�*�*�M��H�H�Q�K��9�9��(�.�.���3�4�!�"2�"� ��

�&�'�'��1A�1E�1E�d�FW�FW�Y`�1a�b�c�������$�$�Y�t�{�{�$�C�D��y�y��y�/�(�3��i���1�>H��i��Y_�I`�bf�>g�$�y�/�&�1�'�:�mv��i���1�"�9�o�l�;��I��z�2�
�""�"2�3�	#�4��
 �e�e�D�k�MW�XY�X]�X]�^d�Xe�gk�Ml����f�b� 1� 5� 5�g�y� I�r{�&'�e�e�L�&9� !���f�b� 1� �u�u�Z�0��4�	#�*"�"3�4�$�5�� �e�e�D�k�MW�XY�X]�X]�^d�Xe�gk�Ml����f�b� 1� 5� 5�g�y� I�r{�&'�e�e�L�&9� !���f�
� !���f�
� !���f�b� 1�%&�U�U�;�%7� �u�u�Z�0�	�5�$�,"�)�_�
�-�� �e�e�D�k�MW�XY�X]�X]�^d�Xe�gk�Ml����f�b� 1� 5� 5�g�y� I�r{�!"���w��&'�e�e�L�&9� !���f�b� 1� �u�u�Z�0�
�-�
�1#�J),�D�1A�,B�(C�),�T�2C�-D�)E�!$�T�)�_�!5�"%�d�+;�&<�"=��D�IZ�D[�@\�"\�_b�cg�hq�cr�_s�"s�	�[3
��h	�h�n�n�[��3�4�	
���	�"&�(�(�d�h�h������d�K�0�	
�������%��!�!�$�'��}�	��G�A�3�-�c�j�j�1��H�H�Q�K�K��	��:C�B��`	#��$��
s9�a'�
b1�	B
b>�B=c�%Bc
�'	b.�03b)�)b.�1b;�__main__)r�rr�rr3rr�r9r�typingrrr�urllib.parser�urllib.requestrr	�urllib.errorr
rr
r��tupler�r(r�rarr�<module>r/sk���.�
��	�	�
��'�'�!�+�,�p
�p
�f6�c�6�e�6�$U(�p�z���F�r