@@ -822,6 +822,42 @@ def isModeExecChanged(src_mode, dst_mode):
822
822
return isModeExec (src_mode ) != isModeExec (dst_mode )
823
823
824
824
825
+ def p4KeysContainingNonUtf8Chars ():
826
+ """Returns all keys which may contain non UTF-8 encoded strings
827
+ for which a fallback strategy has to be applied.
828
+ """
829
+ return ['desc' , 'client' , 'FullName' ]
830
+
831
+
832
+ def p4KeysContainingBinaryData ():
833
+ """Returns all keys which may contain arbitrary binary data
834
+ """
835
+ return ['data' ]
836
+
837
+
838
+ def p4KeyContainsFilePaths (key ):
839
+ """Returns True if the key contains file paths. These are handled by decode_path().
840
+ Otherwise False.
841
+ """
842
+ return key .startswith ('depotFile' ) or key in ['path' , 'clientFile' ]
843
+
844
+
845
+ def p4KeyWhichCanBeDirectlyDecoded (key ):
846
+ """Returns True if the key can be directly decoded as UTF-8 string
847
+ Otherwise False.
848
+
849
+ Keys which can not be encoded directly:
850
+ - `data` which may contain arbitrary binary data
851
+ - `desc` or `client` or `FullName` which may contain non-UTF8 encoded text
852
+ - `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
853
+ """
854
+ if key in p4KeysContainingNonUtf8Chars () or \
855
+ key in p4KeysContainingBinaryData () or \
856
+ p4KeyContainsFilePaths (key ):
857
+ return False
858
+ return True
859
+
860
+
825
861
def p4CmdList (cmd , stdin = None , stdin_mode = 'w+b' , cb = None , skip_info = False ,
826
862
errors_as_exceptions = False , * k , ** kw ):
827
863
@@ -851,15 +887,13 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
851
887
try :
852
888
while True :
853
889
entry = marshal .load (p4 .stdout )
890
+
854
891
if bytes is not str :
855
- # Decode unmarshalled dict to use str keys and values, except for:
856
- # - `data` which may contain arbitrary binary data
857
- # - `desc` or `client` or `FullName` which may contain non-UTF8 encoded text handled below, eagerly converted to bytes
858
- # - `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
892
+ # Decode unmarshalled dict to use str keys and values. Special cases are handled below.
859
893
decoded_entry = {}
860
894
for key , value in entry .items ():
861
895
key = key .decode ()
862
- if isinstance (value , bytes ) and not (key in ( 'data' , 'desc' , 'FullName' , 'path' , 'clientFile' , 'client' ) or key . startswith ( 'depotFile' ) ):
896
+ if isinstance (value , bytes ) and p4KeyWhichCanBeDirectlyDecoded (key ):
863
897
value = value .decode ()
864
898
decoded_entry [key ] = value
865
899
# Parse out data if it's an error response
@@ -869,12 +903,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
869
903
if skip_info :
870
904
if 'code' in entry and entry ['code' ] == 'info' :
871
905
continue
872
- if 'desc' in entry :
873
- entry ['desc' ] = metadata_stream_to_writable_bytes (entry ['desc' ])
874
- if 'client' in entry :
875
- entry ['client' ] = metadata_stream_to_writable_bytes (entry ['client' ])
876
- if 'FullName' in entry :
877
- entry ['FullName' ] = metadata_stream_to_writable_bytes (entry ['FullName' ])
906
+ for key in p4KeysContainingNonUtf8Chars ():
907
+ if key in entry :
908
+ entry [key ] = metadata_stream_to_writable_bytes (entry [key ])
878
909
if cb is not None :
879
910
cb (entry )
880
911
else :
0 commit comments