def test_handle_legalcodes_with_updated_translations(self): helper = TransifexHelper() dummy_repo = DummyRepo("/trans/repo") # No legalcodes, shouldn't call anything or return anything result = helper.handle_legalcodes_with_updated_translations( dummy_repo, [] ) self.assertEqual([], result) # legalcodes for two branches legalcode1 = LegalCodeFactory( license__version="4.0", license__license_code="by-nc", language_code="fr", ) legalcode2 = LegalCodeFactory( license__version="4.0", license__license_code="by-nd", language_code="de", ) with mpo(helper, "handle_updated_translation_branch") as mock_handle: result = helper.handle_legalcodes_with_updated_translations( dummy_repo, [legalcode1, legalcode2] ) self.assertEqual( [legalcode1.branch_name(), legalcode2.branch_name()], result ) self.assertEqual( [ mock.call(dummy_repo, [legalcode1]), mock.call(dummy_repo, [legalcode2]), ], mock_handle.call_args_list, )
def test_transifex_get_pofile_content(self): helper = TransifexHelper() with mpo(helper, "request20") as mock_req20: mock_req20.return_value = mock.MagicMock(content=b"xxxxxx") result = helper.transifex_get_pofile_content("slug", "lang") mock_req20.assert_called_with( "get", "project/CC/resource/slug/translation/lang/?mode=translator&file=PO" ) self.assertEqual(result, b"xxxxxx")
def test_check_for_translation_updates_with_dirty_repo(self): mock_repo = MagicMock() mock_repo.__str__.return_value = "mock_repo" mock_repo.is_dirty.return_value = True with mock.patch.object(git, "Repo") as mock_Repo: mock_Repo.return_value.__enter__.return_value = mock_repo helper = TransifexHelper() with self.assertRaisesMessage(Exception, "is dirty. We cannot continue."): helper.check_for_translation_updates()
def test_check_for_translation_updates_with_no_legalcodes(self): mock_repo = MagicMock() mock_repo.__str__.return_value = "mock_repo" mock_repo.is_dirty.return_value = False with mock.patch.object(git, "Repo") as mock_Repo: mock_Repo.return_value.__enter__.return_value = mock_repo with mock.patch.object( TransifexHelper, "get_transifex_resource_stats" ) as mock_get_transifex_resource_stats: mock_get_transifex_resource_stats.return_value = {} helper = TransifexHelper() helper.check_for_translation_updates()
def test_update_branch_for_legalcode(self): helper = TransifexHelper() dummy_repo = DummyRepo("/trans/repo") legalcode = LegalCodeFactory( license__version="4.0", license__license_code="by-nc", language_code="fr", ) helper._stats = { legalcode.license.resource_slug: { legalcode.language_code: { "translated": { "last_activity": now().isoformat(), } } } } trb = TranslationBranch.objects.create( branch_name=legalcode.branch_name(), version=legalcode.license.version, language_code=legalcode.language_code, complete=False, ) content = b"wxyz" # transifex_get_pofile_content # save_content_as_pofile_and_mofile with mpo( helper, "transifex_get_pofile_content" ) as mock_get_content, mp( "licenses.transifex.save_content_as_pofile_and_mofile" ) as mock_save: mock_get_content.return_value = content mock_save.return_value = [legalcode.translation_filename()] result = helper.update_branch_for_legalcode( dummy_repo, legalcode, trb ) self.assertIsNone(result) mock_get_content.assert_called_with( legalcode.license.resource_slug, legalcode.language_code ) mock_save.assert_called_with(legalcode.translation_filename(), content) self.assertEqual({legalcode}, set(trb.legalcodes.all())) relpath = os.path.relpath( legalcode.translation_filename(), settings.TRANSLATION_REPOSITORY_DIRECTORY, ) dummy_repo.index.add.assert_called_with([relpath])
def test_handle_updated_translation_branch(self): helper = TransifexHelper() dummy_repo = DummyRepo("/trans/repo") result = helper.handle_updated_translation_branch(dummy_repo, []) self.assertIsNone(result) legalcode1 = LegalCodeFactory( license__version="4.0", license__license_code="by-nc", language_code="fr", ) legalcode2 = LegalCodeFactory( license__version="4.0", license__license_code="by-nd", language_code="fr", ) with mp("licenses.transifex.setup_local_branch") as mock_setup, mpo( helper, "update_branch_for_legalcode" ) as mock_update_branch, mp( "licenses.transifex.call_command" ) as mock_call_command, mp( "licenses.transifex.commit_and_push_changes" ) as mock_commit: # setup_local_branch # update_branch_for_legalcode # commit_and_push_changes # branch_object.save() result = helper.handle_updated_translation_branch( dummy_repo, [legalcode1, legalcode2] ) self.assertIsNone(result) mock_setup.assert_called_with(dummy_repo, legalcode1.branch_name()) # Should have published static files for this branch expected = [ mock.call("publish", branch_name=legalcode1.branch_name()), ] self.assertEqual(expected, mock_call_command.call_args_list) trb = TranslationBranch.objects.get() expected = [ mock.call(dummy_repo, legalcode1, trb), mock.call(dummy_repo, legalcode2, trb), ] self.assertEqual(expected, mock_update_branch.call_args_list) mock_commit.assert_called_with( dummy_repo, "Translation changes from Transifex.", "", push=True )
def handle(self, **options): branches_updated = TransifexHelper( verbosity=options["verbosity"]).check_for_translation_updates() # run collectstatic if we're going to publish if branches_updated: call_command("collectstatic", interactive=False) print("Ran collectstatic") for branch_name in branches_updated: # Update the HTML files, commit, and push call_command("publish", branch_name=branch_name) print(f"Updated HTML files for {branch_name}, updated branch," " and pushed if needed")
def tx_upload_messages(self): """ Upload the messages to Transifex, creating the resource if it doesn't already exist. """ # Have to do English first, they get uploaded differently as the "source" messages # and are required if we need to first create the resource in Transifex. en_legalcode = self.get_legalcode_for_language_code(DEFAULT_LANGUAGE_CODE) helper = TransifexHelper() helper.upload_messages_to_transifex(legalcode=en_legalcode) for legalcode in self.legal_codes.exclude(language_code=DEFAULT_LANGUAGE_CODE): helper.upload_messages_to_transifex(legalcode=legalcode)
def setUp(self): self.helper = TransifexHelper()
class TestTransifex(TestCase): def setUp(self): self.helper = TransifexHelper() def test_request20_success(self): with mpo(self.helper.api_v20, "get") as mock_get: mock_get.return_value = mock.MagicMock(status_code=200) self.helper.request20( path="foo/bar", method="get", data={"a": 1}, files=[(1, 2)] ) mock_get.assert_called_with( "https://www.transifex.com/api/2/foo/bar", data={"a": 1}, files=[(1, 2)], ) def test_request25_success(self): with mpo(self.helper.api_v25, "get") as mock_get: mock_get.return_value = mock.MagicMock(status_code=200) self.helper.request25( path="foo/bar", method="get", data={"a": 1}, files=[(1, 2)] ) mock_get.assert_called_with( "https://api.transifex.com/foo/bar", data={"a": 1}, files=[(1, 2)] ) def test_request20_failure(self): error_response = requests.Response() error_response.status_code = 500 error_response.reason = "testing" with mpo(self.helper.api_v20, "get") as mock_get: mock_get.return_value = error_response with self.assertRaises(requests.HTTPError): self.helper.request20( path="foo/bar", method="get", data={"a": 1}, files=[(1, 2)] ) mock_get.assert_called_with( "https://www.transifex.com/api/2/foo/bar", data={"a": 1}, files=[(1, 2)], ) def test_request25_failure(self): error_response = requests.Response() error_response.status_code = 500 error_response.reason = "testing" with mpo(self.helper.api_v25, "get") as mock_get: mock_get.return_value = error_response with self.assertRaises(requests.HTTPError): self.helper.request25( path="foo/bar", method="get", data={"a": 1}, files=[(1, 2)] ) mock_get.assert_called_with( "https://api.transifex.com/foo/bar", data={"a": 1}, files=[(1, 2)] ) def test_get_transifex_resources(self): with mpo(self.helper, "request25") as mock_request: mock_request.return_value.json.return_value = {"a": 1} result = self.helper.get_transifex_resources() mock_request.assert_called_with( "get", "organizations/org/projects/proj/resources/" ) self.assertEqual({"a": 1}, result) def test_files_argument(self): result = self.helper.files_argument("foo", "bar", "baz") self.assertEqual( [("foo", ("bar", "baz", "application/octet-stream"))], result ) def test_create_resource(self): with mpo(self.helper, "request20") as mock_request: self.helper.create_resource( "slug", "name", "pofilename", "pofilecontent" ) mock_request.assert_called_with( "post", "project/proj/resources/", data={"slug": "slug", "name": "name", "i18n_type": "PO"}, files=[ ( "content", ( "pofilename", "pofilecontent", "application/octet-stream", ), ) ], ) def test_update_source_messages(self): with mpo(self.helper, "request20") as mock_request: self.helper.update_source_messages( "slug", "pofilename", "pofilecontent" ) mock_request.assert_called_with( "put", "project/proj/resource/slug/content/", files=[ ( "content", ( "pofilename", "pofilecontent", "application/octet-stream", ), ) ], ) def test_update_translations(self): with mpo(self.helper, "request20") as mock_request: self.helper.update_translations( "slug", "lang", "pofilename", "pofilecontent" ) mock_request.assert_called_with( "put", "project/proj/resource/slug/translation/lang/", files=[ ( "file", ( "pofilename", "pofilecontent", "application/octet-stream", ), ) ], ) def test_upload_messages_to_transifex_no_resource_yet(self): # English so we can create the resource license = LicenseFactory(license_code="by-nd", version="4.0") legalcode = LegalCodeFactory( license=license, language_code=DEFAULT_LANGUAGE_CODE, ) pofile_content = """ msgid "" msgstr "" "Project-Id-Version: by-nd-4.0\n" "Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "license_medium" msgstr "Attribution-NoDerivatives 4.0 International" """ english_pofile = polib.pofile(pofile=pofile_content) with mpo(self.helper, "get_transifex_resources") as mock_gtr: mock_gtr.return_value = [] with mpo(self.helper, "create_resource") as mock_create_resource: with mpo(legalcode, "get_pofile") as mock_gpwem: mock_gpwem.return_value = english_pofile with mp( "licenses.transifex.get_pofile_content" ) as mock_gpc: mock_gpc.return_value = "not really" self.helper.upload_messages_to_transifex(legalcode) mock_create_resource.assert_called_with( "by-nd_40", "CC BY-ND 4.0", "/trans/repo/legalcode/en/LC_MESSAGES/by-nd_40.po", "not really", ) mock_gpwem.assert_called_with() mock_gtr.assert_called_with() def test_upload_messages_to_transifex_no_resource_yet_not_english(self): # Must be english or we can't create the resource # If we try this with a non-english language and there's no resource, # we should get an error. legalcode = LegalCodeFactory(language_code="es") test_pofile = polib.POFile() with mpo(self.helper, "get_transifex_resources") as mock_gtr: mock_gtr.return_value = [] with mpo(legalcode, "get_pofile") as mock_gpwem: mock_gpwem.return_value = test_pofile with self.assertRaisesMessage( ValueError, "Must upload English first" ): self.helper.upload_messages_to_transifex(legalcode) mock_gtr.assert_called_with() mock_gpwem.assert_called_with() def test_upload_messages_english_resource_exists(self): # English because it's the source messages and is handled differently license = LicenseFactory(license_code="by-nd", version="4.0") legalcode = LegalCodeFactory( license=license, language_code=DEFAULT_LANGUAGE_CODE, ) test_resources = [ { "slug": license.resource_slug, } ] test_pofile = polib.POFile() with mpo(self.helper, "get_transifex_resources") as mock_gtr: mock_gtr.return_value = test_resources with mp("licenses.transifex.get_pofile_content") as mock_gpc: mock_gpc.return_value = "not really" with mpo(self.helper, "update_source_messages") as mock_usm: self.helper.upload_messages_to_transifex( legalcode, test_pofile ) mock_gtr.assert_called_with() mock_gpc.assert_called_with(test_pofile) mock_usm.assert_called_with( "by-nd_40", "/trans/repo/legalcode/en/LC_MESSAGES/by-nd_40.po", "not really", ) def test_upload_messages_non_english_resource_exists(self): # non-English because it's not the source messages and is handled # differently license = LicenseFactory(license_code="by-nd", version="4.0") legalcode = LegalCodeFactory(license=license, language_code="fr") test_resources = [ { "slug": license.resource_slug, } ] test_pofile = mock.MagicMock() with mpo(self.helper, "get_transifex_resources") as mock_gtr: mock_gtr.return_value = test_resources with mp("licenses.transifex.get_pofile_content") as mock_gpc: mock_gpc.return_value = "not really" with mpo(self.helper, "update_translations") as mock_ut: self.helper.upload_messages_to_transifex( legalcode, test_pofile ) mock_gtr.assert_called_with() mock_gpc.assert_called_with(test_pofile) mock_ut.assert_called_with( "by-nd_40", "fr", "/trans/repo/legalcode/fr/LC_MESSAGES/by-nd_40.po", "not really", ) def test_get_transifex_resource_stats(self): # First call returns a response whose json value is a list of dicts # with slug keys call0_response = MagicMock() call0_response.json.return_value = [{"slug": "slug0"}] # second call is more data about slug0 - FIXME call1_response = MagicMock() call1_response.json.return_value = {"stats": "stats1"} with mpo(self.helper, "request25") as mock_request25: # Return values for each call to request25 mock_request25.side_effect = [ call0_response, call1_response, ] result = self.helper.get_transifex_resource_stats() calls = mock_request25.call_args_list self.assertEqual( [ call("get", "organizations/org/projects/proj/resources/"), call("get", "organizations/org/projects/proj/resources/slug0"), ], calls, ) self.assertEqual({"slug0": "stats1"}, result)
def help_test_check_for_translation_updates( self, first_time, changed, resource_exists=True, language_exists=True ): """ Helper to test several conditions, since all the setup is so convoluted. """ language_code = "zh-Hans" license = LicenseFactory(version="4.0", license_code="by-nd") first_translation_update_datetime = datetime.datetime( 2007, 1, 25, 12, 0, 0, tzinfo=utc ) changed_translation_update_datetime = datetime.datetime( 2020, 9, 30, 13, 11, 52, tzinfo=utc ) if first_time: # We don't yet know when the last update was. legalcode_last_update = None else: # The last update we know of was at this time. legalcode_last_update = first_translation_update_datetime legalcode = LegalCodeFactory( license=license, language_code=language_code, translation_last_update=legalcode_last_update, ) resource_slug = license.resource_slug # Will need an English legalcode if we need to create the resource if not resource_exists and language_code != DEFAULT_LANGUAGE_CODE: LegalCodeFactory( license=license, language_code=DEFAULT_LANGUAGE_CODE, ) # 'timestamp' returns on translation stats from transifex if changed: # now it's the newer time timestamp = changed_translation_update_datetime.isoformat() else: # it's still the first time timestamp = first_translation_update_datetime.isoformat() mock_repo = MagicMock() mock_repo.is_dirty.return_value = False legalcodes = [legalcode] dummy_repo = DummyRepo("/trans/repo") # A couple of places use git.Repo(path) to get a git repo object. Have # them all get back our same dummy repo. def dummy_repo_factory(path): return dummy_repo helper = TransifexHelper() with mpo( helper, "handle_legalcodes_with_updated_translations" ) as mock_handle_legalcodes, mpo( helper, "get_transifex_resource_stats" ) as mock_get_transifex_resource_stats, mpo( helper, "create_resource" ) as mock_create_resource, mpo( LegalCode, "get_pofile" ) as mock_get_pofile, mpo( helper, "upload_messages_to_transifex" ) as mock_upload: if resource_exists: if language_exists: mock_get_transifex_resource_stats.return_value = { resource_slug: { language_code: { "translated": { "last_activity": timestamp, } } } } else: # language does not exist first time, does the second time mock_get_transifex_resource_stats.side_effect = [ {resource_slug: {}}, { resource_slug: { language_code: { "translated": { "last_activity": timestamp, } } } }, ] else: # First time does not exist, second time does mock_get_transifex_resource_stats.side_effect = [ {}, { resource_slug: { language_code: { "translated": { "last_activity": timestamp, } } } }, ] # Will need pofile mock_get_pofile.return_value = polib.POFile() helper.check_for_translation_updates_with_repo_and_legalcodes( dummy_repo, legalcodes ) if not resource_exists: # Should have tried to create resource mock_create_resource.assert_called_with( resource_slug=resource_slug, resource_name=legalcode.license.fat_code(), pofilename=os.path.basename(legalcode.translation_filename()), pofile_content=get_pofile_content( mock_get_pofile.return_value ), ) else: # Not mock_create_resource.assert_not_called() if language_exists: mock_upload.assert_not_called() else: mock_upload.assert_called() mock_get_transifex_resource_stats.assert_called_with() legalcode.refresh_from_db() if changed: # we mocked the actual processing, so... self.assertEqual( first_translation_update_datetime, legalcode.translation_last_update, ) mock_handle_legalcodes.assert_called_with(dummy_repo, [legalcode]) else: self.assertEqual( first_translation_update_datetime, legalcode.translation_last_update, ) mock_handle_legalcodes.assert_called_with(dummy_repo, []) return