19
19
from babel .core import Locale
20
20
from babel .messages import pofile
21
21
from babel .messages .catalog import Catalog , Message
22
+ from babel .messages .pofile import _enclose_filename_if_necessary , _extract_locations
22
23
from babel .util import FixedOffsetTimezone
23
24
24
25
@@ -438,6 +439,19 @@ def test_missing_plural_in_the_middle(self):
438
439
assert message .string [1 ] == ''
439
440
assert message .string [2 ] == 'Vohs [text]'
440
441
442
+ def test_with_location (self ):
443
+ buf = StringIO ('''\
444
+ #: main.py:1 \u2068 filename with whitespace.py\u2069 :123
445
+ msgid "foo"
446
+ msgstr "bar"
447
+ ''' )
448
+ catalog = pofile .read_po (buf , locale = 'de_DE' )
449
+ assert len (catalog ) == 1
450
+ message = catalog ['foo' ]
451
+ assert message .string == 'bar'
452
+ assert message .locations == [("main.py" , 1 ), ("filename with whitespace.py" , 123 )]
453
+
454
+
441
455
def test_abort_invalid_po_file (self ):
442
456
invalid_po = '''
443
457
msgctxt ""
@@ -841,6 +855,59 @@ def test_no_include_lineno(self):
841
855
msgid "foo"
842
856
msgstr ""'''
843
857
858
+ def test_white_space_in_location (self ):
859
+ catalog = Catalog ()
860
+ catalog .add ('foo' , locations = [('main.py' , 1 )])
861
+ catalog .add ('foo' , locations = [('utils b.py' , 3 )])
862
+ buf = BytesIO ()
863
+ pofile .write_po (buf , catalog , omit_header = True , include_lineno = True )
864
+ assert buf .getvalue ().strip () == b'''#: main.py:1 \xe2 \x81 \xa8 utils b.py\xe2 \x81 \xa9 :3
865
+ msgid "foo"
866
+ msgstr ""'''
867
+
868
+ def test_white_space_in_location_already_enclosed (self ):
869
+ catalog = Catalog ()
870
+ catalog .add ('foo' , locations = [('main.py' , 1 )])
871
+ catalog .add ('foo' , locations = [('\u2068 utils b.py\u2069 ' , 3 )])
872
+ buf = BytesIO ()
873
+ pofile .write_po (buf , catalog , omit_header = True , include_lineno = True )
874
+ assert buf .getvalue ().strip () == b'''#: main.py:1 \xe2 \x81 \xa8 utils b.py\xe2 \x81 \xa9 :3
875
+ msgid "foo"
876
+ msgstr ""'''
877
+
878
+ def test_tab_in_location (self ):
879
+ catalog = Catalog ()
880
+ catalog .add ('foo' , locations = [('main.py' , 1 )])
881
+ catalog .add ('foo' , locations = [('utils\t b.py' , 3 )])
882
+ buf = BytesIO ()
883
+ pofile .write_po (buf , catalog , omit_header = True , include_lineno = True )
884
+ assert buf .getvalue ().strip () == b'''#: main.py:1 \xe2 \x81 \xa8 utils b.py\xe2 \x81 \xa9 :3
885
+ msgid "foo"
886
+ msgstr ""'''
887
+
888
+ def test_tab_in_location_already_enclosed (self ):
889
+ catalog = Catalog ()
890
+ catalog .add ('foo' , locations = [('main.py' , 1 )])
891
+ catalog .add ('foo' , locations = [('\u2068 utils\t b.py\u2069 ' , 3 )])
892
+ buf = BytesIO ()
893
+ pofile .write_po (buf , catalog , omit_header = True , include_lineno = True )
894
+ assert buf .getvalue ().strip () == b'''#: main.py:1 \xe2 \x81 \xa8 utils b.py\xe2 \x81 \xa9 :3
895
+ msgid "foo"
896
+ msgstr ""'''
897
+
898
+
899
+ class RoundtripPoTestCase (unittest .TestCase ):
900
+
901
+ def test_enclosed_filenames_in_location_comment (self ):
902
+ catalog = Catalog ()
903
+ catalog .add ("foo" , lineno = 2 , locations = [("main 1.py" , 1 )], string = "" )
904
+ catalog .add ("bar" , lineno = 6 , locations = [("other.py" , 2 )], string = "" )
905
+ catalog .add ("baz" , lineno = 10 , locations = [("main 1.py" , 3 ), ("other.py" , 4 )], string = "" )
906
+ buf = BytesIO ()
907
+ pofile .write_po (buf , catalog , omit_header = True , include_lineno = True )
908
+ buf .seek (0 )
909
+ catalog2 = pofile .read_po (buf )
910
+ assert True is catalog .is_identical (catalog2 )
844
911
845
912
class PofileFunctionsTestCase (unittest .TestCase ):
846
913
@@ -864,6 +931,51 @@ def test_denormalize_on_msgstr_without_empty_first_line(self):
864
931
assert expected_denormalized == pofile .denormalize (f'""\n { msgstr } ' )
865
932
866
933
934
+ @pytest .mark .parametrize (("line" , "locations" ), [
935
+ ("\u2068 file1.po\u2069 " , ["file1.po" ]),
936
+ ("file1.po \u2068 file 2.po\u2069 file3.po" , ["file1.po" , "file 2.po" , "file3.po" ]),
937
+ ("file1.po:1 \u2068 file 2.po\u2069 :2 file3.po:3" , ["file1.po:1" , "file 2.po:2" , "file3.po:3" ]),
938
+ ("\u2068 file1.po\u2069 :1 \u2068 file\t 2.po\u2069 :2 file3.po:3" ,
939
+ ["file1.po:1" , "file\t 2.po:2" , "file3.po:3" ]),
940
+ ("file1.po file2.po" , ["file1.po" , "file2.po" ]),
941
+ ("file1.po \u2068 \u2069 file2.po" , ["file1.po" , "file2.po" ]),
942
+ ])
943
+ def test_extract_locations_valid_location_comment (line , locations ):
944
+ assert locations == _extract_locations (line )
945
+
946
+
947
+ @pytest .mark .parametrize (("line" ,), [
948
+ ("\u2068 file 1.po" ,),
949
+ ("file 1.po\u2069 " ,),
950
+ ("\u2069 file 1.po\u2068 " ,),
951
+ ("\u2068 file 1.po:1 \u2068 file 2.po\u2069 :2" ,),
952
+ ("\u2068 file 1.po\u2069 :1 file 2.po\u2069 :2" ,),
953
+ ])
954
+ def test_extract_locations_invalid_location_comment (line ):
955
+ with pytest .raises (ValueError ):
956
+ _extract_locations (line )
957
+
958
+
959
+ @pytest .mark .parametrize (("filename" ,), [
960
+ ("file.po" ,),
961
+ ("file_a.po" ,),
962
+ ("file-a.po" ,),
963
+ ("file\n .po" ,),
964
+ ("\u2068 file.po\u2069 " ,),
965
+ ("\u2068 file a.po\u2069 " ,),
966
+ ])
967
+ def test_enclose_filename_if_necessary_no_change (filename ):
968
+ assert filename == _enclose_filename_if_necessary (filename )
969
+
970
+
971
+ @pytest .mark .parametrize (("filename" ,), [
972
+ ("file a.po" ,),
973
+ ("file\t a.po" ,),
974
+ ])
975
+ def test_enclose_filename_if_necessary_enclosed (filename ):
976
+ assert "\u2068 " + filename + "\u2069 " == _enclose_filename_if_necessary (filename )
977
+
978
+
867
979
def test_unknown_language_roundtrip ():
868
980
buf = StringIO (r'''
869
981
msgid ""
0 commit comments