class TestCore: @classmethod @pytest.fixture(autouse=True) def setup_class(self, monkeypatch): self.acc_id = "dummy-twitter" self.core = Core(load_accounts=False) self.account = Account.new("twitter", "dummy") self.account.columns = [Column(self.account.id_, ColumnType.TIMELINE)] self.account2 = Account.new("twitter", "qux") self.account2.columns = [Column(self.account2.id_, ColumnType.TIMELINE)] self.all_accounts = [self.account, self.account2] monkeypatch.setattr(self.core.accman, "get", lambda x: self.account) def test_core_is_a_valid_instance(self): assert isinstance(self.core, Core) def test_local_variables(self): assert self.core.config != None assert isinstance(self.core.config, AppConfig) assert self.core.accman != None assert isinstance(self.core.accman, AccountManager) assert self.core.column_manager != None assert isinstance(self.core.column_manager, ColumnManager) def test_filter_statuses(self, monkeypatch): status = Status() status.id_ = "123" status.username = "******" status.repeated_by = "bar" status.text = "Please, filter me" statuses = [status] monkeypatch.setattr(self.core.config, "load_filters", lambda: []) response = self.core.filter_statuses(statuses) assert response == statuses monkeypatch.setattr(self.core.config, "load_filters", lambda: ['@foo']) response = self.core.filter_statuses(statuses) assert response == [] monkeypatch.setattr(self.core.config, "load_filters", lambda: ['@bar']) response = self.core.filter_statuses(statuses) assert response == [] monkeypatch.setattr(self.core.config, "load_filters", lambda: ['filter']) response = self.core.filter_statuses(statuses) assert response == [] monkeypatch.setattr(self.core.config, "load_filters", lambda: ['dummy']) response = self.core.filter_statuses(statuses) assert response == statuses def test_fetch_image(self, monkeypatch): monkeypatch.setattr(requests, 'get', lambda x: DummyResponse('binarydata')) assert self.core.fetch_image('http://my_image.png') == 'binarydata' def test_list_methods(self): accounts = self.core.list_accounts() assert isinstance(accounts, list) for item in accounts: assert isinstance(item, str) protocols = self.core.list_protocols() assert isinstance(protocols, list) for item in protocols: assert isinstance(item, str) filters = self.core.list_filters() assert isinstance(filters, list) for item in filters: assert isinstance(item, str) def test_registering(self, monkeypatch): dummy = Account('twitter') monkeypatch.setattr(self.core.accman, "register", lambda x: self.acc_id) monkeypatch.setattr(self.core.column_manager, "register", lambda x: "dummy-twitter-column1") result = self.core.register_account(dummy) assert isinstance(result, str) result = self.core.register_column("dummy-twitter-column1") assert isinstance(result, str) def test_unregistering(self, monkeypatch): monkeypatch.setattr(self.core.accman, "unregister", lambda x,y: self.acc_id) monkeypatch.setattr(self.core.column_manager, "unregister", lambda x: "dummy-twitter-column1") result = self.core.unregister_account(self.acc_id) assert isinstance(result, str) result = self.core.unregister_column("dummy-twitter-column1") assert isinstance(result, str) def test_all_columns(self, monkeypatch): monkeypatch.setattr(self.core, 'registered_accounts', lambda: self.all_accounts) columns = self.core.all_columns() assert isinstance(columns, dict) for key, value in columns.iteritems(): assert isinstance(value, list) for col in value: assert (isinstance(col, Column) or isinstance(col, List)) def test_available_columns(self, monkeypatch): monkeypatch.setattr(self.core, 'registered_accounts', lambda: self.all_accounts) columns = self.core.available_columns() assert isinstance(columns, dict) for key, value in columns.iteritems(): assert isinstance(value, list) for col in value: assert (isinstance(col, Column) or isinstance(col, List)) def test_registered_columns(self): columns = self.core.registered_columns() assert isinstance(columns, dict) for key, value in columns.iteritems(): assert isinstance(value, list) for col in value: assert (isinstance(col, Column) or isinstance(col, List)) def test_registered_columns_by_order(self): columns = self.core.registered_columns_by_order() assert isinstance(columns, list) for col in columns: assert (isinstance(col, Column) or isinstance(col, List)) def test_registered_accounts(self): accounts = self.core.registered_accounts() assert isinstance(accounts, list) for acc in accounts: assert isinstance(acc, Account) def test_get_single_column(self, monkeypatch): dummy = Column(self.acc_id, "foo") monkeypatch.setattr(self.core.column_manager, "get", lambda x: dummy) column = self.core.get_single_column("dummy-twitter-column") assert isinstance(column, Column) def test_get_single_account(self): account = self.core.get_single_account(self.acc_id) assert isinstance(account, Account) def test_get_column_statuses(self, monkeypatch): status = Status() result = [status] monkeypatch.setattr(self.account, "get_timeline", lambda x, y: result) response = self.core.get_column_statuses(self.acc_id, "timeline") assert response == result monkeypatch.setattr(self.account, "get_replies", lambda x, y: result) response = self.core.get_column_statuses(self.acc_id, "replies") assert response == result monkeypatch.setattr(self.account, "get_directs", lambda x, y: result) response = self.core.get_column_statuses(self.acc_id, "directs") assert response == result monkeypatch.setattr(self.account, "get_favorites", lambda x: result) response = self.core.get_column_statuses(self.acc_id, "favorites") assert response == result monkeypatch.setattr(self.account, "get_sent", lambda x, y: result) response = self.core.get_column_statuses(self.acc_id, "sent") assert response == result monkeypatch.setattr(self.account, "get_public_timeline", lambda x, y: result) response = self.core.get_column_statuses(self.acc_id, "public") assert response == result list_ = List() list_.id_ = "666" monkeypatch.setattr(self.account, "get_list_id", lambda x: list_) status.id_ = "127" monkeypatch.setattr(self.account, "get_list_statuses", lambda x, y, z: result) response = self.core.get_column_statuses(self.acc_id, "my-list") assert isinstance(response, list) assert response[0].id_, "127" monkeypatch.setattr(self.account, "get_list_id", lambda x: None) with pytest.raises(UserListNotFound): self.core.get_column_statuses(self.acc_id, "unknown-list") monkeypatch.setattr(self.core, 'search', lambda w, x, y, z: result) response = self.core.get_column_statuses(self.acc_id, "search-dummy") assert response == result def test_get_public_timeline(self, monkeypatch): status = Status() status.id_ = "123" result = [status] monkeypatch.setattr(self.account, "get_public_timeline", lambda x, y: result) response = self.core.get_public_timeline(self.acc_id) assert isinstance(response, list) assert response[0].id_, "123" def test_get_followers(self, monkeypatch): profile = Profile() profile.id_ = "dummy" result = [profile] monkeypatch.setattr(self.account, "get_followers", lambda x: result) response = self.core.get_followers(self.acc_id) assert isinstance(response, list) assert response[0].id_, "dummy" def test_get_following(self, monkeypatch): profile = Profile() profile.id_ = "dummy" result = [profile] monkeypatch.setattr(self.account, "get_following", lambda x: result) response = self.core.get_following(self.acc_id) assert isinstance(response, list) assert response[0].id_, "dummy" def test_get_all_friends_list(self, monkeypatch): account = Account.new("twitter") accounts = [account] profile = Profile() profile.username = "******" result = [profile] monkeypatch.setattr(self.core.accman, "accounts", lambda: accounts) monkeypatch.setattr(account, "get_following", lambda: result) friends = self.core.get_all_friends_list() assert isinstance(friends, list) assert friends[0], "dummy" def test_load_all_friends_list(self): result = self.core.load_all_friends_list() assert isinstance(result, list) for friend in result: assert isinstance(friend, str) def test_get_user_profile(self, monkeypatch): profile = Profile() self.account.profile = profile result = [profile] monkeypatch.setattr(self.account, "get_profile", lambda x: profile) monkeypatch.setattr(self.account, "is_friend", lambda x: True) monkeypatch.setattr(self.core, "is_muted", lambda x: False) profile.id_ = "dummy" response = self.core.get_user_profile(self.acc_id) assert isinstance(response, Profile) assert response.id_, "dummy" profile.id_ = "user" response = self.core.get_user_profile(self.acc_id, "user") assert isinstance(response, Profile) assert response.id_, "user" assert response.followed_by, True assert not response.muted, True def test_get_conversation(self, monkeypatch): status = Status() status.id_ = "321" conversation = [status] monkeypatch.setattr(self.account, "get_conversation", lambda x: conversation) response = self.core.get_conversation(self.acc_id, "123") assert isinstance(response, list) assert isinstance(response[0], Status) assert response[0].id_, "321" def test_update_status(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "update_status", lambda x, y, z: status) response = self.core.update_status(self.acc_id, "Dummy message") assert response == status response = self.core.update_status(self.acc_id, "Dummy message", "123456") assert response == status response = self.core.update_status(self.acc_id, "Dummy message", "123456", "/path/to/media") assert response == status def test_broadcast_status(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "update_status", lambda x: status) monkeypatch.setattr(self.core, "registered_accounts", lambda: [self.account]) response = self.core.broadcast_status(None, "Dummy message") assert isinstance(response, dict) assert isinstance(response["dummy-twitter"], Status) assert response["dummy-twitter"] == status response = self.core.broadcast_status(["foo-twitter", "bar-twitter"], "Dummy message") assert isinstance(response, dict) assert isinstance(response["foo-twitter"], Status) assert response["foo-twitter"] == status assert isinstance(response["bar-twitter"], Status) assert response["bar-twitter"] == status monkeypatch.setattr(self.core.accman, "get", lambda x: 'whatever') response = self.core.broadcast_status(["foo-twitter"], "Dummy message") assert isinstance(response["foo-twitter"], Exception) def test_destroy_status(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "destroy_status", lambda x: status) response = self.core.destroy_status("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_get_single_status(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "get_status", lambda x: status) response = self.core.get_single_status("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_repeat_status(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "repeat_status", lambda x: status) response = self.core.repeat_status("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_mark_status_as_favorite(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "mark_as_favorite", lambda x: status) response = self.core.mark_status_as_favorite("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_unmark_status_as_favorite(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "unmark_as_favorite", lambda x: status) response = self.core.unmark_status_as_favorite("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_send_direct_message(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "send_direct_message", lambda x, y: status) response = self.core.send_direct_message("dummy-twitter", "foo", "Dummy message") assert isinstance(response, Status) assert response == status def test_destroy_direct_message(self, monkeypatch): status = Status() monkeypatch.setattr(self.account, "destroy_direct_message", lambda x: status) response = self.core.destroy_direct_message("dummy-twitter", "123") assert isinstance(response, Status) assert response == status def test_update_profile(self, monkeypatch): profile = Profile() monkeypatch.setattr(self.account, "update_profile", lambda w, x, y, z: profile) # TODO: Test with no params # response = self.core.update_profile(self.acc_id) # raise excetion response = self.core.update_profile(self.acc_id, fullname="Another fullname") assert response == profile response = self.core.update_profile(self.acc_id, bio="Dummy bio") assert response == profile response = self.core.update_profile(self.acc_id, url="http://crazy.url") assert response == profile response = self.core.update_profile(self.acc_id, location="Nowhere") assert response == profile response = self.core.update_profile(self.acc_id, "Another fullname", "http://crazy.url", "Dummy bio", "Nowhere") assert response == profile def test_follow(self, monkeypatch): profile = Profile() profile.username = "******" monkeypatch.setattr(self.account, "follow", lambda x, y: profile) monkeypatch.setattr(self.core, "add_friend", lambda x: None) response = self.core.follow(self.acc_id, "foo") assert response == profile response = self.core.follow(self.acc_id, "123", True) assert response == profile def test_unfollow(self, monkeypatch): profile = Profile() profile.username = "******" monkeypatch.setattr(self.account, "unfollow", lambda x: profile) monkeypatch.setattr(self.core, "remove_friend", lambda x: None) response = self.core.unfollow(self.acc_id, "foo") assert response == profile def test_block(self, monkeypatch): profile = Profile() profile.username = "******" monkeypatch.setattr(self.account, "block", lambda x: profile) monkeypatch.setattr(self.core, "remove_friend", lambda x: None) response = self.core.block(self.acc_id, "foo") assert response == profile def test_unblock(self, monkeypatch): profile = Profile() profile.username = "******" monkeypatch.setattr(self.account, "unblock", lambda x: profile) response = self.core.unblock(self.acc_id, "foo") assert response == profile def test_report_as_spam(self, monkeypatch): profile = Profile() profile.username = "******" monkeypatch.setattr(self.account, "report_as_spam", lambda x: profile) monkeypatch.setattr(self.core, "remove_friend", lambda x: None) response = self.core.report_as_spam(self.acc_id, "foo") assert response == profile def test_mute(self, monkeypatch): monkeypatch.setattr(self.core.config, "append_filter", lambda x: "foo") response = self.core.mute("foo") assert response == "foo" def test_unmute(self, monkeypatch): monkeypatch.setattr(self.core.config, "remove_filter", lambda x: "foo") response = self.core.unmute("foo") assert response == "foo" def test_verify_friendship(self, monkeypatch): monkeypatch.setattr(self.account, "is_friend", lambda x: True) response = self.core.verify_friendship(self.acc_id, "foo") assert response is True monkeypatch.setattr(self.account, "is_friend", lambda x: False) response = self.core.verify_friendship(self.acc_id, "foo") assert response is False def test_search(self, monkeypatch): search = [Status()] monkeypatch.setattr(self.account, "search", lambda w, x, y, z: search) response = self.core.search(self.acc_id, "dummy", since_id="123", count=200, extra="ble") assert isinstance(response, list) assert isinstance(response[0], Status) response = self.core.search(self.acc_id, "dummy") assert isinstance(response, list) assert isinstance(response[0], Status) response = self.core.search(self.acc_id, "dummy", 200, "123", "ble") assert isinstance(response, list) assert isinstance(response[0], Status) def test_get_profile_image(self, monkeypatch): monkeypatch.setattr(os.path, "join", lambda x, y: '/path/to/ble') monkeypatch.setattr(os.path, "isfile", lambda x: True) monkeypatch.setattr(self.core.accman, 'get', lambda x: DummyAccount()) monkeypatch.setattr(__builtin__, 'open', lambda x, y: DummyFileHandler()) response = self.core.get_profile_image(self.acc_id, "foo") assert response == "/path/to/ble" monkeypatch.setattr(self.core, 'fetch_image', lambda x: 'binary') monkeypatch.setattr(os.path, "join", lambda x, y: '/path/to/bla') response = self.core.get_profile_image(self.acc_id, "foo", False) assert response == "/path/to/bla" def test_get_status_avatar(self, monkeypatch): status = Status() status.id_ = "123456789" status.account_id = "foo-twitter" status.username = "******" status.avatar = "http://my.dummy/avatar" monkeypatch.setattr(os.path, "join", lambda x, y: '/path/to/ble') monkeypatch.setattr(os.path, "isfile", lambda x: True) monkeypatch.setattr(self.core.accman, 'get', lambda x: DummyAccount()) response = self.core.get_status_avatar(status) assert response == "/path/to/ble" monkeypatch.setattr(os.path, "join", lambda x, y: '/path/to/bla') monkeypatch.setattr(os.path, "isfile", lambda x: False) monkeypatch.setattr(__builtin__, 'open', lambda x, y: DummyFileHandler()) monkeypatch.setattr(self.core, 'fetch_image', lambda x: 'binary') response = self.core.get_status_avatar(status) assert response == "/path/to/bla" def test_get_available_trend_locations(self, monkeypatch): location = TrendLocation('Global', 1) monkeypatch.setattr(self.account, "available_trend_locations", lambda: [location]) response = self.core.get_available_trend_locations(self.acc_id) assert isinstance(response, list) assert response[0] == location def test_get_trending_topics(self, monkeypatch): trend = Trend('Foo') monkeypatch.setattr(self.account, "trends", lambda x: [trend]) response = self.core.get_trending_topics(self.acc_id, "here") assert isinstance(response, list) assert response[0] == trend def test_update_profile_image(self, monkeypatch): profile = Profile() monkeypatch.setattr(self.account, "update_profile_image", lambda x: profile) response = self.core.update_profile_image(self.acc_id, "/path/to/ble") assert response == profile # Services def test_available_short_url_services(self): response = self.core.available_short_url_services() assert isinstance(response, list) assert isinstance(response[0], str) def test_short_single_url(self, monkeypatch): monkeypatch.setattr(self.core, "get_shorten_url_service", lambda: 'is.gd') with pytest.raises(URLAlreadyShort): self.core.short_single_url('http://is.gd/blable') monkeypatch.setattr(self.core, "_Core__get_short_url_object", lambda x: DummyService('http://is.gd/ble')) response = self.core.short_single_url('http://my.looooon.url') assert response == 'http://is.gd/ble' def test_short_url_in_message(self, monkeypatch): monkeypatch.setattr(self.core, "get_shorten_url_service", lambda: 'is.gd') message = "Hello, this is a message with a dumb url http://dumb.url.com" message_with_short_url = "Hello, this is a message with a short url http://is.gd/dumb" message_with_no_url = "Hello, this is a message with no url" message_expected = "Hello, this is a message with a dumb url http://is.gd/dumb" with pytest.raises(NoURLToShorten): self.core.short_url_in_message(message_with_no_url) monkeypatch.setattr(self.core, "short_single_url", lambda x: 'http://is.gd/dumb') response = self.core.short_url_in_message(message) assert response == message_expected def raise_ex(): raise URLAlreadyShort response = self.core.short_url_in_message(message_with_short_url) assert response == message_with_short_url def test_available_preview_media_services(self): response = self.core.available_preview_media_services() assert isinstance(response, list) assert isinstance(response[0], str) def test_preview_media(self, monkeypatch): media = Media.new_image('foo', 'binary content') with pytest.raises(PreviewServiceNotSupported): self.core.preview_media('http://unsupported.service.com/ble') monkeypatch.setattr('libturpial.lib.services.media.preview.pictwitter.PicTwitterMediaContent._get_content_from_url', lambda x, y: '123') response = self.core.preview_media('http://pic.twitter.com/ble') assert isinstance(response, Media) def test_available_upload_media_services(self): response = self.core.available_upload_media_services() assert isinstance(response, list) assert isinstance(response[0], str) def test_upload_media(self, monkeypatch): monkeypatch.setattr(self.core, "get_upload_media_service", lambda: 'ima.ge') monkeypatch.setattr(self.core, "_Core__get_upload_media_object", lambda x: DummyService('http://ima.ge/bla')) response = self.core.upload_media(self.acc_id, '/path/to/file', "Dummy message") assert response == 'http://ima.ge/bla' # Configuration def test_register_new_config_option(self, monkeypatch): monkeypatch.setattr(self.core.config, 'register_extra_option', lambda x, y, z: None) # TODO: How to test that this works? Return 0 maybe? assert self.core.register_new_config_option('foo', 'bar', 'baz') == None def test_get_shorten_url_service(self): response = self.core.get_shorten_url_service() assert isinstance(response, str) def test_get_upload_media_service(self): response = self.core.get_upload_media_service() assert isinstance(response, str) def test_set_shorten_url_service(self, monkeypatch): monkeypatch.setattr(self.core.config, "write", lambda x, y, z: None) response = self.core.set_shorten_url_service('foo') assert response is None def test_set_upload_media_service(self, monkeypatch): monkeypatch.setattr(self.core.config, "write", lambda x, y, z: None) response = self.core.set_upload_media_service('foo') assert response is None def test_has_stored_passwwd(self, monkeypatch): account = Account.new("twitter") profile = Profile() profile.username = "******" account.profile = profile monkeypatch.setattr(self.core.accman, "get", lambda x: account) profile.password = None response = self.core.has_stored_passwd("foo") assert response == False profile.password = '' response = self.core.has_stored_passwd("foo") assert response == False profile.password = '******' response = self.core.has_stored_passwd("foo") assert response == True def test_is_account_logged_in(self, monkeypatch): account = Account.new("twitter") monkeypatch.setattr(self.core.accman, "get", lambda x: account) account.logged_in = False response = self.core.is_account_logged_in("foo") assert response == False account.logged_in = True response = self.core.is_account_logged_in("foo") assert response == True def test_is_muted(self, monkeypatch): monkeypatch.setattr(self.core.config, "load_filters", lambda: ['@foo', '@bar', 'baz']) response = self.core.is_muted('foo') assert response == True response = self.core.is_muted('baz') assert response == False def test_get_default_browser(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: None) response = self.core.get_default_browser() assert response is None monkeypatch.setattr(self.core.config, "read", lambda x, y: 'chromium') response = self.core.get_default_browser() assert response == 'chromium' def test_show_notifications_in_login(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: 'on') response = self.core.show_notifications_in_login() assert response == True monkeypatch.setattr(self.core.config, "read", lambda x, y: 'off') response = self.core.show_notifications_in_login() assert response == False def test_show_notifications_in_updates(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: 'on') response = self.core.show_notifications_in_updates() assert response == True monkeypatch.setattr(self.core.config, "read", lambda x, y: 'off') response = self.core.show_notifications_in_updates() assert response == False def test_play_sounds_in_login(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: 'on') response = self.core.play_sounds_in_login() assert response == True monkeypatch.setattr(self.core.config, "read", lambda x, y: 'off') response = self.core.play_sounds_in_login() assert response == False def test_play_sounds_in_updates(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: 'on') response = self.core.play_sounds_in_updates() assert response == True monkeypatch.setattr(self.core.config, "read", lambda x, y: 'off') response = self.core.play_sounds_in_updates() assert response == False def test_get_max_statuses_per_column(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: '200') response = self.core.get_max_statuses_per_column() assert isinstance(response, int) def test_get_proxy(self, monkeypatch): proxy = Proxy('1.2.3.4', '666') monkeypatch.setattr(self.core.config, "get_proxy", lambda: proxy) response = self.core.get_proxy() assert isinstance(response, Proxy) def test_get_socket_timeout(self, monkeypatch): monkeypatch.setattr(self.core.config, "get_socket_timeout", lambda: '20') response = self.core.get_socket_timeout() assert isinstance(response, int) def test_get_update_interval(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: '200') response = self.core.get_update_interval() assert isinstance(response, int) def test_minimize_on_close(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: 'on') response = self.core.minimize_on_close() assert response == True monkeypatch.setattr(self.core.config, "read", lambda x, y: 'off') response = self.core.minimize_on_close() assert response == False def test_get_config(self, monkeypatch): monkeypatch.setattr(self.core.config, "read_all", lambda: APP_CFG) response = self.core.get_config() assert isinstance(response, dict) def test_read_config_value(self, monkeypatch): monkeypatch.setattr(self.core.config, "read", lambda x, y: "foo") response = self.core.read_config_value("bar", "baz") assert response == "foo" def test_write_config_value(self, monkeypatch): monkeypatch.setattr(self.core.config, "write", lambda x, y, z: None) response = self.core.write_config_value("foo", "bar", "baz") assert response is None def test_save_all_config(self, monkeypatch): monkeypatch.setattr(self.core.config, "save", lambda x: None) response = self.core.save_all_config({}) assert response is None def test_list_filters(self): response = self.core.list_filters() assert isinstance(response, list) def test_save_filters(self, monkeypatch): monkeypatch.setattr(self.core.config, "save_filters", lambda x: None) response = self.core.save_filters([]) assert response is None def test_delete_current_config(self, monkeypatch): monkeypatch.setattr(self.core.config, "delete", lambda: None) response = self.core.delete_current_config() assert response is None def test_delete_cache(self, monkeypatch): monkeypatch.setattr(self.account, "delete_cache", lambda: None) monkeypatch.setattr(self.core, "registered_accounts", lambda: [self.account]) response = self.core.delete_cache() assert response is None def test_get_cache_size(self, monkeypatch): monkeypatch.setattr(self.account, "get_cache_size", lambda: 10) monkeypatch.setattr(self.core, "registered_accounts", lambda: [self.account]) response = self.core.get_cache_size() assert response == 10 def test_add_friend(self, monkeypatch): monkeypatch.setattr(self.core.config, "save_friends", lambda x: None) response = self.core.add_friend("foo") assert response is None def test_remove_friend(self, monkeypatch): monkeypatch.setattr(self.core.config, "save_friends", lambda x: None) monkeypatch.setattr(self.core.config, "load_friends", lambda: ['foo']) response = self.core.remove_friend("foo") assert response is None
class Turpial(cmd.Cmd): def __init__(self): cmd.Cmd.__init__(self) parser = OptionParser() parser.add_option('-d', '--debug', dest='debug', action='store_true', help='show debug info in shell during execution', default=False) parser.add_option('-m', '--command', dest='command', action='store_true', help='execute a single command', default=False) parser.add_option('-c', '--clean', dest='clean', action='store_true', help='clean all bytecodes', default=False) parser.add_option('-s', '--save-credentials', dest='save', action='store_true', help='save user credentials', default=False) parser.add_option('--version', dest='version', action='store_true', help='show the version of Turpial and exit', default=False) (options, args) = parser.parse_args() if options.debug or options.clean: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) self.log = logging.getLogger('Turpial:Cmd') #self.config = None self.prompt = 'turpial> ' self.intro = '\n'.join(INTRO) self.core = Core() #self.app_cfg = ConfigApp() #self.version = self.app_cfg.read('App', 'version') if options.clean: clean_bytecodes(__file__, self.log) sys.exit(0) if options.version: print "turpial (cmd) v%s" % self.version print "libturpial v%s" % libturpial_ver print "python v%X" % sys.hexversion sys.exit(0) self.account = None try: self.cmdloop() except KeyboardInterrupt: self.do_exit() except EOFError: self.do_exit() def __validate_index(self, index, array, blank=False): try: a = array[int(index)] return True except IndexError: return False except ValueError: if blank and index == '': return True elif not blank and index == '': return False elif blank and index != '': return False except TypeError: if index is None: return False def __validate_accounts(self): if len(self.core.list_accounts()) > 0: return True print "You don't have any registered account. Run 'account add' command" return False def __validate_default_account(self): if self.account: return True print "You don't have a default account. Run 'account change' command" return False def __validate_arguments(self, arg_array, value): if value in arg_array: return True else: print 'Invalid Argument' return False def __build_message_menu(self): text = raw_input('Message: ') if text == '': print 'You must write something to post' return None if len(text) > 140: trunc = raw_input ('Your message has more than 140 characters. Do you want truncate it? [Y/n]: ') if trunc.lower() == 'y' or trunc == '': return text[:140] return None return text def __build_accounts_menu(self, _all=False): if len(self.core.list_accounts()) == 1: return self.core.list_accounts()[0] index = None while 1: accounts = self.__show_accounts() if _all: index = raw_input('Select account (or Enter for all): ') else: index = raw_input('Select account: ') if not self.__validate_index(index, accounts, _all): print "Invalid account" else: break if index == '': return '' else: return accounts[int(index)] def __build_password_menu(self, account): passwd = None while 1: passwd = getpass.unix_getpass("Password for '%s' in '%s': " % ( account.split('-')[0], account.split('-')[1])) if passwd: return passwd else: print "Password can't be blank" def __build_change_account_menu(self): if len(self.core.list_accounts()) == 1: if self.account: print "Your unique account is already your default" else: self.__add_first_account_as_default() elif len(self.core.list_accounts()) > 1: while 1: accounts = self.__show_accounts() index = raw_input('Select you new default account (or Enter for keep current): ') if index == '': print "Default account remain with no changes" return True if not self.__validate_index(index, accounts): print "Invalid account" else: break self.account = accounts[int(index)] print "Set %s in %s as your new default account" % ( self.account.split('-')[0], self.account.split('-')[1]) def __build_protocols_menu(self): index = None protocols = self.core.list_protocols() while 1: print "Available protocols:" for i in range(len(protocols)): print "[%i] %s" % (i, protocols[i]) index = raw_input('Select protocol: ') if not self.__validate_index(index, protocols): print "Invalid protocol" else: break return protocols[int(index)] def __build_confirm_menu(self, message): confirm = raw_input(message + ' [y/N]: ') if confirm.lower() == 'y': return True else: return False def __user_input(self, message, blank=False): while 1: text = raw_input(message) if text == '' and not blank: print "You can't leave this field blank" continue break return text def __add_first_account_as_default(self): self.account = self.core.list_accounts()[0] print "Selected account %s in %s as default (*)" % ( self.account.split('-')[0], self.account.split('-')[1]) def __show_accounts(self): if len(self.core.list_accounts()) == 0: print "There are no registered accounts" return accounts = [] print "Available accounts:" for acc in self.core.list_accounts(): ch = '' if acc == self.account: ch = ' (*)' print "[%i] %s - %s%s" % (len(accounts), acc.split('-')[0], acc.split('-')[1], ch) accounts.append(acc) return accounts def __show_profiles(self, people): if not statuses: print "There are no profiles to show" return if people.code > 0: print people.errmsg return for p in people: protected = '<protected>' if p.protected else '' following = '<following>' if p.following else '' header = "@%s (%s) %s %s" % (p.username, p.fullname, following, protected) print header print '-' * len(header) print "URL: %s" % p.url print "Location: %s" % p.location print "Bio: %s" % p.bio if p.last_update: print "Last: %s" % p.last_update print '' def __show_statuses(self, statuses): if not statuses: print "There are no statuses to show" return if statuses.code > 0: print statuses.errmsg return count = 1 for status in statuses: text = status.text.replace('\n', ' ') inreply = '' client = '' if status.in_reply_to_user: inreply = ' in reply to %s' % status.in_reply_to_user if status.source: client = ' from %s' % status.source print "%d. @%s: %s (id: %s)" % (count, status.username, text, status.id_) print "%s%s%s" % (status.datetime, client, inreply) if status.reposted_by: users = '' for u in status.reposted_by: users += u + ' ' print 'Retweeted by %s' % status.reposted_by print count += 1 def __process_login(self, acc): if not self.core.has_stored_passwd(acc): passwd = self.__build_password_menu(acc) username = acc.split('-')[0] protocol = acc.split('-')[1] self.core.register_account(username, protocol, passwd) rtn = self.core.login(acc) if rtn.code > 0: print rtn.errmsg return auth_obj = rtn.items if auth_obj.must_auth(): print "Please visit %s, authorize Turpial and type the pin returned" % auth_obj.url pin = self.__user_input('Pin: ') self.core.authorize_oauth_token(acc, pin) rtn = self.core.auth(acc) if rtn.code > 0: print rtn.errmsg else: print 'Logged in with account %s' % acc.split('-')[0] def default(self, line): print '\n'.join(['Command not found.', INTRO[1], INTRO[2]]) def emptyline(self): pass def do_account(self, arg): if not self.__validate_arguments(ARGUMENTS['account'], arg): self.help_account(False) return False if arg == 'add': username = raw_input('Username: '******'Password: '******'Remember password') protocol = self.__build_protocols_menu() acc_id = self.core.register_account(username, protocol, password, remember) print 'Account added' if len(self.core.list_accounts()) == 1: self.__add_first_account_as_default() elif arg == 'edit': if not self.__validate_default_account(): return False password = getpass.unix_getpass('New Password: '******'-')[0] protocol = self.account.split('-')[1] remember = self.__build_confirm_menu('Remember password') self.core.register_account(username, protocol, password, remember) print 'Account edited' elif arg == 'delete': if not self.__validate_accounts(): return False account = self.__build_accounts_menu() conf = self.__build_confirm_menu('Do you want to delete account %s?' % account) if not conf: print 'Command cancelled' return False del_all = self.__build_confirm_menu('Do you want to delete all data?') self.core.unregister_account(account, del_all) if self.account == account: self.account = None print 'Account deleted' elif arg == 'change': if not self.__validate_accounts(): return False self.__build_change_account_menu() elif arg == 'list': self.__show_accounts() elif arg == 'default': print "Your default account is %s in %s" % ( self.account.split('-')[0], self.account.split('-')[1]) def help_account(self, desc=True): text = 'Manage user accounts' if not desc: text = '' print '\n'.join([text, 'Usage: account <arg>\n', 'Possible arguments are:', ' add:\t\t Add a new user account', ' edit:\t\t Edit an existing user account', ' delete:\t Delete a user account', ' list:\t\t Show all registered accounts', ' default:\t Show default account', ]) def do_login(self, arg): if not self.__validate_accounts(): return False _all = True if len(self.core.list_accounts()) > 1: _all = self.__build_confirm_menu('Do you want to login with all available accounts?') if _all: work = False for acc in self.core.list_accounts(): if self.core.is_account_logged_in(acc): continue work = True self.__process_login(acc) if not work: print "Already logged in with all available accounts" else: acc = self.__build_accounts_menu() self.__process_login(acc) def help_login(self): print 'Login with one or many accounts' def do_profile(self, arg): if not self.__validate_arguments(ARGUMENTS['profile'], arg): self.help_profile(False) return False if not self.__validate_default_account(): return False if arg == 'me': profile = self.core.get_own_profile(self.account) if profile is None: print 'You must be logged in' else: self.__show_profiles(profile) elif arg == 'user': username = raw_input('Type the username: '******'': print 'You must specify a username' return False profile = self.core.get_user_profile(self.account, username) if profile is None: print 'You must be logged in' else: self.__show_profiles(profile) elif arg == 'update': args = {} name = raw_input('Type your name (ENTER for none): ') bio = raw_input('Type your bio (ENTER for none): ') url = raw_input('Type your url (ENTER for none): ') location = raw_input('Type your location (ENTER for none): ') if name != '': args['name'] = name if bio != '': args['description'] = bio if url != '': args['url'] = url if location != '': args['location'] = location result = self.core.update_profile(self.account, args) if result.code > 0: print result.errmsg else: print 'Profile updated' def help_profile(self, desc=True): text = 'Manage user profile' if not desc: text = '' print '\n'.join([text, 'Usage: profile <arg>\n', 'Possible arguments are:', ' me:\t\t Show own profile', ' user:\t\t Show profile for a specific user', ' update:\t Update own profile', ]) def do_status(self, arg): if not self.__validate_default_account(): return False if not self.__validate_arguments(ARGUMENTS['status'], arg): self.help_status(False) return False if arg == 'update': message = self.__build_message_menu() if not message: print 'You must to write something' return False broadcast = self.__build_confirm_menu('Do you want to post the message in all available accounts?') if broadcast: for acc in self.core.list_accounts(): rtn = self.core.update_status(acc, message) if rtn.code > 0: print rtn.errmsg else: print 'Message posted in account %s' % acc.split('-')[0] else: rtn = self.core.update_status(self.account, message) if rtn.code > 0: print rtn.errmsg else: print 'Message posted in account %s' % self.account.split('-')[0] elif arg == 'reply': reply_id = raw_input('Status ID: ') if reply_id == '': print "You must specify a valid id" return False message = self.__build_message_menu() if not message: print 'You must to write something' return False rtn = self.core.update_status(self.account, message, reply_id) if rtn.code > 0: print rtn.errmsg else: print 'Reply posted in account %s' % self.account.split('-')[0] elif arg == 'delete': status_id = raw_input('Status ID: ') if status_id == '': print "You must specify a valid id" return False rtn = self.core.destroy_status(self.account, status_id) if rtn.code > 0: print rtn.errmsg else: print 'Status deleted' elif arg == 'conversation': status_id = raw_input('Status ID: ') if status_id == '': print "You must specify a valid id" return False rtn = self.core.get_conversation(self.account, status_id) if rtn.code > 0: print rtn.errmsg else: self.__show_statuses(rtn) def help_status(self, desc=True): text = 'Manage statuses for each protocol' if not desc: text = '' print '\n'.join([text, 'Usage: status <arg>\n', 'Possible arguments are:', ' update:\t Update status ', ' delete:\t Delete status', ' conversation:\t Show related tweets as conversation', ]) def do_column(self, arg): if not self.__validate_default_account(): return False lists = self.core.list_columns(self.account) if arg == '': self.help_column(False) elif arg == 'list': if len(lists) == 0: print "No column available. Maybe you need to login" return False print "Available columns:" for li in lists: print " %s" % li elif arg == 'public': rtn = self.core.get_public_timeline(self.account) self.__show_statuses(rtn) else: if len(lists) == 0: print "No column available. Maybe you need to login" return False if arg in lists: rtn = self.core.get_column_statuses(self.account, arg) self.__show_statuses(rtn) else: print "Invalid column '%s'" % arg def help_column(self, desc=True): text = 'Show user columns' if not desc: text = '' print '\n'.join([text, 'Usage: column <arg>\n', 'Possible arguments are:', ' list:\t\t List all available columns for that account', ' timeline:\t Show timeline', ' replies:\t Show replies', ' directs:\t Show directs messages', ' favorites:\t Show statuses marked as favorites', ' public:\t Show public timeline', ' <list_id>:\t Show statuses for the user list with id <list_id>', ]) def do_friend(self, arg): if not self.__validate_default_account(): return False if not self.__validate_arguments(ARGUMENTS['friend'], arg): self.help_friend(False) return False if arg == 'list': friends = self.core.get_friends(self.account) if friends.code > 0: print rtn.errmsg return False if len(friends) == 0: print "Hey! What's wrong with you? You've no friends" return False print "Friends list:" for fn in friends: print "+ @%s (%s)" % (fn.username, fn.fullname) elif arg == 'follow': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.follow(self.account, username) if rtn.code > 0: print rtn.errmsg return False print "Following %s" % user elif arg == 'unfollow': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.unfollow(self.account, username) if rtn.code > 0: print rtn.errmsg return False print "Not following %s" % user elif arg == 'block': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.block(self.account, username) if rtn.code > 0: print rtn.errmsg return False print "Blocking user %s" % username elif arg == 'unblock': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.unblock(self.account, username) if rtn.code > 0: print rtn.errmsg return False print "Unblocking user %s" % username elif arg == 'spammer': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.report_spam(self.account, username) if rtn.code > 0: print rtn.errmsg return False print "Reporting user %s as spammer" % username elif arg == 'check': username = raw_input('Username: '******'': print "You must specify a valid user" return False rtn = self.core.is_friend(self.account, username) if rtn.code > 0: print rtn.errmsg return False if rtn.items: print "%s is following you" % username else: print "%s is not following you" % username def help_friend(self, desc=True): text = 'Manage user friends' if not desc: text = '' print '\n'.join([text, 'Usage: friend <arg>\n', 'Possible arguments are:', ' list:\t\t List all friends', ' follow:\t Follow user', ' unfollow:\t Unfollow friend', ' block:\t Block user', ' unblock:\t Unblock user', ' spammer:\t Report user as spammer', ' check:\t Verify if certain user is following you', ]) def do_direct(self, arg): if not self.__validate_default_account(): return False if not self.__validate_arguments(ARGUMENTS['direct'], arg): self.help_direct(False) return False if arg == 'send': username = raw_input('Username: '******'': print "You must specify a valid user" return False message = self.__build_message_menu() if not message: print 'You must to write something' return False rtn = self.core.send_direct(self.account, username, message) if rtn.code > 0: print rtn.errmsg else: print 'Direct message sent' elif arg == 'delete': dm_id = raw_input('Direct message ID: ') if dm_id == '': print "You must specify a valid id" return False rtn = self.core.destroy_direct(self.account, dm_id) if rtn.code > 0: print rtn.errmsg else: print 'Direct message deleted' def help_direct(self, desc=True): text = 'Manage user direct messages' if not desc: text = '' print '\n'.join([text, 'Usage: direct <arg>\n', 'Possible arguments are:', ' send:\t\t Send direct message', ' delete:\t Destroy direct message', ]) def do_favorite(self, arg): if not self.__validate_default_account(): return False if not self.__validate_arguments(ARGUMENTS['favorite'], arg): self.help_status(False) return False if arg == 'mark': status_id = raw_input('Status ID: ') if status_id == '': print "You must specify a valid id" return False rtn = self.core.mark_favorite(self.account, status_id) if rtn.code > 0: print rtn.errmsg else: print 'Status marked as favorite' elif arg == 'unmark': status_id = raw_input('Status ID: ') if status_id == '': print "You must specify a valid id" return False rtn = self.core.unmark_favorite(self.account, status_id) if rtn.code > 0: print rtn.errmsg else: print 'Status unmarked as favorite' def help_favorite(self, desc=True): text = 'Manage favorite marks of statuses' if not desc: text = '' print '\n'.join([text, 'Usage: direct <arg>\n', 'Possible arguments are:', ' mark:\t\t Mark a status as favorite', ' unmark:\t Remove favorite mark from a status', ]) def do_search(self, arg=None): if not self.__validate_default_account(): return False if arg: self.help_search() return False query = raw_input('Type what you want to search for: ') rtn = self.core.search(self.account, query) self.__show_statuses(rtn) def help_search(self): print 'Search for a pattern' def do_trends(self, arg=None): if not self.__validate_default_account(): return False if arg: self.help_trends() return False trends = self.core.trends(self.account) if trends.code > 0: print trends.errmsg return False for trend in trends: print trend.title print "=" * len(trend.title) for topic in trend.items: promoted = '' if topic.promoted: promoted = '*' print "%s%s |" % (topic.name, promoted), print def help_trends(self): print 'Show global and local trends' def do_EOF(self, line): return self.do_exit('') def do_exit(self, line=None): print self.log.debug('Bye') return True def help_help(self): print 'Show help. Dah!' def help_exit(self): print 'Close the application' def help_EOF(self): print 'Close the application' def show_shorten_url(self, text): print "URL Cortada:", text