Ejemplo n.º 1
0
 def __init__(self, body, tags, title='', isStatus=True, visible=False):
     self.published = datetime.utcnow()
     self.title = title
     self.body = body
     self.tags = tags
     if self.title:
         self.slug = slugify(self.published, title)
     else:
         self.slug = slugify(self.published, body[:15])
     self.isStatus = isStatus
     self.visible = visible
Ejemplo n.º 2
0
def test_create_article(client: FlaskClient, user_client: FlaskClient,
                        stuff_client: FlaskClient, app: Flask, title: str,
                        abstract: str, content: str, status_code: int) -> None:
    url = "/articles"
    data = {
        "title": title,
        "abstract": abstract,
        "content": content,
    }

    res = client.post(url, json=data)
    assert res.status_code == 401
    res = user_client.post(url, json=data)
    assert res.status_code == 403
    res = stuff_client.post(url, json=data)
    assert res.status_code == status_code

    if status_code == 400:
        return

    res = stuff_client.post(url, json=data)
    assert res.status_code == 400

    with app.app_context():
        article = Article.query.filter_by(title=title).first()
    assert article
    assert article.slug == slugify(article.title)
    assert article.abstract == abstract
    assert article.content == content
    assert article.author
Ejemplo n.º 3
0
def validate_title(title):
    if len(title) < 1:
        message = (
            'Title is too short, needs to be at least 1 character long.'
        )
        raise InvalidUsage(message)

    # two or more posts can not exist on the same date with the same title
    # because of the slug
    slug = slugify(datetime.utcnow(), title)
    if Post.query.filter_by(slug=slug).first():
        message = 'Title already exist on this date.'
        raise InvalidUsage(message, 409)
Ejemplo n.º 4
0
def test_update_article_detail(client: FlaskClient, user_client: FlaskClient,
                               stuff_client: FlaskClient, app: Flask,
                               data: dict) -> None:
    url = "/articles/{}"
    article = create_article(app)
    res = client.put(url.format(article.slug), json=data)
    assert res.status_code == 401
    res = user_client.put(url.format(article.slug), json=data)
    assert res.status_code == 403
    res = stuff_client.put(url.format(article.slug), json=data)
    assert res.status_code == 200

    with app.app_context():
        article = Article.query.filter_by(title=data.get("title")).first()

    update_fields = ["title", "abstract", "content"]
    for field in update_fields:
        if field in data:
            assert getattr(article, field) == data.get(field)
            assert article.slug == slugify(article.title)
Ejemplo n.º 5
0
def test_update_category_detail(client: FlaskClient, user_client: FlaskClient,
                                stuff_client: FlaskClient, app: Flask,
                                data: dict) -> None:
    url = "/categories/{}"
    category = create_category(app)
    res = client.put(url.format(category.slug), json=data)
    assert res.status_code == 401
    res = user_client.put(url.format(category.slug), json=data)
    assert res.status_code == 403
    res = stuff_client.put(url.format(category.slug), json=data)
    assert res.status_code == 200

    if not data.get("name"):
        return

    with app.app_context():
        category = Category.query.filter_by(name=data.get("name")).first()

    assert category.name == data.get("name")
    assert category.slug == slugify(category.name)
Ejemplo n.º 6
0
def test_create_category(client: FlaskClient, user_client: FlaskClient,
                         stuff_client: FlaskClient, app: Flask, name: str,
                         status_code: int) -> None:
    url = "/categories"
    data = {"name": name}

    res = client.post(url, json=data)
    assert res.status_code == 401
    res = user_client.post(url, json=data)
    assert res.status_code == 403
    res = stuff_client.post(url, json=data)
    assert res.status_code == status_code

    with app.app_context():
        category = Category.query.filter_by(name=name).first()

    if status_code == 400:
        return

    res = stuff_client.post(url, json=data)
    assert res.status_code == 400

    assert category
    assert category.slug == slugify(name)
Ejemplo n.º 7
0
 def save(self, *args, **kwargs):
     self.slug = slugify(self.name, instance=self)
     super(Subscription, self).save(*args, **kwargs)
def standings_helper(url, league, skip_conference_row=False):
    """
    Fetches and parses data.

    Supports layouts with multiple tables or with single tables. At the
    time of writing this, the MLB standings is split into 2 tables,
    while the NHL is 1.

    :param league: The league of the desired scoreboard
    :type league: str

    :returns: A formatted dictionary ready for display
    :rtype: dict
    """

    rv = fetch_cached_data()
    if rv is not None:
        return rv

    soup = help_fetch_soup(url)

    column_list = []
    row_list = []
    stack = {}

    # Iterate over each conference/league
    for table in soup("table"):
        conference = None
        division = None

        # Iterate over each division
        for row in table("tr"):

            if row.get("class") is None:
                continue

            elif "shsTableTtlRow" in row.get("class"):
                if skip_conference_row:
                    continue

                # Single table layout support.
                # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                # If the string conference evaluates to true, then we've
                # encountered a new conference. Save the data that
                # exists in the lists column_list and row_list
                if conference:

                    # Does the list colum_stack have any data?
                    if column_list:
                        # Is this layout split into divisions?
                        if division:
                            row_list.append( { division : column_list } )
                        else:
                            row_list = column_list

                        column_list = []

                    stack[conference] = row_list
                    row_list = []

                conference = row.extract().text.strip().lower().encode("utf-8")
                conference = slugify(text=unicode(conference, "utf-8"), delimiter=u'_')

            elif "shsTableSubttlRow" in row.get("class"):
                # If the string division evaluates to true, then we've
                # encountered a new division. Save the data that
                # exists in the lists column_list and row_list
                if division:
                    # Does the list colum_stack have any data?
                    if column_list:
                        # Is this layout split into divisions?
                        if division:
                            row_list.append( { division : column_list } )
                        else:
                            row_list.append(column_list)

                        column_list = []

                division = row.extract().text.strip().lower().encode("utf-8")
                division = division.replace("division", '')
                division = slugify(text=unicode(division, "utf-8"), delimiter=u'_')

            elif any(css_class.startswith("shsRow") for css_class in row.get("class")):
                cells = row("td")
                value_dict = None

                if "mlb" == league:
                    value_dict = help_parse_mlb_soup(cells)

                elif "nhl" == league:
                    value_dict = help_parse_nhl_soup(cells)

                elif "nfl" == league:
                    value_dict = help_parse_nfl_soup(cells)

                elif "nba" == league:
                    value_dict = help_parse_nba_soup(cells)

                elif "mls" == league:
                    value_dict = help_parse_mls_soup(cells)

                elif "epl" == league:
                    value_dict = help_parse_epl_soup(cells)

                if value_dict is not None:
                    column_list.append(value_dict)

        #end for row in table("tr")

        # Get the last division in the table
        if division:
            row_list.append( { division : column_list } )

        # If there is no division, then make the columns close to the
        # conference
        else:
            row_list = column_list

        column_list = []

        # We must evaluate conference because EPL and MLS do not have
        # conferences
        if conference:
            stack[conference] = row_list

        # If a conference is nonexistent, then check for division's
        # existence. If a division exists, then treat as if it was a
        # conference (i.e. place the division at the highest level).
        # Currently, this only occurs with MLS.
        elif division:
            if row_list[0][division]:
                stack[division] = row_list[0][division]

        # Otherwise, both conference and division are nonexistent.
        # Convert stack into a list so the teams are ordered
        # accordingly.
        # Currently, this only occurs with EPL.
        else:
            # stack is a Dictionary, change it to a list
            del stack
            stack = row_list

        row_list = []

    #end for table in soup("table")
    out = prepare_json_output(stack)
    del row_list, stack

    # Cache for 2 hours
    cache_data(data=out, timeout=60 * 60 * 2)

    return out
Ejemplo n.º 9
0
def _slugify(string):
    if not string:
        return ''
    return utils.slugify(string)
Ejemplo n.º 10
0
def scores_helper(year=None, month=None, day=None, sport=None, league=None):
    """
    Generic helper function to scrape scoring data from STATS's
    JavaScript file.

    :param year: The year of the desired scoreboard
    :type year: int

    :param month: The month of the desired scoreboard
    :type month: int

    :param day: The day of the desired scoreboard
    :type day: int

    :param sport: The sport of the desired scoreboard
    :type sport: str

    :param league: The league of the desired scoreboard
    :type league: str

    :returns: A formatted dictionary ready for display
    :rtype: dict
    """
    try:
        date_string = stats_date_string(date(year, month, day))
    except (ValueError, TypeError):
        date_string = stats_date_string()

    rv = fetch_cached_data()
    if rv is not None:
        return rv

    args = {
        PARAM_SPORT : sport,
        PARAM_DATE : date_string,
        PARAM_LEAGUE : league
    }

    soup = help_fetch_soup(
        SCORES_URL,
        request_params=args,
        source_file_type="JavaScript",
        class_attrs="shsTable"
    )

    # If there is 1 or 0 rows in the document, then, there are probably
    # no scores listed.
    if len(soup("tr")) <= 2:
        # del soup

        # Cache for a day to be safe
        out = {"message" : "No games scheduled for "}

        if not month and not day and not year:
            out["message"] += "today"
        else:
            out["message"] += "{month}/{day}/{year}".format(month=month, day=day, year=year)

        cache_data(data=out, timeout=60 * 60 * 24)

        return out

    stack = {}
    vals = []
    section = ''
    team = None
    has_the_status_cell = False

    # logcat(str(soup))

    for row in soup("tr"):

        # Rows which have team names do not have .
        # This test must be first.
        if row.get("class") is None:
            cells = row("td")
            has_the_status_cell = False

            # Does this row have a status row?
            if any(css_class in "shsMiniStatus" for cell in cells for css_class in cell.get("class") ):
                has_the_status_cell = True

            if len(cells) >= 2:

                team = "home" if team is "away" or None else "away"

                # If the list of values is empty, then initialize it
                if not vals:
                    vals.append({"away": None, "home":None})

                # If the list is complete, then append a new item
                # indicating a new game.
                elif vals[-1]["away"] and vals[-1]["home"]:
                    vals.append({"away": None, "home":None})

                # Add scoring information for the game.
                vals[-1][team] = {
                    "team": cells[0].find('a').extract().text.strip().encode("utf-8"),
                    "score": cells[1].extract().text.strip().encode("utf-8")
                }

                try:
                    # Try to convert the string to an int.
                    vals[-1][team]["score"] = int(vals[-1][team]["score"])
                except (ValueError, TypeError):
                    # If it fails, assign null
                    vals[-1][team]["score"] = None

                if has_the_status_cell:
                    status = cells[2].find('a')

                    # Arbitrary game information, such as "OT" for
                    # overtime
                    extra = cells[2].find('br')

                    time = cells[2].find(name="span", attrs={"class" : "shsTimezone shsGMTZone"})

                    # Set the status only if not null
                    if status:
                        vals[-1]["status"] = status.extract().text.strip().encode("utf-8")
                        if 2 == len(vals[-1]["status"].split('-')):
                            # Save the string to the right of '-' in
                            # extra
                            if not extra:
                                extra = vals[-1]["status"].split('-')[1].strip()
                            vals[-1]["status"] = vals[-1]["status"].split('-')[0].strip()

                        vals[-1]["status"] = vals[-1]["status"].lower()

                    if time:
                        vals[-1]["time"] = time.extract().text.strip().encode("utf-8")

                    if extra:
                        # Sometimes, extra contains a NavigableString
                        try:
                            vals[-1]["extra"] = extra.extract().text.strip().encode("utf-8")

                        # While other times, it's just a str
                        except:
                            vals[-1]["extra"] = extra

                        vals[-1]["extra"] = vals[-1]["extra"].lower()

        # Skip over the first line, it's the title
        elif "shsTableTtlRow" in row.get("class"):
            continue

        elif any(css_class in "shsTableSubttlRow shsSubSectionRow shsMiniRowSpacer" for css_class in row.get("class")):
            cell = row("td")
            section = cell[0].extract().text.strip().encode("utf-8")

            # Are the scores separated into sections? If so, find the
            # separator
            if section:
                section = slugify(text=unicode(section, "utf-8"), delimiter=u'_')
                if vals:
                    stack[section] = vals
                    vals = []
                # return section
                stack[section] = None

    # Save the last value
    else:
        if section:
            stack[section] = vals
        else:
            stack = vals

    del vals

    out = prepare_json_output(stack)

    # Cache for 1 minute
    cache_data(data=out, timeout=60)

    return out
Ejemplo n.º 11
0
 def on_model_change(self, form, instance, is_created):
     instance.slug = utils.slugify(form.title.data)
     super(EventAdmin, self).on_model_change(form, instance, is_created)
Ejemplo n.º 12
0
def format_division(nav_str):
    division = nav_str.extract().text.strip().lower().encode("utf-8")
    division = sub(r"(conference|divisi?on|league|football)\s?", '', division)
    division = slugify(text=unicode(division, "utf-8"), delimiter=u'_')

    return division
Ejemplo n.º 13
0
def test_slugify():
    s = "test test test"
    assert " " not in slugify(s)
    s = "测试 测试 测试"
    assert " " not in slugify(s)
Ejemplo n.º 14
0
 def update_slug(self) -> None:
     self.slug = slugify(self.title)
Ejemplo n.º 15
0
 def update_slug(self) -> None:
     self.slug = slugify(self.name)