def get_logger(logName, stdOutOnly=False): if not stdOutOnly and LogFactory.log_dir != '' and not os.path.exists( LogFactory.log_dir): os.makedirs(LogFactory.log_dir) if logName not in LogFactory.loggers: if not stdOutOnly: FileIO.create_file_if_does_not_exist( f"{LogFactory.log_dir}{os.sep}{logName}.log") LogFactory.loggers[logName] = logging.getLogger(logName) LogFactory.loggers[logName].setLevel( logging.getLevelName(LogFactory.log_level)) formatter = logging.Formatter( '[%(asctime)s %(levelname)s]: %(message)s') if not stdOutOnly: handler = logging.FileHandler( f"{LogFactory.log_dir}{os.sep}{logName}.log", encoding='utf-8') handler.setFormatter(formatter) LogFactory.loggers[logName].addHandler(handler) # create console handler with a higher log level if LogFactory.log_stdout: stdhandler = logging.StreamHandler(sys.stdout) stdhandler.setLevel(logging.getLevelName(LogFactory.log_level)) stdhandler.setFormatter(formatter) LogFactory.loggers[logName].addHandler(stdhandler) return LogFactory.loggers[logName]
def write_messages(outputdir: str, conversation_data: Conversation) -> None: output = FileIO() output.write_txt_file(outputdir, "All_messages.txt", conversation_data.get_messages()) output.write_txt_file(outputdir, "Messages_by_sender.txt", conversation_data.get_messages_by_sender()) output.write_txt_file(outputdir, "Messages_by_day.txt", conversation_data.get_by_day()) output.write_txt_file(outputdir, "Messages_as_table.csv", conversation_data.get_csv())
def graph_data(outputdir: str, conversation_data: Conversation, wordlist: list[str] = None) -> None: outputdir = FileIO.validate_directory(outputdir) plot_frequency( outputdir + "Frequency_hourly", "Message Frequency by Hour", "Frequency", "Hour of Day", conversation_data.get_by_hour(), ) plot_frequency( outputdir + "Frequency_daily", "Message Frequency by Day", "Frequency", "Day of Week", conversation_data.get_by_day(), ) plot_word_frequency(outputdir + "Frequency_words", conversation_data.get_text(), wordlist) message_types_by_sender = conversation_data.get_message_type_count() for sender in message_types_by_sender: plot_message_type_balance( outputdir + sender + "_balance", sender, list(message_types_by_sender[sender].values()), list(message_types_by_sender[sender].keys()), )
class FakedFileIOTests(TestCase): def setUp(self): self.maxDiff = None self.setUpPyfakefs() self.f = FileIO() def tearDown(self): del self.f @patch("builtins.open") def test_write_file_directory_accepts_existing_slash(self, mock_open): fake_directory = "/path/to/dir/" self.fs.create_dir(fake_directory) self.f.write_txt_file(fake_directory, "file.txt", "Data") mock_open.assert_called_once_with("/path/to/dir/file.txt", "w") @patch("builtins.open") def test_write_file_directory_adds_slash_to_path(self, mock_open): fake_directory = "/path/to/dir" self.fs.create_dir(fake_directory) self.f.write_txt_file(fake_directory, "file.txt", "Data") mock_open.assert_called_once_with("/path/to/dir/file.txt", "w") @patch("builtins.open") def test_write_file_writes_dict_data(self, mock_creation): fake_data = {"Data"} fake_dir = "/path/to/dir" self.fs.create_dir(fake_dir) self.f.write_txt_file(fake_dir, "file.txt", fake_data) mock_creation.assert_called_once_with("/path/to/dir/file.txt", "w") mock_creation().write.assert_called_once_with("{'Data'}") @patch("builtins.open") def test_write_file_writes_text_data(self, mock_creation): fake_data = "Data" fake_dir = "/path/to/dir" self.fs.create_dir(fake_dir) self.f.write_txt_file("/path/to/dir", "file.txt", fake_data) mock_creation.assert_called_once_with("/path/to/dir/file.txt", "w") mock_creation().write.assert_called_once_with("Data")
def sleeper(SHUTDOWN_TIME_MINUTES: int = 45, kasaHost: str = ''): LogFactory.MAIN_LOG.info('start sleeper') total_time_seconds: int = SHUTDOWN_TIME_MINUTES * 60 if KasaAPI.KASA_ENABLED: cleanOldScripts() scriptName: str = f"sleeperScript-{random.random()}.sh" scriptContent: str = "" with open(scriptName, "w+") as sleepyScript: sleepyScript.write( f"echo \"sleeping for {SHUTDOWN_TIME_MINUTES} minute(s)\" >> {LOCATION_FORMATTED}{os.sep}{os.sep}sleepy.log\n" ) sleepyScript.write(f"sleep {total_time_seconds}\n") sleepyScript.write( f"echo \"shuting down...\" >> {LOCATION_FORMATTED}{os.sep}{os.sep}sleepy.log\n" ) sleepyScript.write(KasaAPI.kill_kasa_outlet_cmd(kasaHost)) sleepyScript.flush() sleepyScript.close() scriptContent = FileIO.read_file_content(scriptName) # Give time for OS to lay down file above time.sleep(1) os.chmod(scriptName, 0o777) if is_windows(): LogFactory.MAIN_LOG.info("running windows sleeper...") from subprocess import CREATE_NEW_CONSOLE Popen([f"{scriptName}"], creationflags=CREATE_NEW_CONSOLE, shell=True) else: LogFactory.MAIN_LOG.info("running unix sleeper..") Popen(['bash', '-c', f"./{scriptName}"]) LogFactory.MAIN_LOG.info(f"running this script: \n {scriptContent}") LogFactory.MAIN_LOG.info(f"rm {scriptName}") #os.remove(scriptName) exit(0) else: os.system(f"sudo shutdown +{SHUTDOWN_TIME_MINUTES}") exit(0)
class FileIOTest(unittest.TestCase): def setUp(self): self.maxDiff = None self.f = FileIO() def tearDown(self): del self.f def test_OpenSpecifiedFileInSubDir(self): with open("test/Messages/message.json") as file: expected_json = json.load(file) result = self.f.open_json("test/Messages/message.json") self.assertEqual(expected_json, result) self.assertGreater(self.f.data.__len__(), 0) def test_open_text_StripsCommentsFromTxtFiles(self): uncommented = self.f.open_text("test/TextInput/uncommentedwordlist.txt") commented = self.f.open_text("test/TextInput/commentedwordlist.txt") self.assertEqual(uncommented, commented) @patch('os.path.isfile', return_value=True) def test_open_text_RejectsNonTxtFile(self, stub_isfile): badfile = "bad.doc" with self.assertRaises(TypeError) as exception_context: self.f.open_text(badfile) stub_isfile.assert_called() self.assertTrue('Invalid file extension. Must be .txt' in exception_context.exception) @patch('os.path.isfile', return_value=True) def test_open_text_AcceptsTxtFile_Mocked(self, stub_isfile): fake_file = io.StringIO("Mocked\nOutput") with mock.patch("src.FileIO.open", return_value=fake_file, create=True): result = self.f.open_text("/path/to/good.txt") self.assertEqual("Mocked\nOutput", result) stub_isfile.assert_called() def test_validate_directory_accepts_directories(self): result = FileIO.validate_directory(os.getcwd()) self.assertEqual(f'{os.getcwd()}/', result) def test_validate_directory_rejects_file(self): with self.assertRaises(NotADirectoryError) as exception_context: FileIO.validate_directory('/test/path/file.txt') self.assertTrue('must be a directory' in exception_context.exception)
def main() -> List[str]: # Parse Arguments parser = argparse.ArgumentParser( description="Visualize FB messenger data from .json files") parser.add_argument( "-i", "--inputfile", metavar="InFile", dest="inputfile", required=True, nargs=1, help=".json file containing messenger data", ) parser.add_argument( "-o", "--outputdirectory", metavar="OutFile", dest="outputdir", default=None, required=False, nargs=1, help="Pre-existing directory to put visualizations", ) parser.add_argument( "-w", "--wordlist", metavar="Wordlist", dest="wordlist", default=None, required=False, nargs=1, help=".txt file of words to ignore", ) # Analyze Data args = parser.parse_args() # Set up Logging formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger('MessengerViz') logger.setLevel(logging.DEBUG) outputdir = args.outputdir[0] if args.outputdir else None if outputdir: file_handler = logging.FileHandler(f'{outputdir}/MessengerViz.log') else: file_handler = logging.FileHandler(f'MessengerViz.log') file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) console_handler = logging.StreamHandler() console_handler.setLevel(logging.ERROR) console_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.addHandler(console_handler) logger.debug('Program called with %s', args) fileIO = FileIO() inputfile = args.inputfile[0] conversation = Conversation(fileIO.open_json(inputfile)) try: wordlist = fileIO.open_text(args.wordlist[0]) except TypeError: wordlist = None logger.info("Wordlist not defined. Moving on.") if outputdir is None: print_messages(conversation) elif os.path.isdir(outputdir): graph_data(outputdir, conversation, wordlist) write_messages(outputdir, conversation) else: logger.error('Received invalid directory specification: %s', outputdir) parser.print_help() raise getopt.GetoptError('Received invalid directory specification.') return print_messages(conversation)
def setUp(self): self.maxDiff = None self.setUpPyfakefs() self.f = FileIO()
def test_validate_directory_rejects_file(self): with self.assertRaises(NotADirectoryError) as exception_context: FileIO.validate_directory('/test/path/file.txt') self.assertTrue('must be a directory' in exception_context.exception)
def test_validate_directory_accepts_directories(self): result = FileIO.validate_directory(os.getcwd()) self.assertEqual(f'{os.getcwd()}/', result)
def setUp(self): self.maxDiff = None self.f = FileIO()
def setUpClass(cls): cls.maxDiff = None cls.skeleton_JSON = FileIO() cls.skeleton_JSON.open_json("test/Messages/message_skeleton_text.json") cls.message = Message(cls.skeleton_JSON.data)