Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd2f7284

Browse files
committed
Add trailers_list and trailers_list methods to fix the commit trailers functionality. Update trailers tests.
1 parent61ed7ec commitd2f7284

File tree

2 files changed

+126
-58
lines changed

2 files changed

+126
-58
lines changed

‎git/objects/commit.py

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
importos
2727
fromioimportBytesIO
2828
importlogging
29+
fromcollectionsimportdefaultdict
2930

3031

3132
# typing ------------------------------------------------------------------
@@ -335,8 +336,70 @@ def stats(self) -> Stats:
335336
returnStats._list_from_string(self.repo,text)
336337

337338
@property
338-
deftrailers(self)->Dict:
339-
"""Get the trailers of the message as dictionary
339+
deftrailers(self)->Dict[str,str]:
340+
"""Get the trailers of the message as a dictionary
341+
342+
Git messages can contain trailer information that are similar to RFC 822
343+
e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
344+
345+
WARNING: This function only returns the latest instance of each trailer key
346+
and will be deprecated soon. Please see either ``Commit.trailers_list`` or ``Commit.trailers_dict``.
347+
348+
:return:
349+
Dictionary containing whitespace stripped trailer information.
350+
Only the latest instance of each trailer key.
351+
"""
352+
return {
353+
k:v[0]fork,vinself.trailers_dict.items()
354+
}
355+
356+
@property
357+
deftrailers_list(self)->List[str]:
358+
"""Get the trailers of the message as a list
359+
360+
Git messages can contain trailer information that are similar to RFC 822
361+
e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
362+
363+
This functions calls ``git interpret-trailers --parse`` onto the message
364+
to extract the trailer information, returns the raw trailer data as a list.
365+
366+
Valid message with trailer::
367+
368+
Subject line
369+
370+
some body information
371+
372+
another information
373+
374+
key1: value1.1
375+
key1: value1.2
376+
key2 : value 2 with inner spaces
377+
378+
379+
Returned list will look like this::
380+
381+
[
382+
"key1: value1.1",
383+
"key1: value1.2",
384+
"key2 : value 2 with inner spaces",
385+
]
386+
387+
388+
:return:
389+
List containing whitespace stripped trailer information.
390+
"""
391+
cmd= ["git","interpret-trailers","--parse"]
392+
proc:Git.AutoInterrupt=self.repo.git.execute(cmd,as_process=True,istream=PIPE)# type: ignore
393+
trailer:str=proc.communicate(str(self.message).encode())[0].decode()
394+
trailer=trailer.strip()
395+
iftrailer:
396+
return [t.strip()fortintrailer.split("\n")]
397+
398+
return []
399+
400+
@property
401+
deftrailers_dict(self)->Dict[str,List[str]]:
402+
"""Get the trailers of the message as a dictionary
340403
341404
Git messages can contain trailer information that are similar to RFC 822
342405
e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
@@ -345,42 +408,36 @@ def trailers(self) -> Dict:
345408
to extract the trailer information. The key value pairs are stripped of
346409
leading and trailing whitespaces before they get saved into a dictionary.
347410
348-
Valid message with trailer:
349-
350-
.. code-block::
411+
Valid message with trailer::
351412
352413
Subject line
353414
354415
some body information
355416
356417
another information
357418
358-
key1: value1
419+
key1: value1.1
420+
key1: value1.2
359421
key2 : value 2 with inner spaces
360422
361-
dictionary will look like this:
362423
363-
.. code-block::
424+
Returned dictionary will look like this::
364425
365426
{
366-
"key1": "value1",
367-
"key2": "value 2 with inner spaces"
427+
"key1":["value1.1", "value1.2"],
428+
"key2":["value 2 with inner spaces"],
368429
}
369430
370-
:return: Dictionary containing whitespace stripped trailer information
371431
432+
:return:
433+
Dictionary containing whitespace stripped trailer information.
434+
Mapping trailer keys to a list of their corresponding values.
372435
"""
373-
d= {}
374-
cmd= ["git","interpret-trailers","--parse"]
375-
proc:Git.AutoInterrupt=self.repo.git.execute(cmd,as_process=True,istream=PIPE)# type: ignore
376-
trailer:str=proc.communicate(str(self.message).encode())[0].decode()
377-
iftrailer.endswith("\n"):
378-
trailer=trailer[0:-1]
379-
iftrailer!="":
380-
forlineintrailer.split("\n"):
381-
key,value=line.split(":",1)
382-
d[key.strip()]=value.strip()
383-
returnd
436+
d=defaultdict(list)
437+
fortrailerinself.trailers_list:
438+
key,value=trailer.split(":",1)
439+
d[key.strip()].append(value.strip())
440+
returndict(d)
384441

385442
@classmethod
386443
def_iter_from_process_or_stream(cls,repo:"Repo",proc_or_stream:Union[Popen,IO])->Iterator["Commit"]:

‎test/test_commit.py

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -494,52 +494,63 @@ def test_datetimes(self):
494494

495495
deftest_trailers(self):
496496
KEY_1="Hello"
497-
VALUE_1="World"
497+
VALUE_1_1="World"
498+
VALUE_1_2="Another-World"
498499
KEY_2="Key"
499500
VALUE_2="Value with inner spaces"
500501

501-
# Check if KEY 1 & 2 with Value 1 & 2 is extracted from multiple msg variations
502-
msgs= []
503-
msgs.append(f"Subject\n\n{KEY_1}:{VALUE_1}\n{KEY_2}:{VALUE_2}\n")
504-
msgs.append(f"Subject\n\nSome body of a function\n\n{KEY_1}:{VALUE_1}\n{KEY_2}:{VALUE_2}\n")
505-
msgs.append(
506-
f"Subject\n\nSome body of a function\n\nnon-key: non-value\n\n{KEY_1}:{VALUE_1}\n{KEY_2}:{VALUE_2}\n"
507-
)
508-
msgs.append(
509-
f"Subject\n\nSome multiline\n body of a function\n\nnon-key: non-value\n\n{KEY_1}:{VALUE_1}\n{KEY_2} :{VALUE_2}\n"
510-
)
511-
502+
# Check the following trailer example is extracted from multiple msg variations
503+
TRAILER=f"{KEY_1}:{VALUE_1_1}\n{KEY_2}:{VALUE_2}\n{KEY_1}:{VALUE_1_2}"
504+
msgs= [
505+
f"Subject\n\n{TRAILER}\n",
506+
f"Subject\n\nSome body of a function\n\n{TRAILER}\n",
507+
f"Subject\n\nSome body of a function\n\nnon-key: non-value\n\n{TRAILER}\n",
508+
(
509+
# check when trailer has inconsistent whitespace
510+
f"Subject\n\nSome multiline\n body of a function\n\nnon-key: non-value\n\n"
511+
f"{KEY_1}:{VALUE_1_1}\n{KEY_2} :{VALUE_2}\n{KEY_1}:{VALUE_1_2}\n"
512+
),
513+
]
512514
formsginmsgs:
513-
commit=self.rorepo.commit("master")
514-
commit=copy.copy(commit)
515+
commit=copy.copy(self.rorepo.commit("master"))
515516
commit.message=msg
516-
assertKEY_1incommit.trailers.keys()
517-
assertKEY_2incommit.trailers.keys()
518-
assertcommit.trailers[KEY_1]==VALUE_1
519-
assertcommit.trailers[KEY_2]==VALUE_2
520-
521-
# Check that trailer stays empty for multiple msg combinations
522-
msgs= []
523-
msgs.append(f"Subject\n")
524-
msgs.append(f"Subject\n\nBody with some\nText\n")
525-
msgs.append(f"Subject\n\nBody with\nText\n\nContinuation but\n doesn't contain colon\n")
526-
msgs.append(f"Subject\n\nBody with\nText\n\nContinuation but\n only contains one :\n")
527-
msgs.append(f"Subject\n\nBody with\nText\n\nKey: Value\nLine without colon\n")
528-
msgs.append(f"Subject\n\nBody with\nText\n\nLine without colon\nKey: Value\n")
517+
assertcommit.trailers_list== [
518+
f"{KEY_1}:{VALUE_1_1}",
519+
f"{KEY_2}:{VALUE_2}",
520+
f"{KEY_1}:{VALUE_1_2}",
521+
]
522+
assertcommit.trailers_dict== {
523+
KEY_1: [VALUE_1_1,VALUE_1_2],
524+
KEY_2: [VALUE_2],
525+
}
526+
assertcommit.trailers== {
527+
KEY_1:VALUE_1_1,
528+
KEY_2:VALUE_2,
529+
}
530+
531+
# check that trailer stays empty for multiple msg combinations
532+
msgs= [
533+
f"Subject\n",
534+
f"Subject\n\nBody with some\nText\n",
535+
f"Subject\n\nBody with\nText\n\nContinuation but\n doesn't contain colon\n",
536+
f"Subject\n\nBody with\nText\n\nContinuation but\n only contains one :\n",
537+
f"Subject\n\nBody with\nText\n\nKey: Value\nLine without colon\n",
538+
f"Subject\n\nBody with\nText\n\nLine without colon\nKey: Value\n",
539+
]
529540

530541
formsginmsgs:
531-
commit=self.rorepo.commit("master")
532-
commit=copy.copy(commit)
542+
commit=copy.copy(self.rorepo.commit("master"))
533543
commit.message=msg
534-
assertlen(commit.trailers.keys())==0
544+
assertcommit.trailers_list== []
545+
assertcommit.trailers_dict== {}
546+
assertcommit.trailers== {}
535547

536548
# check that only the last key value paragraph is evaluated
537-
commit=self.rorepo.commit("master")
538-
commit=copy.copy(commit)
539-
commit.message=f"Subject\n\nMultiline\nBody\n\n{KEY_1}:{VALUE_1}\n\n{KEY_2}:{VALUE_2}\n"
540-
assertKEY_1notincommit.trailers.keys()
541-
assertKEY_2incommit.trailers.keys()
542-
assertcommit.trailers[KEY_2]==VALUE_2
549+
commit=copy.copy(self.rorepo.commit("master"))
550+
commit.message=f"Subject\n\nMultiline\nBody\n\n{KEY_1}:{VALUE_1_1}\n\n{KEY_2}:{VALUE_2}\n"
551+
assertcommit.trailers_list== [f"{KEY_2}:{VALUE_2}"]
552+
assertcommit.trailers_dict== {KEY_2: [VALUE_2]}
553+
assertcommit.trailers== {KEY_2:VALUE_2}
543554

544555
deftest_commit_co_authors(self):
545556
commit=copy.copy(self.rorepo.commit("4251bd5"))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp