def valid_paragraph_subtitle(para, update_dict): ''' valid_paragraph_subtitle checks to ensure that standalone paragraphs do not have blank or non-unique subtitles. Non-standalone paragraphs are ok either way (technically at least) :param para: This is a dictionary form of the paragraph before it is updated. :type para: Paragraph (program will send in other models, but the method checks) :param update_dict: id, unique_key and fields to be changed :type update_dict: dictionary :return: dictionary with valid key that is true or False. If False, will have error message :rtype: dict ''' if not isinstance(para, Paragraph): return {'valid': True} if utils.key_in_dictionary(update_dict, 'standalone'): para.standalone = update_dict['standalone'] if not para.standalone: return {'valid': True} if utils.key_in_dictionary(update_dict, 'subtitle'): para.subtitle = update_dict['subtitle'] if not para.subtitle.strip(): return { 'valid': False, 'message': f'Empty subtitle on standalone para: {para}' } if Paragraph.objects.exclude(guid=para.guid).filter( subtitle__iexact=para.subtitle).exists(): return { 'valid': False, 'message': f'Not unique subtitle for para: {para}' } return {'valid': True}
def find_and_update_wrapper(self, key, record): ''' find_and_update_wrapper finds the record based on the information in the UPDATE_DATA constant with the given key :param key: key used to find the UPDATE_DATA information :type key: [str :param record: dictionary representation of the record to be found or created :type record: dict ''' if key == 'paragraphs': record = self.associate_ref_para(record) unique_field = crud.UPDATE_DATA[key]['unique_field'] class_ = crud.UPDATE_DATA[key]['class'] find_dict = {unique_field: record[unique_field]} returned_record = self.find_and_update_record(class_, find_dict, record) if utils.key_in_dictionary(returned_record, 'error'): sys.exit(returned_record['error']) self.assign_to_process_data( key, self.ensure_dictionary(class_, returned_record), unique_field, 'update', True)
def which_args(in_data): ''' which_args allows categories from the study selection go to the flashcard page and groups to go to the standalone paragraph page :param in_data: dictionary with group_id as a key or category_id as a key :type in_data: dict :return: information necessary for correct url construction :rtype: dict ''' if utils.key_in_dictionary(in_data, 'term'): identifier = 'projects:study_paragraphs_from_search' kwargs = {'search_term': in_data['term']} elif utils.key_in_dictionary(in_data, 'category'): identifier = 'projects:study_paragraphs_with_category' kwargs = {'category_id': in_data['category']} else: identifier = 'projects:study_paragraphs_with_group' kwargs = {'group_id': in_data['group']} return {'identifier': identifier, 'kwargs': kwargs}
def update_base_html(self): ''' Updating the return manually for now. Starting out with 1 since the theme has never been versioned ''' # Todo: assign this when automation makes it safe (don't want to delete prod versions) file_updater = BaseHtmlProcesser(self.file_data['s3_data_key']) base_html_ret = file_updater.update_base_html_s3_versions( self.versions['curr_version']) if utils.key_in_dictionary(base_html_ret, 'error'): sys.exit(base_html_ret['error']) self.versions['prior_version'] = base_html_ret['prior_version']
def single_para(context): ''' single_para gets a single para with references by para slug :param context: contains slug for single paragraph lookup, also contains is_modal :type subtitle: dict :return: one paragraph object (includes reference(s)) :rtype: dict ''' para = ParagraphsForDisplayOne() is_modal = True if utils.key_in_dictionary(context, 'is_modal') else False return para.retrieve_paragraphs(slug=context['slug'], is_modal=is_modal)
def valid_input_keys(self): ''' valid_input_keys ensures that there is at least one key :return: True if there is at least one valid key, False otherwise :rtype: bool ''' num = 0 for key in crud.VALID_RETRIEVAL_KEYS + crud.COPY_DIRECTLY_TO_OUTPUT: if utils.key_in_dictionary(self.file_data, key): num += 1 return num > 0
def appropriate_context(context, paragraphs): ''' appropriate_context takes the context and the data retriever and returns the information to send to the template :param context: information we already have, will be updated :type context: dict :param paragraphs: information returned from the data retriever :type paragraphs: dict :return: the information the front end needs to display the page :rtype: dict ''' if utils.key_in_dictionary(paragraphs, 'groups'): context = cat_helper.add_paragraphs_by_group_to_context( context, paragraphs) elif utils.key_in_dictionary(paragraphs, 'error'): context = para_helper.add_error_to_context(context, paragraphs, 'error') else: if paragraphs['group_type'] == 'standalone': paragraphs = add_collapse_variables(paragraphs) context = para_helper.add_paragraphs_to_context(context, paragraphs) return context
def link_text_list(self, para): ''' link_text_list initiates the process of turning the list of references' link_text to associations between a given paragraph and all of its references :param para: one paragraph :type para: dict ''' if utils.key_not_in_dictionary(self.input_data, 'ref_link_paragraph'): self.input_data['ref_link_paragraph'] = [] updated_para_ref = helpers.initiate_paragraph_associations( para, crud.PARA_ID_REF_LINK_TEXT, self.input_data['ref_link_paragraph']) if updated_para_ref is not None: self.input_data['ref_link_paragraph'] = updated_para_ref if utils.key_in_dictionary(para, 'link_text_list'): para.pop('link_text_list')
def new_path(self, path): ''' new_path takes path and returns a dictionary with the path with the updated version and also the prior version :param path: path from base.html for the file that we are currently parsing :type path: str :return: dictionary with the updateed path and also the prior version :rtype: dictionary ''' path_info = {} result = self.split_path(path) if utils.key_in_dictionary(result, 'error'): return result path_list = result['path_list'] path_info['prior_version'] = path_list[1] path_info['new_path'] = path_list[ 0] + '_' + self.curr_version + '.' + path_list[2] print(f'orig path == {path}') print(f'new path == {path_info["new_path"]}') return path_info
def __init__(self, **kwargs): group_title = kwargs.get('group_title', 'Temporary') json_only = kwargs.get('json_only', False) updating = kwargs.get('updating', False) super().__init__(group_title, json_only, updating) if utils.key_in_dictionary(kwargs, 'url'): self.url = kwargs['url'] self.html_path = None else: self.url = None self.html_path = kwargs['html_path'] self.process_data['paragraphs'] = [] self.process_data['before_work_experience'] = True self.process_data['before_education'] = True self.process_data['curr_company'] = '' self.process_data['counts'] = { 'total': 0, 'cc': 0, 'ts': 0, 'mas': 0, 'ln': 0 }
def replace_path_attribute(self): ''' replace_path_attribute uses beautifulsoup to find an element by id and then calls a method to replace the line in a new base.html file and then overwrite the old base.html with the new one :return: either the prior version (to be used in the future to delete file on S3) or error msg :rtype: dictionary ''' attr = self.data['attribute'] html = open(self.data['base_html_path']).read() soup = BeautifulSoup(html, features='lxml') el = soup.find(id=self.data['id']) path_info = self.new_path(el[attr]) if utils.key_in_dictionary(path_info, 'error'): return path_info el[attr] = path_info['new_path'] soup.find(id=self.data['id']).replace_with(el) str_element = str(el) params = self.params_for_replace_line_in_file(str_element) utils.replace_line(**params) shutil.move(self.data['new_base_html'], self.data['base_html_path']) return path_info
def loop_through_input_list(self): ''' loop_through_input_list loops through the list of paragraphs or groups and adds the order to either the cat_sort field in the group record or the groupparagraph sort field. It will call the create class in the base class: self.find_and_update_wrapper(key, record) key will either be 'groups' or 'group_paragraph' We will need to retrieve group_paragraph, but we will already have the group id ''' for idx, ordered_rec in enumerate( self.file_data[self.process_data['child_key']]): order_num = idx + 1 if self.process_data['association'] == 'many_to_many': self.assign_many_to_many(ordered_rec, order_num) else: self.assign_one_to_many(ordered_rec, order_num) returned_record = self.find_and_update_record( self.process_data['class'], self.process_data['find_dict'], self.process_data['update_dict']) if utils.key_in_dictionary(returned_record, 'error'): sys.exit(returned_record['error'])
def test_key_in_dictionary(key, expected): result = utils.key_in_dictionary({'name': 'Nemo'}, key) assert result == expected