Skip to content

Commit

Permalink
Added SortBlocksByYearMonthDayMiddleware to sort blocks by time
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Birke committed Oct 28, 2024
1 parent fcba5ad commit ae74c4b
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions bibtexparser/middlewares/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from bibtexparser.middlewares.names import SeparateCoAuthors
from bibtexparser.middlewares.names import SplitNameParts
from bibtexparser.middlewares.sorting_blocks import SortBlocksByTypeAndKeyMiddleware
from bibtexparser.middlewares.sorting_blocks import SortBlocksByYearMonthDayMiddleware
from bibtexparser.middlewares.sorting_entry_fields import SortFieldsAlphabeticallyMiddleware
from bibtexparser.middlewares.sorting_entry_fields import SortFieldsCustomMiddleware

Expand Down
93 changes: 93 additions & 0 deletions bibtexparser/middlewares/sorting_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,96 @@ def _sort_key(block: Block):

blocks.sort(key=_sort_key)
return Library(blocks=blocks)


class SortBlocksByYearMonthDayMiddleware(LibraryMiddleware):
"""Sorts the blocks of a library by year, month and day.
:param descending: uses descending ordering (ascending by default)
:param preserve_comments_on_top: comments remain above same block (default True)
"""

def __init__(
self,
preserve_comments_on_top: bool = True,
descending = False
):
self._preserve_comments_on_top = preserve_comments_on_top
self._descending = descending

# In-place modification is not yet supported, we make this explicit here,
super().__init__(allow_inplace_modification=False)

@staticmethod
# Sort blocks by year and month (default 0 in case entry has no year or month)
# Month should be an integer (recommended to use MonthIntMiddleware beforehand)
def _sort_key(block: Block):
month = 0
year = 0
day = 0
try:
try:
v = block.fields_dict["day"].value
if isinstance(v, str) and v.isdigit():
v = int(v)
if isinstance(v, int):
if v >= 1 or v <= 31:
day = v
except KeyError:
# No year field
pass
try:
v = block.fields_dict["month"].value
if isinstance(v, str) and v.isdigit():
v = int(v)
if isinstance(v, int):
if v >= 1 or v <= 12:
month = v
except KeyError:
# No month field
pass
try:
year = int(block.fields_dict["year"].value)
except KeyError:
# No year field
pass
except AttributeError:
# No fiedlds_dict (e.g. Comments)
pass
return year, month, day

# docstr-coverage: inherited
def transform(self, library: Library) -> Library:
blocks = deepcopy(library.blocks)

if self._preserve_comments_on_top:
# We start creating a new list of block_junks (made of comments and entries)
block_junks = []
current_junk = _BlockJunk()
for block in blocks:
current_junk.blocks.append(block)
current_junk.sort_key = self._sort_key(block)

if not (
isinstance(block, ExplicitComment) or isinstance(block, ImplicitComment)
):
# We added a non-comment block, hence we finish the junk and
# start a new one
block_junks.append(current_junk)
current_junk = _BlockJunk()

if current_junk.blocks:
# That would be a junk with only comments, but we add it at the end for completeness
block_junks.append(current_junk)

def _sort_key(block_junk):
return block_junk.sort_key

block_junks.sort(key=_sort_key, reverse=self._descending)
return Library(
blocks=[block for block_junk in block_junks for block in block_junk.blocks]
)

else:
blocks.sort(key=self._sort_key)
return Library(blocks=blocks)

0 comments on commit ae74c4b

Please sign in to comment.