Пример #1
0
    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))
Пример #2
0
 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
Пример #3
0
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)
Пример #4
0
 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
Пример #6
0
    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__))
Пример #7
0
    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
Пример #8
0
    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
Пример #9
0
    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]
Пример #10
0
    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'])
Пример #11
0
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]))
Пример #12
0
    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)
Пример #13
0
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))
Пример #14
0
    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))
Пример #15
0
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]))