Ejemplo n.º 1
0
def test_source():
    source = Source("foo", "bar")
    assert source.nick == "foo"
    assert source.url == "bar"

    with pytest.raises(TypeError):
        Source()
Ejemplo n.º 2
0
Archivo: cli.py Proyecto: chkry/twtxt
def timeline(ctx, pager, limit, twtfile, sorting, timeout, porcelain, source,
             cache):
    """Retrieve your personal timeline."""
    if source:
        source_obj = ctx.obj["conf"].get_source_by_nick(source)
        if not source_obj:
            logger.debug("Not following {0}, trying as URL".format(source))
            source_obj = Source(source, source)
        sources = [source_obj]
    else:
        sources = ctx.obj["conf"].following

    tweets = get_remote_tweets(sources, limit, timeout, cache)

    if twtfile and not source:
        source = Source(ctx.obj["conf"].nick,
                        ctx.obj["conf"].twturl,
                        file=twtfile)
        tweets.extend(get_local_tweets(source, limit))

    tweets = sort_and_truncate_tweets(tweets, sorting, limit)

    if not tweets:
        return

    if pager:
        click.echo_via_pager(style_timeline(tweets, porcelain))
    else:
        click.echo(style_timeline(tweets, porcelain))
Ejemplo n.º 3
0
def timeline(ctx, pager, limit, twtfile, sorting, timeout, porcelain, source,
             cache, force_update):
    """Retrieve your personal timeline."""
    if source:
        source_obj = ctx.obj["conf"].get_source_by_nick(source)
        if not source_obj:
            logger.debug("Not following {0}, trying as URL".format(source))
            source_obj = Source(source, source)
        sources = [source_obj]
    else:
        sources = ctx.obj["conf"].following

    tweets = []

    if cache:
        try:
            with Cache.discover(update_interval=ctx.obj["conf"].
                                timeline_update_interval) as cache:
                force_update = force_update or not cache.is_valid
                if force_update:
                    tweets = get_remote_tweets(sources, limit, timeout, cache)
                else:
                    logger.debug(
                        "Multiple calls to 'timeline' within {0} seconds. Skipping update"
                        .format(cache.update_interval))
                    # Behold, almighty list comprehensions! (I might have gone overboard here…)
                    tweets = list(
                        chain.from_iterable([
                            cache.get_tweets(source.url) for source in sources
                        ]))
        except OSError as e:
            logger.debug(e)
            tweets = get_remote_tweets(sources, limit, timeout)
    else:
        tweets = get_remote_tweets(sources, limit, timeout)

    if twtfile and not source:
        source = Source(ctx.obj["conf"].nick,
                        ctx.obj["conf"].twturl,
                        file=twtfile)
        tweets.extend(get_local_tweets(source, limit))

    if not tweets:
        return

    tweets = sort_and_truncate_tweets(tweets, sorting, limit)

    if pager:
        click.echo_via_pager(style_timeline(tweets, porcelain))
    else:
        click.echo(style_timeline(tweets, porcelain))
Ejemplo n.º 4
0
    def get_source_by_nick(self, nick):
        """Returns the :class:`Source` of the given nick.

        :param str nick: nickname for which will be searched in the config
        """
        url = self.cfg.get("following", nick, fallback=None)
        return Source(nick, url) if url else None
Ejemplo n.º 5
0
def test_tweet_ordering():
    now = datetime.now(timezone.utc)
    tweet_1 = Tweet("A", now)
    tweet_2 = Tweet("B", now + timedelta(hours=1))
    tweet_3 = Tweet("C", now + timedelta(hours=2))
    tweet_4 = Tweet("D", now + timedelta(hours=2))
    tweet_5 = Tweet("D", now + timedelta(hours=2))

    source = Source("foo", "bar")

    # explicit testing
    with pytest.raises(TypeError):
        tweet_1 < source

    with pytest.raises(TypeError):
        tweet_1 <= source

    with pytest.raises(TypeError):
        tweet_1 > source

    with pytest.raises(TypeError):
        tweet_1 >= source

    assert tweet_1 != source

    assert tweet_1 < tweet_2
    assert tweet_1 <= tweet_2
    assert tweet_2 > tweet_1
    assert tweet_2 >= tweet_1
    assert tweet_3 != tweet_4
    assert tweet_5 == tweet_4
    assert tweet_5 >= tweet_4
    assert tweet_5 <= tweet_4
    assert not (tweet_3 <= tweet_4)
    assert not (tweet_3 >= tweet_4)
Ejemplo n.º 6
0
def test_parse_tweets():
    """Test parsing multiple tweet lines"""
    source = Source("foo", "bar")
    raw_tweets = [
        "2016-02-08T00:00:00\tHallo",
        "2016-02-08T00:00:00\tBar\n",
        "2016-02-08T00:00:00\tFoo\n",
        "3000-02-08T00:00:00\tHallo\n",
    ]
    tweets = parse_tweets(raw_tweets, source)
    assert len(tweets) == 3
Ejemplo n.º 7
0
    def following(self):
        """Returns a list of all source objects."""
        following = []
        try:
            for (nick, url) in self.cfg.items("following"):
                source = Source(nick, url)
                following.append(source)
        except configparser.NoSectionError as e:
            logger.debug(e)

        return following
Ejemplo n.º 8
0
def test_parse_tweet():
    """Test parsing single tweet line."""
    source = Source("foo", "bar")
    raw_line = "2016-02-08T00:00:00\tHallo"
    tweet = parse_tweet(raw_line, source)
    assert tweet.text == "Hallo"
    assert tweet.created_at == datetime(year=2016, month=2, day=8, tzinfo=timezone.utc)

    with pytest.raises(ValueError) as e:
        raw_line = "3000-02-08T00:00:00\tHallo"
        parse_tweet(raw_line, source)
    assert "Tweet is from the future" in str(e.value)
Ejemplo n.º 9
0
def follow(ctx, nick, url):
    """Add a new source to your followings."""
    source = Source(nick, url)
    sources = ctx.obj['conf'].following

    if source.nick in (source.nick for source in sources):
        click.confirm("➤ You’re already following {}. Overwrite?".format(
            click.style(source.nick, bold=True)),
                      default=False,
                      abort=True)
    ctx.obj['conf'].add_source(source)
    click.echo("✓ You’re now following {}.".format(
        click.style(source.nick, bold=True)))
Ejemplo n.º 10
0
def test_add_get_remove_source():
    conf = Config.discover()
    conf.cfg.remove_section("following")

    assert conf.remove_source_by_nick("foo") is False
    assert conf.get_source_by_nick("baz") is None

    conf.add_source(Source("foo", "bar"))
    source = conf.get_source_by_nick("foo")
    assert source.nick == "foo"
    assert source.url == "bar"

    assert conf.remove_source_by_nick("baz") is False
    assert conf.remove_source_by_nick("foo") is True
    assert conf.following == []
Ejemplo n.º 11
0
def test_tweet_init():
    with pytest.raises(ValueError) as e:
        Tweet("")
    assert "empty text" in str(e.value)

    with pytest.raises(TypeError) as e:
        Tweet("foobar", 0)
    assert "created_at is of invalid type" in str(e.value)

    source = Source("foo", "bar")
    created_at = datetime.now(timezone.utc)
    tweet = Tweet("foobar", created_at, source)
    assert tweet.text == "foobar"
    assert tweet.created_at == created_at.replace(microsecond=0)
    assert tweet.source == source
Ejemplo n.º 12
0
def follow(ctx, nick, url, force):
    """Add a new source to your followings."""
    source = Source(nick, url)
    sources = ctx.obj['conf'].following

    if not force:
        if source.nick in (source.nick for source in sources):
            click.confirm("➤ You’re already following {0}. Overwrite?".format(
                click.style(source.nick, bold=True)), default=False, abort=True)

        _, status = get_remote_status([source])[0]
        if status != 200:
            click.confirm("➤ The feed of {0} at {1} is not available. Follow anyway?".format(
                click.style(source.nick, bold=True),
                click.style(source.url, bold=True)), default=False, abort=True)

    ctx.obj['conf'].add_source(source)
    click.echo("✓ You’re now following {0}.".format(
        click.style(source.nick, bold=True)))
Ejemplo n.º 13
0
 def get_source_by_nick(self, nick):
     """Returns the source of the given nick."""
     url = self.cfg.get("following", nick, fallback=None)
     return Source(nick, url) if url else None
Ejemplo n.º 14
0
 def source(self):
     return Source(self.nick, self.twturl)