From 62f5a4012cea8746f7a12b997adb553e9fe3e19b Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 15:44:54 -0500 Subject: [PATCH 01/23] style: add builder for releaselist. --- src/regolith/builders/releaselistbuilder.py | 80 +++++++++++++++++++++ src/regolith/exemplars.json | 7 -- 2 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 src/regolith/builders/releaselistbuilder.py diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py new file mode 100644 index 000000000..5dbd58092 --- /dev/null +++ b/src/regolith/builders/releaselistbuilder.py @@ -0,0 +1,80 @@ +"""Builder for software release lists.""" + +from regolith.builders.basebuilder import LatexBuilderBase +from regolith.fsclient import _id_key +from regolith.sorters import position_key +from regolith.stylers import month_fullnames, sentencecase +from regolith.tools import all_docs_from_collection, filter_software, group_member_ids + + +class ReleaselistBUilder(LatexBuilderBase): + """Build list of released software from database entries.""" + + btype = "releaselist" + needed_colls = ["groups", "institutions", "people", "grants", "software", "contacts"] + + def construct_global_ctx(self): + """Constructs the global context.""" + super().construct_global_ctx() + gtx = self.gtx + rc = self.rc + gtx["people"] = sorted( + all_docs_from_collection(rc.client, "people"), + key=position_key, + reverse=True, + ) + gtx["contacts"] = sorted( + all_docs_from_collection(rc.client, "contacts"), + key=position_key, + reverse=True, + ) + gtx["grants"] = sorted(all_docs_from_collection(rc.client, "grants"), key=_id_key) + gtx["groups"] = sorted(all_docs_from_collection(rc.client, "groups"), key=_id_key) + gtx["software"] = sorted(all_docs_from_collection(rc.client, "software"), key=_id_key) + gtx["institutions"] = sorted(all_docs_from_collection(rc.client, "institutions"), key=_id_key) + gtx["all_docs_from_collection"] = all_docs_from_collection + gtx["float"] = float + gtx["str"] = str + gtx["zip"] = zip + + def latex(self): + """Render latex template.""" + everybody = self.gtx["people"] + self.gtx["contacts"] + for group in self.gtx["groups"]: + grp = group["_id"] + grpmember_ids = group_member_ids(self.gtx["people"], grp) + for member in grpmember_ids: + if self.rc.people: + if member not in self.rc.people: + continue + presclean = filter_software( + everybody, self.gtx["software"], self.gtx["institutions"], member, statuses=["active"] + ) + + if len(presclean) > 0: + presclean = sorted( + presclean, + key=lambda k: k.get("date", None), + reverse=True, + ) + outfile = "software-" + grp + "-" + member + pi = [person for person in self.gtx["people"] if person["_id"] is member][0] + self.render( + "releaselist.tex", + outfile + ".tex", + pi=pi, + presentations=presclean, + sentencecase=sentencecase, + monthstyle=month_fullnames, + ) + self.env.trim_blocks = True + self.env.lstrip_blocks = True + self.render( + "releaselist.txt", + outfile + ".txt", + pi=pi, + presentations=presclean, + sentencecase=sentencecase, + monthstyle=month_fullnames, + ) + self.pdf(outfile) diff --git a/src/regolith/exemplars.json b/src/regolith/exemplars.json index 20ec8f9b7..a30bb94d5 100644 --- a/src/regolith/exemplars.json +++ b/src/regolith/exemplars.json @@ -61,13 +61,6 @@ "title": "My Vision", "year": 2015 }, - "software": { - "_id": "unique-package-id", - "active": true, - "url": "https://github.com/diffpy/diffpy.utils", - "grants": ["dmref15", "SymPy-1.1"], - "groups": ["ergs"] - }, "citations": [ { "_id": "meurer2016sympy", From 82aa55b415b2823414c9e29f84845de055adbe30 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 15:52:45 -0500 Subject: [PATCH 02/23] chore: add news item. --- news/releasebuilder.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/releasebuilder.rst diff --git a/news/releasebuilder.rst b/news/releasebuilder.rst new file mode 100644 index 000000000..2ab14e58b --- /dev/null +++ b/news/releasebuilder.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add releasebuilder functionality. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From b34f33d1d4831c0e2d791a1bf6983041ea0b6a80 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 16:33:47 -0500 Subject: [PATCH 03/23] style: add ReleaselistBuilder in builder.py --- news/releasebuilder.rst | 2 +- src/regolith/builder.py | 2 + src/regolith/builders/releaselistbuilder.py | 2 +- src/regolith/tools.py | 153 ++++++++++++++++++++ 4 files changed, 157 insertions(+), 2 deletions(-) diff --git a/news/releasebuilder.rst b/news/releasebuilder.rst index 2ab14e58b..80867acc5 100644 --- a/news/releasebuilder.rst +++ b/news/releasebuilder.rst @@ -1,6 +1,6 @@ **Added:** -* Add releasebuilder functionality. +* Add Releaselistbuilder functionality. **Changed:** diff --git a/src/regolith/builder.py b/src/regolith/builder.py index 0cd1a8c18..6bb56e203 100644 --- a/src/regolith/builder.py +++ b/src/regolith/builder.py @@ -18,6 +18,7 @@ from regolith.builders.publistbuilder import PubListBuilder from regolith.builders.readinglistsbuilder import ReadingListsBuilder from regolith.builders.reimbursementbuilder import ReimbursementBuilder +from regolith.builders.releaselistbuilder import ReleaselistBuilder from regolith.builders.resumebuilder import ResumeBuilder BUILDERS = { @@ -35,6 +36,7 @@ "postdocad": PostdocadBuilder, "preslist": PresListBuilder, "publist": PubListBuilder, + "releaselist": ReleaselistBUilder, "reading-lists": ReadingListsBuilder, "reimb": ReimbursementBuilder, "recent-collabs": RecentCollaboratorsBuilder, diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index 5dbd58092..e9ae9aef6 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -7,7 +7,7 @@ from regolith.tools import all_docs_from_collection, filter_software, group_member_ids -class ReleaselistBUilder(LatexBuilderBase): +class ReleaselistBuilder(LatexBuilderBase): """Build list of released software from database entries.""" btype = "releaselist" diff --git a/src/regolith/tools.py b/src/regolith/tools.py index f4cb0aa57..ab7e690be 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -711,6 +711,159 @@ def filter_presentations( return presclean + +def filter_software( + people, software, institutions, target, types=None, since=None, before=None, statuses=None +): + f""" + filters presentations for different types and date ranges + + Parameters + ---------- + people: iterable of dicts + The people collection + software: iterable of dicts + The software collection + institutions: iterable of dicts + The institutions collection + target: str + The id of the person you will build the list for + types: list of strings. Optional, default = all + The types to filter for. Allowed types are + {*RELEASE_TYPES, } + since: date. Optional, default is None + The begin date to filter from + before: date. Optional, default is None + The end date to filter for. None does not apply this filter + statuses: list of str. Optional. Default is active. + The list of statuses to filter for. + + Returns + ------- + list of presentation documents + + """ + if not types: + types = ["all"] + if not statuses: + statuses = ["active"] + presentations = deepcopy(presentations) + + firstclean = list() + secondclean = list() + thirdclean = list() + fourthclean = list() + presclean = list() + + # build the filtered collection + # only list the talk if the group member is an author + for pres in presentations: + pauthors = pres["authors"] + if isinstance(pauthors, str): + pauthors = [pauthors] + authors = [ + fuzzy_retrieval( + people, + ["aka", "name", "_id"], + author, + case_sensitive=False, + ) + for author in pauthors + ] + authorids = [author["_id"] if author is not None else author for author in authors] + if target in authorids: + firstclean.append(pres) + # only list the presentation if it has status in statuses + for pres in firstclean: + if pres["status"] in statuses or "all" in statuses: + secondclean.append(pres) + # only list the presentation if it has type in types + for pres in secondclean: + if pres["type"] in types or "all" in types: + thirdclean.append(pres) + # if specified, only list presentations in specified date ranges + if since: + for pres in thirdclean: + if get_dates(pres).get("date"): + presdate = get_dates(pres).get("date") + else: + presdate = get_dates(pres).get("begin_date") + if presdate > since: + fourthclean.append(pres) + else: + fourthclean = thirdclean + if before: + for pres in fourthclean: + if get_dates(pres).get("date"): + presdate = get_dates(pres).get("date") + else: + presdate = get_dates(pres).get("begin_date") + if presdate < before: + presclean.append(pres) + else: + presclean = fourthclean + + # build author list + for pres in presclean: + pauthors = pres["authors"] + if isinstance(pauthors, str): + pauthors = [pauthors] + pres["authors"] = [ + ( + author + if fuzzy_retrieval( + people, + ["aka", "name", "_id"], + author, + case_sensitive=False, + ) + is None + else fuzzy_retrieval( + people, + ["aka", "name", "_id"], + author, + case_sensitive=False, + )["name"] + ) + for author in pauthors + ] + authorlist = ", ".join(pres["authors"]) + pres["authors"] = authorlist + if get_dates(pres).get("date"): + presdate = get_dates(pres).get("date") + else: + presdate = get_dates(pres).get("begin_date") + pres["begin_month"] = presdate.month + pres["begin_year"] = presdate.year + pres["begin_day"] = presdate.day + end_date = get_dates(pres).get("end_date") + if end_date: + pres["end_day"] = end_date.day + pres["date"] = presdate + for day in ["begin_", "end_", ""]: + try: + pres["{}day_suffix".format(day)] = number_suffix(get_dates(pres).get(f"{day}date").day) + except AttributeError: + print(f"presentation {pres.get('_id')} has no {day}date") + if "institution" in pres: + inst = {"institution": pres.get("institution"), "department": pres.get("department")} + dereference_institution(inst, institutions) + pres["institution"] = { + "name": inst.get("institution", ""), + "city": inst.get("city"), + "state": inst.get("state"), + "country": inst.get("country"), + } + pres["department"] = {"name": inst.get("department")} + if len(presclean) > 0: + presclean = sorted( + presclean, + key=lambda k: k.get("date", None), + reverse=True, + ) + return presclean + + def awards_grants_honors(person, target_name, funding=True, service_types=None): """Make sorted awards grants and honors list. From 932db621572f15a704831d7199227e6a9adc8c3c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:34:14 +0000 Subject: [PATCH 04/23] [pre-commit.ci] auto fixes from pre-commit hooks --- src/regolith/tools.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index ab7e690be..021fdb5dd 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -711,10 +711,7 @@ def filter_presentations( return presclean - -def filter_software( - people, software, institutions, target, types=None, since=None, before=None, statuses=None -): +def filter_software(people, software, institutions, target, types=None, since=None, before=None, statuses=None): f""" filters presentations for different types and date ranges @@ -736,7 +733,7 @@ def filter_software( before: date. Optional, default is None The end date to filter for. None does not apply this filter statuses: list of str. Optional. Default is active. - The list of statuses to filter for. + The list of statuses to filter for. Returns ------- From d8994462f7d41e470a668a8fc5f152023627d300 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 16:37:36 -0500 Subject: [PATCH 05/23] chore: Fix spelling issue --- src/regolith/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/regolith/builder.py b/src/regolith/builder.py index 6bb56e203..cc00a46a3 100644 --- a/src/regolith/builder.py +++ b/src/regolith/builder.py @@ -36,7 +36,7 @@ "postdocad": PostdocadBuilder, "preslist": PresListBuilder, "publist": PubListBuilder, - "releaselist": ReleaselistBUilder, + "releaselist": ReleaselistBuilder, "reading-lists": ReadingListsBuilder, "reimb": ReimbursementBuilder, "recent-collabs": RecentCollaboratorsBuilder, From 7e44307f0f012817280d4346c4458739b689b3d6 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 16:44:24 -0500 Subject: [PATCH 06/23] chore: change filter for software, need more discussion for this. --- src/regolith/tools.py | 77 +++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index 021fdb5dd..bfb9210d8 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -712,8 +712,7 @@ def filter_presentations( def filter_software(people, software, institutions, target, types=None, since=None, before=None, statuses=None): - f""" - filters presentations for different types and date ranges + """Filters presentations for different types and date ranges. Parameters ---------- @@ -726,8 +725,7 @@ def filter_software(people, software, institutions, target, types=None, since=No target: str The id of the person you will build the list for types: list of strings. Optional, default = all - The types to filter for. Allowed types are - {*RELEASE_TYPES, } + The types to filter for. Allowed types are release_types. since: date. Optional, default is None The begin date to filter from before: date. Optional, default is None @@ -738,13 +736,12 @@ def filter_software(people, software, institutions, target, types=None, since=No Returns ------- list of presentation documents - """ if not types: types = ["all"] if not statuses: statuses = ["active"] - presentations = deepcopy(presentations) + software = deepcopy(software) firstclean = list() secondclean = list() @@ -754,8 +751,8 @@ def filter_software(people, software, institutions, target, types=None, since=No # build the filtered collection # only list the talk if the group member is an author - for pres in presentations: - pauthors = pres["authors"] + for sof in software: + pauthors = sof["authors"] if isinstance(pauthors, str): pauthors = [pauthors] authors = [ @@ -769,34 +766,34 @@ def filter_software(people, software, institutions, target, types=None, since=No ] authorids = [author["_id"] if author is not None else author for author in authors] if target in authorids: - firstclean.append(pres) + firstclean.append(sof) # only list the presentation if it has status in statuses - for pres in firstclean: - if pres["status"] in statuses or "all" in statuses: - secondclean.append(pres) + for sof in firstclean: + if sof["status"] in statuses or "all" in statuses: + secondclean.append(sof) # only list the presentation if it has type in types - for pres in secondclean: - if pres["type"] in types or "all" in types: - thirdclean.append(pres) + for sof in secondclean: + if sof["type"] in types or "all" in types: + thirdclean.append(sof) # if specified, only list presentations in specified date ranges if since: - for pres in thirdclean: - if get_dates(pres).get("date"): - presdate = get_dates(pres).get("date") + for sof in thirdclean: + if get_dates(sof).get("date"): + presdate = get_dates(sof).get("date") else: - presdate = get_dates(pres).get("begin_date") + presdate = get_dates(sof).get("begin_date") if presdate > since: - fourthclean.append(pres) + fourthclean.append(sof) else: fourthclean = thirdclean if before: - for pres in fourthclean: - if get_dates(pres).get("date"): - presdate = get_dates(pres).get("date") + for sof in fourthclean: + if get_dates(sof).get("date"): + presdate = get_dates(sof).get("date") else: - presdate = get_dates(pres).get("begin_date") + presdate = get_dates(sof).get("begin_date") if presdate < before: - presclean.append(pres) + presclean.append(sof) else: presclean = fourthclean @@ -825,33 +822,33 @@ def filter_software(people, software, institutions, target, types=None, since=No for author in pauthors ] authorlist = ", ".join(pres["authors"]) - pres["authors"] = authorlist - if get_dates(pres).get("date"): - presdate = get_dates(pres).get("date") + sof["authors"] = authorlist + if get_dates(sof).get("date"): + presdate = get_dates(sof).get("date") else: - presdate = get_dates(pres).get("begin_date") - pres["begin_month"] = presdate.month - pres["begin_year"] = presdate.year - pres["begin_day"] = presdate.day - end_date = get_dates(pres).get("end_date") + presdate = get_dates(sof).get("begin_date") + sof["begin_month"] = presdate.month + sof["begin_year"] = presdate.year + sof["begin_day"] = presdate.day + end_date = get_dates(sof).get("end_date") if end_date: - pres["end_day"] = end_date.day - pres["date"] = presdate + sof["end_day"] = end_date.day + sof["date"] = presdate for day in ["begin_", "end_", ""]: try: - pres["{}day_suffix".format(day)] = number_suffix(get_dates(pres).get(f"{day}date").day) + sof["{}day_suffix".format(day)] = number_suffix(get_dates(sof).get(f"{day}date").day) except AttributeError: - print(f"presentation {pres.get('_id')} has no {day}date") + print(f"presentation {sof.get('_id')} has no {day}date") if "institution" in pres: - inst = {"institution": pres.get("institution"), "department": pres.get("department")} + inst = {"institution": sof.get("institution"), "department": sof.get("department")} dereference_institution(inst, institutions) - pres["institution"] = { + sof["institution"] = { "name": inst.get("institution", ""), "city": inst.get("city"), "state": inst.get("state"), "country": inst.get("country"), } - pres["department"] = {"name": inst.get("department")} + sof["department"] = {"name": inst.get("department")} if len(presclean) > 0: presclean = sorted( presclean, From 53fe4504593c1f7dd6b913ed171cac6792a0a424 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 16:46:04 -0500 Subject: [PATCH 07/23] chore: change typo for ReleaseListBuilder --- src/regolith/builder.py | 4 ++-- src/regolith/builders/releaselistbuilder.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/regolith/builder.py b/src/regolith/builder.py index cc00a46a3..b9cbeb403 100644 --- a/src/regolith/builder.py +++ b/src/regolith/builder.py @@ -18,7 +18,7 @@ from regolith.builders.publistbuilder import PubListBuilder from regolith.builders.readinglistsbuilder import ReadingListsBuilder from regolith.builders.reimbursementbuilder import ReimbursementBuilder -from regolith.builders.releaselistbuilder import ReleaselistBuilder +from regolith.builders.releaselistbuilder import ReleaseListBuilder from regolith.builders.resumebuilder import ResumeBuilder BUILDERS = { @@ -36,7 +36,7 @@ "postdocad": PostdocadBuilder, "preslist": PresListBuilder, "publist": PubListBuilder, - "releaselist": ReleaselistBuilder, + "releaselist": ReleaseListBuilder, "reading-lists": ReadingListsBuilder, "reimb": ReimbursementBuilder, "recent-collabs": RecentCollaboratorsBuilder, diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index e9ae9aef6..d1ed30d9a 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -7,7 +7,7 @@ from regolith.tools import all_docs_from_collection, filter_software, group_member_ids -class ReleaselistBuilder(LatexBuilderBase): +class ReleaseListBuilder(LatexBuilderBase): """Build list of released software from database entries.""" btype = "releaselist" From a60cb79d7cddac6889ae27f780313f9cc8681f5e Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 17:10:00 -0500 Subject: [PATCH 08/23] fix: fix iterator name to make compatible. --- src/regolith/tools.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index bfb9210d8..61fc41e50 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -735,7 +735,7 @@ def filter_software(people, software, institutions, target, types=None, since=No Returns ------- - list of presentation documents + list of software documents """ if not types: types = ["all"] @@ -798,8 +798,8 @@ def filter_software(people, software, institutions, target, types=None, since=No presclean = fourthclean # build author list - for pres in presclean: - pauthors = pres["authors"] + for sof in presclean: + pauthors = sof["authors"] if isinstance(pauthors, str): pauthors = [pauthors] pres["authors"] = [ @@ -839,7 +839,7 @@ def filter_software(people, software, institutions, target, types=None, since=No sof["{}day_suffix".format(day)] = number_suffix(get_dates(sof).get(f"{day}date").day) except AttributeError: print(f"presentation {sof.get('_id')} has no {day}date") - if "institution" in pres: + if "institution" in sof: inst = {"institution": sof.get("institution"), "department": sof.get("department")} dereference_institution(inst, institutions) sof["institution"] = { From c158e64216f7f64ac7ff4616febfd2078694433f Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 3 Nov 2025 17:28:13 -0500 Subject: [PATCH 09/23] chore: change iterator to sof --- src/regolith/tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index 61fc41e50..c2d07fa6b 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -802,7 +802,7 @@ def filter_software(people, software, institutions, target, types=None, since=No pauthors = sof["authors"] if isinstance(pauthors, str): pauthors = [pauthors] - pres["authors"] = [ + sof["authors"] = [ ( author if fuzzy_retrieval( @@ -821,7 +821,7 @@ def filter_software(people, software, institutions, target, types=None, since=No ) for author in pauthors ] - authorlist = ", ".join(pres["authors"]) + authorlist = ", ".join(sof["authors"]) sof["authors"] = authorlist if get_dates(sof).get("date"): presdate = get_dates(sof).get("date") From ba232d7dafeae4ead5e79d95f4003fa8ccbe04fd Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Thu, 6 Nov 2025 14:43:49 -0500 Subject: [PATCH 10/23] fix: change get date level from release level. --- src/regolith/tools.py | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index c2d07fa6b..bd9145adf 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -778,20 +778,16 @@ def filter_software(people, software, institutions, target, types=None, since=No # if specified, only list presentations in specified date ranges if since: for sof in thirdclean: - if get_dates(sof).get("date"): - presdate = get_dates(sof).get("date") - else: - presdate = get_dates(sof).get("begin_date") + if get_dates(sof).get("release").get("release_date"): + presdate = get_dates(sof).get("release").get("release_date") if presdate > since: fourthclean.append(sof) else: fourthclean = thirdclean if before: for sof in fourthclean: - if get_dates(sof).get("date"): - presdate = get_dates(sof).get("date") - else: - presdate = get_dates(sof).get("begin_date") + if get_dates(sof).get("release").get("release_date"): + presdate = get_dates(sof).get("release").get("release_date") if presdate < before: presclean.append(sof) else: @@ -823,22 +819,14 @@ def filter_software(people, software, institutions, target, types=None, since=No ] authorlist = ", ".join(sof["authors"]) sof["authors"] = authorlist - if get_dates(sof).get("date"): - presdate = get_dates(sof).get("date") - else: - presdate = get_dates(sof).get("begin_date") - sof["begin_month"] = presdate.month - sof["begin_year"] = presdate.year - sof["begin_day"] = presdate.day - end_date = get_dates(sof).get("end_date") - if end_date: - sof["end_day"] = end_date.day - sof["date"] = presdate + if get_dates(sof).get("release").get("release_date"): + presdate = get_dates(sof).get("release").get("release_date") + sof["release_date"] = presdate for day in ["begin_", "end_", ""]: try: sof["{}day_suffix".format(day)] = number_suffix(get_dates(sof).get(f"{day}date").day) except AttributeError: - print(f"presentation {sof.get('_id')} has no {day}date") + print(f"software {sof.get('_id')} has no {day}date") if "institution" in sof: inst = {"institution": sof.get("institution"), "department": sof.get("department")} dereference_institution(inst, institutions) From 784067617862cfbd776353000b5ea7f6eeec8ac8 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Thu, 6 Nov 2025 19:32:16 -0500 Subject: [PATCH 11/23] style: add program_description to compatible to output template, add jinja2 for releaselist --- news/releasebuilder.rst | 2 +- src/regolith/exemplars.json | 3 + src/regolith/schemas.json | 5 ++ src/regolith/templates/releaselist.tex | 46 ++++++++++++++ src/regolith/tools.py | 88 +++++++++++--------------- 5 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 src/regolith/templates/releaselist.tex diff --git a/news/releasebuilder.rst b/news/releasebuilder.rst index 80867acc5..c3f9346f3 100644 --- a/news/releasebuilder.rst +++ b/news/releasebuilder.rst @@ -1,6 +1,6 @@ **Added:** -* Add Releaselistbuilder functionality. +* Add `ReleaseListBuilder` functionality **Changed:** diff --git a/src/regolith/exemplars.json b/src/regolith/exemplars.json index a30bb94d5..bcc173fb5 100644 --- a/src/regolith/exemplars.json +++ b/src/regolith/exemplars.json @@ -2177,6 +2177,7 @@ "repo_name": "diffpy.utils", "platform_name": "Github", "grants": ["NSF Funding"], + "program_description": "General utilities for analyzing diffraction data", "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], "release": [ { @@ -2204,6 +2205,7 @@ "repo_name": "diffpy.srxplanar", "platform_name": "Github", "grants": ["NSF Funding"], + "program_description": "2D diffraction image integration using non splitting pixel algorithm.", "release": [ { "major": 0, @@ -2236,6 +2238,7 @@ "repo_name": "diffpy.distanceprinter", "platform_name": "Github", "grants": ["NSF Funding"], + "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], "release": [ { diff --git a/src/regolith/schemas.json b/src/regolith/schemas.json index 85817e32e..0df17585e 100644 --- a/src/regolith/schemas.json +++ b/src/regolith/schemas.json @@ -2956,6 +2956,11 @@ "required": true, "type": "list" }, + "program_description": { + "description": "The short description of the software.", + "required": true, + "type": "string" + }, "release": { "description": "The release information of the software.", "required": true, diff --git a/src/regolith/templates/releaselist.tex b/src/regolith/templates/releaselist.tex new file mode 100644 index 000000000..3129f1892 --- /dev/null +++ b/src/regolith/templates/releaselist.tex @@ -0,0 +1,46 @@ +\documentclass[prl,tighten,amsmath,amssymb,floatfix]{revtex4-1} +\usepackage{graphicx} +\usepackage{times} +\usepackage{booktabs,dcolumn} +\usepackage{siunitx} +\usepackage[utf8]{inputenc} +\usepackage{xcolor} +\usepackage{hyperref} +\usepackage{enumitem} + +\begin{document} + +\noindent +\colorbox{gray!40}{% + \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} + \textbf{\Large {{-latex_safe(pi['name']).upper()}}} & \textbf{\today} \\ + {{-latex_safe(pi['institution'])}} & {{-latex_safe(pi['email']}} \\ + \end{tabular*}% +}\vspace{1em} + +\textbf{Software Releaselist} + +\begin{enumerate} +{% for program in software if program.active %} + \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name'])-}}/{{ latex_safe(program['repo_name'])-}}}{{ "{" ~ latex_safe(s['org_name']) ~ "/" ~ latex_safe(s['repo_name']) ~ "}" }}:}\\ + \hspace*{1em}{{ latex_safe(program['program_description'])-}}\\ + \hspace*{1em}\textit{Authors: {{ latex_safe(', '.join(program.get('author', [])))-}}}\\ + \hspace*{1em}Url: https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(s['repo_name']) }}\\ + \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} + \begin{itemize}[label={}] + {% for release in program['release'] %} + \item \textbf{{ latex_safe(release['release_id']) }}: {{ latex_safe(release['release_date']) }} + \begin{itemize}[label={}, leftmargin=2em] + {% if release.get('summary') %} + \item \textit{{ latex_safe(release['summary']) }} + {% endif %} + {% for change in release.get('changes', []) %} + \item {{ latex_safe(change) }} + {% endfor %} + \end{itemize} + {% endfor %} + \end{itemize} +{% endfor %} +\end{enumerate} + +\end{document} diff --git a/src/regolith/tools.py b/src/regolith/tools.py index bd9145adf..7b2ecc924 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -711,7 +711,7 @@ def filter_presentations( return presclean -def filter_software(people, software, institutions, target, types=None, since=None, before=None, statuses=None): +def filter_software(people, software,target, types=None, since=None, before=None, statuses=None): """Filters presentations for different types and date ranges. Parameters @@ -720,8 +720,6 @@ def filter_software(people, software, institutions, target, types=None, since=No The people collection software: iterable of dicts The software collection - institutions: iterable of dicts - The institutions collection target: str The id of the person you will build the list for types: list of strings. Optional, default = all @@ -751,8 +749,8 @@ def filter_software(people, software, institutions, target, types=None, since=No # build the filtered collection # only list the talk if the group member is an author - for sof in software: - pauthors = sof["authors"] + for program in software: + pauthors = program["authors"] if isinstance(pauthors, str): pauthors = [pauthors] authors = [ @@ -766,39 +764,39 @@ def filter_software(people, software, institutions, target, types=None, since=No ] authorids = [author["_id"] if author is not None else author for author in authors] if target in authorids: - firstclean.append(sof) - # only list the presentation if it has status in statuses - for sof in firstclean: - if sof["status"] in statuses or "all" in statuses: - secondclean.append(sof) - # only list the presentation if it has type in types - for sof in secondclean: - if sof["type"] in types or "all" in types: - thirdclean.append(sof) - # if specified, only list presentations in specified date ranges + firstclean.append(program) + # only list the program if it has status in statuses + for program in firstclean: + if program["status"] in statuses or "all" in statuses: + secondclean.append(program) + # only list the program if it has type in types + for program in secondclean: + if program["type"] in types or "all" in types: + thirdclean.append(program) + # if specified, only list program in specified date ranges if since: - for sof in thirdclean: - if get_dates(sof).get("release").get("release_date"): - presdate = get_dates(sof).get("release").get("release_date") - if presdate > since: - fourthclean.append(sof) + for program in thirdclean: + if get_dates(program).get("release").get("release_date"): + pregdate = get_dates(program).get("release").get("release_date") + if pregdate > since: + fourthclean.append(program) else: fourthclean = thirdclean if before: - for sof in fourthclean: - if get_dates(sof).get("release").get("release_date"): - presdate = get_dates(sof).get("release").get("release_date") - if presdate < before: - presclean.append(sof) + for program in fourthclean: + if get_dates(program).get("release").get("release_date"): + pregdate = get_dates(program).get("release").get("release_date") + if pregdate < before: + progclean.append(program) else: - presclean = fourthclean + progclean = fourthclean # build author list - for sof in presclean: - pauthors = sof["authors"] + for program in progclean: + pauthors = program["authors"] if isinstance(pauthors, str): pauthors = [pauthors] - sof["authors"] = [ + program["authors"] = [ ( author if fuzzy_retrieval( @@ -817,33 +815,23 @@ def filter_software(people, software, institutions, target, types=None, since=No ) for author in pauthors ] - authorlist = ", ".join(sof["authors"]) - sof["authors"] = authorlist - if get_dates(sof).get("release").get("release_date"): - presdate = get_dates(sof).get("release").get("release_date") - sof["release_date"] = presdate + authorlist = ", ".join(program["authors"]) + program["authors"] = authorlist + if get_dates(program).get("release").get("release_date"): + pregdate = get_dates(program).get("release").get("release_date") + program["release_date"] = pregdate for day in ["begin_", "end_", ""]: try: - sof["{}day_suffix".format(day)] = number_suffix(get_dates(sof).get(f"{day}date").day) + program["{}day_suffix".format(day)] = number_suffix(get_dates(program).get(f"{day}date").day) except AttributeError: - print(f"software {sof.get('_id')} has no {day}date") - if "institution" in sof: - inst = {"institution": sof.get("institution"), "department": sof.get("department")} - dereference_institution(inst, institutions) - sof["institution"] = { - "name": inst.get("institution", ""), - "city": inst.get("city"), - "state": inst.get("state"), - "country": inst.get("country"), - } - sof["department"] = {"name": inst.get("department")} - if len(presclean) > 0: - presclean = sorted( - presclean, + print(f"software {program.get('_id')} has no {day}date") + if len(progclean) > 0: + progclean = sorted( + progclean, key=lambda k: k.get("date", None), reverse=True, ) - return presclean + return progclean def awards_grants_honors(person, target_name, funding=True, service_types=None): From 610ebfaaa2b79e17526de8e9ddc4fa3c47f01eae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 00:33:01 +0000 Subject: [PATCH 12/23] [pre-commit.ci] auto fixes from pre-commit hooks --- src/regolith/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index 7b2ecc924..0e631542d 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -711,7 +711,7 @@ def filter_presentations( return presclean -def filter_software(people, software,target, types=None, since=None, before=None, statuses=None): +def filter_software(people, software, target, types=None, since=None, before=None, statuses=None): """Filters presentations for different types and date ranges. Parameters From 402223d3225422fe20d7edc5494b9896783f7e47 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Thu, 6 Nov 2025 19:35:31 -0500 Subject: [PATCH 13/23] chore: change typo for correction of pre-commit --- src/regolith/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index 0e631542d..e7d4baf90 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -745,7 +745,7 @@ def filter_software(people, software, target, types=None, since=None, before=Non secondclean = list() thirdclean = list() fourthclean = list() - presclean = list() + progclean = list() # build the filtered collection # only list the talk if the group member is an author From f3ccd01c056e4aa237c6fdf1cbea569111e08dc8 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 10 Nov 2025 18:57:16 -0500 Subject: [PATCH 14/23] feat: Add filter for releasebuilder by active status, release type, and time interval. --- src/regolith/tools.py | 92 ++++++++++-------- tests/test_tools.py | 216 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 39 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index e7d4baf90..4b27c90a6 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -711,7 +711,7 @@ def filter_presentations( return presclean -def filter_software(people, software, target, types=None, since=None, before=None, statuses=None): +def filter_software(people, software, target, types=None, since=None, before=None, active=None): """Filters presentations for different types and date ranges. Parameters @@ -730,27 +730,20 @@ def filter_software(people, software, target, types=None, since=None, before=Non The end date to filter for. None does not apply this filter statuses: list of str. Optional. Default is active. The list of statuses to filter for. - - Returns - ------- - list of software documents """ + if not types: types = ["all"] - if not statuses: - statuses = ["active"] software = deepcopy(software) - firstclean = list() - secondclean = list() - thirdclean = list() - fourthclean = list() - progclean = list() + firstclean = [] + secondclean = [] + thirdclean = [] + fourthclean = [] + progclean = [] - # build the filtered collection - # only list the talk if the group member is an author for program in software: - pauthors = program["authors"] + pauthors = program.get("author", []) if isinstance(pauthors, str): pauthors = [pauthors] authors = [ @@ -765,35 +758,53 @@ def filter_software(people, software, target, types=None, since=None, before=Non authorids = [author["_id"] if author is not None else author for author in authors] if target in authorids: firstclean.append(program) - # only list the program if it has status in statuses - for program in firstclean: - if program["status"] in statuses or "all" in statuses: + + if active is True: + for program in firstclean: + if program.get("active") is True: + secondclean.append(program) + else: + for program in firstclean: secondclean.append(program) - # only list the program if it has type in types + for program in secondclean: - if program["type"] in types or "all" in types: + releases = program.get("release") + filtered_releases = [ + release for release in releases + if "all" in types or release.get("release_type") in types + ] + if filtered_releases: + program["release"] = filtered_releases thirdclean.append(program) - # if specified, only list program in specified date ranges + if since: for program in thirdclean: - if get_dates(program).get("release").get("release_date"): - pregdate = get_dates(program).get("release").get("release_date") - if pregdate > since: + filtered_releases = [] + for release in program.get("release", []): + releasedate = release.get("release_date") + if releasedate >= since: + filtered_releases.append(release) + if filtered_releases: + program["release"] = filtered_releases fourthclean.append(program) else: fourthclean = thirdclean + if before: for program in fourthclean: - if get_dates(program).get("release").get("release_date"): - pregdate = get_dates(program).get("release").get("release_date") - if pregdate < before: + filtered_releases = [] + for release in program.get("release", []): + releasedate = release.get("release_date") + if releasedate <= before: + filtered_releases.append(release) + if filtered_releases: + program["release"] = filtered_releases progclean.append(program) else: progclean = fourthclean - # build author list for program in progclean: - pauthors = program["authors"] + pauthors = program["author"] if isinstance(pauthors, str): pauthors = [pauthors] program["authors"] = [ @@ -815,20 +826,23 @@ def filter_software(people, software, target, types=None, since=None, before=Non ) for author in pauthors ] - authorlist = ", ".join(program["authors"]) + authorlist = ", ".join(program["author"]) program["authors"] = authorlist - if get_dates(program).get("release").get("release_date"): - pregdate = get_dates(program).get("release").get("release_date") - program["release_date"] = pregdate - for day in ["begin_", "end_", ""]: - try: - program["{}day_suffix".format(day)] = number_suffix(get_dates(program).get(f"{day}date").day) - except AttributeError: - print(f"software {program.get('_id')} has no {day}date") + + for release in program.get("release", []): + releasedate = release.get("release_date") + if isinstance(releasedate, str): + release["release_date"] = releasedate + if len(progclean) > 0: progclean = sorted( progclean, - key=lambda k: k.get("date", None), + key=lambda k: max( + datetime.fromisoformat(rel["release_date"]) + if isinstance(rel.get("release_date"), str) + else rel["release_date"] + for rel in k["release"] + ), reverse=True, ) return progclean diff --git a/tests/test_tools.py b/tests/test_tools.py index ca9686fc8..f22bc990e 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -44,6 +44,7 @@ search_collection, update_schemas, validate_meeting, + filter_software ) PEOPLE_COLL = [ @@ -2999,6 +3000,221 @@ def test_filter_presentations(args, kwargs, expected): actual = filter_presentations(*args, **kwargs) assert actual == expected +person3 = {"_id": "sbillinge", "aka": "Simon", "name": "Simon Billinge"} +person4 = {"_id": "stevenhua0320", "aka": "Steven hua", "name": "Rundong Hua"} +PEOPLE = [person3, person4] +software1 = { + "_id": "diffpy.utils", + "groups": ["xrd"], + "active": True, + "org_name": "diffpy", + "repo_name": "diffpy.utils", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "General utilities for analyzing diffraction data", + "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], + "release": [ + { + "major": 3, + "minor": 1, + "patch": 0, + "release_type": "major", + "release_date": "2025-10-25", + "summary": "Python 3.14 and something else", + "changes": ["deprecated python2 feature.", + "changed to scikit-packaged standard.", + "Add some functionality.", + "Modify existing function to make convenient." + ], + "release_id": "3.1.0" + } + ] + } +software2 = { + "_id": "diffpy.srxplanar", + "groups": ["billingegroup"], + "active": True, + "author": ["Xiaohao Yang", "Rundong Hua","Zhiming Xu", "Simon Billinge"], + "org_name": "diffpy", + "repo_name": "diffpy.srxplanar", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "2D diffraction image integration using non splitting pixel algorithm.", + "release": [ + { + "major": 1, + "minor": 0, + "patch": 1, + "release_type": "major", + "release_date": "2025-10-26", + "summary": "Python 3.14 and something else", + "changes": [], + "release_id": "1.0.0" + }, + { + "major": 0, + "minor": 1, + "patch": 1, + "release_type": "pre-release", + "pre_release": 2, + "release_date": "2025-10-20", + "summary": "Package pre-release", + "changes": ["change package to scikit-package level-5 standard."], + "release_id": "0.1.1-rc.2" + } + ] + } +software3 = { + "_id": "diffpy.distanceprinter", + "groups": ["billingegroup"], + "active": False, + "org_name": "diffpy", + "repo_name": "diffpy.distanceprinter", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", + "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], + "release": [ + { + "major": 0, + "minor": 1, + "patch": 0, + "release_type": "minor", + "release_date": "2025-10-26", + "summary": "Python 3.14 and something else", + "changes": [], + "release_id": "1.0.0" + } + ] + } +SOFTWARE = [software1, software2, software3] + +expected4 = { + '_id': 'diffpy.srxplanar', + 'active': True, + 'author': ['Xiaohao Yang', 'Rundong Hua', 'Zhiming Xu', 'Simon Billinge'], + 'authors': 'Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge', + 'grants': ['NSF Funding'], + 'groups': ['billingegroup'], + 'org_name': 'diffpy', + 'platform_name': 'Github', + 'program_description': '2D diffraction image integration using non splitting ' + 'pixel algorithm.', + 'release': [{'changes': [], + 'major': 1, + 'minor': 0, + 'patch': 1, + 'release_date': "2025-10-26", + 'release_id': '1.0.0', + 'release_type': 'major', + 'summary': 'Python 3.14 and something else'}, + {'changes': ['change package to scikit-package level-5 ' + 'standard.'], + 'major': 0, + 'minor': 1, + 'patch': 1, + 'pre_release': 2, + 'release_date': "2025-10-20", + 'release_id': '0.1.1-rc.2', + 'release_type': 'pre-release', + 'summary': 'Package pre-release'}], + 'repo_name': 'diffpy.srxplanar'} + +expected5 = { + '_id': 'diffpy.distanceprinter', + 'active': False, + 'author': ['Xiaohao Yang', 'Dasun Abeykoon', 'Simon Billinge'], + 'authors': 'Xiaohao Yang, Dasun Abeykoon, Simon Billinge', + 'grants': ['NSF Funding'], + 'groups': ['billingegroup'], + 'org_name': 'diffpy', + 'platform_name': 'Github', + 'program_description': 'Distance Printer, calculate the inter atomic ' + 'distances. Part of xPDFsuite', + 'release': [{'changes': [], + 'major': 0, + 'minor': 1, + 'patch': 0, + 'release_date':"2025-10-26", + 'release_id': '1.0.0', + 'release_type': 'minor', + 'summary': 'Python 3.14 and something else'}], + 'repo_name': 'diffpy.distanceprinter'} + +expected6 = {'_id': 'diffpy.utils', + 'active': True, + 'author': ['Simon Billinge', + 'Sanjoon Bob Lee', + 'Zhiming Xu', + 'Tieqiong Zhang'], + 'authors': 'Simon Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang', + 'grants': ['NSF Funding'], + 'groups': ['xrd'], + 'org_name': 'diffpy', + 'platform_name': 'Github', + 'program_description': 'General utilities for analyzing diffraction data', + 'release': [{'changes': ['deprecated python2 feature.', + 'changed to scikit-packaged standard.', + 'Add some functionality.', + 'Modify existing function to make convenient.'], + 'major': 3, + 'minor': 1, + 'patch': 0, + 'release_date': "2025-10-25", + 'release_id': '3.1.0', + 'release_type': 'major', + 'summary': 'Python 3.14 and something else'}], + 'repo_name': 'diffpy.utils'} + +expected7 = { + '_id': 'diffpy.srxplanar', + 'active': True, + 'author': ['Xiaohao Yang', 'Rundong Hua', 'Zhiming Xu', 'Simon Billinge'], + 'authors': 'Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge', + 'grants': ['NSF Funding'], + 'groups': ['billingegroup'], + 'org_name': 'diffpy', + 'platform_name': 'Github', + 'program_description': '2D diffraction image integration using non splitting ' + 'pixel algorithm.', + 'release': [{'changes': [], + 'major': 1, + 'minor': 0, + 'patch': 1, + 'release_date': "2025-10-26", + 'release_id': '1.0.0', + 'release_type': 'major', + 'summary': 'Python 3.14 and something else'}, + ], + 'repo_name': 'diffpy.srxplanar'} + +@pytest.mark.parametrize( + "args, kwargs, expected", + [ + # this tests no kwargs + ([PEOPLE, SOFTWARE, "sbillinge"], {}, [expected4, expected5, expected6]), + # this tests 'statuses' kwarg + ([PEOPLE, SOFTWARE, "sbillinge"], {"active": True}, [expected4, expected6]), + # this tests 'active' and 'types' kwargs together + ([PEOPLE, SOFTWARE, "stevenhua0320"], {"active": True, "types": ["major"]}, [expected7]), + # this tests 'active' and 'since' kwargs together + ( + [PEOPLE, SOFTWARE, "sbillinge"], + {"active": True, "since": "2025-10-21"}, + [expected7, expected6], + ), + # this tests the 'active' and 'before' kwargs together + ( + [PEOPLE, SOFTWARE, "sbillinge"], + {"active": True, "before": "2025-10-30"}, + [expected4, expected6], + ), + ], +) + +def test_filter_software(args, kwargs, expected): + actual = filter_software(*args, **kwargs) + assert actual == expected @pytest.mark.parametrize( "coll, expected", From a478a72701e1da02f563a4b777b80a0fec21243e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 23:57:43 +0000 Subject: [PATCH 15/23] [pre-commit.ci] auto fixes from pre-commit hooks --- src/regolith/tools.py | 11 +- tests/test_tools.py | 372 ++++++++++++++++++++++-------------------- 2 files changed, 202 insertions(+), 181 deletions(-) diff --git a/src/regolith/tools.py b/src/regolith/tools.py index 4b27c90a6..d343db72c 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -770,8 +770,7 @@ def filter_software(people, software, target, types=None, since=None, before=Non for program in secondclean: releases = program.get("release") filtered_releases = [ - release for release in releases - if "all" in types or release.get("release_type") in types + release for release in releases if "all" in types or release.get("release_type") in types ] if filtered_releases: program["release"] = filtered_releases @@ -838,9 +837,11 @@ def filter_software(people, software, target, types=None, since=None, before=Non progclean = sorted( progclean, key=lambda k: max( - datetime.fromisoformat(rel["release_date"]) - if isinstance(rel.get("release_date"), str) - else rel["release_date"] + ( + datetime.fromisoformat(rel["release_date"]) + if isinstance(rel.get("release_date"), str) + else rel["release_date"] + ) for rel in k["release"] ), reverse=True, diff --git a/tests/test_tools.py b/tests/test_tools.py index f22bc990e..110db1a8c 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -18,6 +18,7 @@ filter_employment_for_advisees, filter_presentations, filter_publications, + filter_software, fragment_retrieval, fuzzy_retrieval, get_appointments, @@ -44,7 +45,6 @@ search_collection, update_schemas, validate_meeting, - filter_software ) PEOPLE_COLL = [ @@ -3000,193 +3000,213 @@ def test_filter_presentations(args, kwargs, expected): actual = filter_presentations(*args, **kwargs) assert actual == expected + person3 = {"_id": "sbillinge", "aka": "Simon", "name": "Simon Billinge"} person4 = {"_id": "stevenhua0320", "aka": "Steven hua", "name": "Rundong Hua"} PEOPLE = [person3, person4] software1 = { - "_id": "diffpy.utils", - "groups": ["xrd"], - "active": True, - "org_name": "diffpy", - "repo_name": "diffpy.utils", - "platform_name": "Github", - "grants": ["NSF Funding"], - "program_description": "General utilities for analyzing diffraction data", - "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], - "release": [ - { - "major": 3, - "minor": 1, - "patch": 0, - "release_type": "major", - "release_date": "2025-10-25", - "summary": "Python 3.14 and something else", - "changes": ["deprecated python2 feature.", - "changed to scikit-packaged standard.", - "Add some functionality.", - "Modify existing function to make convenient." - ], - "release_id": "3.1.0" - } - ] + "_id": "diffpy.utils", + "groups": ["xrd"], + "active": True, + "org_name": "diffpy", + "repo_name": "diffpy.utils", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "General utilities for analyzing diffraction data", + "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], + "release": [ + { + "major": 3, + "minor": 1, + "patch": 0, + "release_type": "major", + "release_date": "2025-10-25", + "summary": "Python 3.14 and something else", + "changes": [ + "deprecated python2 feature.", + "changed to scikit-packaged standard.", + "Add some functionality.", + "Modify existing function to make convenient.", + ], + "release_id": "3.1.0", } + ], +} software2 = { - "_id": "diffpy.srxplanar", - "groups": ["billingegroup"], - "active": True, - "author": ["Xiaohao Yang", "Rundong Hua","Zhiming Xu", "Simon Billinge"], - "org_name": "diffpy", - "repo_name": "diffpy.srxplanar", - "platform_name": "Github", - "grants": ["NSF Funding"], - "program_description": "2D diffraction image integration using non splitting pixel algorithm.", - "release": [ - { - "major": 1, - "minor": 0, - "patch": 1, - "release_type": "major", - "release_date": "2025-10-26", - "summary": "Python 3.14 and something else", - "changes": [], - "release_id": "1.0.0" - }, - { - "major": 0, - "minor": 1, - "patch": 1, - "release_type": "pre-release", - "pre_release": 2, - "release_date": "2025-10-20", - "summary": "Package pre-release", - "changes": ["change package to scikit-package level-5 standard."], - "release_id": "0.1.1-rc.2" - } - ] - } + "_id": "diffpy.srxplanar", + "groups": ["billingegroup"], + "active": True, + "author": ["Xiaohao Yang", "Rundong Hua", "Zhiming Xu", "Simon Billinge"], + "org_name": "diffpy", + "repo_name": "diffpy.srxplanar", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "2D diffraction image integration using non splitting pixel algorithm.", + "release": [ + { + "major": 1, + "minor": 0, + "patch": 1, + "release_type": "major", + "release_date": "2025-10-26", + "summary": "Python 3.14 and something else", + "changes": [], + "release_id": "1.0.0", + }, + { + "major": 0, + "minor": 1, + "patch": 1, + "release_type": "pre-release", + "pre_release": 2, + "release_date": "2025-10-20", + "summary": "Package pre-release", + "changes": ["change package to scikit-package level-5 standard."], + "release_id": "0.1.1-rc.2", + }, + ], +} software3 = { - "_id": "diffpy.distanceprinter", - "groups": ["billingegroup"], - "active": False, - "org_name": "diffpy", - "repo_name": "diffpy.distanceprinter", - "platform_name": "Github", - "grants": ["NSF Funding"], - "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", - "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], - "release": [ - { - "major": 0, - "minor": 1, - "patch": 0, - "release_type": "minor", - "release_date": "2025-10-26", - "summary": "Python 3.14 and something else", - "changes": [], - "release_id": "1.0.0" - } - ] + "_id": "diffpy.distanceprinter", + "groups": ["billingegroup"], + "active": False, + "org_name": "diffpy", + "repo_name": "diffpy.distanceprinter", + "platform_name": "Github", + "grants": ["NSF Funding"], + "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", + "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], + "release": [ + { + "major": 0, + "minor": 1, + "patch": 0, + "release_type": "minor", + "release_date": "2025-10-26", + "summary": "Python 3.14 and something else", + "changes": [], + "release_id": "1.0.0", } + ], +} SOFTWARE = [software1, software2, software3] expected4 = { - '_id': 'diffpy.srxplanar', - 'active': True, - 'author': ['Xiaohao Yang', 'Rundong Hua', 'Zhiming Xu', 'Simon Billinge'], - 'authors': 'Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge', - 'grants': ['NSF Funding'], - 'groups': ['billingegroup'], - 'org_name': 'diffpy', - 'platform_name': 'Github', - 'program_description': '2D diffraction image integration using non splitting ' - 'pixel algorithm.', - 'release': [{'changes': [], - 'major': 1, - 'minor': 0, - 'patch': 1, - 'release_date': "2025-10-26", - 'release_id': '1.0.0', - 'release_type': 'major', - 'summary': 'Python 3.14 and something else'}, - {'changes': ['change package to scikit-package level-5 ' - 'standard.'], - 'major': 0, - 'minor': 1, - 'patch': 1, - 'pre_release': 2, - 'release_date': "2025-10-20", - 'release_id': '0.1.1-rc.2', - 'release_type': 'pre-release', - 'summary': 'Package pre-release'}], - 'repo_name': 'diffpy.srxplanar'} - -expected5 = { - '_id': 'diffpy.distanceprinter', - 'active': False, - 'author': ['Xiaohao Yang', 'Dasun Abeykoon', 'Simon Billinge'], - 'authors': 'Xiaohao Yang, Dasun Abeykoon, Simon Billinge', - 'grants': ['NSF Funding'], - 'groups': ['billingegroup'], - 'org_name': 'diffpy', - 'platform_name': 'Github', - 'program_description': 'Distance Printer, calculate the inter atomic ' - 'distances. Part of xPDFsuite', - 'release': [{'changes': [], - 'major': 0, - 'minor': 1, - 'patch': 0, - 'release_date':"2025-10-26", - 'release_id': '1.0.0', - 'release_type': 'minor', - 'summary': 'Python 3.14 and something else'}], - 'repo_name': 'diffpy.distanceprinter'} - -expected6 = {'_id': 'diffpy.utils', - 'active': True, - 'author': ['Simon Billinge', - 'Sanjoon Bob Lee', - 'Zhiming Xu', - 'Tieqiong Zhang'], - 'authors': 'Simon Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang', - 'grants': ['NSF Funding'], - 'groups': ['xrd'], - 'org_name': 'diffpy', - 'platform_name': 'Github', - 'program_description': 'General utilities for analyzing diffraction data', - 'release': [{'changes': ['deprecated python2 feature.', - 'changed to scikit-packaged standard.', - 'Add some functionality.', - 'Modify existing function to make convenient.'], - 'major': 3, - 'minor': 1, - 'patch': 0, - 'release_date': "2025-10-25", - 'release_id': '3.1.0', - 'release_type': 'major', - 'summary': 'Python 3.14 and something else'}], - 'repo_name': 'diffpy.utils'} + "_id": "diffpy.srxplanar", + "active": True, + "author": ["Xiaohao Yang", "Rundong Hua", "Zhiming Xu", "Simon Billinge"], + "authors": "Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge", + "grants": ["NSF Funding"], + "groups": ["billingegroup"], + "org_name": "diffpy", + "platform_name": "Github", + "program_description": "2D diffraction image integration using non splitting " "pixel algorithm.", + "release": [ + { + "changes": [], + "major": 1, + "minor": 0, + "patch": 1, + "release_date": "2025-10-26", + "release_id": "1.0.0", + "release_type": "major", + "summary": "Python 3.14 and something else", + }, + { + "changes": ["change package to scikit-package level-5 " "standard."], + "major": 0, + "minor": 1, + "patch": 1, + "pre_release": 2, + "release_date": "2025-10-20", + "release_id": "0.1.1-rc.2", + "release_type": "pre-release", + "summary": "Package pre-release", + }, + ], + "repo_name": "diffpy.srxplanar", +} + +expected5 = { + "_id": "diffpy.distanceprinter", + "active": False, + "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], + "authors": "Xiaohao Yang, Dasun Abeykoon, Simon Billinge", + "grants": ["NSF Funding"], + "groups": ["billingegroup"], + "org_name": "diffpy", + "platform_name": "Github", + "program_description": "Distance Printer, calculate the inter atomic " "distances. Part of xPDFsuite", + "release": [ + { + "changes": [], + "major": 0, + "minor": 1, + "patch": 0, + "release_date": "2025-10-26", + "release_id": "1.0.0", + "release_type": "minor", + "summary": "Python 3.14 and something else", + } + ], + "repo_name": "diffpy.distanceprinter", +} + +expected6 = { + "_id": "diffpy.utils", + "active": True, + "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], + "authors": "Simon Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang", + "grants": ["NSF Funding"], + "groups": ["xrd"], + "org_name": "diffpy", + "platform_name": "Github", + "program_description": "General utilities for analyzing diffraction data", + "release": [ + { + "changes": [ + "deprecated python2 feature.", + "changed to scikit-packaged standard.", + "Add some functionality.", + "Modify existing function to make convenient.", + ], + "major": 3, + "minor": 1, + "patch": 0, + "release_date": "2025-10-25", + "release_id": "3.1.0", + "release_type": "major", + "summary": "Python 3.14 and something else", + } + ], + "repo_name": "diffpy.utils", +} expected7 = { - '_id': 'diffpy.srxplanar', - 'active': True, - 'author': ['Xiaohao Yang', 'Rundong Hua', 'Zhiming Xu', 'Simon Billinge'], - 'authors': 'Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge', - 'grants': ['NSF Funding'], - 'groups': ['billingegroup'], - 'org_name': 'diffpy', - 'platform_name': 'Github', - 'program_description': '2D diffraction image integration using non splitting ' - 'pixel algorithm.', - 'release': [{'changes': [], - 'major': 1, - 'minor': 0, - 'patch': 1, - 'release_date': "2025-10-26", - 'release_id': '1.0.0', - 'release_type': 'major', - 'summary': 'Python 3.14 and something else'}, - ], - 'repo_name': 'diffpy.srxplanar'} + "_id": "diffpy.srxplanar", + "active": True, + "author": ["Xiaohao Yang", "Rundong Hua", "Zhiming Xu", "Simon Billinge"], + "authors": "Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon Billinge", + "grants": ["NSF Funding"], + "groups": ["billingegroup"], + "org_name": "diffpy", + "platform_name": "Github", + "program_description": "2D diffraction image integration using non splitting " "pixel algorithm.", + "release": [ + { + "changes": [], + "major": 1, + "minor": 0, + "patch": 1, + "release_date": "2025-10-26", + "release_id": "1.0.0", + "release_type": "major", + "summary": "Python 3.14 and something else", + }, + ], + "repo_name": "diffpy.srxplanar", +} + @pytest.mark.parametrize( "args, kwargs, expected", @@ -3211,11 +3231,11 @@ def test_filter_presentations(args, kwargs, expected): ), ], ) - def test_filter_software(args, kwargs, expected): actual = filter_software(*args, **kwargs) assert actual == expected + @pytest.mark.parametrize( "coll, expected", [ From ca239ff5bb7f48d737c39d1d6bbaa9f50c82334b Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 10 Nov 2025 19:21:23 -0500 Subject: [PATCH 16/23] fix: change variable and function argument to make it right --- src/regolith/builders/releaselistbuilder.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index d1ed30d9a..69d73ca7b 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -11,7 +11,7 @@ class ReleaseListBuilder(LatexBuilderBase): """Build list of released software from database entries.""" btype = "releaselist" - needed_colls = ["groups", "institutions", "people", "grants", "software", "contacts"] + needed_colls = ["groups", "people", "grants", "software", "contacts"] def construct_global_ctx(self): """Constructs the global context.""" @@ -31,7 +31,6 @@ def construct_global_ctx(self): gtx["grants"] = sorted(all_docs_from_collection(rc.client, "grants"), key=_id_key) gtx["groups"] = sorted(all_docs_from_collection(rc.client, "groups"), key=_id_key) gtx["software"] = sorted(all_docs_from_collection(rc.client, "software"), key=_id_key) - gtx["institutions"] = sorted(all_docs_from_collection(rc.client, "institutions"), key=_id_key) gtx["all_docs_from_collection"] = all_docs_from_collection gtx["float"] = float gtx["str"] = str @@ -47,13 +46,13 @@ def latex(self): if self.rc.people: if member not in self.rc.people: continue - presclean = filter_software( - everybody, self.gtx["software"], self.gtx["institutions"], member, statuses=["active"] + progclean = filter_software( + everybody, self.gtx["software"], member, active=True ) if len(presclean) > 0: - presclean = sorted( - presclean, + progclean = sorted( + progclean, key=lambda k: k.get("date", None), reverse=True, ) @@ -63,7 +62,7 @@ def latex(self): "releaselist.tex", outfile + ".tex", pi=pi, - presentations=presclean, + presentations=progclean, sentencecase=sentencecase, monthstyle=month_fullnames, ) @@ -73,7 +72,7 @@ def latex(self): "releaselist.txt", outfile + ".txt", pi=pi, - presentations=presclean, + presentations=progclean, sentencecase=sentencecase, monthstyle=month_fullnames, ) From fc64966f9b76e7522ea16faf824165eb2478f774 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:21:59 +0000 Subject: [PATCH 17/23] [pre-commit.ci] auto fixes from pre-commit hooks --- src/regolith/builders/releaselistbuilder.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index 69d73ca7b..86e1a7eb8 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -46,9 +46,7 @@ def latex(self): if self.rc.people: if member not in self.rc.people: continue - progclean = filter_software( - everybody, self.gtx["software"], member, active=True - ) + progclean = filter_software(everybody, self.gtx["software"], member, active=True) if len(presclean) > 0: progclean = sorted( From 7df50f379ce522683dbdc8a5c0bf3d7bc4e1f49f Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 10 Nov 2025 19:31:32 -0500 Subject: [PATCH 18/23] fix: change latex render level in releaselistbuilder and add releaselist in test_builders --- src/regolith/builders/releaselistbuilder.py | 76 ++++++++++----------- tests/test_builders.py | 1 + 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index 86e1a7eb8..1e571e8ff 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -36,42 +36,42 @@ def construct_global_ctx(self): gtx["str"] = str gtx["zip"] = zip - def latex(self): - """Render latex template.""" - everybody = self.gtx["people"] + self.gtx["contacts"] - for group in self.gtx["groups"]: - grp = group["_id"] - grpmember_ids = group_member_ids(self.gtx["people"], grp) - for member in grpmember_ids: - if self.rc.people: - if member not in self.rc.people: - continue - progclean = filter_software(everybody, self.gtx["software"], member, active=True) + def latex(self): + """Render latex template.""" + everybody = self.gtx["people"] + self.gtx["contacts"] + for group in self.gtx["groups"]: + grp = group["_id"] + grpmember_ids = group_member_ids(self.gtx["people"], grp) + for member in grpmember_ids: + if self.rc.people: + if member not in self.rc.people: + continue + progclean = filter_software(everybody, self.gtx["software"], member, active=True) - if len(presclean) > 0: - progclean = sorted( - progclean, - key=lambda k: k.get("date", None), - reverse=True, - ) - outfile = "software-" + grp + "-" + member - pi = [person for person in self.gtx["people"] if person["_id"] is member][0] - self.render( - "releaselist.tex", - outfile + ".tex", - pi=pi, - presentations=progclean, - sentencecase=sentencecase, - monthstyle=month_fullnames, - ) - self.env.trim_blocks = True - self.env.lstrip_blocks = True - self.render( - "releaselist.txt", - outfile + ".txt", - pi=pi, - presentations=progclean, - sentencecase=sentencecase, - monthstyle=month_fullnames, - ) - self.pdf(outfile) + if len(progclean) > 0: + progclean = sorted( + progclean, + key=lambda k: k.get("date", None), + reverse=True, + ) + outfile = "software-" + grp + "-" + member + pi = [person for person in self.gtx["people"] if person["_id"] is member][0] + self.render( + "releaselist.tex", + outfile + ".tex", + pi=pi, + presentations=progclean, + sentencecase=sentencecase, + monthstyle=month_fullnames, + ) + self.env.trim_blocks = True + self.env.lstrip_blocks = True + self.render( + "releaselist.txt", + outfile + ".txt", + pi=pi, + presentations=progclean, + sentencecase=sentencecase, + monthstyle=month_fullnames, + ) + self.pdf(outfile) diff --git a/tests/test_builders.py b/tests/test_builders.py index 6e9ca2626..bec722f01 100644 --- a/tests/test_builders.py +++ b/tests/test_builders.py @@ -24,6 +24,7 @@ "internalhtml", "preslist", "publist", + "releaselist", "recent-collabs", "grant-report", "resume", From 2b151473cbacb1a795027f1560bba07bf04010d1 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Mon, 10 Nov 2025 19:56:26 -0500 Subject: [PATCH 19/23] fix: change format of releaselist.tex --- src/regolith/templates/releaselist.tex | 19 +++--- tests/outputs/releaselist/releaselist.tex | 71 +++++++++++++++++++++++ 2 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/outputs/releaselist/releaselist.tex diff --git a/src/regolith/templates/releaselist.tex b/src/regolith/templates/releaselist.tex index 3129f1892..51f81acd9 100644 --- a/src/regolith/templates/releaselist.tex +++ b/src/regolith/templates/releaselist.tex @@ -13,26 +13,26 @@ \noindent \colorbox{gray!40}{% \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} - \textbf{\Large {{-latex_safe(pi['name']).upper()}}} & \textbf{\today} \\ - {{-latex_safe(pi['institution'])}} & {{-latex_safe(pi['email']}} \\ + \textbf{\Large {{- latex_safe(pi['name']).upper() -}}} & \textbf{\today} \\ + {{- latex_safe(pi['institution']) -}} & {{- latex_safe(pi['email']) -}}\\ \end{tabular*}% }\vspace{1em} \textbf{Software Releaselist} \begin{enumerate} -{% for program in software if program.active %} - \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name'])-}}/{{ latex_safe(program['repo_name'])-}}}{{ "{" ~ latex_safe(s['org_name']) ~ "/" ~ latex_safe(s['repo_name']) ~ "}" }}:}\\ - \hspace*{1em}{{ latex_safe(program['program_description'])-}}\\ - \hspace*{1em}\textit{Authors: {{ latex_safe(', '.join(program.get('author', [])))-}}}\\ - \hspace*{1em}Url: https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(s['repo_name']) }}\\ +{% for program in software %} + \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}}{ {{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }} }:}\\ + \hspace*{1em}{{ latex_safe(program['program_description']) }}\\ + \hspace*{1em}\textit{Authors: {{ latex_safe(', '.join(program.get('author', []))) }}}\\ + \hspace*{1em}Url: https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} \begin{itemize}[label={}] {% for release in program['release'] %} - \item \textbf{{ latex_safe(release['release_id']) }}: {{ latex_safe(release['release_date']) }} + \item \textbf{ {{ latex_safe(release['release_id']) }} }: {{ latex_safe(release['release_date']) }} \begin{itemize}[label={}, leftmargin=2em] {% if release.get('summary') %} - \item \textit{{ latex_safe(release['summary']) }} + \item \textit{ {{ latex_safe(release['summary']) }} } {% endif %} {% for change in release.get('changes', []) %} \item {{ latex_safe(change) }} @@ -44,3 +44,4 @@ \end{enumerate} \end{document} + diff --git a/tests/outputs/releaselist/releaselist.tex b/tests/outputs/releaselist/releaselist.tex new file mode 100644 index 000000000..b9b7ab839 --- /dev/null +++ b/tests/outputs/releaselist/releaselist.tex @@ -0,0 +1,71 @@ +\documentclass[prl,tighten,amsmath,amssymb,floatfix]{revtex4-1} +\usepackage{graphicx} +\usepackage{times} +\usepackage{booktabs,dcolumn} +\usepackage{siunitx} +\usepackage[utf8]{inputenc} +\usepackage{xcolor} +\usepackage{hyperref} +\usepackage{enumitem} + + +\begin{document} + +\noindent +\colorbox{gray!40}{% + \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} + \textbf{\Large Prof. Simon J.~L.~Billinge} & \textbf{\today} \\ + Columbia University in the City of New York & sb2896@columbia.edu \\ + \end{tabular*}% +}\vspace{1em} + +\textbf{Software Releaselist} + + +\begin{enumerate} + \item \textbf{\href{https://github.com/diffpy/diffpy.utils}{diffpy/diffpy.utils}:}\\ + \hspace*{1em}General utilities for analyzing diffraction data\\ + \hspace*{1em}\textit{Authors: Simon J.~L. Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang}\\ + \hspace*{1em}Url: https://github.com/diffpy/diffpy.utils\\ + \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} + \begin{itemize}[label={}] + \item \textbf{3.1.0:} 2025-10-25 + \begin{itemize}[label={}, leftmargin=2em] + \item Deprecated Python 2 feature + \item Changed to scikit-packaged standard. + \item Add some functionality + \item Modify existing function to make convenient. + \end{itemize} + \end{itemize} + + \item \textbf{\href{https://github.com/diffpy/diffpy.srxplanar}{diffpy/diffpy.srxplanar}:}\\ + \hspace*{1em}2D diffraction image integration using non splitting pixel algorithm.\\ + \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ + \hspace*{1em}Url: https://github.com/diffpy/diffpy.srxplanar\\ + \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} + \begin{itemize}[label={}] + \item \textbf{1.0.1:} 2025-10-26 + \begin{itemize}[label={}, leftmargin=2em] + \item Fix loadimage function correctly finds files when passed a relative path. + \end{itemize} + \item \textbf{0.1.1-rc.2:} 2025-10-20 + \begin{itemize}[label={}, leftmargin=2em] + \item change package to scikit-package level-5 standard. + \end{itemize} + \end{itemize} + + \item \textbf{\href{https://github.com/diffpy/diffpy.distanceprinter}{diffpy/diffpy.distanceprinter}:}\\ + \hspace*{1em}Distance Printer, calculate the inter atomic distances. Part of xPDFsuite\\ + \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ + \hspace*{1em}Url: https://github.com/diffpy/diffpy.distanceprinter\\ + \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} + \begin{itemize}[label={}] + \item \textbf{0.1.0:} 2025-10-26 + \begin{itemize}[label={}, leftmargin=2em] + \item Python 3.14 and something else + \end{itemize} + \end{itemize} + +\end{enumerate} + +\end{document} From 05c72d576163f50340dc04d812a4f2a25ee443ca Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:56:50 +0000 Subject: [PATCH 20/23] [pre-commit.ci] auto fixes from pre-commit hooks --- src/regolith/templates/releaselist.tex | 1 - 1 file changed, 1 deletion(-) diff --git a/src/regolith/templates/releaselist.tex b/src/regolith/templates/releaselist.tex index 51f81acd9..cd998635a 100644 --- a/src/regolith/templates/releaselist.tex +++ b/src/regolith/templates/releaselist.tex @@ -44,4 +44,3 @@ \end{enumerate} \end{document} - From ae7ef2e617b446acf69c609419792c0a16ffd9b4 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Tue, 18 Nov 2025 22:17:58 -0500 Subject: [PATCH 21/23] fix: correctly render the tex file, next step fix error. --- src/regolith/builders/releaselistbuilder.py | 46 +++++++++---------- src/regolith/exemplars.json | 12 ++--- src/regolith/templates/releaselist.tex | 20 ++++---- src/regolith/tools.py | 13 ++---- .../{releaselist.tex => software-report.tex} | 0 tests/test_builders.py | 2 +- 6 files changed, 45 insertions(+), 48 deletions(-) rename tests/outputs/releaselist/{releaselist.tex => software-report.tex} (100%) diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index 1e571e8ff..697450185 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -46,32 +46,32 @@ def latex(self): if self.rc.people: if member not in self.rc.people: continue - progclean = filter_software(everybody, self.gtx["software"], member, active=True) + progclean = filter_software(everybody, self.gtx["software"], member) if len(progclean) > 0: progclean = sorted( progclean, - key=lambda k: k.get("date", None), + key=lambda k: max(release["release_date"] for release in k["release"]), reverse=True, ) - outfile = "software-" + grp + "-" + member - pi = [person for person in self.gtx["people"] if person["_id"] is member][0] - self.render( - "releaselist.tex", - outfile + ".tex", - pi=pi, - presentations=progclean, - sentencecase=sentencecase, - monthstyle=month_fullnames, - ) - self.env.trim_blocks = True - self.env.lstrip_blocks = True - self.render( - "releaselist.txt", - outfile + ".txt", - pi=pi, - presentations=progclean, - sentencecase=sentencecase, - monthstyle=month_fullnames, - ) - self.pdf(outfile) + outfile = "software-report" + pi = [person for person in self.gtx["people"] if person["_id"] == member][0] + self.render( + "releaselist.tex", + outfile + ".tex", + pi=pi, + software=progclean, + sentencecase=sentencecase, + monthstyle=month_fullnames, + ) + self.env.trim_blocks = True + self.env.lstrip_blocks = True + # self.render( + # "releaselist.txt", + # outfile + ".txt", + # pi=pi, + # software=progclean, + # sentencecase=sentencecase, + # monthstyle=month_fullnames, + # ) + # self.pdf(outfile) diff --git a/src/regolith/exemplars.json b/src/regolith/exemplars.json index bcc173fb5..c224ff4f0 100644 --- a/src/regolith/exemplars.json +++ b/src/regolith/exemplars.json @@ -2171,14 +2171,14 @@ "software": [ { "_id": "diffpy.utils", - "groups": ["xrd"], + "groups": ["aeinstein_grp"], "active": true, "org_name": "diffpy", "repo_name": "diffpy.utils", "platform_name": "Github", "grants": ["NSF Funding"], "program_description": "General utilities for analyzing diffraction data", - "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang"], + "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang", "aeinstein"], "release": [ { "major": 3, @@ -2198,9 +2198,9 @@ }, { "_id": "diffpy.srxplanar", - "groups": ["billingegroup"], + "groups": ["aeinstein_grp"], "active": true, - "author": ["Xiaohao Yang", "Rundong Hua","Zhiming Xu", "Simon Billinge"], + "author": ["Xiaohao Yang", "Rundong Hua","Zhiming Xu", "Simon Billinge", "aeinstein"], "org_name": "diffpy", "repo_name": "diffpy.srxplanar", "platform_name": "Github", @@ -2232,14 +2232,14 @@ }, { "_id": "diffpy.distanceprinter", - "groups": ["billingegroup"], + "groups": ["aeinstein_grp"], "active": false, "org_name": "diffpy", "repo_name": "diffpy.distanceprinter", "platform_name": "Github", "grants": ["NSF Funding"], "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", - "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge"], + "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge", "aeinstein"], "release": [ { "major": 0, diff --git a/src/regolith/templates/releaselist.tex b/src/regolith/templates/releaselist.tex index cd998635a..2bf8b4fc5 100644 --- a/src/regolith/templates/releaselist.tex +++ b/src/regolith/templates/releaselist.tex @@ -10,34 +10,38 @@ \begin{document} +{% raw %} \noindent \colorbox{gray!40}{% \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} - \textbf{\Large {{- latex_safe(pi['name']).upper() -}}} & \textbf{\today} \\ - {{- latex_safe(pi['institution']) -}} & {{- latex_safe(pi['email']) -}}\\ +{% endraw %} + \textbf{\Large {{ latex_safe(pi['name']).upper() }}} & \textbf{\today} \\ + {{ latex_safe(pi['institution']) }} & {{ latex_safe(pi['email']) }} \\ +{% raw %} \end{tabular*}% }\vspace{1em} +{% endraw %} \textbf{Software Releaselist} \begin{enumerate} {% for program in software %} - \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}}{ {{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }} }:}\\ + \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}}{ {{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }} }}:\\ \hspace*{1em}{{ latex_safe(program['program_description']) }}\\ \hspace*{1em}\textit{Authors: {{ latex_safe(', '.join(program.get('author', []))) }}}\\ \hspace*{1em}Url: https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} - \begin{itemize}[label={}] + \begin{itemize}[label={}, leftmargin=2em] {% for release in program['release'] %} \item \textbf{ {{ latex_safe(release['release_id']) }} }: {{ latex_safe(release['release_date']) }} - \begin{itemize}[label={}, leftmargin=2em] - {% if release.get('summary') %} - \item \textit{ {{ latex_safe(release['summary']) }} } - {% endif %} + {% if release.get('summary') %} + \begin{itemize}[label={}, leftmargin=1em] + \item { {{ latex_safe(release['summary']) }} } {% for change in release.get('changes', []) %} \item {{ latex_safe(change) }} {% endfor %} \end{itemize} + {% endif %} {% endfor %} \end{itemize} {% endfor %} diff --git a/src/regolith/tools.py b/src/regolith/tools.py index d343db72c..fadc3c7b9 100644 --- a/src/regolith/tools.py +++ b/src/regolith/tools.py @@ -830,20 +830,13 @@ def filter_software(people, software, target, types=None, since=None, before=Non for release in program.get("release", []): releasedate = release.get("release_date") - if isinstance(releasedate, str): - release["release_date"] = releasedate + if isinstance(releasedate, date): + release["release_date"] = releasedate.isoformat() if len(progclean) > 0: progclean = sorted( progclean, - key=lambda k: max( - ( - datetime.fromisoformat(rel["release_date"]) - if isinstance(rel.get("release_date"), str) - else rel["release_date"] - ) - for rel in k["release"] - ), + key=lambda k: max(release["release_date"] for release in k["release"]), reverse=True, ) return progclean diff --git a/tests/outputs/releaselist/releaselist.tex b/tests/outputs/releaselist/software-report.tex similarity index 100% rename from tests/outputs/releaselist/releaselist.tex rename to tests/outputs/releaselist/software-report.tex diff --git a/tests/test_builders.py b/tests/test_builders.py index bec722f01..4910e75f3 100644 --- a/tests/test_builders.py +++ b/tests/test_builders.py @@ -24,13 +24,13 @@ "internalhtml", "preslist", "publist", - "releaselist", "recent-collabs", "grant-report", "resume", "review-man", # reading-lists need tests for this "reimb", + "releaselist", ] db_srcs = ["mongo", "fs"] From 7412568295333a7a34fbef4fbc0859a25014e272 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 19 Nov 2025 17:51:33 -0500 Subject: [PATCH 22/23] fix: match latex build with the test output template. --- src/regolith/builders/releaselistbuilder.py | 2 +- src/regolith/exemplars.json | 34 +++++++++------- src/regolith/templates/releaselist.tex | 11 +++--- ...report.tex => software-report-scopatz.tex} | 39 +++++++++---------- 4 files changed, 46 insertions(+), 40 deletions(-) rename tests/outputs/releaselist/{software-report.tex => software-report-scopatz.tex} (77%) diff --git a/src/regolith/builders/releaselistbuilder.py b/src/regolith/builders/releaselistbuilder.py index 697450185..28eaaa749 100644 --- a/src/regolith/builders/releaselistbuilder.py +++ b/src/regolith/builders/releaselistbuilder.py @@ -54,7 +54,7 @@ def latex(self): key=lambda k: max(release["release_date"] for release in k["release"]), reverse=True, ) - outfile = "software-report" + outfile = "software-report-" + member pi = [person for person in self.gtx["people"] if person["_id"] == member][0] self.render( "releaselist.tex", diff --git a/src/regolith/exemplars.json b/src/regolith/exemplars.json index c224ff4f0..ee38aa20e 100644 --- a/src/regolith/exemplars.json +++ b/src/regolith/exemplars.json @@ -2178,7 +2178,7 @@ "platform_name": "Github", "grants": ["NSF Funding"], "program_description": "General utilities for analyzing diffraction data", - "author": ["Simon Billinge", "Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang", "aeinstein"], + "author": ["Sanjoon Bob Lee", "Zhiming Xu", "Tieqiong Zhang", "ANTHONY SCOPATZ"], "release": [ { "major": 3, @@ -2187,10 +2187,10 @@ "release_type": "major", "release_date": "2025-10-25", "summary": "Python 3.14 and something else", - "changes": ["deprecated python2 feature.", - "changed to scikit-packaged standard.", - "Add some functionality.", - "Modify existing function to make convenient." + "changes": ["Deprecated Python 2 feature", + "Changed to scikit-packaged standard", + "Add some functionality", + "Modify existing function to make convenient" ], "release_id": "3.1.0" } @@ -2200,7 +2200,7 @@ "_id": "diffpy.srxplanar", "groups": ["aeinstein_grp"], "active": true, - "author": ["Xiaohao Yang", "Rundong Hua","Zhiming Xu", "Simon Billinge", "aeinstein"], + "author": ["Xiaohao Yang", "Rundong Hua", "Zhiming Xu", "ANTHONY SCOPATZ"], "org_name": "diffpy", "repo_name": "diffpy.srxplanar", "platform_name": "Github", @@ -2208,14 +2208,14 @@ "program_description": "2D diffraction image integration using non splitting pixel algorithm.", "release": [ { - "major": 0, + "major": 1, "minor": 0, "patch": 1, "release_type": "patch", "release_date": "2025-10-26", "summary": "Python 3.14 and something else", - "changes": [], - "release_id": "1.0.0" + "changes": ["Fix loadimage function correctly finds files when passed a relative path."], + "release_id": "1.0.1" }, { "major": 0, @@ -2232,14 +2232,22 @@ }, { "_id": "diffpy.distanceprinter", - "groups": ["aeinstein_grp"], + "groups": [ + "aeinstein_grp" + ], "active": false, "org_name": "diffpy", "repo_name": "diffpy.distanceprinter", "platform_name": "Github", - "grants": ["NSF Funding"], + "grants": [ + "NSF Funding" + ], "program_description": "Distance Printer, calculate the inter atomic distances. Part of xPDFsuite", - "author": ["Xiaohao Yang", "Dasun Abeykoon", "Simon Billinge", "aeinstein"], + "author": [ + "Xiaohao Yang", + "Dasun Abeykoon", + "ANTHONY SCOPATZ" + ], "release": [ { "major": 0, @@ -2248,7 +2256,7 @@ "release_type": "minor", "release_date": "2025-10-26", "summary": "Python 3.14 and something else", - "changes": [], + "changes": ["Python 3.14 and something else"], "release_id": "1.0.0" } ] diff --git a/src/regolith/templates/releaselist.tex b/src/regolith/templates/releaselist.tex index 2bf8b4fc5..afa758726 100644 --- a/src/regolith/templates/releaselist.tex +++ b/src/regolith/templates/releaselist.tex @@ -26,17 +26,16 @@ \begin{enumerate} {% for program in software %} - \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}}{ {{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }} }}:\\ + \item \textbf{\href{https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}}{ {{- latex_safe(program['org_name']) -}}/{{- latex_safe(program['repo_name']) -}}}:}\\ \hspace*{1em}{{ latex_safe(program['program_description']) }}\\ \hspace*{1em}\textit{Authors: {{ latex_safe(', '.join(program.get('author', []))) }}}\\ \hspace*{1em}Url: https://github.com/{{ latex_safe(program['org_name']) }}/{{ latex_safe(program['repo_name']) }}\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} - \begin{itemize}[label={}, leftmargin=2em] + \begin{itemize}[label={}] {% for release in program['release'] %} - \item \textbf{ {{ latex_safe(release['release_id']) }} }: {{ latex_safe(release['release_date']) }} - {% if release.get('summary') %} - \begin{itemize}[label={}, leftmargin=1em] - \item { {{ latex_safe(release['summary']) }} } + \item \textbf{ {{- latex_safe(release['release_id']) -}}:} {{ latex_safe(release['release_date']) }} + \begin{itemize}[label={}, leftmargin=2em] + {% if release.get('changes') %} {% for change in release.get('changes', []) %} \item {{ latex_safe(change) }} {% endfor %} diff --git a/tests/outputs/releaselist/software-report.tex b/tests/outputs/releaselist/software-report-scopatz.tex similarity index 77% rename from tests/outputs/releaselist/software-report.tex rename to tests/outputs/releaselist/software-report-scopatz.tex index b9b7ab839..04f6de7db 100644 --- a/tests/outputs/releaselist/software-report.tex +++ b/tests/outputs/releaselist/software-report-scopatz.tex @@ -14,8 +14,8 @@ \noindent \colorbox{gray!40}{% \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} - \textbf{\Large Prof. Simon J.~L.~Billinge} & \textbf{\today} \\ - Columbia University in the City of New York & sb2896@columbia.edu \\ + \textbf{\Large ANTHONY SCOPATZ} & \textbf{\today} \\ + & scopatz@cec.sc.edu \\ \end{tabular*}% }\vspace{1em} @@ -23,24 +23,20 @@ \begin{enumerate} - \item \textbf{\href{https://github.com/diffpy/diffpy.utils}{diffpy/diffpy.utils}:}\\ - \hspace*{1em}General utilities for analyzing diffraction data\\ - \hspace*{1em}\textit{Authors: Simon J.~L. Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang}\\ - \hspace*{1em}Url: https://github.com/diffpy/diffpy.utils\\ + \item \textbf{\href{https://github.com/diffpy/diffpy.distanceprinter}{diffpy/diffpy.distanceprinter}:}\\ + \hspace*{1em}Distance Printer, calculate the inter atomic distances. Part of xPDFsuite\\ + \hspace*{1em}\textit{Authors: Xiaohao Yang, Dasun Abeykoon, ANTHONY SCOPATZ}\\ + \hspace*{1em}Url: https://github.com/diffpy/diffpy.distanceprinter\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} \begin{itemize}[label={}] - \item \textbf{3.1.0:} 2025-10-25 + \item \textbf{1.0.0:} 2025-10-26 \begin{itemize}[label={}, leftmargin=2em] - \item Deprecated Python 2 feature - \item Changed to scikit-packaged standard. - \item Add some functionality - \item Modify existing function to make convenient. + \item Python 3.14 and something else \end{itemize} \end{itemize} - - \item \textbf{\href{https://github.com/diffpy/diffpy.srxplanar}{diffpy/diffpy.srxplanar}:}\\ + \item \textbf{\href{https://github.com/diffpy/diffpy.srxplanar}{diffpy/diffpy.srxplanar}:}\\ \hspace*{1em}2D diffraction image integration using non splitting pixel algorithm.\\ - \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ + \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, ANTHONY SCOPATZ}\\ \hspace*{1em}Url: https://github.com/diffpy/diffpy.srxplanar\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} \begin{itemize}[label={}] @@ -54,15 +50,18 @@ \end{itemize} \end{itemize} - \item \textbf{\href{https://github.com/diffpy/diffpy.distanceprinter}{diffpy/diffpy.distanceprinter}:}\\ - \hspace*{1em}Distance Printer, calculate the inter atomic distances. Part of xPDFsuite\\ - \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ - \hspace*{1em}Url: https://github.com/diffpy/diffpy.distanceprinter\\ + \item \textbf{\href{https://github.com/diffpy/diffpy.utils}{diffpy/diffpy.utils}:}\\ + \hspace*{1em}General utilities for analyzing diffraction data\\ + \hspace*{1em}\textit{Authors: Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang, ANTHONY SCOPATZ}\\ + \hspace*{1em}Url: https://github.com/diffpy/diffpy.utils\\ \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} \begin{itemize}[label={}] - \item \textbf{0.1.0:} 2025-10-26 + \item \textbf{3.1.0:} 2025-10-25 \begin{itemize}[label={}, leftmargin=2em] - \item Python 3.14 and something else + \item Deprecated Python 2 feature + \item Changed to scikit-packaged standard + \item Add some functionality + \item Modify existing function to make convenient \end{itemize} \end{itemize} From d7cb793863ec94bbe6bd8ed1b342eb704acd581f Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 19 Nov 2025 18:17:15 -0500 Subject: [PATCH 23/23] Fix: capitalize letter to pass test --- news/releasebuilder.rst | 2 +- tests/outputs/releaselist/releaselist.tex | 71 ------------------- .../releaselist/software-report-scopatz.tex | 2 +- 3 files changed, 2 insertions(+), 73 deletions(-) delete mode 100644 tests/outputs/releaselist/releaselist.tex diff --git a/news/releasebuilder.rst b/news/releasebuilder.rst index c3f9346f3..cbebfabcf 100644 --- a/news/releasebuilder.rst +++ b/news/releasebuilder.rst @@ -1,6 +1,6 @@ **Added:** -* Add `ReleaseListBuilder` functionality +* Add `ReleaseListBuilder` functionality, filter criteria **Changed:** diff --git a/tests/outputs/releaselist/releaselist.tex b/tests/outputs/releaselist/releaselist.tex deleted file mode 100644 index b9b7ab839..000000000 --- a/tests/outputs/releaselist/releaselist.tex +++ /dev/null @@ -1,71 +0,0 @@ -\documentclass[prl,tighten,amsmath,amssymb,floatfix]{revtex4-1} -\usepackage{graphicx} -\usepackage{times} -\usepackage{booktabs,dcolumn} -\usepackage{siunitx} -\usepackage[utf8]{inputenc} -\usepackage{xcolor} -\usepackage{hyperref} -\usepackage{enumitem} - - -\begin{document} - -\noindent -\colorbox{gray!40}{% - \begin{tabular*}{7in}{l@{\extracolsep{\fill}}r} - \textbf{\Large Prof. Simon J.~L.~Billinge} & \textbf{\today} \\ - Columbia University in the City of New York & sb2896@columbia.edu \\ - \end{tabular*}% -}\vspace{1em} - -\textbf{Software Releaselist} - - -\begin{enumerate} - \item \textbf{\href{https://github.com/diffpy/diffpy.utils}{diffpy/diffpy.utils}:}\\ - \hspace*{1em}General utilities for analyzing diffraction data\\ - \hspace*{1em}\textit{Authors: Simon J.~L. Billinge, Sanjoon Bob Lee, Zhiming Xu, Tieqiong Zhang}\\ - \hspace*{1em}Url: https://github.com/diffpy/diffpy.utils\\ - \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} - \begin{itemize}[label={}] - \item \textbf{3.1.0:} 2025-10-25 - \begin{itemize}[label={}, leftmargin=2em] - \item Deprecated Python 2 feature - \item Changed to scikit-packaged standard. - \item Add some functionality - \item Modify existing function to make convenient. - \end{itemize} - \end{itemize} - - \item \textbf{\href{https://github.com/diffpy/diffpy.srxplanar}{diffpy/diffpy.srxplanar}:}\\ - \hspace*{1em}2D diffraction image integration using non splitting pixel algorithm.\\ - \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ - \hspace*{1em}Url: https://github.com/diffpy/diffpy.srxplanar\\ - \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} - \begin{itemize}[label={}] - \item \textbf{1.0.1:} 2025-10-26 - \begin{itemize}[label={}, leftmargin=2em] - \item Fix loadimage function correctly finds files when passed a relative path. - \end{itemize} - \item \textbf{0.1.1-rc.2:} 2025-10-20 - \begin{itemize}[label={}, leftmargin=2em] - \item change package to scikit-package level-5 standard. - \end{itemize} - \end{itemize} - - \item \textbf{\href{https://github.com/diffpy/diffpy.distanceprinter}{diffpy/diffpy.distanceprinter}:}\\ - \hspace*{1em}Distance Printer, calculate the inter atomic distances. Part of xPDFsuite\\ - \hspace*{1em}\textit{Authors: Xiaohao Yang, Rundong Hua, Zhiming Xu, Simon J.~L.~Billinge}\\ - \hspace*{1em}Url: https://github.com/diffpy/diffpy.distanceprinter\\ - \hspace*{1em}\textbf{Releases:}\vspace{-0.5em} - \begin{itemize}[label={}] - \item \textbf{0.1.0:} 2025-10-26 - \begin{itemize}[label={}, leftmargin=2em] - \item Python 3.14 and something else - \end{itemize} - \end{itemize} - -\end{enumerate} - -\end{document} diff --git a/tests/outputs/releaselist/software-report-scopatz.tex b/tests/outputs/releaselist/software-report-scopatz.tex index 04f6de7db..8ab5e97e2 100644 --- a/tests/outputs/releaselist/software-report-scopatz.tex +++ b/tests/outputs/releaselist/software-report-scopatz.tex @@ -46,7 +46,7 @@ \end{itemize} \item \textbf{0.1.1-rc.2:} 2025-10-20 \begin{itemize}[label={}, leftmargin=2em] - \item change package to scikit-package level-5 standard. + \item Change package to scikit-package level-5 standard. \end{itemize} \end{itemize}