
    jq                     >    d dl  d dlZd dlZd dlmZ  G d d      Zy)    )*N)Listc                        e Zd ZdZe fd       Ze fd       Zd Z fdZd Z	d Z
 fdZd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Z fdZ fdZd Zdee   fdZd Z xZS )CmfPluginCsvTestcasesMixinu   Миксин для импорта тест-кейсов с полной поддержкой маппинга полей и секций шагов.c                    i }t        t               d      r|j                  t        |                 |j                  i dddddddddddddd	ddd
d	ddddddddddddddddddddddddddddddddddddddddddddddddddd ddd!dddd"ddd"ddd"ddd"dd#d"dd$d"dd%       |S )&N_get_default_mappingIDext_idCmfTestcase)
field_name
model_nameKeyz	Issue KeyNamenameSummaryStatusstatus	ObjectivetextDescriptionFolderfolderzTest Repository PathPrioritysignificance	Component
components
ComponentsLabelstagsOwner	cmf_ownerAssigneeresponsiblezEstimated Timeestimate_timecovered_taskscovered_reqCmfTestcaseStep	test_dataexpected_result)zCoverage (Issues)zCoverage (Pages)Preconditionz!Test Script (Step-by-Step) - StepzTest Script (Plain Text)zTest Script (BDD)z&Test Script (Step-by-Step) - Test Dataz,Test Script (Step-by-Step) - Expected Result)hasattrsuperupdater   )clsdefault_mapping	__class__s     <./modules/settings/models/cmf_plugin_csv_mixins/testcases.pyr   z/CmfPluginCsvTestcasesMixin._get_default_mapping	   s   5723""57#?#AB  
G 
 (-H	 

 N 
 6G 
 fMJ 
 X]K 
 mL 
 &N 
 X]K 
 #8=$Y 
 ~]S 
 MR 
 ]S 
  V=I! 
" K}M# 
$ }MR% 
& _MZ' 
( 1@}!]/<M Z+1ARS@FVg1h7=M^(_06FW!XEP`q6rK\l}<~9 
 	<     c                    dt         j                  j                         t         j                  j                  ddt         j                  j                         t         j                  j                  ddt         j
                  j                         t         j
                  j                  ddt         j                  j                         t         j                  j                  dg}t        t               d      r|t        | %         z  }|S )Nu   Поля тест-кейсов)captionfieldsiconu)   Поля шагов тест-кейсовu3   Поля тест-кейсов тестплановu*   Поля выполнения тестовcalc_models_settings)
modelsr   import_shop_fieldsr6   r'   CmfTestplanTestcaseCmfTestcaseRunr+   r,   r7   )r.   resr0   s     r1   r7   z/CmfPluginCsvTestcasesMixin.calc_models_settings/   s     9FDVDVDiDiDk'',,.CvOeOeOxOxOz++002MY_YsYs  ZG  ZG  ZI//446DPVPePePxPxPz**//1	 572357/11C
r2   c                    | j                   j                  d   }| j                  ||t        j                        r| j                   j                  d       | j                  ||t        j                        r| j                   j                  d       | j                  ||t        j                        r| j                   j                  d       y y )Nimport_settingstestcasetestcase_steptestplan)
cmf_importjson_settings_map_objectr8   r   inc_statr'   CmfTestplan)selfrowr>   s      r1   _calc_statsz&CmfPluginCsvTestcasesMixin._calc_stats?   s    //778IJC&2D2DEOO$$Z0C&2H2HIOO$$_5C&2D2DEOO$$Z0 Fr2   c                 .   t        t               d      rt        
| 	  ||       | j                  |       | j	                  ||       | j
                  j                  d   }|j                  di       }| j                  ||t        j                        }|r|j                  d      rm|d   }|j                  ||i d      }| j                  ||t        j                        }|r/|j                  d      r|d   }	|d   j                  |	d|i       yyyyy)	uf   Хук для сбора всех метаданных тест-кейсов и тест-планов._prepare_import_data_hookr>   	testplansr   )datacyclesrN   rM   N)r+   r,   rK   rI   _collect_testcase_foldersrB   rC   
setdefaultrD   r8   rF   getr;   )rG   rH   projectr>   project_testplans	plan_data	plan_name	plan_inforun_data
cycle_namer0   s             r1   rK   z4CmfPluginCsvTestcasesMixin._prepare_import_data_hookH   s	   5778G-c7;&&sG4//778IJ#..{B?$$S/6;M;MN	v.!&)I)44Y^`@abI''_f>S>STHHLL0%f-
(#..zFH;MN 1x /9r2   c                    | j                   j                  j                  j                  d      }|s|S | j                  j                         D ])  }|j                  d      }|s|j                  |k(  s'|c S  t        j                  j                  |      }|st        d| d      | j                  j                  |||j                  |j                  |j                  dg g g g g d      S )u  При target_project_id (UI-импорт всегда задаёт) папки должны идти в bucket
        target-проекта, а не в проект из CSV-колонки «Название проекта» — иначе folder
        и тест-кейс расходятся по разным проектам и folder lookup возвращает None.
        target_project_idproject_objidu>   Целевой проект импорта (target_project_id=u@   ) не найден в базе — импорт прерван.)r   r]   )r[   r]   rM   	workflowssprintsr   	companiespersons)rB   rC   valuerQ   projectsvaluesr]   r8   
CmfProjectCmfErrorrP   r   )rG   rR   rZ   	proj_dataproj_objtarget_projs         r1   _resolve_target_project_bucketz9CmfPluginCsvTestcasesMixin._resolve_target_project_bucket\   s    
 !OO99??CCDWX N--/ 	!I }}]3HHKK+<<  	! ''++/@+A PQbPc dQ R  }}''*!nn!,!1!1H 	
 	
r2   c                 2   | j                  |      }| j                  j                  d   }| j                  ||t        j
                        }| j                  |j                  d            }|r*|j                  dt                     j                  |       yy)u   Извлекает путь папки из строки и складывает его в bucket нужного проекта.r>   r   testcase_foldersN)rj   rB   rC   rD   r8   r   _extract_folder_pathrQ   rP   setadd)rG   rH   rR   r>   tc_datapaths         r1   rO   z4CmfPluginCsvTestcasesMixin._collect_testcase_folders~   s    55g>//778IJ""39K9KL((X)>?1359==dC r2   c                 B   t        t               d      rt        | 	          i | _        | j                  j                         D ]W  }|j                  d      }|sZ|j                  di       j                  dd      }| j                  j                  d| ddd	
       | xj                  dz  c_	        q| j                  |       t                |j                  di       j                         D ]  \  }}|d   }|d   |d<   | j                  | j                  t        j                  |      \  }}t                |d   j                         D ]I  \  }	}
|
d   }||d<   ||d<   | j                  | j                  t        j                   |       t                K  Z y)uY   Создает структуру папок и планов перед импортом._global_objsr[   rM   r   UnknownuR   Не удалось найти или создать объект проекта 'uZ   '. Связанные данные (папки, планы) будут пропущены.zERR-0081re   obj_type   rL   r]   parentrN   rA   N)r+   r,   rs   _tests_registry_cacherc   rd   rQ   rB   	log_error_has_errors_process_testcase_folders
cmf_commititemsprocess_any_table_fieldsr8   rF   CmfTestcycle)rG   project_datar[   project_namerU   rV   rT   plan_obj_rX   
cycle_info
cycle_datar0   s               r1   rs   z'CmfPluginCsvTestcasesMixin._global_objs   s   57N+G " &(" MM002 	!L&**=9K+//;??	R))hiuhv wn o)	 *    A% **<8L(4(8(8b(I(O(O(Q !$	9%f-	&24&8	(#";;DOOVM_M_ajk!.7.A.G.G.I !*J
!+F!3J-5Jz*+6Jx(11$//6CVCVXbcL!!!	!r2   c                     |j                  d      }|j                  dg       }|r| j                  |       t        |      D ]  }| j                  ||        y )Nr[   rl   )rQ   _get_testcase_registrysorted_find_or_create_testcase_folder)rG   r   r[   pathsrq   s        r1   r|   z4CmfPluginCsvTestcasesMixin._process_testcase_folders   s[    "&&}5  !3R8''45M 	DD00{C	Dr2   c                 B   | j                   j                  |j                        }||S t        j                  j                  |ddg      }|&t        d|j                   d|j                   d      | j                  |       || j                   |j                  <   |S )u|   Возвращает реестр 'Тест-кейсы' проекта, с кешем; raise если реестра нет.r   tree_node_is_branch)rx   typer5   uH   Реестр 'Тест-кейсы' не найден в проекте 'z' (id=u6   ) — проект создан без scaffold_tests.)ry   rQ   r]   r8   CmfRegistryrf   r   _ensure_tree_branch)rG   r[   cachedregistrys       r1   r   z1CmfPluginCsvTestcasesMixin._get_testcase_registry   s    ++//?M%%))])* * 
 Z[f[k[kZl m"~~&&\^  	  *5="";>>2r2   c                 $    |j                    d| S )Nz::r\   )rG   folder_pathr[   s      r1   _build_folder_ext_idz/CmfPluginCsvTestcasesMixin._build_folder_ext_id   s    ..!K=11r2   c                     t        |t              r)|j                  d      xs |j                  d      xs d}n|rt        |      }ny|j	                         j	                  d      S )u   Достаёт нормализованный путь папки из значения CSV-поля (dict / строка / None).r
   r    /)
isinstancedictrQ   strstrip)rG   folder_fieldraws      r1   rm   z/CmfPluginCsvTestcasesMixin._extract_folder_path   sX    lD)""8,N0@0@0HNBCl#Cyy{  %%r2   c                    | j                  ||      }t        j                  j                  ||      }|r|S | j	                  ||      \  }}| j                  ||      }|r| j                  ||       |S | j                  ||||      S )N)r
   rR   )r   r8   CmfTestcaseFolderrQ   _resolve_folder_tree_parent_find_folder_by_name_sync_folder_ext_id_create_testcase_folder)rG   r   r[   r
   r   r   tree_parents          r1   r   z:CmfPluginCsvTestcasesMixin._find_or_create_testcase_folder   s    **;D))--V[-QM <<[+Vk**4=$$VV4M++D&+{SSr2   c                     |j                  dd      }|d   }t        |      dk(  r|| j                  |      fS | j                  |d   |      }| j	                  |       ||fS )u{   Для 'a/b/c' возвращает (имя='c', tree_parent=папка 'a/b'); для 'a' — реестр проекта.r   rw   r   )rsplitlenr   r   r   )rG   r   r[   partsr   parent_folders         r1   r   z6CmfPluginCsvTestcasesMixin._resolve_folder_tree_parent   sm    ""3*Ryu:?44[AAA<<U1X{S  /]""r2   c                 t    |j                  dg       |j                  sd|_        |j                  d       y y )Nr   T	only_data)load_fieldsr   save)rG   nodes     r1   r   z.CmfPluginCsvTestcasesMixin._ensure_tree_branch   s8    /01'''+D$III% (r2   c                 H    t         j                  j                  ||dg      S )Nr
   )r   r   r5   )r8   r   rQ   )rG   r   r   s      r1   r   z/CmfPluginCsvTestcasesMixin._find_folder_by_name   s)    ''++;z , 
 	
r2   c                 V    |j                   |k7  r||_         |j                  d       y y )NTr   )r
   r   )rG   r   r
   s      r1   r   z.CmfPluginCsvTestcasesMixin._sync_folder_ext_id   s(    ==F""FMKK$K' #r2   c                    |||||d}| j                  | j                  t        j                  |      \  }}|rdnd}| j                  j	                  | d| d|        t                | j                  j                  dd       |S )N)r   rx   rR   r
   r      Создали   Изменилиu    папку ext_id=z name=rl   	processed)r   rB   r8   r   logr}   rE   )	rG   r   r
   r   r[   folder_data
folder_objis_newverbs	            r1   r   z2CmfPluginCsvTestcasesMixin._create_testcase_folder   s    !"&
 "::OOV55{

F $*/Atf$7xvdVLM  !3[Ar2   c                 r   | j                  ||t        j                        }|r.|j                  d      r|r|j	                  |dz   |f       |g|fS | j                  ||t        j
                        }|r|r|j                  |       ||fS |r|j	                  |dz   |f       t        	| !  |||g |d      S )u   
        Оркестрация группировки: собирает тест-кейс и его шаги в один пакет для воркера.
        r   rw   r   )	rD   r8   r   rQ   putr'   appendr,   _process_grouped_rows)
rG   rH   r>   irows	row_queuei_headtestcase_data	step_datar0   s
            r1   r   z0CmfPluginCsvTestcasesMixin._process_grouped_rows  s    
 ((ov?Q?QR]..v6vz4015!8O $$S/6;Q;QR	KK< MM6A:t,- w,S/1b)UVWWr2   c                    | j                   j                  d   }| j                   j                  j                  j                  d      }t	        |d   t
        t        f      r%| j                  |d   |t        j                        }n!| j                  ||t        j                        }|j                  d      r|d   }| j                  |      }|s"|r t        j                  j                  |      }|r| j                  |||       y| j                   j                  ddd	       | xj                  d
z  c_        yt        t!               d      rt         | E  |       yy)u`   Воркер: определяет тип данных и запускает обработку.r>   rZ   r   r   r\   u   Невозможно импортировать тесткейс без проекта: создайте проект или укажите ID в файлеzERR-0079r   ru   rw   _process_rowN)rB   rC   rb   rQ   r   tuplelistrD   r8   r   _get_projectre   _process_testcase_with_stepsrz   r{   r+   r,   r   )rG   row_datar>   rZ   r?   	first_rowrR   r0   s          r1   r   z'CmfPluginCsvTestcasesMixin._process_row.  s2   //778IJ OO99??CCDWXhqkE4=1''_fFXFXYH''/6CUCUVH<< I''	2G0 ++//3D/E11(OWU)) s* * 
   A% uw/$X. 0r2   c           	      
   | j                  ||t        j                        }|r|j                  d      sy||d<   ||d<   | j	                  |j                  d            }|r| j                  ||      |d<   n|j                  dd       t        j                  j                  d      |d<   t        j                  j                  d      |d	<   |j                  d
      rg dg dg dd}|d
   }t        |t              r!|j                  dd      j                         }nt        |      j                         }d}	|j                         D ]  \  }
}||v s|
}	 n |	rA|d	   }t        j                  j                  ||	      }|r||d
<   nUdddd}|	|||	   d|d
<   nBt        |d
   t              r| j                  |      |d
   d<   n|| j                  |      d|d
<   i dddddddddddddd d!d d"d d#d d$d%d&d%d'd(d)d(d*d(d+d(d,d(}|j                  d-      }t        |t               s|j                  |d%      }||d-<   |j                  d.      }|rt        |t              r	 d%}d/|v r2|j#                  d/      }t!        |d%         d0z  t!        |d          z   }nt%        j&                  d1|      }t%        j&                  d2|      }|r |t!        |j)                  d             d0z  z  }|r|t!        |j)                  d             z  }|s|s|j+                         rt!        |      }||d.<   | j2                  j8                  j:                  | _        d8D ]F  }|j                  |      r$| j?                  |j                  |            ||<   8| j<                  ||<   H d9d:| j2                  j@                  gg d;dd:|d   gg}|j                  d<      r	d<d:|d<   g}n"|j                  d      rd=d<d:|d   gdd:|d   gg}dd:|d   g|g}| jC                  | j2                  t        j                  ||>      \  }}|rt        jE                  d?| jF                  jH                   d@| jF                  jJ                   dA|| j2                  dBC      jM                  dBD       | j2                  jO                  dE| dF|        |S | j2                  jO                  dG| dF|        |S # t,        t.        t0        f$ rR}| j2                  j5                  d3| d4t        |       d5d67       | xj6                  d z  c_        d%|d.<   Y d}~d}~ww xY w)Huv   Создает или обновляет тест-кейс со всей бизнес-логикой маппинга.r   NrR   rx   r   ztestcase.base:default)code
logic_typeworkflowr   )u%   Требуется доработкаDraftu   Черновик)u
   ГотовApprovedu   Утверждено)u   Не готовFailu   Устаревший)draftapprovedfailr
   r   )r   r   OPENCLOSED)r   r
   status_typer   )r
   r   u   Блокирующий   BlockerBlockingHighestu   Критический   Criticalu   Важныйrw   MajorHighMediumu   Нормальныйr   Normalu   Незначительныйr   MinorTrivialLowLowestr   r$   :<   z(\d+)hz(\d+)mu6   Некорректный формат времени 'u   ' для тесткейса: zERR-0080r   ru   )
cmf_authorr!   r#   zcmf_import.plugin==)import_originalr   Tr   OR
filter_objuD   Тесткейс импортирован из файла: <a href="z">z</a>T)r   rx   rB   r   )save_importu(   Создали тесткейс _filter=z, testcase=u*   Изменили тесткейс _filter=)(rD   r8   r   rQ   rm   r   popCmfLogicTypeCmfWorkflowr   r   r   r   r~   	CmfStatuscalc_status_typeintsplitresearchgroupisdigit
ValueError
IndexError	TypeErrorrB   rz   r{   r   rb   _fallback_person_get_personpluginr   
CmfCommentimport_fileurlr   r   r   )rG   rH   r>   rR   r?   r   statuses
status_valstatus_ext_id
found_coder   variantswf
status_objst_typessignificance_mapvalestimatetotalr   hmekey_filterobjr   s                              r1   _create_or_update_testcasez5CmfPluginCsvTestcasesMixin._create_or_update_testcaseJ  sC   ##C&:L:LMx||F3D%$//X0FG!%!E!EkSZ![HXLL4(!'!4!4!8!8>U!8!V%1155;R5S<<!!g$V SUH
 "(+J*d+ *x < B B D #J 5 5 7 J"*.."2 h H,!%J
  j)#--112J1O
)3HX& *0XxXH *"/'/
';*HX& hx0$78<8M8Mm8\HX&}5 #0'+'<'<]'K*HX&
$a
)2A
7A1
FOQR
$a
)3Q
 A
  '
 ,21
 7?
 #A	
 (0	

 +B

 18

 >G

 MRSU

 X`ac
 ll>*#s#"&&sA.C#& <<0
8S1.(?$NN3/EaMB.U1X>E 		)X6A		)X6A%3qwwqz?R#77%%3qwwqz?2% Q8+;+;+= #H,1) !% : : @ @= 	6C||C  $ 0 0c1B C $ 5 5		6 (t/E/EFHgjprv  yA  BH  yI  jJ  K<<FD(6:J+K\\(#vtXhEW6X194(AS0T0VW dHX$67A33DOOVEWEWYanu3vV[\`\l\l\p\p[qqstx  uE  uE  uJ  uJ  tK  KO  Pt   dtd$OO"J7)S^_g^h ij 
 OO"LWIU`ai`j kl
C 
I6 .))LXJVstwxytzs{|* * 
   A% ,-).s   5C	S2 2UAUUr   c                    | j                  |d   ||      }|syd}d}d}d}t        |d   d         D ]O  \  }	}
|
d   dk(  r|	}|
j                  d      s#|
d   d   dk(  s/|
d   d	   j                  d
      d   dk(  sM|	} n |D ]y  }| j	                  ||t
        j                        }|s(|duxr |t        |      k  xr ||   }|duxr |t        |      k  xr ||   }|r|dz  }t        |      }||   |d<   |j                  |d|d       dd|d   gdd|gg dg}| j                  | j                  t
        j                  ||      \  }}| j                  j                  |rdnd d|        |s|dz  }||   |d<   |j                  |d|d       dd|d   gdd|gg dg}| j                  | j                  t
        j                  ||      \  }}| j                  j                  |rdnd d|        | t                y)u~   Обрабатывает тест-кейс и распределяет данные строк по секциям шагов.r   Nr5   titler*   model_fieldr   r   field_qualname.r'   rw   pre)rx   step_sectionstep_numberr   rx   )r   r   r  r   r   r   u*    шаг предусловия filter_obj=main)r   r   r"  u    шаг filter_obj=)r  	enumeraterQ   r   rD   r8   r'   r   r   r-   r   rB   r   r}   )rG   r   r>   rR   r  r!  pre_step_numberprecondition_idxstep_idxr   f_maprH   r   has_preconditionhas_steppre_datar   r   r   s                      r1   r   z7CmfPluginCsvTestcasesMixin._process_testcase_with_steps  s   --d1gPF!/!"4X">? 	HAuW~/#$ ))M*&|4>&'78>>sCAFJ[[	  	|C((ov?U?UVI/t;u@PSVWZS[@[u`cdt`ut+U3s80CUHH  1$	?#&'7#8 3Ve fg%tXf-=>4QT@UWtu
 99$//6KaKack  yC9  D	6##6'7GY&Z  [E  FP  EQ  %R  S q $'M	&!  CXc!de%tYv->?(DRUAVXvw
 99$//6KaKacl  zD9  E	6##6'7GY&ZZmnxmy$z{3	|6 	r2   c                     | j                  ||t        j                        }|r|j                  d      ry| j                  ||t        j                        }|ryy)u   
        Определяет, является ли строка шагом тест-кейса (хвостом группы).
        r   FT)rD   r8   r   rQ   r'   )rG   rH   r>   rp   r   s        r1   _is_group_tailz)CmfPluginCsvTestcasesMixin._is_group_tail  sV    
 ""39K9KLw{{6* $$S/6;Q;QR	 r2   )__name__
__module____qualname____doc__classmethodr   r7   rI   rK   rj   rO   rs   r|   r   r   rm   r   r   r   r   r   r   r   r   r  r   r   r,  __classcell__)r0   s   @r1   r   r      s     `# #J  1O( 
D	D#!JD$2&T#&

("X:/8FP.d .`r2   r   )cmf.includehashlibr   typingr   r    r2   r1   <module>r7     s      	 K Kr2   