Example #1
0
    def __import_search_state(self):
        """
        Import the search terms that were used on previous page loads.
        Some of these terms may be prefixed with a #, which makes them either
        cardtypes or channel names.

        Output is either strings of search/filter terms, or None
        """
        self.search = BaseState._find_state_variable(self, 'xs')
        # TODO: Must check each application's search state before turning on shuffle mode.
        # Python's recommended way to see if a string is empty or null is using the not operator.
        # This doesn't differentiate between None and an empty string '' though.
        if not self.search and isinstance(self.search, str):
            self.reshuffle = True
        else:
            self.reshuffle = False

        # First, check if any of the search terms should be processed as a
        # cardtype and be added to the filter state instead.
        if self.search is not None:
            searchterms = self.search.split(' ')
            searchterms = list(filter(None, searchterms))  # remove nulls
            [newfilters, removeterms
             ] = BaseState._process_search_strings(self, '#', searchterms)
            # Remove filter strings from the search state list if they exist
            [searchterms.remove(term) for term in removeterms]
            self.search = searchterms
            # Take off leading #-sigil for card type searches
            self.card_filter = list(map(lambda x: x[1:], newfilters))
            for ctype in self.card_filter:
                getattr(self, ctype).filtertype = True
            if self.card_filter == []:
                self.card_filter = None
Example #2
0
    def __init__(self, in_state=None, env={}):
        BaseState.__init__(self, in_state, None)
        self.config = GlobalConfig
        self.headers = []

        # Getting defaults from the other states requires us to first import
        # any random seed value. Then, we can finish setting the imported state
        self.__import_random_seed()
        self.__set_application_state_defaults()
        self.__import_state()
Example #3
0
    def __init__(self, in_state=None):
        # Open the config file, and set card type defaults per state variable
        BaseState.__init__(self, in_state, 'medusa.ini')
        # Process all state variables listed in medusa.ini
        self.__import_state()

        # Now that we've imported, shuffle any card types we want to shuffle
        for ctype in self.config.get("card_properties",
                                     "randomize").replace(" ", "").split(","):
            getattr(self, ctype).shuffle()
Example #4
0
    def __import_filtered_card_count(self):
        """
        Filtered card count, tracked when we have a query type and a filter count
        and cards on previous pages were omitted from being displayed. Tracking
        this allows you to fix the page count to represent reality better.

        Output must be an integer.
        """
        self.filtered = BaseState._find_state_variable(self, 'xx')
        if ((self.filtered is not None) and (self.search is not None)
                and (self.card_filter is not None)):
            self.filtered = BaseState._int_translate(self, self.filtered, 1, 0)
        else:
            self.filtered = 0
Example #5
0
    def __import_page_count_state(self):
        """
        For all subsequent "infinite-scroll AJAX" content after the initial page
        load, we track the current page number of content.

        Output must be an integer.
        """
        self.page = BaseState._find_state_variable(self, 'xp')

        # If page was read in as a special state variable, use that (for search results)
        if self.page is not None:
            self.page = BaseState._int_translate(self, self.page, 2, 0)
        else:
            self.page = 0
Example #6
0
    def export_state(self, cards, query_terms, filter_terms, filtered_count):
        """
        Once all cards are read, calculate a new state variable to
        embed in the more-contents page link.
        """
        # Start by calculating the distance from the next page for each
        # card type. This updates the state.ctype.distance values
        BaseState._calculate_last_distance(self, cards, common="news")

        # Finally, construct the state string for the next page
        export_parts = [
            self.__export_card_state(),
            self.__export_search_state(query_terms),
            self.__export_filter_state(filter_terms),
            self.__export_filtered_card_count(filtered_count)
        ]

        export_parts = filter(None, export_parts)
        export_string = ':'.join(export_parts)
        return export_string
Example #7
0
    def __import_filter_state(self):
        """
        This must run after the import_search_state!

        If no filter strings were found during search, we may need to process a set
        of filter strings that were excised out on a previous page load.
        """
        if self.card_filter is None:
            self.card_filter = BaseState._find_state_variable(self, 'xo')

            if self.card_filter is not None:
                filterterms = self.card_filter.split(' ')
                # Add-filter-cardtypes expects strings that start with #
                hashtag_process = map(lambda x: "#" + x, filterterms)
                [newfilters, removeterms
                 ] = BaseState._process_search_strings(self, '#',
                                                       hashtag_process)
                # Take off leading #-sigil for card type searches
                self.card_filter = map(lambda x: x[1:], newfilters)
                # Record filters being set
                for ctype in self.card_filter:
                    getattr(self, ctype).filtertype = True
                if self.card_filter == []:
                    self.card_filter = None
Example #8
0
    def __import_theme_state(self):
        """
        In the top-level state object, we track an appearance variable, which
        corresponds to the exact state variable imported (and exported) for the
        appearance of the entire Constantina site.

        The appearance value lets us look up which theme we display for the user.
        This theme value is a path fragment to a theme's images and stylesheets.
        """
        # Look for appearance state in the QUERY_PARAMS
        appearance_state = BaseState._find_state_variable(self, 'xa')

        if appearance_state is not None:
            # Read in single char of theme state value
            self.appearance = BaseState._int_translate(self, appearance_state,
                                                       1, 0)

        # If the configuration supports a random theme, and we didn't have a
        # theme provided in the initial state, let's choose one randomly
        seed()  # Enable non-seeded choice
        GlobalTheme.set(self.appearance)
        if self.seed:  # Re-enable seeded nonrandom choice
            seed(self.seed)
        self.theme = GlobalTheme.theme
Example #9
0
    def __import_random_seed(self):
        """
        Set the return seed based on a 14-digit string from the state variable.
        As an input to seed(), this has to be a float between zero and one.

        This seed is used to consistently seed the shuffle function, so that
        between page loads, we know the shuffled card functions give the same
        shuffle ordering.
        """
        self.seed = BaseState._find_state_variable(self, "seed")
        if self.seed is None:
            self.seed = round(random(), 14)
        else:
            self.seed = float(str("0." + self.seed))
        seed(self.seed)  # Now the RNG is seeded with our consistent value
Example #10
0
    def __import_permalink_state(self):
        """
        Any card type that can be displayed on its own is a permalink-type
        card, and will have state that describes which permalink page should
        be loaded.

        Output is either string (filename, as utime), or None.
        """
        permalink_states = [
            sv[0] for sv in self.config.items("special_states")
            if sv[1].find("permalink") != -1
        ]
        for state in permalink_states:
            value = BaseState._find_state_variable(self, state)
            if value != None:
                attrib = self.config.get("special_states", state)
                setattr(self, attrib, value)
                return  # Only one permalink state per page. First one takes precedence
Example #11
0
    def __import_card_state(self):
        """
        News cards and other content cards' state is tracked here. Seed tracking
        between page loads means we don't need to log which content cards were
        shown on a previous page.

        However, to preserve card spacing rules, we do need to track the distance
        of each card type from the first element of the current page.

        Output is an integer or None.
        """
        # For each content card type, populate the state variables
        # as necessary.
        for state_var in [s[0] for s in self.config.options('card_counts')]:
            # NOTE: This ctype attribute naming requires each content card type to
            # begin with a unique alphanumeric character.
            ctype = [
                value for value in self.config.options("card_counts")
                if value[0] == state_var
            ][0]
            distance = BaseState._find_state_variable(self, state_var)
            getattr(self, ctype).distance = distance