<s> import io <EOL> import json <EOL> import logging <EOL> import os <EOL> import re <EOL> import six <EOL> from jirafs import constants , utils <EOL> from jirafs . readers import GitRevisionReader , WorkingCopyReader <EOL> class JiraFieldManager ( dict ) : <EOL> FIELD_MATCHER = re . compile ( <EOL> '<STR_LIT>' % ( <EOL> constants . TICKET_FILE_FIELD_TEMPLATE . replace ( <EOL> '<STR_LIT>' , '<STR_LIT>' <EOL> ) <EOL> ) <EOL> ) <EOL> def __init__ ( self , data = None , names = None ) : <EOL> if names is None : <EOL> self . _data , self . _names = self . get_fields_from_string ( data ) <EOL> else : <EOL> self . _data = data <EOL> self . _names = names <EOL> super ( JiraFieldManager , self ) . __init__ ( self . _data ) <EOL> def __sub__ ( self , other ) : <EOL> differing = { } <EOL> for k , v in other . items ( ) : <EOL> if ( self . get ( k ) or v ) and self . get ( k ) != v : <EOL> tx = self . get ( k ) <EOL> differing [ k ] = ( v , tx , self . get ( k ) , ) <EOL> return differing <EOL> def get_human_name_for_field ( self , field ) : <EOL> try : <EOL> return self . _names [ field ] <EOL> except KeyError : <EOL> return field <EOL> def items_transformed ( self ) : <EOL> for k , v in self . items ( ) : <EOL> if k in self . get_requested_per_ticket_fields ( ) : <EOL> result = self . folder . process_macros ( v ) <EOL> yield k , result <EOL> else : <EOL> yield k , v <EOL> def get_transformed ( self , field_name , default = None ) : <EOL> if field_name not in self . get_requested_per_ticket_fields ( ) : <EOL> return self [ field_name ] <EOL> try : <EOL> return self . folder . process_macros ( self [ field_name ] ) <EOL> except KeyError : <EOL> return default <EOL> @ classmethod <EOL> def create ( cls , folder , revision = None , path = None ) : <EOL> if revision and path : <EOL> raise TypeError ( <EOL> '<STR_LIT>' <EOL> ) <EOL> if revision : <EOL> return GitRevisionJiraFieldManager ( folder , revision ) <EOL> else : <EOL> return WorkingCopyJiraFieldManager ( folder , path ) <EOL> def get_requested_per_ticket_fields ( self ) : <EOL> return constants . FILE_FIELDS <EOL> def get_used_per_ticket_fields ( self ) : <EOL> raise NotImplementedError ( ) <EOL> def get_field_data_files ( self ) : <EOL> all_files = [ <EOL> constants . TICKET_DETAILS , <EOL> ] <EOL> used_per_ticket_fields = [ ] <EOL> try : <EOL> for field in self . get_used_per_ticket_fields ( ) : <EOL> all_files . append ( <EOL> constants . TICKET_FILE_FIELD_TEMPLATE . format ( <EOL> field_name = field , <EOL> ) <EOL> ) <EOL> except NotImplementedError : <EOL> pass <EOL> for field in self . get_requested_per_ticket_fields ( ) : <EOL> all_files . append ( <EOL> constants . TICKET_FILE_FIELD_TEMPLATE . format ( <EOL> field_name = field , <EOL> ) <EOL> ) <EOL> return all_files <EOL> def set_data_value ( self , data , field_name , raw_value ) : <EOL> raw_value = raw_value . strip ( ) <EOL> try : <EOL> value = json . loads ( raw_value ) <EOL> except ( TypeError , ValueError ) : <EOL> value = raw_value <EOL> data [ field_name ] = value <EOL> def get_fields_from_string ( self , string ) : <EOL> """<STR_LIT>""" <EOL> data = { } <EOL> field_name = '<STR_LIT>' <EOL> human_names = { } <EOL> value = '<STR_LIT>' <EOL> if not string : <EOL> return data , human_names <EOL> lines = string . split ( '<STR_LIT:\n>' ) <EOL> for idx , line in enumerate ( lines ) : <EOL> if line . startswith ( '<STR_LIT:*>' ) : <EOL> if value : <EOL> self . set_data_value ( data , field_name , value ) <EOL> value = '<STR_LIT>' <EOL> raw_field_name = re . match ( '<STR_LIT>' , line ) . group ( <NUM_LIT:1> ) <EOL> if '<STR_LIT:(>' in raw_field_name : <EOL> match = re . match ( <EOL> '<STR_LIT>' , <EOL> raw_field_name <EOL> ) <EOL> field_name = match . group ( <NUM_LIT:2> ) <EOL> human_names [ field_name ] = match . group ( <NUM_LIT:1> ) <EOL> else : <EOL> field_name = raw_field_name . replace ( '<STR_LIT:U+0020>' , '<STR_LIT:_>' ) <EOL> elif field_name : <EOL> value = value + '<STR_LIT:\n>' + line . strip ( ) <EOL> if value : <EOL> self . set_data_value ( data , field_name , value ) <EOL> return data , human_names <EOL> class AutomaticJiraFieldManager ( JiraFieldManager ) : <EOL> def __init__ ( self ) : <EOL> data , names = self . load ( ) <EOL> super ( AutomaticJiraFieldManager , self ) . __init__ ( <EOL> data , names = names <EOL> ) <EOL> def load ( self ) : <EOL> fields , names = self . get_fields_from_string ( <EOL> self . get_file_contents ( constants . TICKET_DETAILS ) <EOL> ) <EOL> used_fields = set ( self . get_used_per_ticket_fields ( ) ) <EOL> requested_fields = set ( self . get_requested_per_ticket_fields ( ) ) <EOL> file_fields = { } <EOL> for field_name in used_fields | requested_fields : <EOL> try : <EOL> field_path = constants . TICKET_FILE_FIELD_TEMPLATE . format ( <EOL> field_name = field_name <EOL> ) <EOL> file_fields [ field_name ] = self . get_file_contents ( field_path ) <EOL> except ( IOError , OSError ) : <EOL> pass <EOL> fields . update ( file_fields ) <EOL> return fields , names <EOL> def get_file_contents ( self , path ) : <EOL> raise NotImplemented ( ) <EOL> class WorkingCopyJiraFieldManager ( <EOL> WorkingCopyReader , AutomaticJiraFieldManager <EOL> ) : <EOL> def get_used_per_ticket_fields ( self ) : <EOL> fields = [ ] <EOL> for filename in os . listdir ( self . path ) : <EOL> full_path = os . path . join ( self . path , filename ) <EOL> matched = self . FIELD_MATCHER . match ( filename ) <EOL> if matched and os . path . isfile ( full_path ) : <EOL> field_name = matched . group ( <NUM_LIT:1> ) <EOL> if field_name not in constants . FILE_FIELD_BLACKLIST : <EOL> fields . append ( field_name ) <EOL> return fields <EOL> def write ( self ) : <EOL> folder_path = self . folder . get_path ( constants . TICKET_DETAILS ) <EOL> used_fields = set ( self . get_used_per_ticket_fields ( ) ) <EOL> requested_fields = set ( self . get_requested_per_ticket_fields ( ) ) <EOL> with io . open ( folder_path , '<STR_LIT:w>' , encoding = '<STR_LIT:utf-8>' ) as out : <EOL> for field in sorted ( self . keys ( ) ) : <EOL> if field not in used_fields | requested_fields : <EOL> out . write ( <EOL> u'<STR_LIT>' . format ( <EOL> human = self . get_human_name_for_field ( field ) , <EOL> field = field , <EOL> ) <EOL> ) <EOL> field_string = self [ field ] <EOL> if field_string is None : <EOL> field_string = '<STR_LIT>' <EOL> elif not isinstance ( field_string , six . string_types ) : <EOL> field_string = json . dumps ( <EOL> field_string , <EOL> sort_keys = True , <EOL> indent = <NUM_LIT:4> , <EOL> ensure_ascii = False , <EOL> ) <EOL> padded_lines = [ <EOL> u'<STR_LIT>' % f for f in field_string . split ( '<STR_LIT:\n>' ) <EOL> ] <EOL> for line in padded_lines : <EOL> out . write ( line ) <EOL> else : <EOL> field_path = constants . TICKET_FILE_FIELD_TEMPLATE . format ( <EOL> field_name = field <EOL> ) <EOL> with io . open ( field_path , '<STR_LIT:w>' , encoding = '<STR_LIT:utf-8>' ) as fout : <EOL> fout . write ( self [ field ] ) <EOL> fout . write ( u'<STR_LIT:\n>' ) <EOL> class GitRevisionJiraFieldManager ( <EOL> GitRevisionReader , AutomaticJiraFieldManager <EOL> ) : <EOL> def get_used_per_ticket_fields ( self ) : <EOL> files = self . folder . run_git_command ( <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> self . revision <EOL> ) . split ( ) <EOL> fields = [ ] <EOL> for filename in files : <EOL> matched = self . FIELD_MATCHER . match ( filename ) <EOL> if matched : <EOL> field_name = matched . group ( <NUM_LIT:1> ) <EOL> if field_name not in constants . FILE_FIELD_BLACKLIST : <EOL> fields . append ( field_name ) <EOL> return fields </s>
