[med-svn] [Git][med-team/dssp][upstream] New upstream version 4.6.0

Maarten L. Hekkelman (@mhekkel-guest) gitlab at salsa.debian.org
Tue Mar 24 10:01:00 GMT 2026



Maarten L. Hekkelman pushed to branch upstream at Debian Med / dssp


Commits:
a41ec052 by Maarten L. Hekkelman at 2026-03-24T10:51:28+01:00
New upstream version 4.6.0
- - - - -


17 changed files:

- + .clang-format
- + .clang-tidy
- .github/workflows/cmake-multi-platform.yml
- CMakeLists.txt
- changelog
- cmake/revision.hpp.in
- libdssp/VERSION
- libdssp/include/dssp.hpp
- libdssp/src/dssp-io.cpp
- libdssp/src/dssp.cpp
- python-module/CMakeLists.txt
- python-module/dssp-python-plugin.cpp
- src/mkdssp.cpp
- test/CMakeLists.txt
- + test/test_numpy2_compat.py
- test/unit-test-dssp.cpp
- tools/depends.cmd


Changes:

=====================================
.clang-format
=====================================
@@ -0,0 +1,22 @@
+BasedOnStyle: LLVM
+UseTab: AlignWithSpaces
+IndentWidth: 4
+TabWidth: 4
+BreakBeforeBraces: Allman
+ColumnLimit: 0
+NamespaceIndentation: Inner
+FixNamespaceComments: true
+AccessModifierOffset: -2
+AllowShortCaseLabelsOnASingleLine: true
+IndentCaseLabels: true
+BreakConstructorInitializers: BeforeComma
+BraceWrapping:
+  BeforeLambdaBody: false
+AlignAfterOpenBracket: DontAlign
+Cpp11BracedListStyle: false
+IncludeBlocks: Regroup
+LambdaBodyIndentation: Signature
+AllowShortLambdasOnASingleLine: Inline
+EmptyLineBeforeAccessModifier: LogicalBlock
+IndentPPDirectives: AfterHash
+PPIndentWidth: 1


=====================================
.clang-tidy
=====================================
@@ -0,0 +1,18 @@
+Checks: '-*,
+         bugprone-*,
+         -bugprone-easily-swappable-parameters,
+         cert-*,
+         modernize*,
+         -modernize-use-trailing-return-type,
+         -modernize-avoid-c-arrays,
+         -modernize-use-designated-initializers,
+         performance
+         '
+
+# HeaderFilterRegex: '.*'
+ExcludeHeaderFilterRegex: 'Eigen|Eigen/Eigenvalues|eigen3/Eigen/Eigenvalues|sqlite3.h'
+CheckOptions:
+  - key: bugprone-narrowing-conversions.WarnOnIntegerNarrowingConversion
+    value: false
+  - key: bugprone-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion
+    value: false


=====================================
.github/workflows/cmake-multi-platform.yml
=====================================
@@ -6,6 +6,10 @@ on:
   pull_request:
     branches: [ "trunk" ]
 
+env:
+  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+  BUILD_TYPE: Release
+
 jobs:
   build:
     runs-on: ${{ matrix.os }}
@@ -25,7 +29,7 @@ jobs:
             cpp_compiler: clang++
 
     steps:
-    - uses: actions/checkout at v3
+    - uses: actions/checkout at v6
 
     - name: Set reusable strings
       id: strings
@@ -35,17 +39,17 @@ jobs:
     - name: Install Catch2 Ubuntu
       if: matrix.os == 'ubuntu-latest'
       run: >
-        sudo apt-get update && sudo apt-get install catch2 libpython3-all-dev libboost1.83-all-dev
+        sudo apt-get update && sudo apt-get install catch2 libpython3-all-dev
 
     - name: setup python
-      uses: actions/setup-python at v5
+      uses: actions/setup-python at v6
       with:
         python-version: ${{ matrix.python-version }}
 
     - name: Install Catch2 macOS
       if: matrix.os == 'macos-latest'
       run: >
-        brew install catch2 boost-python3
+        brew install catch2
 
     - name: Install dependencies Window
       if: matrix.os == 'windows-latest'
@@ -60,7 +64,8 @@ jobs:
         -DBUILD_TESTING=ON
         -DBUILD_PYTHON_MODULE=ON
         -S ${{ github.workspace }}
-        
+        -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local
+
     - name: Build
       run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config Release
 


=====================================
CMakeLists.txt
=====================================
@@ -93,13 +93,6 @@ if(MSVC)
 	# make msvc standards compliant...
 	add_compile_options(/permissive- /bigobj)
 	add_link_options(/NODEFAULTLIB:library)
-
-	# This is dubious...
-	if(BUILD_SHARED_LIBS)
-		set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
-	else()
-		set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
-	endif()
 endif()
 
 # Create a revision file, containing the current git version info
@@ -124,15 +117,15 @@ CPMFindPackage(
 	GIT_TAG v1.4.2
 	EXCLUDE_FROM_ALL YES)
 
-# CPMFindPackage does not pass on variables set with set_and_check
-# Working around this here
-find_package(cifpp 9 QUIET)
+# No longer using CPM for libcifpp. It is now simply required to install it first.
+find_package(cifpp 10.0.1 QUIET)
 
-if(NOT cifpp_FOUND)
+if(NOT (cifpp_FOUND OR TARGET cifpp))
+	# message(FATAL_ERROR "Could not find libcifpp. Please make sure you install libcifpp first, code can be found at https://github.com/PDB-REDO/libcifpp")
 	CPMAddPackage(
 		NAME cifpp
-		GIT_REPOSITORY https://github.com/pdb-redo/libcifpp.git
-		GIT_TAG v9.0.0
+		GIT_REPOSITORY "https://github.com/PDB-REDO/libcifpp"
+		GIT_TAG v10.0.1
 		EXCLUDE_FROM_ALL YES)
 endif()
 


=====================================
changelog
=====================================
@@ -1,3 +1,10 @@
+Version 4.6.0
+- Using new libcifpp version 10.0
+
+Version 4.5.8
+- Using newer version of Boost for the python plugin,
+  this was needed to be able to use Numpy >= 2.x
+
 Version 4.5.7
 - Fix for unit-test in Debian repository
 


=====================================
cmake/revision.hpp.in
=====================================
@@ -96,6 +96,7 @@ class version_info : public version_info_base
   public:
 	using implementation_type = T;
 
+    // NOLINTNEXTLINE
 	version_info(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date, bool is_main)
 		: version_info_base(name, version, build_number, git_tag, revision_date, is_main)
 	{
@@ -118,4 +119,4 @@ const class version_info_ at IDENT_PREFIX@impl : public version_info_v1_1::version_
 		: version_info(k at VAR_PREFIX@ProjectName, k at VAR_PREFIX@VersionNumber, k at VAR_PREFIX@BuildNumber, k at VAR_PREFIX@RevisionGitTag, k at VAR_PREFIX@RevisionDate, @BOOL_IS_MAIN@)
 	{
 	}
-} s_version_info_ at IDENT_PREFIX@instance;
+} s_version_info_ at IDENT_PREFIX@instance; // NOLINT


=====================================
libdssp/VERSION
=====================================
@@ -1 +1 @@
-4.5.7
\ No newline at end of file
+4.6.0
\ No newline at end of file


=====================================
libdssp/include/dssp.hpp
=====================================
@@ -29,9 +29,11 @@
 /// \file DSSP.hpp
 /// Calculate DSSP-like secondary structure information.
 
-#include <cif++.hpp>
+#include <cif++/cif++.hpp>
 
 #include <filesystem>
+#include <iterator>
+#include <ranges>
 
 class dssp
 {
@@ -105,7 +107,7 @@ class dssp
 	dssp(const dssp &) = delete;
 	dssp &operator=(const dssp &) = delete;
 
-	statistics get_statistics() const;
+	[[nodiscard]] statistics get_statistics() const;
 
 	class iterator;
 	using res_iterator = typename std::vector<residue>::iterator;
@@ -120,37 +122,37 @@ class dssp
 		residue_info &operator=(const residue_info &rhs) = default;
 
 		explicit operator bool() const { return not empty(); }
-		bool empty() const { return m_impl == nullptr; }
+		[[nodiscard]] bool empty() const { return m_impl == nullptr; }
 
-		std::string asym_id() const;
-		int seq_id() const;
-		std::string alt_id() const;
-		std::string compound_id() const;
-		char compound_letter() const; // Single letter for residue compound type, or 'X' in case it is not known
+		[[nodiscard]] std::string asym_id() const;
+		[[nodiscard]] int seq_id() const;
+		[[nodiscard]] std::string alt_id() const;
+		[[nodiscard]] std::string compound_id() const;
+		[[nodiscard]] char compound_letter() const; // Single letter for residue compound type, or 'X' in case it is not known
 
-		std::string auth_asym_id() const;
-		int auth_seq_id() const;
+		[[nodiscard]] std::string auth_asym_id() const;
+		[[nodiscard]] int auth_seq_id() const;
 
-		std::string pdb_strand_id() const;
-		int pdb_seq_num() const;
-		std::string pdb_ins_code() const;
+		[[nodiscard]] std::string pdb_strand_id() const;
+		[[nodiscard]] int pdb_seq_num() const;
+		[[nodiscard]] std::string pdb_ins_code() const;
 
-		std::optional<float> alpha() const;
-		std::optional<float> kappa() const;
-		std::optional<float> phi() const;
-		std::optional<float> psi() const;
-		std::optional<float> tco() const;
-		std::optional<float> omega() const;
+		[[nodiscard]] std::optional<float> alpha() const;
+		[[nodiscard]] std::optional<float> kappa() const;
+		[[nodiscard]] std::optional<float> phi() const;
+		[[nodiscard]] std::optional<float> psi() const;
+		[[nodiscard]] std::optional<float> tco() const;
+		[[nodiscard]] std::optional<float> omega() const;
 
-		bool is_pre_pro() const;
-		bool is_cis() const { return std::abs(omega().value_or(360)) < 30.0f; }
+		[[nodiscard]] bool is_pre_pro() const;
+		[[nodiscard]] bool is_cis() const { return std::abs(omega().value_or(360)) < 30.0f; }
 
-		float chiral_volume() const;
+		[[nodiscard]] float chiral_volume() const;
 
-		std::size_t nr_of_chis() const;
-		float chi(std::size_t index) const;
+		[[nodiscard]] std::size_t nr_of_chis() const;
+		[[nodiscard]] float chi(std::size_t index) const;
 
-		std::vector<float> chis() const
+		[[nodiscard]] std::vector<float> chis() const
 		{
 			std::vector<float> result;
 			for (size_t i = 0; i < nr_of_chis(); ++i)
@@ -158,34 +160,34 @@ class dssp
 			return result;
 		}
 
-		std::tuple<float, float, float> ca_location() const;
+		[[nodiscard]] std::tuple<float, float, float> ca_location() const;
 
-		chain_break_type chain_break() const;
+		[[nodiscard]] chain_break_type chain_break() const;
 
 		/// \brief the internal number in DSSP
-		int nr() const;
+		[[nodiscard]] int nr() const;
 
-		structure_type type() const;
+		[[nodiscard]] structure_type type() const;
 
-		int ssBridgeNr() const;
+		[[nodiscard]] int ssBridgeNr() const;
 
-		helix_position_type helix(helix_type helixType) const;
+		[[nodiscard]] helix_position_type helix(helix_type helixType) const;
 
-		bool is_alpha_helix_end_before_start() const;
+		[[nodiscard]] bool is_alpha_helix_end_before_start() const;
 
-		bool bend() const;
+		[[nodiscard]] bool bend() const;
 
-		double accessibility() const;
+		[[nodiscard]] double accessibility() const;
 
 		/// \brief returns resinfo, ladder and parallel
-		std::tuple<residue_info, int, bool> bridge_partner(int i) const;
+		[[nodiscard]] std::tuple<residue_info, int, bool> bridge_partner(int i) const;
 
-		int sheet() const;
-		int strand() const;
+		[[nodiscard]] int sheet() const;
+		[[nodiscard]] int strand() const;
 
 		/// \brief return resinfo and the energy of the bond
-		std::tuple<residue_info, double> acceptor(int i) const;
-		std::tuple<residue_info, double> donor(int i) const;
+		[[nodiscard]] std::tuple<residue_info, double> acceptor(int i) const;
+		[[nodiscard]] std::tuple<residue_info, double> donor(int i) const;
 
 		/// \brief Simple compare equals
 		bool operator==(const residue_info &rhs) const
@@ -196,7 +198,7 @@ class dssp
 		/// \brief Returns \result true if there is a bond between two residues
 		friend bool test_bond(residue_info const &a, residue_info const &b);
 
-		residue_info next() const;
+		[[nodiscard]] residue_info next() const;
 
 	  private:
 		residue_info(residue *res)
@@ -211,17 +213,18 @@ class dssp
 	{
 	  public:
 		using iterator_category = std::bidirectional_iterator_tag;
-		using value_type = residue_info;
+		using value_type = const residue_info;
 		using difference_type = std::ptrdiff_t;
 		using pointer = value_type *;
 		using reference = value_type &;
 
+		iterator() = default;
 		iterator(const iterator &i) = default;
 		iterator(residue *res);
 		iterator &operator=(const iterator &i) = default;
 
-		reference operator*() { return m_current; }
-		pointer operator->() { return &m_current; }
+		reference operator*() const { return m_current; }
+		pointer operator->() const { return &m_current; }
 
 		iterator &operator++();
 		iterator operator++(int)
@@ -246,17 +249,22 @@ class dssp
 		residue_info m_current;
 	};
 
+	static_assert(std::input_iterator<iterator>);
+
 	using value_type = residue_info;
 
 	// To access residue info by key, i.e. LabelAsymID and LabelSeqID
 	using key_type = std::tuple<std::string, int>;
 
-	iterator begin() const;
-	iterator end() const;
+	[[nodiscard]] iterator begin() const;
+	[[nodiscard]] iterator end() const;
+
+	[[nodiscard]] iterator cbegin() const;
+	[[nodiscard]] iterator cend() const;
 
 	residue_info operator[](const key_type &key) const;
 
-	bool empty() const { return begin() == end(); }
+	[[nodiscard]] bool empty() const { return begin() == end(); }
 
 	// --------------------------------------------------------------------
 	// Writing out the data, either in legacy format...
@@ -276,8 +284,10 @@ class dssp
 		AUTHOR
 	};
 
-	std::string get_pdb_header_line(pdb_record_type pdb_record) const;
+	[[nodiscard]] std::string get_pdb_header_line(pdb_record_type pdb_record) const;
 
   private:
 	struct DSSP_impl *m_impl;
 };
+
+static_assert(std::ranges::input_range<dssp>);
\ No newline at end of file


=====================================
libdssp/src/dssp-io.cpp
=====================================
@@ -25,15 +25,19 @@
  */
 
 #include "dssp-io.hpp"
+
+#include "cif++/category.hpp"
+#include "cif++/item.hpp"
+#include "cif++/validate.hpp"
 #include "revision.hpp"
 
-#include <cif++.hpp>
+#include <algorithm>
+#include <cif++/cif++.hpp>
 #include <cif++/dictionary_parser.hpp>
-
-#include <exception>
-#include <filesystem>
-#include <fstream>
+#include <cif++/row.hpp>
+#include <format>
 #include <iostream>
+#include <type_traits>
 
 // --------------------------------------------------------------------
 
@@ -121,20 +125,20 @@ std::string ResidueToDSSPLine(const dssp::residue_info &info)
 		if (acceptor)
 		{
 			auto d = acceptor.nr() - info.nr();
-			NHO[i] = cif::format("{:d},{:3.1f}", d, acceptorE);
+			NHO[i] = std::format("{:d},{:3.1f}", d, acceptorE);
 		}
 
 		if (donor)
 		{
 			auto d = donor.nr() - info.nr();
-			ONH[i] = cif::format("{:d},{:3.1f}", d, donorE);
+			ONH[i] = std::format("{:d},{:3.1f}", d, donorE);
 		}
 	}
 
 	// auto ca = residue.atomByID("CA");
 	auto const &[cax, cay, caz] = residue.ca_location();
 
-	return cif::format("{:5d}{:5d}{:1.1s}{:1.1s} {:1c}  {:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:4d}{:4d}{:1c}{:4.0f} {:>11s}{:>11s}{:>11s}{:>11s}  {:6.3f}{:6.1f}{:6.1f}{:6.1f}{:6.1f} {:6.1f} {:6.1f} {:6.1f}",
+	return std::format("{:5d}{:5d}{:1.1s}{:1.1s} {:1c}  {:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:4d}{:4d}{:1c}{:4.0f} {:>11s}{:>11s}{:>11s}{:>11s}  {:6.3f}{:6.1f}{:6.1f}{:6.1f}{:6.1f} {:6.1f} {:6.1f} {:6.1f}",
 		info.nr(), residue.pdb_seq_num(), residue.pdb_ins_code(), residue.pdb_strand_id(), code,
 		ss, helix[3], helix[0], helix[1], helix[2], bend, chirality, bridgelabel[0], bridgelabel[1],
 		bp[0], bp[1], sheet, floor(info.accessibility() + 0.5),
@@ -167,40 +171,40 @@ void writeDSSP(const dssp &dssp, std::ostream &os)
 	   << dssp.get_pdb_header_line(dssp::pdb_record_type::SOURCE) << '.' << std::endl
 	   << dssp.get_pdb_header_line(dssp::pdb_record_type::AUTHOR) << '.' << std::endl;
 
-	os << cif::format("{:5d}{:3d}{:3d}{:3d}{:3d} TOTAL NUMBER OF RESIDUES, NUMBER OF CHAINS, NUMBER OF SS-BRIDGES(TOTAL,INTRACHAIN,INTERCHAIN)                .",
+	os << std::format("{:5d}{:3d}{:3d}{:3d}{:3d} TOTAL NUMBER OF RESIDUES, NUMBER OF CHAINS, NUMBER OF SS-BRIDGES(TOTAL,INTRACHAIN,INTERCHAIN)                .",
 			  stats.count.residues, stats.count.chains, stats.count.SS_bridges, stats.count.intra_chain_SS_bridges, (stats.count.SS_bridges - stats.count.intra_chain_SS_bridges))
 	   << std::endl;
 
-	os << cif::format("{:8.1f}   ACCESSIBLE SURFACE OF PROTEIN (ANGSTROM**2)                                                                         .", stats.accessible_surface) << std::endl;
+	os << std::format("{:8.1f}   ACCESSIBLE SURFACE OF PROTEIN (ANGSTROM**2)                                                                         .", stats.accessible_surface) << std::endl;
 
 	// hydrogenbond summary
 
-	os << cif::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(J)  , SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds, (stats.count.H_bonds * 100.0 / stats.count.residues)) << std::endl;
+	os << std::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(J)  , SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds, (stats.count.H_bonds * 100.0 / stats.count.residues)) << std::endl;
 
-	os << cif::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS IN     PARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds_in_parallel_bridges, (stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues)) << std::endl;
+	os << std::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS IN     PARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds_in_parallel_bridges, (stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues)) << std::endl;
 
-	os << cif::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS IN ANTIPARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds_in_antiparallel_bridges, (stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues)) << std::endl;
+	os << std::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS IN ANTIPARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_bonds_in_antiparallel_bridges, (stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues)) << std::endl;
 
 	for (int k = 0; k < 11; ++k)
-		os << cif::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(I{:1c}{:1d}), SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_Bonds_per_distance[k], (stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues), (k - 5 < 0 ? '-' : '+'), abs(k - 5)) << std::endl;
+		os << std::format("{:5d}{:5.1f}   TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(I{:1c}{:1d}), SAME NUMBER PER 100 RESIDUES                              .", stats.count.H_Bonds_per_distance[k], (stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues), (k - 5 < 0 ? '-' : '+'), abs(k - 5)) << std::endl;
 
 	// histograms...
 	os << "  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30     *** HISTOGRAMS OF ***           ." << std::endl;
 
 	for (auto hi : stats.histogram.residues_per_alpha_helix)
-		os << cif::format("{:3d}", hi);
+		os << std::format("{:3d}", hi);
 	os << "    RESIDUES PER ALPHA HELIX         ." << std::endl;
 
 	for (auto hi : stats.histogram.parallel_bridges_per_ladder)
-		os << cif::format("{:3d}", hi);
+		os << std::format("{:3d}", hi);
 	os << "    PARALLEL BRIDGES PER LADDER      ." << std::endl;
 
 	for (auto hi : stats.histogram.antiparallel_bridges_per_ladder)
-		os << cif::format("{:3d}", hi);
+		os << std::format("{:3d}", hi);
 	os << "    ANTIPARALLEL BRIDGES PER LADDER  ." << std::endl;
 
 	for (auto hi : stats.histogram.ladders_per_sheet)
-		os << cif::format("{:3d}", hi);
+		os << std::format("{:3d}", hi);
 	os << "    LADDERS PER SHEET                ." << std::endl;
 
 	// per residue information
@@ -214,7 +218,7 @@ void writeDSSP(const dssp &dssp, std::ostream &os)
 		// can be the transition to a different chain, or missing residues in the current chain
 
 		if (ri.nr() != last + 1)
-			os << cif::format("{:5d}        !{:1c}             0   0    0      0, 0.0     0, 0.0     0, 0.0     0, 0.0   0.000 360.0 360.0 360.0 360.0    0.0    0.0    0.0",
+			os << std::format("{:5d}        !{:1c}             0   0    0      0, 0.0     0, 0.0     0, 0.0     0, 0.0   0.000 360.0 360.0 360.0 360.0    0.0    0.0    0.0",
 					  (last + 1), (ri.chain_break() == dssp::chain_break_type::NewChain ? '*' : ' '))
 			   << std::endl;
 
@@ -274,7 +278,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
 					data.emplace_back("acceptor_1_auth_seq_id", acceptor.auth_seq_id());
 					data.emplace_back("acceptor_1_auth_asym_id", acceptor.auth_asym_id());
 					data.emplace_back("acceptor_1_pdbx_PDB_ins_code", acceptor.pdb_ins_code());
-					data.emplace_back("acceptor_1_energy", acceptorEnergy, 1);
+					data.emplace_back("acceptor_1_energy", { acceptorEnergy, 1 });
 				}
 				else
 				{
@@ -285,7 +289,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
 					data.emplace_back("acceptor_2_auth_seq_id", acceptor.auth_seq_id());
 					data.emplace_back("acceptor_2_auth_asym_id", acceptor.auth_asym_id());
 					data.emplace_back("acceptor_2_pdbx_PDB_ins_code", acceptor.pdb_ins_code());
-					data.emplace_back("acceptor_2_energy", acceptorEnergy, 1);
+					data.emplace_back("acceptor_2_energy", { acceptorEnergy, 1 });
 				}
 			}
 
@@ -300,7 +304,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
 					data.emplace_back("donor_1_auth_seq_id", donor.auth_seq_id());
 					data.emplace_back("donor_1_auth_asym_id", donor.auth_asym_id());
 					data.emplace_back("donor_1_pdbx_PDB_ins_code", donor.pdb_ins_code());
-					data.emplace_back("donor_1_energy", donorEnergy, 1);
+					data.emplace_back("donor_1_energy", { donorEnergy, 1 });
 				}
 				else
 				{
@@ -311,7 +315,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
 					data.emplace_back("donor_2_auth_seq_id", donor.auth_seq_id());
 					data.emplace_back("donor_2_auth_asym_id", donor.auth_asym_id());
 					data.emplace_back("donor_2_pdbx_PDB_ins_code", donor.pdb_ins_code());
-					data.emplace_back("donor_2_energy", donorEnergy, 1);
+					data.emplace_back("donor_2_energy", { donorEnergy, 1 });
 				}
 			}
 		}
@@ -329,9 +333,8 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
 	// clean up old info first
 
 	for (auto sheet_cat : { "struct_sheet", "struct_sheet_order", "struct_sheet_range", "struct_sheet_hbond", "pdbx_struct_sheet_hbond" })
-		db.erase(remove_if(db.begin(), db.end(), [sheet_cat](const cif::category &cat)
-					 { return cat.name() == sheet_cat; }),
-			db.end());
+		std::erase_if(db, [sheet_cat](const cif::category &cat)
+			{ return cat.name() == sheet_cat; });
 
 	// create a list of strands, based on the SS info in DSSP. Store sheet number along with the strand.
 
@@ -370,7 +373,7 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
 
 			std::string strandID = cif::cif_id_for_number(strand.front().strand() - 1);
 
-			std::sort(strand.begin(), strand.end(), [](dssp::residue_info const &a, dssp::residue_info const &b)
+			std::ranges::sort(strand, [](dssp::residue_info const &a, dssp::residue_info const &b)
 				{ return a.nr() < b.nr(); });
 
 			auto &beg = strand.front();
@@ -388,10 +391,10 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
 				{ "pdbx_end_PDB_ins_code", end.pdb_ins_code() },
 				{ "beg_auth_comp_id", beg.compound_id() },
 				{ "beg_auth_asym_id", beg.auth_asym_id() },
-				{ "beg_auth_seq_id", beg.auth_seq_id() },
+				{ "beg_auth_seq_id", std::to_string(beg.auth_seq_id()) },
 				{ "end_auth_comp_id", end.compound_id() },
 				{ "end_auth_asym_id", end.auth_asym_id() },
-				{ "end_auth_seq_id", end.auth_seq_id() } });
+				{ "end_auth_seq_id", std::to_string(end.auth_seq_id()) } });
 		}
 	}
 }
@@ -439,7 +442,7 @@ void writeLadders(cif::datablock &db, const dssp &dssp)
 
 				assert(l.parallel == parallel);
 
-				if (find_if(l.pairs.begin(), l.pairs.end(), [na = p.nr(), nb = res.nr()](const auto &p)
+				if (std::ranges::find_if(l.pairs, [na = p.nr(), nb = res.nr()](const auto &p)
 						{ return p.first.nr() == na and p.second.nr() == nb; }) != l.pairs.end())
 				{
 					is_new = false;
@@ -458,7 +461,7 @@ void writeLadders(cif::datablock &db, const dssp &dssp)
 		}
 	}
 
-	std::sort(ladders.begin(), ladders.end());
+	std::ranges::sort(ladders, std::less<>());
 
 	auto &dssp_struct_ladder = db["dssp_struct_ladder"];
 
@@ -517,37 +520,36 @@ void writeStatistics(cif::datablock &db, const dssp &dssp)
 	if (stats.accessible_surface > 0)
 		surface_accessibility = stats.accessible_surface;
 
-	auto stats_i = dssp_statistics.emplace({ //
-		{ "entry_id", db.name() },
+	auto stats_i = dssp_statistics.emplace({ { "entry_id", db.name() },
 		{ "nr_of_residues", stats.count.residues },
 		{ "nr_of_chains", stats.count.chains },
 		{ "nr_of_ss_bridges_total", stats.count.SS_bridges },
 		{ "nr_of_ss_bridges_intra_chain", stats.count.intra_chain_SS_bridges },
 		{ "nr_of_ss_bridges_inter_chain", stats.count.SS_bridges - stats.count.intra_chain_SS_bridges },
-		{ "accessible_surface_of_protein", surface_accessibility, 2 } });
+		{ "accessible_surface_of_protein", { surface_accessibility, 2 } } });
 
 	auto &dssp_struct_hbonds = db["dssp_statistics_hbond"];
 
 	dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
 		{ "type", "O(I)-->H-N(J)" },
 		{ "count", stats.count.H_bonds },
-		{ "count_per_100", stats.count.H_bonds * 100.0 / stats.count.residues, 1 } });
+		{ "count_per_100", { stats.count.H_bonds * 100.0 / stats.count.residues, 1 } } });
 
 	dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
 		{ "type", "PARALLEL BRIDGES" },
 		{ "count", stats.count.H_bonds_in_parallel_bridges },
-		{ "count_per_100", stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues, 1 } });
+		{ "count_per_100", { stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues, 1 } } });
 
 	dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
 		{ "type", "ANTIPARALLEL BRIDGES" },
 		{ "count", stats.count.H_bonds_in_antiparallel_bridges },
-		{ "count_per_100", stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues, 1 } });
+		{ "count_per_100", { stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues, 1 } } });
 
 	for (int k = 0; k < 11; ++k)
 		dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
-			{ "type", "O(I)-->H-N(I"s + char(k - 5 < 0 ? '-' : '+') + std::to_string(abs(k - 5)) + ")" },
+			{ "type", "O(I)-->H-N(I"s + (k - 5 < 0 ? '-' : '+') + std::to_string(abs(k - 5)) + ")" },
 			{ "count", stats.count.H_Bonds_per_distance[k] },
-			{ "count_per_100", stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues, 1 } });
+			{ "count_per_100", { stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues, 1 } } });
 
 	auto &dssp_statistics_histogram = db["dssp_statistics_histogram"];
 
@@ -700,43 +702,54 @@ void writeSummary(cif::datablock &db, const dssp &dssp)
 			{ "ladder_1", ladders[0] },
 			{ "ladder_2", ladders[1] },
 
-			{ "x_ca", cax, 1 },
-			{ "y_ca", cay, 1 },
-			{ "z_ca", caz, 1 },
+			{ "x_ca", { cax, 1 } },
+			{ "y_ca", { cay, 1 } },
+			{ "z_ca", { caz, 1 } },
 		};
 
 		if (writeAccessibility)
-			data.emplace_back("accessibility", res.accessibility(), 1);
+			data.emplace_back("accessibility", { res.accessibility(), 1 });
 
 		if (res.tco().has_value())
-			data.emplace_back("TCO", *res.tco(), 3);
+			data.emplace_back("TCO", { *res.tco(), 3 });
 		else
-			data.emplace_back("TCO", ".");
+			data.set_value("TCO", cif::item_value_type::INAPPLICABLE);
 
 		if (res.kappa().has_value())
-			data.emplace_back("kappa", *res.kappa(), 1);
+			data.emplace_back("kappa", { *res.kappa(), 1 });
 		else
-			data.emplace_back("kappa", ".");
+			data.set_value("kappa", cif::item_value_type::INAPPLICABLE);
 
 		if (res.alpha().has_value())
-			data.emplace_back("alpha", *res.alpha(), 1);
+			data.emplace_back("alpha", { *res.alpha(), 1 });
 		else
-			data.emplace_back("alpha", ".");
+			data.set_value("alpha", cif::item_value_type::INAPPLICABLE);
 
 		if (res.phi().has_value())
-			data.emplace_back("phi", *res.phi(), 1);
+			data.emplace_back("phi", { *res.phi(), 1 });
 		else
-			data.emplace_back("phi", ".");
+			data.set_value("phi", cif::item_value_type::INAPPLICABLE);
 
 		if (res.psi().has_value())
-			data.emplace_back("psi", *res.psi(), 1);
+			data.emplace_back("psi", { *res.psi(), 1 });
 		else
-			data.emplace_back("psi", ".");
+			data.set_value("psi", cif::item_value_type::INAPPLICABLE);
 
 		dssp_struct_summary.emplace(std::move(data));
 	}
 }
 
+// Work around stupid change in signature of cif::validator_factory::get...
+template <typename ValidatorFactory>
+void fill_audit_conform(cif::category &audit_conform)
+{
+	auto &cf = ValidatorFactory::instance();
+	if constexpr (std::is_pointer_v<decltype(std::declval<cif::validator_factory>().get(""))>)
+		cf.get("mmcif_pdbx.dic")->fill_audit_conform(audit_conform);
+	else
+		cf.get("mmcif_pdbx.dic").fill_audit_conform(audit_conform);
+}
+
 void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool writeNewFormat)
 {
 	using namespace std::literals;
@@ -744,10 +757,7 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
 	auto &audit_conform = db["audit_conform"];
 
 	if (audit_conform.empty())
-	{
-		auto &cf = cif::validator_factory::instance();
-		cf.get("mmcif_pdbx.dic").fill_audit_conform(audit_conform);
-	}
+		fill_audit_conform<cif::validator_factory>(audit_conform);
 
 	audit_conform.erase(cif::key("dict_name") == "dssp-extension.dic");
 	audit_conform.emplace({ //
@@ -771,10 +781,10 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
 				 "dssp_statistics",
 				 "dssp_statistics_hbond",
 				 "dssp_statistics_histogram",
-				 "dssp_struct_summary"
-			 })
+				 "dssp_struct_summary" })
 		{
-			db.erase(std::remove_if(db.begin(), db.end(), [cat] (cif::category &c) { return c.name() == cat; }), db.end());
+			std::erase_if(db, [cat](cif::category &c)
+				{ return c.name() == cat; });
 		}
 
 		if (writeNewFormat)
@@ -868,10 +878,10 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
 
 					{ "beg_auth_comp_id", rb.compound_id() },
 					{ "beg_auth_asym_id", rb.auth_asym_id() },
-					{ "beg_auth_seq_id", rb.auth_seq_id() },
+					{ "beg_auth_seq_id", std::to_string(rb.auth_seq_id()) },
 					{ "end_auth_comp_id", re.compound_id() },
 					{ "end_auth_asym_id", re.auth_asym_id() },
-					{ "end_auth_seq_id", re.auth_seq_id() } });
+					{ "end_auth_seq_id", std::to_string(re.auth_seq_id()) } });
 
 				st = t;
 			}


=====================================
libdssp/src/dssp.cpp
=====================================
@@ -30,8 +30,11 @@
 
 #include "dssp-io.hpp"
 
+#include <algorithm>
 #include <deque>
 #include <iomanip>
+#include <memory>
+#include <numbers>
 #include <numeric>
 #include <thread>
 
@@ -49,7 +52,7 @@ using chain_break_type = dssp::chain_break_type;
 // --------------------------------------------------------------------
 
 const double
-	kPI = 3.141592653589793238462643383279502884;
+	kPI = std::numbers::pi;
 
 struct point
 {
@@ -263,7 +266,6 @@ struct dssp::residue
 		: mPDBStrandID(pdb_strand_id)
 		, mPDBSeqNum(pdb_seq_num)
 		, mPDBInsCode(pdb_ins_code)
-		, mChainBreak(chain_break_type::None)
 		, m_model_nr(model_nr)
 	{
 		// update the box containing all atoms
@@ -276,7 +278,7 @@ struct dssp::residue
 			p = {};
 	}
 
-	void addAtom(cif::row_handle atom)
+	void addAtom(cif::const_row_handle atom)
 	{
 		std::string asymID, compID, atomID, type, authAsymID;
 		std::optional<std::string> altID;
@@ -393,7 +395,7 @@ struct dssp::residue
 			auto pc = mPrev->mC;
 			auto po = mPrev->mO;
 
-			float CODistance = static_cast<float>(distance(pc, po));
+			auto CODistance = static_cast<float>(distance(pc, po));
 
 			mH.mX += (pc.mX - po.mX) / CODistance;
 			mH.mY += (pc.mY - po.mY) / CODistance;
@@ -402,7 +404,7 @@ struct dssp::residue
 	}
 
 	void SetSecondaryStructure(structure_type inSS) { mSecondaryStructure = inSS; }
-	structure_type GetSecondaryStructure() const { return mSecondaryStructure; }
+	[[nodiscard]] structure_type GetSecondaryStructure() const { return mSecondaryStructure; }
 
 	void SetBetaPartner(uint32_t n, residue &inResidue, uint32_t inLadder, bool inParallel)
 	{
@@ -413,38 +415,38 @@ struct dssp::residue
 		mBetaPartner[n].parallel = inParallel;
 	}
 
-	bridge_partner GetBetaPartner(uint32_t n) const
+	[[nodiscard]] bridge_partner GetBetaPartner(uint32_t n) const
 	{
 		assert(n == 0 or n == 1);
 		return mBetaPartner[n];
 	}
 
 	void SetSheet(uint32_t inSheet) { mSheet = inSheet; }
-	uint32_t GetSheet() const { return mSheet; }
+	[[nodiscard]] uint32_t GetSheet() const { return mSheet; }
 
 	void SetStrand(uint32_t inStrand) { mStrand = inStrand; }
-	uint32_t GetStrand() const { return mStrand; }
+	[[nodiscard]] uint32_t GetStrand() const { return mStrand; }
 
-	bool IsBend() const { return mBend; }
+	[[nodiscard]] bool IsBend() const { return mBend; }
 	void SetBend(bool inBend) { mBend = inBend; }
 
-	helix_position_type GetHelixFlag(helix_type helixType) const
+	[[nodiscard]] helix_position_type GetHelixFlag(helix_type helixType) const
 	{
-		size_t stride = static_cast<size_t>(helixType);
+		auto stride = static_cast<size_t>(helixType);
 		assert(stride < 4);
 		return mHelixFlags[stride];
 	}
 
-	bool IsHelixStart(helix_type helixType) const
+	[[nodiscard]] bool IsHelixStart(helix_type helixType) const
 	{
-		size_t stride = static_cast<size_t>(helixType);
+		auto stride = static_cast<size_t>(helixType);
 		assert(stride < 4);
 		return mHelixFlags[stride] == helix_position_type::Start or mHelixFlags[stride] == helix_position_type::StartAndEnd;
 	}
 
 	void SetHelixFlag(helix_type helixType, helix_position_type inHelixFlag)
 	{
-		size_t stride = static_cast<size_t>(helixType);
+		auto stride = static_cast<size_t>(helixType);
 		assert(stride < 4);
 		mHelixFlags[stride] = inHelixFlag;
 	}
@@ -456,7 +458,7 @@ struct dssp::residue
 		mSSBridgeNr = inBridgeNr;
 	}
 
-	uint8_t GetSSBridgeNr() const
+	[[nodiscard]] uint8_t GetSSBridgeNr() const
 	{
 		if (mType != kCysteine)
 			throw std::runtime_error("Only cysteine residues can form sulphur bridges");
@@ -466,7 +468,7 @@ struct dssp::residue
 	float CalculateSurface(const std::vector<residue> &inResidues);
 	float CalculateSurface(const point &inAtom, float inRadius, const std::vector<residue *> &inNeighbours);
 
-	bool AtomIntersectsBox(const point &atom, float inRadius) const
+	[[nodiscard]] bool AtomIntersectsBox(const point &atom, float inRadius) const
 	{
 		return atom.mX + inRadius >= mBox[0].mX and
 		       atom.mX - inRadius <= mBox[1].mX and
@@ -572,9 +574,9 @@ class accumulator
 		double radius;
 		double distance;
 
-		bool operator<(const candidate &rhs) const
+		auto operator<=>(const candidate &rhs) const
 		{
-			return distance < rhs.distance;
+			return distance <=> rhs.distance;
 		}
 	};
 
@@ -593,13 +595,13 @@ class accumulator
 			candidate c = { b - a, r * r, distance };
 
 			m_x.push_back(c);
-			push_heap(m_x.begin(), m_x.end());
+			std::ranges::push_heap(m_x, std::less<>());
 		}
 	}
 
 	void sort()
 	{
-		sort_heap(m_x.begin(), m_x.end());
+		std::ranges::sort_heap(m_x, std::less<>());
 	}
 
 	std::vector<candidate> m_x;
@@ -611,9 +613,9 @@ class MSurfaceDots
   public:
 	static MSurfaceDots &Instance();
 
-	size_t size() const { return mPoints.size(); }
+	[[nodiscard]] size_t size() const { return mPoints.size(); }
 	const point &operator[](size_t inIx) const { return mPoints[inIx]; }
-	double weight() const { return mWeight; }
+	[[nodiscard]] double weight() const { return mWeight; }
 
   private:
 	MSurfaceDots(int32_t inN);
@@ -634,14 +636,14 @@ MSurfaceDots::MSurfaceDots(int32_t N)
 {
 	auto P = 2 * N + 1;
 
-	const float kGoldenRatio = (1 + std::sqrt(5.0f)) / 2;
+	const float kGoldenRatio = std::numbers::phi_v<float>;
 
 	mWeight = (4 * kPI) / P;
 
 	for (auto i = -N; i <= N; ++i)
 	{
 		float lat = std::asin((2.0f * i) / P);
-		float lon = static_cast<float>(std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio);
+		auto lon = static_cast<float>(std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio);
 
 		mPoints.emplace_back(point{ std::sin(lon) * std::cos(lat), std::cos(lon) * std::cos(lat), std::sin(lat) });
 	}
@@ -778,8 +780,8 @@ double CalculateHBondEnergy(residue &inDonor, residue &inAcceptor)
 void CalculateHBondEnergies(std::vector<residue> &inResidues, std::vector<std::tuple<uint32_t, uint32_t>> &q)
 {
 	std::unique_ptr<cif::progress_bar> progress;
-	if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
-		progress.reset(new cif::progress_bar(q.size(), "calculate hbond energies"));
+	if (cif::VERBOSE >= 0)
+		progress = std::make_unique<cif::progress_bar>(q.size(), "calculate hbond energies");
 
 	for (const auto &[i, j] : q)
 	{
@@ -873,8 +875,8 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
 	// 	std::cerr << "calculating beta sheets" << std::endl;
 
 	std::unique_ptr<cif::progress_bar> progress;
-	if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
-		progress.reset(new cif::progress_bar(q.size(), "calculate beta sheets"));
+	if (cif::VERBOSE >= 0)
+		progress = std::make_unique<cif::progress_bar>(q.size(), "calculate beta sheets");
 
 	// Calculate Bridges
 	std::vector<bridge> bridges;
@@ -929,7 +931,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
 	}
 
 	// extend ladders
-	std::sort(bridges.begin(), bridges.end());
+	std::ranges::sort(bridges, std::less<>());
 
 	for (uint32_t i = 0; i < bridges.size(); ++i)
 	{
@@ -1069,7 +1071,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
 		{
 			stats.count.H_bonds_in_parallel_bridges += bridge.i.back() - bridge.i.front() + 2;
 
-			std::deque<uint32_t>::iterator j = bridge.j.begin();
+			auto j = bridge.j.begin();
 			for (uint32_t i : bridge.i)
 				inResidues[i].SetBetaPartner(betai, inResidues[*j++], bridge.ladder, true);
 
@@ -1081,7 +1083,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
 		{
 			stats.count.H_bonds_in_antiparallel_bridges += bridge.i.back() - bridge.i.front() + 2;
 
-			std::deque<uint32_t>::reverse_iterator j = bridge.j.rbegin();
+			auto j = bridge.j.rbegin();
 			for (uint32_t i : bridge.i)
 				inResidues[i].SetBetaPartner(betai, inResidues[*j++], bridge.ladder, false);
 
@@ -1390,7 +1392,7 @@ struct DSSP_impl
 
 	auto findRes(const std::string &asymID, int seqID)
 	{
-		return std::find_if(mResidues.begin(), mResidues.end(), [&](auto &r)
+		return std::ranges::find_if(mResidues, [&](auto &r)
 			{ return r.mAsymID == asymID and r.mSeqID == seqID; });
 	}
 
@@ -1454,9 +1456,8 @@ DSSP_impl::DSSP_impl(const cif::datablock &db, int model_nr, int min_poly_prolin
 	for (auto &residue : mResidues)
 		residue.finish();
 
-	mResidues.erase(std::remove_if(mResidues.begin(), mResidues.end(), [](const dssp::residue &r)
-						{ return not r.mComplete; }),
-		mResidues.end());
+	std::erase_if(mResidues, [](const dssp::residue &r)
+		{ return not r.mComplete; });
 	mStats.count.chains = 1;
 
 	chain_break_type brk = chain_break_type::NewChain;
@@ -1592,8 +1593,8 @@ void DSSP_impl::calculateSecondaryStructure()
 		cAlphas.emplace_back(r.mCAlpha);
 
 	std::unique_ptr<cif::progress_bar> progress;
-	if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
-		progress.reset(new cif::progress_bar((mResidues.size() * (mResidues.size() - 1)) / 2, "calculate distances"));
+	if (cif::VERBOSE >= 0)
+		progress = std::make_unique<cif::progress_bar>((mResidues.size() * (mResidues.size() - 1)) / 2, "calculate distances");
 
 	// Calculate the HBond energies
 	std::vector<std::tuple<uint32_t, uint32_t>> near;
@@ -1646,7 +1647,7 @@ void DSSP_impl::calculateSecondaryStructure()
 			auto id = r.mAsymID + ':' + std::to_string(r.mSeqID) + '/' + r.mCompoundID;
 
 			std::cerr << id << std::string(12 - id.length(), ' ')
-					  << char(r.mSecondaryStructure) << ' '
+					  << static_cast<char>(r.mSecondaryStructure) << ' '
 					  << helix
 					  << std::endl;
 		}
@@ -1751,14 +1752,14 @@ std::string DSSP_impl::GetPDBHEADERLine()
 
 	for (auto r : cat1)
 	{
-		keywords = FixStringLength(r["pdbx_keywords"].as<std::string>(), 40);
+		keywords = FixStringLength(r["pdbx_keywords"].get<std::string>(), 40);
 		break;
 	}
 
 	std::string date;
 	for (auto r : mDB["pdbx_database_status"])
 	{
-		date = r["recvd_initial_deposition_date"].as<std::string>();
+		date = r["recvd_initial_deposition_date"].get<std::string>();
 		if (date.empty())
 			continue;
 		date = cif2pdbDate(date);
@@ -1769,7 +1770,7 @@ std::string DSSP_impl::GetPDBHEADERLine()
 	{
 		for (auto r : mDB["database_PDB_rev"])
 		{
-			date = r["date_original"].as<std::string>();
+			date = r["date_original"].get<std::string>();
 			if (date.empty())
 				continue;
 			date = cif2pdbDate(date);
@@ -1784,8 +1785,8 @@ std::string DSSP_impl::GetPDBHEADERLine()
 	char header[] =
 		"HEADER    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDDDDDDDDD   IIII";
 
-	std::copy(keywords.begin(), keywords.end(), header + 10);
-	std::copy(date.begin(), date.end(), header + 50);
+	std::ranges::copy(keywords, header + 10);
+	std::ranges::copy(date, header + 50);
 
 	std::string id = mDB.name();
 	if (id.length() < 4)
@@ -1793,7 +1794,7 @@ std::string DSSP_impl::GetPDBHEADERLine()
 	else if (id.length() > 4)
 		id.erase(id.begin() + 4, id.end());
 
-	std::copy(id.begin(), id.end(), header + 62);
+	std::ranges::copy(id, header + 62);
 
 	return FixStringLength(header);
 }
@@ -1809,45 +1810,45 @@ std::string DSSP_impl::GetPDBCOMPNDLine()
 
 	for (auto r : mDB["entity"].find("type"_key == "polymer"))
 	{
-		std::string entityID = r["id"].as<std::string>();
+		auto entityID = r["id"].get<std::string>();
 
 		++molID;
 		cmpnd.push_back("MOL_ID: " + std::to_string(molID));
 
-		std::string molecule = r["pdbx_description"].as<std::string>();
+		auto molecule = r["pdbx_description"].get<std::string>();
 		cmpnd.push_back("MOLECULE: " + molecule);
 
 		auto poly = mDB["entity_poly"].find("entity_id"_key == entityID);
 		if (not poly.empty())
 		{
-			std::string chains = poly.front()["pdbx_strand_id"].as<std::string>();
+			auto chains = poly.front()["pdbx_strand_id"].get<std::string>();
 			cif::replace_all(chains, ",", ", ");
 			cmpnd.push_back("CHAIN: " + chains);
 		}
 
-		std::string fragment = r["pdbx_fragment"].as<std::string>();
+		auto fragment = r["pdbx_fragment"].get<std::string>();
 		if (not fragment.empty())
 			cmpnd.push_back("FRAGMENT: " + fragment);
 
 		for (auto sr : mDB["entity_name_com"].find("entity_id"_key == entityID))
 		{
-			std::string syn = sr["name"].as<std::string>();
+			auto syn = sr["name"].get<std::string>();
 			if (not syn.empty())
 				cmpnd.push_back("SYNONYM: " + syn);
 		}
 
-		std::string mutation = r["pdbx_mutation"].as<std::string>();
+		auto mutation = r["pdbx_mutation"].get<std::string>();
 		if (not mutation.empty())
 			cmpnd.push_back("MUTATION: " + mutation);
 
-		std::string ec = r["pdbx_ec"].as<std::string>();
+		auto ec = r["pdbx_ec"].get<std::string>();
 		if (not ec.empty())
 			cmpnd.push_back("EC: " + ec);
 
 		if (r["src_method"] == "man" or r["src_method"] == "syn")
-			cmpnd.push_back("ENGINEERED: YES");
+			cmpnd.emplace_back("ENGINEERED: YES");
 
-		std::string details = r["details"].as<std::string>();
+		auto details = r["details"].get<std::string>();
 		if (not details.empty())
 			cmpnd.push_back("OTHER_DETAILS: " + details);
 	}
@@ -1869,13 +1870,13 @@ std::string DSSP_impl::GetPDBSOURCELine()
 		if (r["type"] != "polymer")
 			continue;
 
-		std::string entityID = r["id"].as<std::string>();
+		auto entityID = r["id"].get<std::string>();
 
 		++molID;
 		source.push_back("MOL_ID: " + std::to_string(molID));
 
 		if (r["src_method"] == "syn")
-			source.push_back("SYNTHETIC: YES");
+			source.emplace_back("SYNTHETIC: YES");
 
 		auto &gen = mDB["entity_src_gen"];
 		const std::pair<const char *, const char *> kGenSourceMapping[] = {
@@ -1905,7 +1906,7 @@ std::string DSSP_impl::GetPDBSOURCELine()
 				std::string cname, sname;
 				tie(cname, sname) = m;
 
-				std::string s = gr[cname].as<std::string>();
+				auto s = gr[cname].get<std::string>();
 				if (not s.empty())
 					source.push_back(sname + ": " + s);
 			}
@@ -1930,7 +1931,7 @@ std::string DSSP_impl::GetPDBSOURCELine()
 				std::string cname, sname;
 				tie(cname, sname) = m;
 
-				std::string s = nr[cname].as<std::string>();
+				auto s = nr[cname].get<std::string>();
 				if (not s.empty())
 					source.push_back(sname + ": " + s);
 			}
@@ -1945,7 +1946,7 @@ std::string DSSP_impl::GetPDBAUTHORLine()
 	// AUTHOR
 	std::vector<std::string> author;
 	for (auto r : mDB["audit_author"])
-		author.push_back(cif2pdbAuth(r["name"].as<std::string>()));
+		author.push_back(cif2pdbAuth(r["name"].get<std::string>()));
 
 	return FixStringLength("AUTHOR    " + cif::join(author, "; "), kTruncateAt);
 }
@@ -2186,7 +2187,7 @@ std::tuple<dssp::residue_info, double> dssp::residue_info::donor(int i) const
 
 dssp::residue_info dssp::residue_info::next() const
 {
-	return residue_info(m_impl ? m_impl->mNext : nullptr);
+	return { m_impl ? m_impl->mNext : nullptr };
 }
 
 // --------------------------------------------------------------------
@@ -2220,7 +2221,8 @@ dssp::dssp(const cif::datablock &db, int model_nr, int min_poly_proline_stretch,
 {
 	if (calculateSurfaceAccessibility)
 	{
-		std::thread t(std::bind(&DSSP_impl::calculateSurface, m_impl));
+		std::thread t([this]
+			{ m_impl->calculateSurface(); });
 		m_impl->calculateSecondaryStructure();
 		t.join();
 	}
@@ -2235,7 +2237,7 @@ dssp::~dssp()
 
 dssp::iterator dssp::begin() const
 {
-	return iterator(m_impl->mResidues.empty() ? nullptr : m_impl->mResidues.data());
+	return { m_impl->mResidues.empty() ? nullptr : m_impl->mResidues.data() };
 }
 
 dssp::iterator dssp::end() const
@@ -2248,12 +2250,12 @@ dssp::iterator dssp::end() const
 		res += m_impl->mResidues.size();
 	}
 
-	return iterator(res);
+	return { res };
 }
 
 dssp::residue_info dssp::operator[](const key_type &key) const
 {
-	auto i = std::find_if(begin(), end(),
+	auto i = std::ranges::find_if(*this,
 		[key](const residue_info &res)
 		{ return res.asym_id() == std::get<0>(key) and res.seq_id() == std::get<1>(key); });
 


=====================================
python-module/CMakeLists.txt
=====================================
@@ -25,55 +25,41 @@
 include(CPM)
 
 if(CMAKE_VERSION GREATER_EQUAL 3.30)
-	cmake_policy(SET CMP0167 NEW)
+    cmake_policy(SET CMP0167 NEW)
 endif()
 
-find_package(Python REQUIRED COMPONENTS Interpreter Development)
-find_package(Boost 1.83 QUIET COMPONENTS python)
+find_package(Python 3.13 REQUIRED COMPONENTS Interpreter Development)
 
-if(NOT Boost_FOUND)
-	# boost is a huge project and directly downloading the 'alternate release'
-	# from github is much faster than recursively cloning the repo.
-	CPMAddPackage(
-		NAME Boost
-		VERSION 1.84.0
-		URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz
-		URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e
-		OPTIONS
-		"BOOST_ENABLE_CMAKE ON"
-		"BOOST_INCLUDE_LIBRARIES python"
-		"BOOST_ENABLE_PYTHON ON"
-		"CMAKE_POSITION_INDEPENDENT_CODE ON"
-	)
+if(NOT EXISTS ${Python_LIBRARIES})
+    message(FATAL_ERROR "The python library ${Python_LIBRARIES} does not seem to exist?")
 endif()
 
+find_package(Boost 1.86 REQUIRED COMPONENTS python)
+
 # ---------
 add_library(mkdssp_module SHARED dssp-python-plugin.cpp)
 
 target_compile_features(mkdssp_module PUBLIC cxx_std_20)
-
 target_include_directories(mkdssp_module PRIVATE ${Python_INCLUDE_DIRS})
-target_link_libraries(mkdssp_module dssp::dssp Boost::python ${Python_LIBRARIES})
+target_link_libraries(mkdssp_module PRIVATE dssp::dssp ${Python_LIBRARIES} Boost::python)
 
 set_target_properties(mkdssp_module
-	PROPERTIES
-	PREFIX ""
-	SUFFIX ".so"
-	OUTPUT_NAME mkdssp
-	LINKER_LANGUAGE CXX
-	LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
-)
+    PROPERTIES
+    PREFIX ""
+    SUFFIX ".so"
+    OUTPUT_NAME mkdssp
+    LINKER_LANGUAGE CXX
+    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 
 if(WIN32)
-	# python modules use this on Windows
-	set_target_properties(
-		mkdssp_module
-		PROPERTIES
-		SUFFIX ".pyd"
-		RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-	)
+    # python modules use this on Windows
+    set_target_properties(
+        mkdssp_module
+        PROPERTIES
+        SUFFIX ".pyd"
+        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 
-	install(TARGETS mkdssp_module RUNTIME DESTINATION "${Python_SITELIB}")
+    install(TARGETS mkdssp_module RUNTIME DESTINATION "${Python_SITELIB}")
 else()
-	install(TARGETS mkdssp_module LIBRARY DESTINATION "${Python_SITELIB}")
-endif()
\ No newline at end of file
+    install(TARGETS mkdssp_module LIBRARY DESTINATION "${Python_SITELIB}")
+endif()


=====================================
python-module/dssp-python-plugin.cpp
=====================================
@@ -2,6 +2,7 @@
 #include <Python.h>
 
 #include <dssp.hpp>
+#include <memory>
 
 struct statistics_wrapper
 {
@@ -42,7 +43,7 @@ class dssp_wrapper
 		std::istream is(&buffer);
 
 		auto f = cif::pdb::read(is);
-		m_dssp.reset(new dssp(f.front(), model_nr, min_poly_proline_stretch_length, calculateSurfaceAccessibility));
+		m_dssp = std::make_shared<dssp>(f.front(), model_nr, min_poly_proline_stretch_length, calculateSurfaceAccessibility);
 	}
 
 	dssp_wrapper(const dssp_wrapper &) = default;
@@ -83,7 +84,7 @@ class dssp_wrapper
 		iterator(const iterator &i) = default;
 		iterator &operator=(const iterator &i) = default;
 
-		reference operator*() { return residue_info_handle(m_current); }
+		reference operator*() { return {m_current}; }
 		pointer operator->() { return &m_current; }
 
 		iterator &operator++()
@@ -126,12 +127,12 @@ class dssp_wrapper
 // Custom exceptions
 struct AttributeError : std::exception
 {
-	const char *what() const throw() { return "AttributeError exception"; }
+	[[nodiscard]] const char *what() const noexcept override { return "AttributeError exception"; }
 };
 
 struct TypeError : std::exception
 {
-	const char *what() const throw() { return "TypeError exception"; }
+	[[nodiscard]] const char *what() const noexcept override { return "TypeError exception"; }
 };
 
 // Set python exceptions


=====================================
src/mkdssp.cpp
=====================================
@@ -33,7 +33,7 @@
 #include <fstream>
 #include <iostream>
 
-#include <cif++.hpp>
+#include <cif++/cif++.hpp>
 #include <mcfp/mcfp.hpp>
 
 #include "dssp.hpp"


=====================================
test/CMakeLists.txt
=====================================
@@ -1,32 +1,39 @@
 CPMFindPackage(
-	NAME Catch2 3
-	GIT_REPOSITORY https://github.com/catchorg/Catch2.git
-	GIT_TAG v3.4.0
-	EXCLUDE_FROM_ALL YES)
+    NAME Catch2 3
+    GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+    GIT_TAG v3.4.0
+    EXCLUDE_FROM_ALL YES)
 
 add_executable(unit-test-dssp ${CMAKE_CURRENT_SOURCE_DIR}/unit-test-dssp.cpp ${PROJECT_SOURCE_DIR}/libdssp/src/dssp-io.cpp)
 
 target_include_directories(unit-test-dssp PRIVATE
-	${CMAKE_CURRENT_SOURCE_DIR}/src
-	${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${CMAKE_CURRENT_SOURCE_DIR}/src
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
 )
 
 target_link_libraries(unit-test-dssp PRIVATE dssp cifpp::cifpp Catch2::Catch2)
 
 if(MSVC)
-	# Specify unwind semantics so that MSVC knowns how to handle exceptions
-	target_compile_options(unit-test-dssp PRIVATE /EHsc)
+    # Specify unwind semantics so that MSVC knowns how to handle exceptions
+    target_compile_options(unit-test-dssp PRIVATE /EHsc)
 endif()
 
 add_test(NAME unit-test-dssp COMMAND $<TARGET_FILE:unit-test-dssp>
-	--data-dir ${CMAKE_CURRENT_SOURCE_DIR}
-	--rsrc-dir ${CMAKE_CURRENT_SOURCE_DIR}/../libdssp/mmcif_pdbx/)
+    --data-dir ${CMAKE_CURRENT_SOURCE_DIR}
+    --rsrc-dir ${CIFPP_DATA_DIR})
 
 if(BUILD_PYTHON_MODULE)
-	find_package(Python REQUIRED Interpreter)
+    find_package(Python REQUIRED Interpreter)
 
-	add_test(NAME python_module COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test-python.py")
-	set_tests_properties(python_module PROPERTIES
-		ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>"
-		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
-endif()
\ No newline at end of file
+    add_test(NAME python_module COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test-python.py")
+    set_tests_properties(python_module PROPERTIES
+        ENVIRONMENT
+        "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>;LIBCIFPP_DATA_DIR=${CIFPP_DATA_DIR}"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+
+    add_test(NAME python_module_numpy COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test_numpy2_compat.py")
+    set_tests_properties(python_module_numpy PROPERTIES
+        ENVIRONMENT
+        "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>;LIBCIFPP_DATA_DIR=${CIFPP_DATA_DIR}"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+endif()


=====================================
test/test_numpy2_compat.py
=====================================
@@ -0,0 +1,176 @@
+"""
+DSSP numpy 2.x compatibility test script
+This script tests whether the DSSP module works correctly with numpy 2.x
+"""
+
+import sys
+import os
+import gzip
+import traceback
+
+def find_test_file():
+    """Find the test CIF file in the repository"""
+    # Possible paths relative to script location
+    possible_paths = [
+        "test/1cbs.cif.gz",  # From repository root
+        "../test/1cbs.cif.gz",  # From python-module directory
+        "1cbs.cif.gz",  # From test directory
+    ]
+    
+    for path in possible_paths:
+        if os.path.exists(path):
+            return path
+    
+    return None
+
+def test_numpy_version():
+    """Check numpy version"""
+    try:
+        import numpy as np
+        print(f"✓ numpy version: {np.__version__}")
+        major_version = int(np.__version__.split('.')[0])
+        if major_version >= 2:
+            print("✓ numpy 2.x detected")
+        else:
+            print(f"⚠ numpy {np.__version__} detected (not 2.x)")
+        return True
+    except ImportError as e:
+        print(f"✗ Failed to import numpy: {e}")
+        return False
+
+def test_mkdssp_import():
+    """Test mkdssp module import"""
+    try:
+        import mkdssp
+        print("✓ Successfully imported mkdssp module")
+        return True
+    except ImportError as e:
+        print(f"✗ Failed to import mkdssp: {e}")
+        traceback.print_exc()
+        return False
+
+def test_basic_functionality():
+    """Test basic functionality"""
+    try:
+        from mkdssp import dssp, TestBond, helix_type, chain_break_type, helix_position_type, structure_type
+        print("✓ Successfully imported all mkdssp classes/functions")
+        
+        # Find test file
+        test_file = find_test_file()
+        if test_file is None:
+            print("✗ Could not find test file (1cbs.cif.gz)")
+            print("  Please run this script from the repository root or test directory")
+            return False
+        
+        print(f"✓ Found test file: {test_file}")
+        
+        # Read test file
+        try:
+            with gzip.open(test_file, "rt") as f:
+                file_content = f.read()
+            print("✓ Successfully read test file")
+        except Exception as e:
+            print(f"✗ Failed to read test file: {e}")
+            return False
+        
+        # Test DSSP object creation
+        try:
+            dssp_obj = dssp(file_content)
+            print("✓ Successfully created DSSP object")
+        except Exception as e:
+            print(f"✗ Failed to create DSSP object: {e}")
+            traceback.print_exc()
+            return False
+        
+        # Test statistics
+        try:
+            stats = dssp_obj.statistics
+            print(f"✓ Successfully retrieved statistics")
+            print(f"  - Residues: {stats.residues}")
+            print(f"  - Chains: {stats.chains}")
+            print(f"  - H-bonds: {stats.H_bonds}")
+        except Exception as e:
+            print(f"✗ Failed to retrieve statistics: {e}")
+            traceback.print_exc()
+            return False
+        
+        # Test iteration
+        try:
+            count = 0
+            for res in dssp_obj:
+                count += 1
+                if count == 1:
+                    # Check first residue
+                    print(f"  - First residue: {res.asym_id} {res.seq_id} {res.compound_id}")
+            print(f"✓ Successfully iterated through {count} residues")
+        except Exception as e:
+            print(f"✗ Failed to iterate through residues: {e}")
+            traceback.print_exc()
+            return False
+        
+        # Test TestBond function
+        try:
+            a = dssp_obj.get('A', 137)
+            b = dssp_obj.get('A', 6)
+            result = TestBond(a, b)
+            print(f"✓ Successfully tested TestBond function: {result}")
+        except Exception as e:
+            print(f"✗ Failed to test TestBond function: {e}")
+            traceback.print_exc()
+            return False
+        
+        return True
+        
+    except Exception as e:
+        print(f"✗ Basic functionality test failed: {e}")
+        traceback.print_exc()
+        return False
+
+def main():
+    """Main test function"""
+    print("=" * 60)
+    print("DSSP numpy 2.x Compatibility Test")
+    print("=" * 60)
+    print()
+    
+    all_passed = True
+    
+    # Test 1: Check numpy version
+    print("Test 1: Check numpy version")
+    if not test_numpy_version():
+        all_passed = False
+    print()
+    
+    # Test 2: Import mkdssp
+    print("Test 2: Import mkdssp module")
+    if not test_mkdssp_import():
+        all_passed = False
+        print("\n⚠ Cannot import mkdssp, skipping remaining tests")
+        print_summary(False)
+        return 1
+    print()
+    
+    # Test 3: Basic functionality
+    print("Test 3: Test basic functionality")
+    if not test_basic_functionality():
+        all_passed = False
+    print()
+    
+    # Summary
+    print_summary(all_passed)
+    
+    return 0 if all_passed else 1
+
+def print_summary(all_passed):
+    """Print test summary"""
+    print("=" * 60)
+    if all_passed:
+        print("✓ All tests passed!")
+        print("✓ DSSP appears to be compatible with numpy 2.x")
+    else:
+        print("✗ Some tests failed")
+        print("✗ There may be compatibility issues with numpy 2.x")
+    print("=" * 60)
+
+if __name__ == "__main__":
+    sys.exit(main())


=====================================
test/unit-test-dssp.cpp
=====================================
@@ -24,16 +24,13 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdexcept>
-
 #define CATCH_CONFIG_RUNNER
 
-#include <catch2/catch_all.hpp>
-
 #include "../libdssp/src/dssp-io.hpp"
 #include "../src/revision.hpp"
 #include "dssp.hpp"
 
+#include <catch2/catch_all.hpp>
 #include <cif++/dictionary_parser.hpp>
 
 namespace fs = std::filesystem;
@@ -56,10 +53,12 @@ cif::file operator""_cf(const char *text, size_t length)
 
 // --------------------------------------------------------------------
 
-std::filesystem::path gTestDir = std::filesystem::current_path();
+std::filesystem::path gTestDir;
 
 int main(int argc, char *argv[])
 {
+	gTestDir = std::filesystem::current_path();
+
 	Catch::Session session; // There must be exactly one instance
 
 	// Build a new parser on top of Catch2's
@@ -156,8 +155,6 @@ TEST_CASE("ut_mmcif_2")
 
 	dssp dssp(f.front(), 1, 3, true);
 
-	std::stringstream test;
-
 	dssp.annotate(f.front(), true, true);
 
 	cif::file rf(gTestDir / "1cbs-dssp.cif");
@@ -166,12 +163,12 @@ TEST_CASE("ut_mmcif_2")
 	auto &db2 = rf.front();
 
 	db1["software"].erase("name"_key == "dssp");
-	db1.erase(find_if(db1.begin(), db1.end(), [](cif::category &cat)
-		{ return cat.name() == "audit_conform"; }));
+	std::erase_if(db1, [](cif::category &cat)
+		{ return cat.name() == "audit_conform"; });
 
 	db2["software"].erase("name"_key == "dssp");
-	db2.erase(find_if(db2.begin(), db2.end(), [](cif::category &cat)
-		{ return cat.name() == "audit_conform"; }));
+	std::erase_if(db2, [](cif::category &cat)
+		{ return cat.name() == "audit_conform"; });
 
 	// generate some output on different files:
 	// cif::VERBOSE = 2;


=====================================
tools/depends.cmd
=====================================
@@ -1,6 +1,5 @@
 @ECHO OFF
 SET ZLIB_VERSION=1.3
-SET PCRE2_VERSION=10.45
 
 IF NOT EXIST build_ci\libs (
   MKDIR build_ci\libs
@@ -22,19 +21,4 @@ cmake --build build --target ALL_BUILD --config Release || EXIT /b 1
 cmake --build build --target RUN_TESTS --config Release || EXIT /b 1
 cmake --build build --target INSTALL --config Release || EXIT /b 1
 
- at REM Install PCRE2
-IF NOT EXIST pcre2-%PCRE2_VERSION%.zip (
-  ECHO Downloading https://github.com/PCRE2Project/pcre2/releases/download/pcre2-%PCRE2_VERSION%/pcre2-%PCRE2_VERSION%.zip
-  curl -L -o pcre2-%PCRE2_VERSION%.zip https://github.com/PCRE2Project/pcre2/releases/download/pcre2-%PCRE2_VERSION%/pcre2-%PCRE2_VERSION%.zip || EXIT /b 1
-)
-IF NOT EXIST pcre2-%PCRE2_VERSION% (
-  ECHO Unpacking pcre2-%PCRE2_VERSION%.zip
-  C:\windows\system32\tar.exe -x -f pcre2-%PCRE2_VERSION%.zip || EXIT /b 1
-)
-CD pcre2-%PCRE2_VERSION%
-cmake -B build -DPCRE2_BUILD_PCRE2GREP=OFF || EXIT /b 1
-cmake --build build --target ALL_BUILD --config Release || EXIT /b 1
- at REM cmake --build build --target RUN_TESTS --config Release || EXIT /b 1
-cmake --build build --target INSTALL --config Release || EXIT /b 1
-
 @EXIT /b 0



View it on GitLab: https://salsa.debian.org/med-team/dssp/-/commit/a41ec052abf2c8c326646b10b68a5231ce815173

-- 
View it on GitLab: https://salsa.debian.org/med-team/dssp/-/commit/a41ec052abf2c8c326646b10b68a5231ce815173
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260324/8f7e7079/attachment-0001.htm>


More information about the debian-med-commit mailing list