예제 #1
0
class Test(unittest.TestCase):
    def tearDown(self):
        self._mdb.client().drop_database("TESTWRITER")

    def test_write_group(self):
        self._mdb = MUGAlyserMongoDB("mongodb://localhost:27017/TESTWRITER")
        self._audit = Audit(self._mdb)
        batchID = self._audit.start_batch({"test": 1})
        self._writer = MeetupWriter(get_meetup_key(), batchID, self._mdb)
        self._writer.write_groups("nopro", ["DublinMUG"])
        self._writer.write_groups("pro", ["DublinMUG"])
        self.assertTrue(self._mdb.groupsCollection().find_one(
            {"group.urlname": "DublinMUG"}))
        self.assertTrue(self._mdb.proGroupsCollection().find_one(
            {"group.urlname": "DublinMUG"}))
        self._audit.end_batch(batchID)

    def testProcessMembers(self):
        self._mdb = MUGAlyserMongoDB("mongodb://localhost:27017/TESTWRITER")
        self._audit = Audit(self._mdb)
        batchID = self._audit.start_batch({"test": 2})
        self._writer = MeetupWriter(get_meetup_key(), batchID, self._mdb)
        self._writer.write_members("pro", ["DublinMUG"])
        self._writer.write_members("nopro", ["DublinMUG"])
        self.assertTrue(self._mdb.proMembersCollection().find_one(
            {"member.member_name": "Joe Drumgoole"}))
        self.assertTrue(self._mdb.membersCollection().find_one(
            {"member.name": "Joe Drumgoole"}))
        self._audit.end_batch(batchID)
예제 #2
0
class Test_audit(unittest.TestCase):

    def setUp(self):
        self._mdb = MUGAlyserMongoDB( uri="mongodb://localhost/TEST_AUDIT" )
        self._audit = Audit( self._mdb )
    

    def tearDown(self):
        self._mdb.client().drop_database( "TEST_AUDIT" )
    
    #@unittest.skip
    def test_get_current_batch_id(self):
        self.assertFalse( self._audit.in_batch())
        
        batch_id = self._audit.start_batch( doc = { "test" : "doc"})
        self.assertTrue( self._audit.in_batch())
        self._audit.end_batch( batch_id )
        
        self.assertTrue( self._audit.get_batch( batch_id ))
        
        self.assertFalse( self._audit.in_batch())
        self.assertEqual( batch_id, self._audit.get_last_valid_batch_id())
    
    def test_get_valid_batches(self):
        id1 = self._audit.start_batch( doc = { "test" : "doc"})
        id2 = self._audit.start_batch( doc = { "test" : "doc"})

        self.assertTrue( self._audit.in_batch())
        self._audit.end_batch( id2 )
        self.assertTrue( self._audit.in_batch())
        self._audit.end_batch( id1 )
        batch = self._audit.get_batch_end( id1 )
        self.assertGreaterEqual( batch[ 'end'], parse( "1-Jun-2017", ) )
        self.assertFalse( self._audit.in_batch())
        
        idlist = list( self._audit.get_valid_batch_ids())
        self.assertTrue( id1 in idlist )
        self.assertTrue( id2 in idlist )
        
    def test_get_last_batch_id(self):
        id1 = self._audit.start_batch( doc = { "test" : "doc"})
        id2 = self._audit.start_batch( doc = { "test" : "doc"})
        self.assertEqual( 101, self._audit.get_last_batch_id())
        self._audit.end_batch( id2 )
        self.assertEqual( 101, self._audit.get_last_batch_id())
        self._audit.end_batch( id1 )
        
        id1 = self._audit.start_batch( doc = { "test" : "doc"})
        self.assertEqual( 102, self._audit.get_last_batch_id())
        self._audit.end_batch( id1 )
        
    def test_pro_batch_id(self):
예제 #3
0
def mugalyser(argv=None):  # IGNORE:C0111
    '''Command line options.'''

    try:
        # Setup argument parser

        parser = ArgumentParser(description='''
Read data from the Meetup API and write it do a MongoDB database. Each run of this program
creates a new batch of data identified by a batchID. The default database is MUGS. You can change
this by using the --host parameter and specifying a different database in the mongodb URI.
If you use the --pro arguement your API key must be a meetup pro account API key. If not the api
calls to the pro interface will fail.

If you are and adminstrator on the pro account you should use the --admin flag to give you
access to the admin APIs.
''')
        #
        # MongoDB Args

        parser.add_argument('--host',
                            default="mongodb://localhost:27017/MUGS",
                            help='URI to connect to : [default: %(default)s]')
        parser.add_argument("-v",
                            "--version",
                            action='version',
                            version=__programName__ + " " + __version__)
        parser.add_argument(
            '--mugs',
            nargs="+",
            default=[],
            help='Process MUGs list list mugs by name [default: %(default)s]')

        parser.add_argument("--collect",
                            choices=["pro", "nopro", "all"],
                            default="all",
                            help="Use pro API calls, no pro API calls or both")
        parser.add_argument(
            "--admin",
            default=False,
            action="store_true",
            help=
            "Some calls are only available to admin users, use this if you are not an admin"
        )
        parser.add_argument(
            "--database",
            default="MUGS",
            help="Default database name to write to [default: %(default)s]")
        parser.add_argument('--phases',
                            nargs="+",
                            choices=[
                                "groups", "members", "attendees",
                                "upcomingevents", "pastevents"
                            ],
                            default=["all"],
                            help='execution phases')

        parser.add_argument(
            '--loglevel',
            default="INFO",
            choices=["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"],
            help='Logging level [default: %(default)s]')

        parser.add_argument('--apikey',
                            default=None,
                            help='Default API key for meetup')

        parser.add_argument("--batchname",
                            default=__programName__,
                            help="Batch name used in creating audit batches")
        parser.add_argument(
            '--urlfile',
            help=
            "File containing a list of MUG URLs to be used to parse data [ default: %(default)s]"
        )
        parser.add_argument(
            "--drop",
            default=False,
            action="store_true",
            help="drop the database before writing data [default: %(default)s]"
        )
        parser.add_argument("--organizer_id",
                            type=int,
                            help="Organizer ID is required for non pro groups")
        # Process arguments
        args = parser.parse_args(argv)

        apikey = ""

        if args.apikey:
            apikey = args.apikey
        else:
            apikey = get_meetup_key()

        mugalyser_logger = Logger(__programName__, args.loglevel)
        # mugalyser_logger.add_stream_handler( args.loglevel )
        mugalyser_logger.add_file_handler("mugalyser.log", args.loglevel)

        api = MeetupAPI(apikey, reshape=True)
        logger = mugalyser_logger.log()

        # Turn off logging for requests
        logging.getLogger("requests").setLevel(logging.WARNING)
        logging.getLogger("urllib3").setLevel(logging.WARNING)

        mdb = MUGAlyserMongoDB(uri=args.host, database_name=args.database)

        if args.drop:
            logger.warn(f"Dropping database:'{args.database}'")
            mdb.drop(args.database)

        audit = Audit(mdb)

        batchID = audit.start_batch({
            "args": vars(args),
            "version": __programName__ + " " + __version__,
            "name": args.batchname
        })

        start = datetime.utcnow()
        logger.info("Started MUG processing for batch ID: %i", batchID)
        logger.info("Writing to database : '%s'", mdb.database().name)

        group_dict = {}

        count = 0
        group_list = []
        if args.mugs:
            for url in args.mugs:
                group_list.append(api.get_group(url))
        else:
            group_list = list(api.get_groups())

        for url, group in group_list:

            #print(f"Checking:{group['urlname']}")
            urlname = group['urlname']
            url, full_group = api.get_group(urlname)
            if args.collect in ["pro", "all"]:
                if "pro_network" in full_group and full_group["pro_network"][
                        "name"] == "MongoDB":
                    count = count + 1
                    logger.info(
                        f"{count}. Processing pro group: {group['urlname']}")
                    group_dict[urlname] = full_group

            if args.collect in ["nopro", "all"]:
                if args.organizer_id:
                    if full_group["organizer"]["id"] == args.organizer_id:
                        count = count + 1
                        logger.info(
                            f"{count}. Processing normal group: {group['urlname']}"
                        )
                        group_dict[urlname] = full_group
                else:
                    logger.error(
                        "You must specify --organizer_id  when collecting nopro groups"
                    )
                    sys.exit(1)

        if args.urlfile:
            urlfile = os.path.abspath(args.urlfile)
            logger.info("Reading groups from: '%s'", urlfile)
            with open(urlfile) as f:
                lines = f.read().splitlines()
                # string comments
                regex = "^\s*#.*|^\s*$"  # comments with # or blank lines
                for i in lines:
                    clean_line = i.rstrip()
                    if not re.match(regex, clean_line):
                        group_dict[clean_line] = None

        # scoop up any command line args
        for i in args.mugs:
            group_dict[i] = None

        writer = MeetupWriter(apikey, batchID, mdb, reshape=True)

        if "all" in args.phases:
            phases = ["groups", "members", "upcomingevents", "pastevents"]

        else:
            phases = args.phases

        if args.admin:
            logger.info("--admin : we will collect attendee info")
            phases.append("attendees")
        else:
            logger.info("No admin account")
            logger.info(
                "We will not collect attendee info: ignoring attendees")

        logger.info("Processing phases: %s", phases)

        if "groups" in phases:
            logger.info("processing group info for %i groups: collect=%s",
                        len(group_dict), args.collect)
            writer.write_groups(group_dict.keys())
            phases.remove("groups")
        if "members" in phases:
            logger.info("processing members info for %i groups: collect=%s",
                        len(group_dict), args.collect)
            writer.write_members(group_dict.keys())
            phases.remove("members")

        for i in group_dict.keys():
            writer.capture_snapshot(i, args.admin, phases)

        audit.end_batch(batchID)
        end = datetime.utcnow()

        elapsed = end - start

        logger.info("MUG processing took %s for BatchID : %i", elapsed,
                    batchID)

    except KeyboardInterrupt:
        print("Keyboard interrupt : Exiting...")
        sys.exit(2)

    except pymongo.errors.ServerSelectionTimeoutError as e:
        print("Failed to connect to MongoDB Server (server timeout): %s" % e)
        sys.exit(2)