def test_thumbnail_icons_exist_for_each_category(self): all_categories = list(constants.CATEGORIES_TO_COLORS.keys()) # Test that an icon exists for each default category. for category in all_categories: utils.get_file_contents( os.path.join(self.get_static_asset_filepath(), 'assets', 'images', 'subjects', '%s.svg' % category.replace(' ', ''))) # Test that the default icon exists. utils.get_file_contents( os.path.join(self.get_static_asset_filepath(), 'assets', 'images', 'subjects', '%s.svg' % constants.DEFAULT_THUMBNAIL_ICON))
def test_convert_png_binary_to_data_url(self) -> None: filepath_png = os.path.join('core', 'tests', 'data', 'test_png_img.png') file_contents_png = utils.get_file_contents(filepath_png, raw_bytes=True, mode='rb') self.assertEqual(utils.convert_png_binary_to_data_url(file_contents_png), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAGCAIAAACAbBMhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAySURBVBhXY/iPDYBEV6xY0draCuFDAEgUKMTAANUEUYFuAkQFihIIGwigosiG/P//HwD5HmjphyAmJQAAAABJRU5ErkJggg%3D%3D') # pylint: disable=line-too-long
def load_demo(collection_id: str) -> None: """Loads a demo collection. The resulting collection will have version 2 (one for its initial creation and one for its subsequent modification). Args: collection_id: str. ID of the collection to be loaded. """ delete_demo(collection_id) demo_filepath = os.path.join(feconf.SAMPLE_COLLECTIONS_DIR, feconf.DEMO_COLLECTIONS[collection_id]) yaml_content = utils.get_file_contents(demo_filepath) collection = save_new_collection_from_yaml(feconf.SYSTEM_COMMITTER_ID, yaml_content, collection_id) system_user = user_services.get_system_user() publish_collection_and_update_user_profiles(system_user, collection_id) index_collections_given_ids([collection_id]) # Now, load all of the demo explorations that are part of the collection. for collection_node in collection.nodes: exp_id = collection_node.exploration_id # Only load the demo exploration if it is not yet loaded. if exp_fetchers.get_exploration_by_id(exp_id, strict=False) is None: exp_services.load_demo(exp_id) logging.info('Collection with id %s was loaded.' % collection_id)
def validator_html(self): """The HTML code containing validators for the interaction's customization_args and submission handler. """ return ('<script>%s</script>\n' % utils.get_file_contents( os.path.join(feconf.INTERACTIONS_DIR, self.id, '%sValidationService.js' % self.id)))
def test_rte_components_are_valid(self): """Test that the default RTE components are valid.""" rte_components = ( rte_component_registry.Registry.get_all_rte_components()) for (component_id, component_specs) in rte_components.items(): # Check that the component id is valid. hyphenated_component_id = utils.camelcase_to_hyphenated( component_id) self.assertTrue(self._is_camel_cased(component_id)) # Check that the component directory exists. component_dir = os.path.join( feconf.RTE_EXTENSIONS_DIR, component_id) self.assertTrue(os.path.isdir(component_dir)) # In this directory there should be a /directives directory, an # an icon .png file and a protractor.js file, and an optional # preview .png file. # In /directives directory should be HTML file, a JS file, # there could be multiple JS and HTML files. dir_contents = self._listdir_omit_ignored(component_dir) self.assertLessEqual(len(dir_contents), 4) directives_dir = os.path.join(component_dir, 'directives') png_file = os.path.join(component_dir, '%s.png' % component_id) protractor_file = os.path.join(component_dir, 'protractor.js') self.assertTrue(os.path.isdir(directives_dir)) self.assertTrue(os.path.isfile(png_file)) self.assertTrue(os.path.isfile(protractor_file)) main_ts_file = os.path.join( directives_dir, 'oppia-noninteractive-%s.component.ts' % hyphenated_component_id) main_html_file = os.path.join( directives_dir, '%s.component.html' % hyphenated_component_id) self.assertTrue(os.path.isfile(main_ts_file)) self.assertTrue(os.path.isfile(main_html_file)) ts_file_content = utils.get_file_contents(main_ts_file) self.assertIn( 'oppiaNoninteractive%s' % component_id, ts_file_content) self.assertNotIn('<script>', ts_file_content) self.assertNotIn('</script>', ts_file_content) # Check that the configuration file contains the correct # top-level keys, and that these keys have the correct types. for item, item_type in _COMPONENT_CONFIG_SCHEMA: self.assertTrue(isinstance( component_specs[item], item_type)) # The string attributes should be non-empty. if item_type == str: self.assertTrue(component_specs[item]) self._validate_customization_arg_specs( component_specs['customization_arg_specs']) # pylint: disable=protected-access
def get_html_template(cls): """Returns the HTML template for the class. Returns: str. The HTML template corresponding to the class. """ return utils.get_file_contents( os.path.join(os.getcwd(), feconf.VALUE_GENERATORS_DIR, 'templates', '%s.html' % cls.__name__))
def rules_dict(self): """A dict of rule names to rule properties.""" if self._cached_rules_dict is not None: return self._cached_rules_dict rules_index_dict = json.loads( utils.get_file_contents(feconf.RULES_DESCRIPTIONS_FILE_PATH)) self._cached_rules_dict = rules_index_dict[self.id] return self._cached_rules_dict
def html_body(self): """The HTML code containing directives and templates for the interaction. This contains everything needed to display the interaction once the necessary attributes are supplied. Each interaction has two directive/template pairs, one for the interaction itself and the other for displaying the learner's response in a read-only view after it has been submitted. """ html_templates = utils.get_file_contents(os.path.join( feconf.INTERACTIONS_DIR, self.id, '%s.html' % self.id)) return html_templates
def get_html_field_types_to_rule_specs(cls, state_schema_version=None): """Returns a dict containing a html_field_types_to_rule_specs dict of the specified state schema verison, if available. Args: state_schema_version: int|None. The state schema version to retrieve the html_field_types_to_rule_specs for. If None, the current state schema version's html_field_types_to_rule_specs will be returned. Returns: dict. The html_field_types_to_rule_specs specs for the given state schema version. Raises: Exception. No html_field_types_to_rule_specs json file found for the given state schema version. """ cached = ( state_schema_version in cls._state_schema_version_to_html_field_types_to_rule_specs) if not cached and state_schema_version is None: cls._state_schema_version_to_html_field_types_to_rule_specs[ state_schema_version] = json.loads( utils.get_file_contents( feconf.HTML_FIELD_TYPES_TO_RULE_SPECS_FILE_PATH)) elif not cached: file_name = 'html_field_types_to_rule_specs_state_v%i.json' % ( state_schema_version) spec_file = os.path.join( feconf. LEGACY_HTML_FIELD_TYPES_TO_RULE_SPECS_FILE_PATH_FILE_DIR, file_name) try: with python_utils.open_file(spec_file, 'r') as f: specs_from_json = json.loads(f.read()) except: raise Exception( 'No specs json file found for state schema v%i' % state_schema_version) cls._state_schema_version_to_html_field_types_to_rule_specs[ state_schema_version] = specs_from_json return cls._state_schema_version_to_html_field_types_to_rule_specs[ state_schema_version]
def _init_classify_inputs(self, exploration_id): """Initializes all the classification inputs of the exploration corresponding to the given exploration id. """ test_exp_filepath = os.path.join(feconf.TESTS_DATA_DIR, 'string_classifier_test.yaml') yaml_content = utils.get_file_contents(test_exp_filepath) assets_list = [] with self.swap(feconf, 'ENABLE_ML_CLASSIFIERS', True): exp_services.save_new_exploration_from_yaml_and_assets( feconf.SYSTEM_COMMITTER_ID, yaml_content, exploration_id, assets_list) self.exp_id = exploration_id self.exp_state = ( exp_fetchers.get_exploration_by_id(exploration_id).states['Home'])
def index(): """ Initialize the github folders. """ auth = initialize() if auth and auth[0]: init = auth[1] repo = init.get('repo') # get the posts location in github posts_folder = get_post_folder() if posts_folder: folders = get_contents(repo, posts_folder) else: return redirect('/configure') contents = get_content_from_folder(repo, folders) display_pages = {} for key, value in contents.items(): files = value['files'] for file in files: temp = {} if not allowed_file(file.path): text = decode_content(file.content, True) display_content = get_file_contents(text)[0] temp = get_article_data(display_content) if temp.get('title'): temp['path'] = value['path'] display_pages[temp['title']] = temp else: print(key, value) return render_template('index.html', pages=display_pages) elif not auth: return render_template('index.html') else: return redirect(url_for('core.' + auth[1]))
def test_default_interactions_are_valid(self): """Test that the default interactions are valid.""" all_interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) for interaction_id in all_interaction_ids: # Check that the interaction id is valid. self.assertTrue(self._is_camel_cased(interaction_id)) hyphenated_interaction_id = ( utils.camelcase_to_hyphenated(interaction_id)) # Check that the interaction directory exists. interaction_dir = os.path.join(feconf.INTERACTIONS_DIR, interaction_id) self.assertTrue(os.path.isdir(interaction_dir)) # The interaction directory should contain the following files: # Required: # * A python file called {InteractionName}.py. # * An __init__.py file used to import the Python file. # * A TypeScript file called {InteractionName}.ts. # * If migrated to Angular2+, a module.ts file called # {InteractionName}-interactions.module.ts # * A directory name 'directives' containing TS and HTML files # for directives # * A directory named 'static' containing at least a .png file. # Optional: # * A JS file called protractor.js. interaction_dir_contents = ( self._listdir_omit_ignored(interaction_dir)) interaction_dir_optional_dirs_and_files_count = 0 try: self.assertTrue( os.path.isfile( os.path.join(interaction_dir, 'protractor.js'))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue( os.path.isfile( os.path.join( interaction_dir, '%s-interactions.module.ts' % hyphenated_interaction_id))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue( os.path.isfile( os.path.join( interaction_dir, '%s-prediction.service.ts' % hyphenated_interaction_id))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue( os.path.isfile( os.path.join( interaction_dir, '%s-prediction.service.spec.ts' % hyphenated_interaction_id))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass self.assertEqual(interaction_dir_optional_dirs_and_files_count + 5, len(interaction_dir_contents)) py_file = os.path.join(interaction_dir, '%s.py' % interaction_id) ts_file = os.path.join(interaction_dir, '%s.ts' % interaction_id) self.assertTrue(os.path.isfile(py_file)) self.assertTrue(os.path.isfile(ts_file)) # Check that __init__.py file exists. init_file = os.path.join(interaction_dir, '__init__.py') self.assertTrue(os.path.isfile(init_file)) # Check that the directives subdirectory exists. directives_dir = os.path.join(interaction_dir, 'directives') self.assertTrue(os.path.isdir(directives_dir)) # The directives directory should contain the following files: # Required: # * A TS file called # oppia-interactive-{InteractionName}.directive.ts. # * A TS file called OppiaResponse{InteractionName}.directive.ts. # * A TS file called # oppia-short-response-{InteractionName}.directive.ts. # * A TS file called {InteractionName}-rules.service.ts. # * A TS file called {InteractionName}-validation.service.ts. # * A HTML file called # {InteractionName}-interaction.directive.html. # * A HTML file called # {InteractionName}-response.directive.html. # * A HTML file called # {InteractionName}-short-response.directive.html. # Optional: # * A TS file called # {InteractionName}-validation.service.specs.ts. # * A TS file called {InteractionName}-rules.service.specs.ts. hyphenated_interaction_id = ( utils.camelcase_to_hyphenated(interaction_id)) if interaction_id in INTERACTIONS_THAT_USE_COMPONENTS: interaction_ts_file = os.path.join( directives_dir, 'oppia-interactive-%s.component.ts' % (hyphenated_interaction_id)) response_ts_file = os.path.join( directives_dir, 'oppia-response-%s.component.ts' % hyphenated_interaction_id) short_response_ts_file = os.path.join( directives_dir, 'oppia-short-response-%s.component.ts' % (hyphenated_interaction_id)) rules_service_ts_file = os.path.join( directives_dir, '%s-rules.service.ts' % hyphenated_interaction_id) validation_service_ts_file = os.path.join( directives_dir, '%s-validation.service.ts' % hyphenated_interaction_id) interaction_html = os.path.join( directives_dir, '%s-interaction.component.html' % hyphenated_interaction_id) response_html = os.path.join( directives_dir, '%s-response.component.html' % hyphenated_interaction_id) short_response_html = os.path.join( directives_dir, '%s-short-response.component.html' % hyphenated_interaction_id) else: interaction_ts_file = os.path.join( directives_dir, 'oppia-interactive-%s.directive.ts' % (hyphenated_interaction_id)) response_ts_file = os.path.join( directives_dir, 'oppia-response-%s.directive.ts' % hyphenated_interaction_id) short_response_ts_file = os.path.join( directives_dir, 'oppia-short-response-%s.directive.ts' % (hyphenated_interaction_id)) rules_service_ts_file = os.path.join( directives_dir, '%s-rules.service.ts' % hyphenated_interaction_id) validation_service_ts_file = os.path.join( directives_dir, '%s-validation.service.ts' % hyphenated_interaction_id) interaction_html = os.path.join( directives_dir, '%s-interaction.directive.html' % hyphenated_interaction_id) response_html = os.path.join( directives_dir, '%s-response.directive.html' % hyphenated_interaction_id) short_response_html = os.path.join( directives_dir, '%s-short-response.directive.html' % hyphenated_interaction_id) self.assertTrue(os.path.isfile(interaction_ts_file)) self.assertTrue(os.path.isfile(response_ts_file)) self.assertTrue(os.path.isfile(short_response_ts_file)) self.assertTrue(os.path.isfile(interaction_html)) self.assertTrue(os.path.isfile(response_html)) self.assertTrue(os.path.isfile(short_response_html)) self.assertTrue(os.path.isfile(rules_service_ts_file)) self.assertTrue(os.path.isfile(validation_service_ts_file)) # Check that the PNG thumbnail image has the correct dimensions. static_dir = os.path.join(interaction_dir, 'static') self.assertTrue(os.path.isdir(static_dir)) png_file = os.path.join(interaction_dir, 'static', '%s.png' % interaction_id) self.assertTrue(os.path.isfile(png_file)) with python_utils.open_file(png_file, 'rb', encoding=None) as f: img_data = f.read() width, height = struct.unpack('>LL', img_data[16:24]) self.assertEqual(int(width), INTERACTION_THUMBNAIL_WIDTH_PX) self.assertEqual(int(height), INTERACTION_THUMBNAIL_HEIGHT_PX) interaction_ts_file_content = utils.get_file_contents( interaction_ts_file) response_ts_file_content = utils.get_file_contents( response_ts_file) short_response_ts_file_content = ( utils.get_file_contents(short_response_ts_file)) ts_file_content = utils.get_file_contents(ts_file) rules_service_ts_file_content = utils.get_file_contents( rules_service_ts_file) validation_service_ts_file_content = utils.get_file_contents( validation_service_ts_file) self.assertIn('oppiaInteractive%s' % interaction_id, interaction_ts_file_content) self.assertIn('oppiaResponse%s' % interaction_id, response_ts_file_content) self.assertIn('oppiaShortResponse%s' % interaction_id, short_response_ts_file_content) self.assertIn( '%sRulesService' % (interaction_id[0] + interaction_id[1:]), rules_service_ts_file_content) self.assertIn('%sValidationService' % interaction_id, validation_service_ts_file_content) # Check that the html template includes js script for the # interaction. self.assertTrue('oppia-interactive-%s.component.ts' % hyphenated_interaction_id in ts_file_content or ('oppia-interactive-%s.directive.ts' % hyphenated_interaction_id in ts_file_content)) self.assertTrue('oppia-response-%s.component.ts' % hyphenated_interaction_id in ts_file_content or ('oppia-response-%s.directive.ts' % hyphenated_interaction_id in ts_file_content)) self.assertTrue('oppia-short-response-%s.component.ts' % hyphenated_interaction_id in ts_file_content or ('oppia-short-response-%s.directive.ts' % hyphenated_interaction_id in ts_file_content)) self.assertIn('%s-rules.service.ts' % hyphenated_interaction_id, ts_file_content) self.assertIn( '%s-validation.service.ts' % hyphenated_interaction_id, ts_file_content) self.assertNotIn('<script>', interaction_ts_file_content) self.assertNotIn('</script>', interaction_ts_file_content) self.assertNotIn('<script>', response_ts_file_content) self.assertNotIn('</script>', response_ts_file_content) self.assertNotIn('<script>', short_response_ts_file_content) self.assertNotIn('</script>', short_response_ts_file_content) self.assertNotIn('<script>', rules_service_ts_file_content) self.assertNotIn('</script>', rules_service_ts_file_content) self.assertNotIn('<script>', validation_service_ts_file_content) self.assertNotIn('</script>', validation_service_ts_file_content) interaction = interaction_registry.Registry.get_interaction_by_id( interaction_id) # Check that the specified interaction id is the same as the class # name. self.assertTrue(interaction_id, msg=interaction.__class__.__name__) # Check that the configuration file contains the correct # top-level keys, and that these keys have the correct types. for item, item_type in _INTERACTION_CONFIG_SCHEMA: self.assertIsInstance(getattr(interaction, item), item_type) if item_type == str: self.assertTrue(getattr(interaction, item)) self.assertIn(interaction.display_mode, base.ALLOWED_DISPLAY_MODES) if interaction.is_linear or interaction.is_terminal: self.assertIsNone(interaction.answer_type) else: # Check that the answer_type corresponds to a valid object # class. object_registry.Registry.get_object_class_by_type( interaction.answer_type) self._validate_customization_arg_specs( interaction.customization_arg_specs) answer_visualization_specs = ( interaction.answer_visualization_specs) self._validate_answer_visualization_specs( answer_visualization_specs) answer_visualizations = interaction.answer_visualizations for ind, visualization in enumerate(answer_visualizations): self.assertEqual(visualization.id, answer_visualization_specs[ind]['id']) self.assertEqual( visualization.calculation_id, answer_visualization_specs[ind]['calculation_id']) self.assertEqual(visualization.options, answer_visualization_specs[ind]['options']) # Check that the derived visualization is valid. visualization.validate() # Check that supplemental interactions have instructions, and # inline ones do not. if interaction.display_mode == base.DISPLAY_MODE_INLINE: self.assertIsNone(interaction.instructions) self.assertIsNone(interaction.narrow_instructions) else: self.assertIsInstance(interaction.instructions, str) self.assertIsNotNone(interaction.instructions) self.assertIsNotNone(interaction.narrow_instructions) # Check that terminal interactions are not linear. if interaction.is_terminal: self.assertFalse(interaction.is_linear) # Check that only linear interactions have a # default_outcome_heading property. if interaction.is_linear: self.assertTrue( isinstance(interaction.default_outcome_heading, str) and interaction.default_outcome_heading) else: self.assertIsNone(interaction.default_outcome_heading) # Check that interactions that can have solution cannot be linear. if interaction.can_have_solution: self.assertFalse(interaction.is_linear) default_object_values = object_registry.get_default_object_values() # Check that the rules for this interaction have object editor # templates and default values. for rule_name in list(interaction.rules_dict.keys()): param_list = interaction.get_rule_param_list(rule_name) for (_, param_obj_cls) in param_list: # TODO(sll): Get rid of these special cases. if param_obj_cls.__name__ in [ 'NonnegativeInt', 'ListOfCodeEvaluation', 'ListOfCoordTwoDim', 'ListOfGraph', 'SetOfNormalizedString' ]: continue # Check that the rule has a default value. self.assertIn(param_obj_cls.__name__, default_object_values)
def get_default_object_values(): """Returns a dictionary containing the default object values.""" # TODO(wxy): Cache this as it is accessed many times. return json.loads( utils.get_file_contents(feconf.OBJECT_DEFAULT_VALUES_FILE_PATH))
def test_html_field_types_to_rule_specs_mapping_are_valid(self): """Test that the structure of the file html_field_types_to_rule_specs. json are valid. This test ensures that whenever any new type of interaction or rule type with HTML string is added, the file html_field_types_to_rule_specs.json should be updated accordingly. """ # The file having the information about the assembly of the html in the # rule specs. html_field_types_to_rule_specs_dict = json.loads( utils.get_file_contents( feconf.HTML_FIELD_TYPES_TO_RULE_SPECS_FILE_PATH)) # The file having the templates for the structure of the rule specs. # Contents of the file html_field_types_to_rule_specs.json will be # verified against this file. rule_descriptions_dict = json.loads( utils.get_file_contents(feconf.RULES_DESCRIPTIONS_FILE_PATH)) # In the following part, we generate the html_field_types_to_rule_specs # dict based on the values in the rule_descriptions.json file. generated_html_field_types_dict = (collections.defaultdict( lambda: collections.defaultdict(lambda: collections.defaultdict( lambda: collections.defaultdict(lambda: collections. defaultdict(set)))))) # Verify that each html_type dict has a format key, which must be # unique. After verification we delete the key for comparison with # the generated html_field_types_to_rule_specs dict. We compare # everything except the format, because the format can't be generated # from the rule_descriptions.json file. for html_type, html_type_dict in ( html_field_types_to_rule_specs_dict.items()): self.assertTrue('format' in html_type_dict) self.assertTrue(html_type_dict['format'] in feconf.ALLOWED_HTML_RULE_VARIABLE_FORMATS) del html_type_dict['format'] for interaction_id, interaction_rules in ( rule_descriptions_dict.items()): for rule_type, rule_description in interaction_rules.items(): description = rule_description['description'] # Extract the input variables and html_types from the rule # description. input_variables_with_html_type = (re.findall( r'{{([a-z])\|([^}]*)}', description)) input_variables = set() input_variables_to_html_type_mapping_dict = ( collections.defaultdict(set)) for value in input_variables_with_html_type: if 'Html' in value[1] and 'HtmlContentId' not in value[1]: input_variables_to_html_type_mapping_dict[ value[1]].add(value[0]) # We need to iterate through the html_types for each rule_type, # because only after visiting each rule_type the inner dict # structure for each html_type gets generated. for html_type, input_variables in ( input_variables_to_html_type_mapping_dict.items()): html_type_dict = ( generated_html_field_types_dict[html_type]) # TODO(#9588): This generation (and the format of the # html_field_types_dict) assumes that there is at most one # interaction ID that uses a given HTML object type. If this # changes in the future, the structure of the dict needs to # be amended so that the each HTML object type can # accommodate more than one interaction. Corresponding # checks in state_domain.AnswerGroup # get_all_html_content_strings() also needs to be updated. if isinstance(html_type_dict['interactionId'], python_utils.BASESTRING): # The above type check is required because, # all the keys in the generated html type # dict is initialized as defaultdict object. # Below, we raise an exception if the existing # interaction ID is overwritten by another # interaction ID. if (html_type_dict['interactionId'] != interaction_id): raise Exception( 'Each html type should refer to only' ' one interaction_id.') html_type_dict['interactionId'] = interaction_id html_type_dict['ruleTypes'][rule_type][ 'htmlInputVariables'] = sorted(input_variables) self.assertEqual(html_field_types_to_rule_specs_dict, dict(generated_html_field_types_dict))
def edit_page(): if request.method == 'GET': clear_temp_static(True) path = request.args.get('path', None) folder_path = path.split('/')[-1] if path: get_repo = initialize() if get_repo[0]: init = get_repo[1] repo = init.get('repo') file_contents = get_contents(repo, path) for file in file_contents: if not allowed_file(file.path): # text = decode_content(file.content, True) text = file.decoded_content display_content = get_file_contents(text) file_meta = get_article_data(display_content[0]) add_image_desc = re.sub('!\[\]\(.', '![](temp/{}'.format(folder_path), display_content[1]) # TODO: fix it in proper way (workround found to remove the extra spaces) remove_extra_lines = add_image_desc.replace('\r\n\r\n \r\n\r\n', '\r\n') \ .replace('\r\n\r\n', '\r\n').replace('\r\n', '\n') markdown = md2.markdown(add_image_desc, extras=['fenced-code-blocks']) fix_front_quotes = re.sub('<blockquote>\n', '<blockquote>', markdown) fixed_quotes = re.sub('\n</blockquote>\n', '</blockquote>', fix_front_quotes) # breakpoint() description = re.sub('\n', '<br/>', \ fixed_quotes \ .replace('\n\n', '\n').replace('</li>\n', '</li>') \ .replace('\n<li>', '<li>').replace('<p><em>', '<em>') \ .replace('</em></p>', '</em>').replace('\n \n', '') ) # breakpoint() else: file_path = os.path.join(UPLOAD_FOLDER + '/{}'.format(folder_path), file.name) os.makedirs(os.path.dirname(file_path), exist_ok=True) # file_path = os.path.join(UPLOAD_FOLDER, file.name) with open(file_path, 'wb') as f: f.write(decode_content(file.content)) form = CreateForm(data=file_meta) return render_template('edit.html', form=form, description=description, path=path) else: return redirect(url_for('core.' + get_repo[1])) else: return render_template('edit.html', content=None) if request.method == 'POST': # breakpoint() get_repo = initialize() if get_repo[0]: init = get_repo[1] repo = init.get('repo') tree = init.get('tree') branch = init.get('branch') master_ref = init.get('master_ref') form = request.form path = form.get('path') title_text = form.get('title') category_text = form.get('category') folder_text = form.get('folder') created_date = form.get('date') file_path = path.split('/')[-1] # get file content description = form.get('description') is_draft = form.get('draft') # find image current_image = re.findall('temp/.*?\.[jpg|jpeg|png|gif]+', description) previous_image = new_images = remove_images = [] if current_image: try: previous_image = os.listdir(UPLOAD_FOLDER + '/' + file_path) except: previous_image = [] # go thorugh all the image take the list of added and removed images new_images = [image.split('/')[-1] for image in current_image if image.split('/')[-1] not in previous_image] remove_images = [image for image in previous_image if 'temp/' + file_path + '/' + image not in current_image] # get content current folder content_folder = get_content_type(path) updated_image = re.sub('\(/temp|temp/[a-z0-9\-]+', '(.', description) # recheck the image added to temp folder updated_desc = re.sub('\(\(./', '(./', updated_image) # update the file current_time = datetime.now().strftime("%d-%b-%Y") title = 'title: ' + title_text + '\n' category = 'category: ' + category_text + '\n' author = 'author: ' + 'arunkumar' + '\n' date = 'date: ' + '{}'.format(created_date) + '\n' updated = 'updated: ' + '{}'.format(current_time) + '\n' folder = 'folder: ' + folder_text + '\n' file_meta = '---\n' + title + category + author + date + updated + folder + '---\n' content = file_meta + updated_desc commit_message = 'Updated {} at {}'.format(file_path, current_time) file = repo.get_contents('{}/index.md'.format(path)) """ find the content folder location and check for saving type(draft or post) if draft i) content_folder is draft leave to the flow ii) contet_folder is post: update the folder meta_data for content and create new draft content if post i) content_folder is post leave the flow ii) content_folder is draft: check file_meta_data folder folder is empty --> create new content folder is not empty --> update the path leave the flow """ if is_draft and content_folder == 'drafts' or not is_draft and content_folder == 'posts': # leave the flow if current_image: github_remove_images(remove_images, path, repo) github_upload_images(new_images, UPLOAD_FOLDER, path, repo, tree, branch, master_ref) elif is_draft and content_folder == 'posts': # Update the folder path and create new draft content content = re.sub('folder:', 'folder:{}'.format(path), content) # create element tree blob = create_git_blob(repo, content, 'utf-8|base64') draft_folder = get_post_folder(draft) git_dir = file_path git_path = draft_folder + git_dir index_element = create_input_git_tree(git_path + '/index.md', '100644', 'blob', blob.sha) element_tree = [index_element] # create git tree git_tree = create_git_tree(repo, element_tree, tree) # create git commit parent = repo.get_git_commit(branch.commit.sha) git_commit = create_git_commit(repo, 'new draft post added in {}'.format(git_dir), git_tree, parent) # update the head commit update_commit(master_ref, git_commit.sha) github_upload_images(new_images, UPLOAD_FOLDER, git_path) # upload current image github_upload_images(previous_image, UPLOAD_FOLDER + '/' + file_path, git_path) return redirect('/drafts') elif not is_draft and not folder_text: # create new post content blob = create_git_blob(repo, content, 'utf-8|base64') posts_folder = get_post_folder(is_draft) git_dir = file_path git_path = posts_folder + git_dir index_element = create_input_git_tree(git_path + '/index.md', '100644', 'blob', blob.sha) element_tree = [index_element] # create git tree git_tree = create_git_tree(repo, element_tree, tree) # create git commit parent = repo.get_git_commit(branch.commit.sha) git_commit = create_git_commit(repo, 'new draft post added in {}'.format(git_dir), git_tree, parent) # update the head commit update_commit(master_ref, git_commit.sha) github_upload_images(new_images, UPLOAD_FOLDER, path) github_upload_images(previous_image, UPLOAD_FOLDER + '/' + file_path, git_path) return redirect(root_url) elif not is_draft and folder_text: # leave the flow and update the path path = folder_text file = repo.get_contents('{}/index.md'.format(path)) # update the folder text to empty content = re.sub('folder: [a-z]+/[a-z]+/[a-zA-z0-9\-]+', 'folder:', content) github_remove_images(remove_images, path, repo) github_upload_images(new_images, UPLOAD_FOLDER, path) update_file(repo, path + '/index.md', commit_message, content, file.sha) clear_temp_static(True) # TODO exception handling and send the form again with data return redirect(root_url) else: return redirect(url_for('core.' + get_repo[1]))