# Path: tests/test_models.py
# class MongoTestMixin(object):
# 
#     def setUp(self):
#         """
#         Create the mongomock connection
#         """
#         self.conn = connect(host='mongomock://localhost')
#         assert isinstance(self.conn, MockMongoClient)
# 
#         # Clear out the database
#         for feed in Feed.objects(): feed.delete()
#         for post in Post.objects(): post.delete()
# 
#     def tearDown(self):
#         """
#         Drop the mongomock connection
#         """
#         assert isinstance(self.conn, MockMongoClient)
#         self.conn = None
# 
#     def assertDateTimeEqual(self, dta, dtb):
#         """
#         Assert that two datetimes are within 1 second of each other
#         """
#         dta = dta.replace(microsecond=0)
#         dtb = dta.replace(microsecond=0)
# 
#         if dta.second != dtb.second:
#             self.assertLessThanEqual(
#                 abs(dta.second - dtb.second), 1, "datetimes are not one second apart!"
#             )
#             dta = dta.replace(second=0)
#             dtb = dtb.replace(second=0)
# 
#         self.assertEqual(dta, dtb)
# 
# Path: baleen/opml.py
# class OPML(object):
# 
#     def __init__(self, path):
#         """
#         Reader for OPML XML files.
#         """
#         self.path = path
# 
#     def categories(self):
#         """
#         Reads the file to capture all the categories
#         """
#         with open(self.path, 'r') as data:
#             soup = BeautifulSoup(data, 'xml')
#             for topic in soup.select('body > outline'):
#                 yield topic['title']
# 
#     def counts(self):
#         """
#         Returns the counts of feeds in each category
#         """
#         counts = Counter()
#         for item in self:
#             counts[item['category']] += 1
#         return counts
# 
#     def __iter__(self):
#         """
#         Yields a dictionary representing the attributes of the RSS feed
#         from the OPML file; also captures category data.
#         """
#         with open(self.path, 'r') as data:
#             soup = BeautifulSoup(data, 'xml')
#             for topic in soup.select('body > outline'):
#                 for feed in topic.find_all('outline'):
#                     data = feed.attrs.copy()
#                     data['category'] = topic['title']
#                     yield data
# 
#     def __len__(self):
#         return sum(1 for item in self)
# 
#     def __str__(self):
#         counts = self.counts()
#         return "OPML with {} categories and {} feeds".format(
#             len(counts), sum(counts.values())
#         )
# 
#     def __repr__(self):
#         return "<{} at {}>".format(self.__class__.__name__, self.path)
# 
# def load_opml(path):
#     """
#     Loads an OPML file into the Mongo database; returns the count of the
#     number of documents added to the database.
#     """
# 
#     opml = OPML(path)
#     rows = 0
#     for feed in opml:
#         feed.pop('type')                    # Unneeded for database
#         feed.pop('text')                    # Unneeded for database
#         feed['link'] = feed.pop('xmlUrl')   # Rename the XML URL
#         feed['urls'] = {
#             'xmlUrl':  feed['link'],        # Add xmlUrl to urls
#             'htmlUrl': feed.pop('htmlUrl'), # Add htmlUrl to urls
#         }
#         feed = db.Feed(**feed)              # Construct without an ObjectId
# 
#         try:
#             feed.save()
#             rows += 1
#         except NotUniqueError:
#             continue
#     return rows
# 
# Path: baleen/models.py
# class Feed(me.DynamicDocument):
# 
#     version   = me.StringField(choices=FEEDTYPES)
#     etag      = me.StringField()
#     modified  = me.StringField()
#     title     = me.StringField(max_length=256)
#     link      = me.URLField(required=True, unique=True)
#     urls      = me.DictField()
#     category  = me.StringField(required=True)
#     active    = me.BooleanField(default=True)
#     fetched   = me.DateTimeField(default=None)
#     created   = me.DateTimeField(default=datetime.now, required=True)
#     updated   = me.DateTimeField(default=datetime.now, required=True)
# 
#     @classmethod
#     def pre_save(cls, sender, document, **kwargs):
#         document.updated = datetime.now()
# 
#     meta      = {
#         'collection': 'feeds',
#     }
# 
#     @property
#     def xmlurl(self):
#         return self.link
# 
#     @property
#     def htmlurl(self):
#         return self.urls.get('htmlUrl')
# 
#     def count_posts(self):
#         """
#         Count the number of associated posts
# 
#         TODO: This is very, very slow on Mongo (fix and make better).
#         """
#         return Post.objects(feed=self).count()
# 
#     def __unicode__(self):
#         return self.title if self.title else self.link


import os
import unittest
    import mock
from .test_models import MongoTestMixin
    from unittest import mock
from baleen.opml import OPML, load_opml
from baleen.models import Feed
FIXTURES = os.path.join(os.path.dirname(__file__), "fixtures")
FEEDLY   = os.path.join(FIXTURES, "feedly.opml")

##########################################################################
## Test Load OPML command
##########################################################################

class LoadOPMLTests(MongoTestMixin, unittest.TestCase):

    def test_load_opml_integrated(self):
        """
        Test the integration of the ingest helper function
        """
        self.assertEqual(Feed.objects.count(), 0)
        self.assertEqual(load_opml(FEEDLY), 36)
        self.assertEqual(Feed.objects.count(), 36)

        for feed in Feed.objects():
            self.assertIn('xmlUrl', feed.urls)
            self.assertIn('htmlUrl', feed.urls)

    def test_load_opml_no_duplicates(self):
        """
        Assert multiple calls to the load_opml creates no duplicates
        """
        self.assertEqual(Feed.objects.count(), 0)
        self.assertEqual(load_opml(FEEDLY), 36)
        self.assertEqual(Feed.objects.count(), 36)

        for _ in xrange(10):

# Path: tests/test_models.py
# class MongoTestMixin(object):
# 
#     def setUp(self):
#         """
#         Create the mongomock connection
#         """
#         self.conn = connect(host='mongomock://localhost')
#         assert isinstance(self.conn, MockMongoClient)
# 
#         # Clear out the database
#         for feed in Feed.objects(): feed.delete()
#         for post in Post.objects(): post.delete()
# 
#     def tearDown(self):
#         """
#         Drop the mongomock connection
#         """
#         assert isinstance(self.conn, MockMongoClient)
#         self.conn = None
# 
#     def assertDateTimeEqual(self, dta, dtb):
#         """
#         Assert that two datetimes are within 1 second of each other
#         """
#         dta = dta.replace(microsecond=0)
#         dtb = dta.replace(microsecond=0)
# 
#         if dta.second != dtb.second:
#             self.assertLessThanEqual(
#                 abs(dta.second - dtb.second), 1, "datetimes are not one second apart!"
#             )
#             dta = dta.replace(second=0)
#             dtb = dtb.replace(second=0)
# 
#         self.assertEqual(dta, dtb)
# 
# Path: baleen/opml.py
# class OPML(object):
# 
#     def __init__(self, path):
#         """
#         Reader for OPML XML files.
#         """
#         self.path = path
# 
#     def categories(self):
#         """
#         Reads the file to capture all the categories
#         """
#         with open(self.path, 'r') as data:
#             soup = BeautifulSoup(data, 'xml')
#             for topic in soup.select('body > outline'):
#                 yield topic['title']
# 
#     def counts(self):
#         """
#         Returns the counts of feeds in each category
#         """
#         counts = Counter()
#         for item in self:
#             counts[item['category']] += 1
#         return counts
# 
#     def __iter__(self):
#         """
#         Yields a dictionary representing the attributes of the RSS feed
#         from the OPML file; also captures category data.
#         """
#         with open(self.path, 'r') as data:
#             soup = BeautifulSoup(data, 'xml')
#             for topic in soup.select('body > outline'):
#                 for feed in topic.find_all('outline'):
#                     data = feed.attrs.copy()
#                     data['category'] = topic['title']
#                     yield data
# 
#     def __len__(self):
#         return sum(1 for item in self)
# 
#     def __str__(self):
#         counts = self.counts()
#         return "OPML with {} categories and {} feeds".format(
#             len(counts), sum(counts.values())
#         )
# 
#     def __repr__(self):
#         return "<{} at {}>".format(self.__class__.__name__, self.path)
# 
# def load_opml(path):
#     """
#     Loads an OPML file into the Mongo database; returns the count of the
#     number of documents added to the database.
#     """
# 
#     opml = OPML(path)
#     rows = 0
#     for feed in opml:
#         feed.pop('type')                    # Unneeded for database
#         feed.pop('text')                    # Unneeded for database
#         feed['link'] = feed.pop('xmlUrl')   # Rename the XML URL
#         feed['urls'] = {
#             'xmlUrl':  feed['link'],        # Add xmlUrl to urls
#             'htmlUrl': feed.pop('htmlUrl'), # Add htmlUrl to urls
#         }
#         feed = db.Feed(**feed)              # Construct without an ObjectId
# 
#         try:
#             feed.save()
#             rows += 1
#         except NotUniqueError:
#             continue
#     return rows
# 
# Path: baleen/models.py
# class Feed(me.DynamicDocument):
# 
#     version   = me.StringField(choices=FEEDTYPES)
#     etag      = me.StringField()
#     modified  = me.StringField()
#     title     = me.StringField(max_length=256)
#     link      = me.URLField(required=True, unique=True)
#     urls      = me.DictField()
#     category  = me.StringField(required=True)
#     active    = me.BooleanField(default=True)
#     fetched   = me.DateTimeField(default=None)
#     created   = me.DateTimeField(default=datetime.now, required=True)
#     updated   = me.DateTimeField(default=datetime.now, required=True)
# 
#     @classmethod
#     def pre_save(cls, sender, document, **kwargs):
#         document.updated = datetime.now()
# 
#     meta      = {
#         'collection': 'feeds',
#     }
# 
#     @property
#     def xmlurl(self):
#         return self.link
# 
#     @property
#     def htmlurl(self):
#         return self.urls.get('htmlUrl')
# 
#     def count_posts(self):
#         """
#         Count the number of associated posts
# 
#         TODO: This is very, very slow on Mongo (fix and make better).
#         """
#         return Post.objects(feed=self).count()
# 
#     def __unicode__(self):
#         return self.title if self.title else self.link


# Path: tests/test_opml.py
import os
import unittest
    import mock
from .test_models import MongoTestMixin
    from unittest import mock
from baleen.opml import OPML, load_opml
from baleen.models import Feed

FIXTURES = os.path.join(os.path.dirname(__file__), "fixtures")
FEEDLY   = os.path.join(FIXTURES, "feedly.opml")

##########################################################################
## Test Load OPML command
##########################################################################

class LoadOPMLTests(MongoTestMixin, unittest.TestCase):

    def test_load_opml_integrated(self):
        """
        Test the integration of the ingest helper function
        """
        self.assertEqual(Feed.objects.count(), 0)
        self.assertEqual(load_opml(FEEDLY), 36)
        self.assertEqual(Feed.objects.count(), 36)

        for feed in Feed.objects():
            self.assertIn('xmlUrl', feed.urls)
            self.assertIn('htmlUrl', feed.urls)

    def test_load_opml_no_duplicates(self):
        """
        Assert multiple calls to the load_opml creates no duplicates
        """
        self.assertEqual(Feed.objects.count(), 0)
        self.assertEqual(load_opml(FEEDLY), 36)
        self.assertEqual(Feed.objects.count(), 36)

        for _ in xrange(10):

            self.assertEqual(load_opml(FEEDLY), 0)