def _download_attachments(self): """ Downloads all attachments from the project manager. """ # attachments function is a callback to the project manager attachments_function = self.projectmanager.server.attachments if not attachments_function or attachments_function is None: raise InvalidCallbackError('attachments callback function has not been set') for item in self._content: with open(os.path.join(self._output_path, item.filename), 'wb') as output_file: try: attachment_url = attachments_function(str(item.attachment_id), item.filename) Logger().info('Downloading file \'' + item.filename + '\' from \'' + attachment_url + '\'') curl_instance = pycurl.Curl() curl_instance.setopt(curl_instance.URL, attachment_url) curl_instance.setopt( pycurl.USERPWD, '{username}:{password}'.format( username=Configuration().jira.username, password=Configuration().jira.password ) ) curl_instance.setopt(curl_instance.WRITEDATA, output_file) curl_instance.perform() if curl_instance.getinfo(pycurl.RESPONSE_CODE) != 200: Logger().error( 'Error in downloading attachments. Got response code {0}'.format( curl_instance.getinfo(pycurl.RESPONSE_CODE) ) ) except pycurl.error as exception: Logger().error(exception) curl_instance.close()
def test_config_locations_returns_six_paths(self, mock_load): """ Purely for code coverage... """ mock_load.return_value = None config = Configuration(filename='') self.assertEquals(6, len(config._get_locations()))
def test_replace_date_in_release_date(self, mock_config_list, mock_arg): self.tearDown() mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'tests.mocks' config = Configuration(filename='valid_config.json') config.check = True self.assertTrue(config.check) self.assertIsInstance(config.replacements, Replacements) today = date.today() releasedate = Calendar().get_last_day_of_month_ahead() value_format = '%A, %d %B %Y' reldate = datetime.strftime( releasedate, value_format.replace('%d', '{th}')).replace( '{th}', (str(releasedate.day) + ("th" if 4 <= releasedate.day % 100 <= 20 else { 1: "st", 2: "nd", 3: "rd" }.get(releasedate.day % 10, "th")))) self.assertEquals(config.replacements.replace('{RELEASE_DATE}'), reldate)
def test_run_raises_type_error_if_attachments_callback_function_is_not_set( self, mock_config_list, mock_results, mock_jira_results, mock_jira_client, mock_open ): mock_jira_client.return_value = None mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'pyccata.core' report = ReportManager() report.add_callback('attachments', None) mock_jira_results.return_value = DataProviders._test_data_for_attachments() server = namedtuple('Server', 'server_address attachments') mock_results.return_value = server(server_address=None, attachments=None) self.assertIsInstance(Configuration().replacements, Replacements) Config = namedtuple('Config', 'query fields collate output_path') config = Config( query='project=test and attachments is not empty', fields=[ 'key', 'attachments' ], collate='zip', output_path='/tmp/{FIX_VERSION}' ) attachments = None with patch('os.path.exists') as mock_exists: mock_exists.return_value = False with patch('os.makedirs') as mock_os: attachments = Attachments(self._thread_manager, config) mock_os.assert_called_with('/tmp/' + Configuration().replacements.replace('{FIX_VERSION}')) self._thread_manager.append(attachments) with patch('pycurl.Curl') as mock_curl: with patch('pycurl.Curl.setopt') as mock_setopt: with patch('pycurl.Curl.perform') as mock_perform: with patch('pycurl.Curl.close') as mock_close: Curl = namedtuple('Curl', 'URL WRITEDATA setopt perform close getinfo') mock_curl.return_value = Curl( URL=None, WRITEDATA=None, setopt=mock_setopt, perform=mock_perform, close=mock_close, getinfo=lambda x: 200 ) with self.assertRaises(InvalidCallbackError): self._thread_manager.execute() self.assertIsInstance(attachments.failure, InvalidCallbackError) mock_setopt.assert_not_called() mock_perform.assert_not_called() mock_close.assert_not_called() mock_open.assert_not_called()
def test_report_callback_returns_callback(self, mock_config_list, mock_parser): mock_parser.return_value = [] mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'pyccata.core' config = Configuration(filename='valid_config.json') config.check = True report = ReportManager() report.add_callback('test', 'test_callback') self.assertEquals('test_callback', report.get_callback('test'))
def test_config_parse_flags(self, mock_config_list, mock_arguments, mock_parser): mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'tests.mocks' mock_parser.return_value = [] config = Configuration(filename='valid_config.json') self.assertGreater(mock_parser.call_count, 0) config.check = True self.assertTrue(config.check) self.assertIsInstance(config.replacements, Replacements)
def test_replace_words_in_string(self, string, response, mock_config_list, mock_arg): self.tearDown() mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'tests.mocks' config = Configuration(filename='valid_config.json') config.check = True self.assertTrue(config.check) self.assertIsInstance(config.replacements, Replacements) self.assertEquals(config.replacements.replace(string), response)
def test_build_pipeline(self, mock_locations, mock_flags): mock_locations.return_value = [self._path] config = Configuration(filename='pipeline-config.json') config.check = True self._cleanup() pipeline = PipelineController() with patch('subprocess.Popen.poll') as mock_poll: with patch('subprocess.Popen._execute_child') as mock_command: with patch('subprocess.Popen.communicate') as mock_comms: mock_comms.return_value = True pipeline.build() self.assertEquals(3, pipeline.length)
def test_configuration_raises_invalid_class_error_if_required_class_does_not_exist( self, data_key, data_driver, mock_config_list, mock_load): mock_config = DataProviders._get_config_for_test_with_invalid_classes() mock_load.return_value = None self.tearDown() mock_config_list.return_value = [self._path] Configuration._configuration = mock_config with self.assertRaises(InvalidClassError): config = Configuration(filename='config_sections.json') config.validate_config([data_key]) mock_load.assert_called_once_with()
def test_configuration_raises_requried_key_error_if_required_config_is_not_found( self, data_key, data_driver, mock_config_list, mock_load, mock_parser): mock_config = DataProviders._get_config_for_test_without_report( manager=data_driver, reporting=data_driver) mock_config_list.return_value = [self._path] Configuration._configuration = mock_config driver = data_driver if data_key != 'reporting' else 'report' with self.assertRaisesRegexp(RequiredKeyError, '.*\'<root>[./]?{0}\'.*'.format(driver)): config = Configuration(filename='config_missing.json') config.validate_config([data_key]) mock_load.assert_called_once_with()
def test_manager_loading_returns_true_if_required_is_valid( self, data_key, data_driver, mock_config_list, mock_load): mock_config = DataProviders._get_config_for_test(manager=data_driver, reporting=data_driver) mock_load.return_value = None self.tearDown() mock_config_list.return_value = [self._path] Configuration._configuration = mock_config Configuration.NAMESPACE = 'tests.mocks' config = Configuration(filename='config_sections.json') config.validate_config([data_key]) mock_load.assert_called_once_with() self.assertEquals(data_driver, getattr(config, data_key))
def setUp(self, mock_config, mock_parser, mock_log): self.tearDown() mock_log.return_value = None Logger._instance = mock_log path = os.path.dirname(os.path.realpath(__file__ + '../../../../')) self._path = os.path.join(path, os.path.join('tests', 'conf')) mock_config.return_value = [self._path] mock_parser.return_value = [] config = None with patch('argparse.ArgumentParser.add_argument'): config = Configuration(filename='valid_config.json') config.check = True self._report_manager = ReportManager() self._thread_manager = ThreadManager()
def __init__(self, content): """ initialise the object """ self._content = [ line for line in read_file( content, report_path=Configuration().report.datapath).split( "\n\n") ]
def test_configuration_calls_validation_once_config_is_loaded( self, data_key, data_driver, mock_config_list, mock_load): mock_config = DataProviders._get_config_for_test() mock_config_list.return_value = [self._path] mock_load.return_value = None self.tearDown() Configuration._configuration = mock_config required_elements = [data_key] config = Configuration(filename='config_sections.json') mock_load.assert_called_once_with() with patch('pyccata.core.configuration.Configuration.{0}'.format( data_key), new_callable=PropertyMock) as mock_manager: mock_manager.return_value = object() self.assertTrue(config.validate_config(required_elements)) mock_manager.assert_called_with(data_driver)
def test_configuration_calls_validation_once_config_is_loaded( self, mock_validate, mock_config_list): mock_config_list.return_value = [self._path] mock_validate.return_value = True self.tearDown() Configuration(filename='config_sections.json') mock_validate.assert_called_with(['manager'])
def test_build_raises_exception_if_parts_class_does_not_exist( self, mock_config, mock_parser): mock_config.return_value = [self._path] with self.assertRaises(InvalidClassError): Configuration('invalid_report_parts.json') document = DocumentController() document.build()
def test_render(self, mock_config, mock_parser): mock_config.return_value = [self._path] Configuration('config_simple.json') document = DocumentController() self.assertIsInstance(document.configuration, Configuration) self.assertIsInstance(document.threadmanager, ThreadManager) self.assertIsInstance(document.reportmanager, ReportManager) self.assertIsInstance(document.partfactory, DocumentPartFactory) with patch('docx.document.Document.add_heading') as mock_heading, \ patch('docx.document.Document.add_paragraph') as mock_paragraph, \ patch('docx.document.Document.save') as mock_save: document.build() heading_calls = [ call('Test document structure for WeeklyReport/Helicopter view', 0), call('Week 41', 1), call('hello world', 1), #call('Test title', 3), call('This has sub-sections', 1), call('this is sub section 1', 2), call('this is sub section 2', 2), call('This section uses a file path for its text', 1) ] self.assertEquals(mock_heading.call_count, len(heading_calls)) mock_heading.assert_has_calls(heading_calls) self.assertEquals(17, mock_paragraph.call_count)
def test_setup_and_run_handles_exception(self, mock_config_list, mock_parser, mock_failure): mock_parser.return_value = [] mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'pyccata.core' report = ReportManager() # never actually thrown from the filter but useful for testing and coverage ;-) mock_failure.return_value = InvalidFilenameError('The specified file does not exist') report.add_callback('test', 'test_callback') self.assertEquals('test_callback', report.get_callback('test')) self.assertIsInstance(Configuration().replacements, Replacements) Config = namedtuple('Config', 'query fields collate output_path') config = Config( query='project=test and attachments is not empty', fields=[ 'key', 'attachments' ], collate='zip', output_path='/tmp/{FIX_VERSION}' ) Replacements().find('FIX_VERSION').value = '28/Jul/2016' attachments = None with patch('os.makedirs') as mock_os: attachments = Attachments(self._thread_manager, config) mock_os.assert_called_with('/tmp/28/Jul/2016') with patch('pyccata.core.filter.Filter.failed', return_value=True): attachments.run() self.assertEquals(str(attachments._content.failure), 'The specified file does not exist')
def test_threadmanager_raises_exception_during_initialisation( self, mock_threadmanager, mock_config, mock_parser): mock_config.return_value = [self._path] Configuration('config_sections.json') mock_threadmanager.side_effect = AttributeError( 'Invalid attribute \'foo\' for manager ThreadManager') with self.assertRaises(AttributeError): DocumentController()
def configuration(self): """ Get the cofiguration object - load on demand """ if self._configuration is None: self._configuration = Configuration() return self._configuration
def test_thread_manager_raises_exception(self, exception, message, mock_config, mock_manager_load, mock_parser): mock_manager_load.side_effect = exception(message) mock_config.return_value = [self._path] Configuration('config_sections.json') with self.assertRaises(exception): DocumentController()
def test_configuration_raises_io_exception_if_config_file_cannot_be_found( self, mock_config_list): mock_config_list.return_value = ['/i/dont/exist'] # patching initialises singletons - tear-down to ensure a clean start self.tearDown() with self.assertRaises(IOError): Configuration()
def test_replace_date_in_fix_version(self, mock_config_list, mock_arg): self.tearDown() mock_config_list.return_value = [self._path] Configuration.NAMESPACE = 'tests.mocks' config = Configuration(filename='valid_config.json') config.check = True self.assertTrue(config.check) self.assertIsInstance(config.replacements, Replacements) config.replacements.find('FIX_VERSION').value = '28/Jul/2016' today = date.today() releasedate = today + timedelta((3 - today.weekday()) % 7) self.assertEquals(config.replacements.replace('{FIX_VERSION}'), '28/Jul/2016') self.assertEquals(config.replacements.replace('some text'), 'Some Replacement Text')
def test_report_manager_loads_document_part_factory( self, mock_config, mock_parser): mock_config.return_value = [self._path] Configuration('config_sections.json') document = DocumentController() self.assertIsInstance(document.configuration, Configuration) self.assertIsInstance(document.threadmanager, ThreadManager) self.assertIsInstance(document.reportmanager, ReportManager) self.assertIsInstance(document.partfactory, DocumentPartFactory)
def test_report_manager_raises_invalid_module_error_if_parts_module_doesnt_exist( self, mock_config, mock_parser): mock_config.return_value = [self._path] Configuration('config_sections.json') with self.assertRaises(InvalidModuleError): with patch('pyccata.core.factory.DocumentPartFactory.MODULE', new_callable=PropertyMock) as mock_module: mock_module.return_value = 'pts' DocumentController()
def configuration(self): """ Lazy load the Configuration singleton instance @return Configuration """ if self._configuration is None: self._configuration = Configuration() return self._configuration
def setUp(self, mock_config, mock_log, mock_parser): path = os.path.dirname(os.path.realpath(__file__ + '../../../../')) self._path = os.path.join(path, os.path.join('tests', 'conf')) mock_config.return_value = [self._path] mock_log.return_value = None mock_parser.return_value = [] Logger._instance = mock_log Configuration('config_sections.json') self._thread_manager = ThreadManager()
def setup(self, query, fields=None, collate=None, output_path='/tmp'): """ Set up the attachments object """ # pylint: disable=arguments-differ self._content = Filter(query, max_results=50, fields=fields) self.threadmanager.append(self._content) self.projectmanager = Configuration().manager self._collate = collate.split(',') self._output_path = Replacements().replace(output_path) create_directory(self._output_path)
def test_configuration_raises_requried_key_error_if_required_value_is_not_defined( self, mock_config_list): key = 'idontexist' mock_config_list.return_value = [self._path] self.tearDown() Configuration._required_root_elements = [key] required_elements = Configuration._required_root_elements with self.assertRaisesRegexp(RequiredKeyError, '.*\'<root>[./]?{0}\'.*'.format(key)): config = Configuration(filename='config_sections.json')
def test_render_image(self, width, expected, mock_picture): Config = namedtuple('Config', 'filename width') config = Config(filename='department.png', width=width) picture = Picture(self._thread_manager, config) picture.run() picture.render(ReportManager()) mock_picture.assert_called_with(os.path.join( os.getcwd(), Configuration().report.datapath, config.filename), width=expected)