def test_feed_and_article_deletion(self): ccontr = CategoryController(2) cat = ccontr.read().first() ccontr.delete(cat.id) self.assertEqual(0, ArticleController().read(category_id=cat.id).count()) self.assertEqual(0, FeedController().read(category_id=cat.id).count())
def test_cluster_same_feed(self): article = ArticleController().read(category_id__ne=None).first() cluster = article.cluster # all is enabled, article in cluster update_on_all_objs(articles=cluster.articles, cluster_enabled=True, cluster_same_feed=True) article = self.create_article_from(cluster, cluster.main_article.feed) self.assertInCluster(article, cluster) # feed's disabled, won't cluster FeedController().update( {'id__in': [a.feed_id for a in cluster.articles]}, {'cluster_same_feed': False}) article = self.create_article_from(cluster, cluster.main_article.feed) self.assertNotInCluster(article, cluster) # category's disabled, won't cluster FeedController().update( {'id__in': [a.feed_id for a in cluster.articles]}, {'cluster_same_feed': None}) CategoryController().update({'id': cluster.main_article.category.id}, {'cluster_same_feed': False}) article = self.create_article_from(cluster, cluster.main_article.feed) self.assertNotInCluster(article, cluster) # user's disable, won't cluster CategoryController().update({'id': cluster.main_article.category.id}, {'cluster_same_feed': None}) UserController().update({'id': cluster.user_id}, {'cluster_same_feed': False}) article = self.create_article_from(cluster, cluster.main_article.feed) self.assertNotInCluster(article, cluster) # reenabling user, will cluster UserController().update({'id': cluster.user_id}, {'cluster_same_feed': True}) article = self.create_article_from(cluster, cluster.main_article.feed) self.assertInCluster(article, cluster)
def setUp(self): super().setUp() login = '******' self.user = UserController().get(login=login) self.user2 = UserController().get(login='******') self.fctrl = FeedController(self.user.id) self.cctrl = CategoryController(self.user.id) self.uctrl = UserController()
def put(category_id): """Update an existing category.""" cctrl = CategoryController(current_identity.id) attrs = parse_meaningful_params(parser_edit) if attrs: changed = cctrl.update({'id': category_id}, attrs) if not changed: cctrl.assert_right_ok(category_id) return None, 204
def populate_db(): fcontr = FeedController() ccontr = CategoryController() UserController().create( **{ 'is_admin': True, 'is_api': True, 'cluster_enabled': False, 'login': '******', 'password': '******' }) user1, user2 = [ UserController().create(login=name, cluster_enabled=False, email="*****@*****.**" % name, password=name) for name in ["user1", "user2"] ] for iteration in range(2): article_total = 0 for user in (user1, user2): for iter_cat in range(3): cat_id = None if iter_cat: cat_id = ccontr.create(user_id=user.id, name=to_name( user, iteration, iter_cat)).id feed_id = fcontr.create( link="feed%d%d" % (iteration, iter_cat), user_id=user.id, category_id=cat_id, title=to_name(user, iteration, iter_cat, iter_cat)).id for iter_art in range(3): entry = to_name(user, iteration, iter_cat, iter_cat, iter_art) tags = [ to_name(user, iteration, iter_cat, iter_cat, iter_art, str(i)) for i in range(2) ] article_total += 1 ArticleController().create( entry_id=entry, link='http://test.te/%d' % article_total, feed_id=feed_id, user_id=user.id, tags=tags, category_id=cat_id, title=entry, date=utc_now() + timedelta(seconds=iteration), content="content %d" % article_total) session.commit() session.flush() ClusterController().clusterize_pending_articles()
def delete(category_id): """Delete an existing category.""" try: CategoryController(current_identity.id).delete(category_id) except NotFound: user_id = CategoryController().get(id=category_id).user_id if user_id != current_identity.id: raise Forbidden() raise return None, 204
def post(): opml_file = request.files['opml_file'] try: subscriptions = opml.from_string(opml_file.read()) except Exception as error: raise UnprocessableEntity("Couldn't parse OPML file (%r)" % error) ccontr = CategoryController(current_identity.id) fcontr = FeedController(current_identity.id) counts = {'created': 0, 'existing': 0, 'failed': 0, 'exceptions': []} categories = {cat.name: cat.id for cat in ccontr.read()} for line in subscriptions: try: link = line.xmlUrl except Exception as error: counts['failed'] += 1 counts['exceptions'].append(str(error)) continue # don't import twice if fcontr.read(link=link).count(): counts['existing'] += 1 continue # handling categories cat_id = None category = getattr(line, 'category', '').lstrip('/') if category: if category not in categories: new_category = ccontr.create(name=category) categories[new_category.name] = new_category.id cat_id = categories[category] fcontr.create(title=getattr(line, 'text', None), category_id=cat_id, description=getattr(line, 'description', None), link=link, site_link=getattr(line, 'htmlUrl', None)) counts['created'] += 1 code = 200 if counts.get('created'): code = 201 elif counts.get('failed'): code = 400 return counts, code
def test_list_feeds(self): resp = self.jarr_client('get', 'list-feeds', user=self.user.login) fcount = FeedController(self.user.id).read().count() ccount = CategoryController(self.user.id).read().count() self.assertEqual(fcount + ccount + 1, len(resp.json)) self.assertEqual(fcount, len([r for r in resp.json if r['type'] == 'feed'])) self.assertEqual(ccount, len([r for r in resp.json if r['type'] == 'categ']))
def update(self, filters, attrs, return_objs=False, commit=True): user_id = attrs.get('user_id', self.user_id) if 'feed_id' in attrs: feed = FeedController().get(id=attrs['feed_id']) if not (self.user_id is None or feed.user_id == user_id): raise Forbidden("no right on feed %r" % feed.id) attrs['category_id'] = feed.category_id if attrs.get('category_id'): cat = CategoryController().get(id=attrs['category_id']) if not (self.user_id is None or cat.user_id == user_id): raise Forbidden("no right on cat %r" % cat.id) return super().update(filters, attrs, return_objs, commit)
def test_cluster_enabled(self): ccontr = ClusterController() cluster = ccontr.read().first() feed = FeedController(cluster.user_id).read( category_id__ne=None, id__nin=[art.feed_id for art in cluster.articles]).first() category = feed.category # clustering works when all is true update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_enabled=True) article = self.create_article_from(cluster, feed) self.assertInCluster(article, cluster) # disabling on user desactivate all clustering by default update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_enabled=None) UserController().update({'id': cluster.user_id}, {'cluster_enabled': False}) article = self.create_article_from(cluster, feed) self.assertNotInCluster(article, cluster) # disabling on article's feed prevents from clustering update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_enabled=True) FeedController().update({'id': feed.id}, {'cluster_enabled': False}) article = self.create_article_from(cluster, feed) self.assertNotInCluster(article, cluster) # disabling on feed from cluster's articles prevents from clustering update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_enabled=True) FeedController().update( {'id__in': [a.feed_id for a in cluster.articles]}, {'cluster_enabled': False}) article = self.create_article_from(cluster, feed) self.assertNotInCluster(article, cluster) # disabling on article's category prevents from clustering CategoryController(cluster.user_id).update({'id': category.id}, {'cluster_enabled': False}) article = self.create_article_from(cluster, feed) self.assertNotInCluster(article, cluster) update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_enabled=True) article = self.create_article_from(cluster, feed) self.assertInCluster(article, cluster)
def __clean_feed_fields(self, attrs): if attrs.get('category_id') == 0: attrs['category_id'] = None if self.user_id and attrs.get('category_id'): from jarr.controllers import CategoryController category = CategoryController().get(id=attrs['category_id']) if category.user_id != self.user_id: raise Forbidden() if 'filters' in attrs: attrs['filters'] = [ filter_ for filter_ in (attrs['filters'] or []) if isinstance(filter_, dict) ]
def get(): user_id = current_identity.id user = UserController(user_id).get(id=user_id) categories = { cat.id: cat for cat in CategoryController(user_id).read() } response = make_response( render_template('opml.xml', user=user, categories=categories, feeds=FeedController(user_id).read(), now=utc_now())) for key, value in OK_GET_HEADERS.items(): response.headers[key] = value return response
def update_on_all_objs(articles=None, feeds=None, categories=None, users=None, **kwargs): articles = articles or [] feeds = feeds or [] categories = categories or [] users = users or [] feed_ids = {a.feed_id for a in articles}.union({f.id for f in feeds}) category_ids = {a.category_id for a in articles if a.category_id}\ .union({f.category_id for f in feeds if f.category_id})\ .union({c.id for c in categories}) user_ids = {a.user_id for a in articles}\ .union({f.user_id for f in feeds})\ .union({c.user_id for c in categories})\ .union({u.id for u in users}) FeedController().update( { '__or__': [{ 'id__in': feed_ids }, { 'category_id__in': category_ids }, { 'user_id__in': user_ids }] }, kwargs) CategoryController().update( {'__or__': [{ 'id__in': category_ids }, { 'user_id__in': user_ids }]}, kwargs) UserController().update( {'id__in': user_ids}, # pushing default to user if not specifically false {k: v if v is not None else True for k, v in kwargs.items()})
def test_no_cluster_same_category_on_original_category(self): article = ArticleController().read(category_id__ne=None).first() art_cat_id = article.category_id cat_ctrl = CategoryController(article.user_id) cluster = article.cluster feed = FeedController(cluster.user_id).create(title='new feed', category_id=art_cat_id) update_on_all_objs(articles=cluster.articles, feeds=[feed], cluster_same_category=None, cluster_enabled=True) cat_ctrl.update({'id': art_cat_id}, {'cluster_same_category': False}) article = self.create_article_from(cluster, feed) self.assertNotInCluster(article, cluster) cat_ctrl.update({'id': art_cat_id}, {'cluster_same_category': True}) article = self.create_article_from(cluster, feed) self.assertInCluster(article, cluster)
def test_cluster_disabled_on_original_category(self): article = ArticleController().read(category_id__ne=None).first() art_cat_id = article.category_id cat_ctrl = CategoryController(article.user_id) cluster = article.cluster fctrl = FeedController(cluster.user_id) feed = fctrl.create(title='new feed', category_id=art_cat_id) fno_cat = fctrl.create(title='category-less') update_on_all_objs(users=[cluster.user], cluster_enabled=None) cat_ctrl.update({}, {'cluster_enabled': False}) article = self.create_article_from(cluster, feed) self.assertEqual(1, len(article.cluster.articles)) self.assertNotInCluster(article, cluster) article = self.create_article_from(cluster, fno_cat) self.assertEqual(1, len(article.cluster.articles)) self.assertNotInCluster(article, cluster) cat_ctrl.update({'id': art_cat_id}, {'cluster_enabled': True}) article = self.create_article_from(cluster, fno_cat) self.assertEqual(2, len(article.cluster.articles)) self.assertInCluster(article, cluster) article = self.create_article_from(cluster, feed) self.assertEqual(3, len(article.cluster.articles)) self.assertInCluster(article, cluster)
class OPMLTest(JarrFlaskCommon): def setUp(self): super().setUp() login = '******' self.user = UserController().get(login=login) self.user2 = UserController().get(login='******') self.fctrl = FeedController(self.user.id) self.cctrl = CategoryController(self.user.id) self.uctrl = UserController() def test_opml_dump_and_restore(self): # downloading OPML export file resp = self.jarr_client('get', '/opml', user=self.user.login) self.assertStatusCode(200, resp) opml_dump = resp.data.decode() self.assertTrue( opml_dump.startswith('<?xml version="1.0" encoding="utf-8"')) self.assertTrue(opml_dump.endswith('</opml>')) # cleaning db actrl = ArticleController(self.user.id) for item in actrl.read(): actrl.delete(item.id) self.assertEqual(0, ClusterController(self.user.id).read().count()) self.assertEqual(0, ArticleController(self.user.id).read().count()) no_category_feed = [] existing_feeds = {} for feed in self.fctrl.read(): if feed.category: if feed.category.name in existing_feeds: existing_feeds[feed.category.name].append(feed.title) else: existing_feeds[feed.category.name] = [feed.title] else: no_category_feed.append(feed.title) self.fctrl.delete(feed.id) for category in self.cctrl.read(): self.cctrl.delete(category.id) # re-importing OPML import_resp = self.jarr_client( 'post', 'opml', to_json=False, data={'opml_file': (BytesIO(resp.data), 'opml.xml')}, headers=None, user=self.user.login) self.assertStatusCode(201, import_resp) self.assertEqual(0, import_resp.json['existing']) self.assertEqual(0, import_resp.json['failed']) self._check_opml_imported(existing_feeds, no_category_feed) import_resp = self.jarr_client( 'post', 'opml', to_json=False, data={'opml_file': (BytesIO(resp.data), 'opml.xml')}, headers=None, user=self.user.login) self.assertStatusCode(200, import_resp) self.assertEqual(0, import_resp.json['created']) self.assertEqual(0, import_resp.json['failed']) def _check_opml_imported(self, existing_feeds, no_category_feed): self.assertEqual( sum(map(len, existing_feeds.values())) + len(no_category_feed), self.fctrl.read().count()) self.assertEqual(len(existing_feeds), self.cctrl.read().count()) for feed in self.fctrl.read(): if feed.category: self.assertIn(feed.category.name, existing_feeds) self.assertIn(feed.title, existing_feeds[feed.category.name]) else: self.assertIn(feed.title, no_category_feed)
def post(): """Create a new category.""" attrs = parse_meaningful_params(parser) return CategoryController(current_identity.id).create(**attrs), 201
def get(): """List all categories with their unread counts.""" return list(CategoryController(current_identity.id).read()), 200
def test_feed_rights(self): cat = CategoryController(2).read().first() self.assertEqual(3, ArticleController().read(category_id=cat.id).count()) self.assertEqual(1, FeedController().read(category_id=cat.id).count()) self._test_controller_rights(cat, UserController().get(id=cat.user_id))
def get(category_id): """Read an existing category.""" return CategoryController(current_identity.id).get(id=category_id), \ 200