Repository: qpdf/qpdf
Pull request #1381: Update release notes and reverse making QPDFObjectHandle final
Author: login: m-holger
Created: 2025-03-05T13:24:32Z | Merged: 2025-03-05T23:40:58Z

and delay to qpdf 13 to give users notice of the change.


Diff:
diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh
index fd4b19d4b..97031778f 100644
--- a/include/qpdf/QPDFObjectHandle.hh
+++ b/include/qpdf/QPDFObjectHandle.hh
@@ -63,7 +63,7 @@ class Pl_QPDFTokenizer;
 class QPDFMatrix;
 class QPDFParser;
 
-class QPDFObjectHandle final: public qpdf::BaseHandle
+class QPDFObjectHandle: public qpdf::BaseHandle
 {
     friend class QPDFParser;
 
diff --git a/manual/release-notes.rst b/manual/release-notes.rst
index 51fd21948..dc4698783 100644
--- a/manual/release-notes.rst
+++ b/manual/release-notes.rst
@@ -1,3 +1,6 @@
+.. _ticket: https://issues.qpdf.org
+.. _shared null: https://wiki.qpdf.org/PDF-null-objects-vs-qpdf-null-objects
+
 .. _release-notes:
 
 Release Notes
@@ -41,13 +44,42 @@ more detail.
     - ``QIntC.hh`` contained the typo ``substract`` in function names,
       which has been fixed to ``subtract``.
 
+    - The protected ``QPDFObjectHelper::oh`` data member has been replaced with
+      the new accessor method ``QPDFObjectHelper::oh()``.
+
+    - Except for abstract classes and the exceptions listed below, sub-classing of
+      qpdf classes is not supported. These classes were never designed to be used as a
+      base class and will be made final in version 13. If you have a use case for
+      extending one of these classes, please open a ticket_.
+
+      Exceptions:
+
+      - ``QPDFDocumentHelper``
+      - ``QPDFObjectHelper``
+
+    - Upcasting to ``QPDFObjectHelper`` and ``QPDFDocumentHelper`` is not supported. Their
+      destructors will be made protected in version 13.
+
+    - Catching of logic errors thrown as the result of using an uninitialized
+      ``QPDFObjectHandle`` is not supported. In version 13 uninitialized object handles
+      will be treated as immutable `shared null`_ objects. Using them will no longer throw
+      any logic errors, but may where appropriate generate type warnings or exceptions.
+
 .. _r12-0-0-deprecate:
 
     - The following are believed to be not in use and have been deprecated.
-      If you are relying on them please open a `ticket <https://issues.qpdf.org>`__:
+      If you are relying on them please open a ticket_.
 
       - All ``QPDFTokenizer`` push-mode methods.
 
+  - CLI breaking Changes
+
+    - To support the future introduction of sub-commands, the use of filenames without
+      extension and path element as the first argument is no longer supported, and the
+      result may change in the future. For example, ``qpdf check out.pdf`` currently
+      copies the file ``check`` to ``out.pdf`` but may in future check ``out.pdf``.
+      Use ``qpdf ./check out.pdf`` or ``qpdf -- check out.pdf`` instead.
+
   - Library Enhancements
 
     - ``QPDFObjectHandle`` supports move construction/assignment.
@@ -59,6 +91,12 @@ more detail.
 
     - Most ``QPDFObjectHandle`` accessor methods are now const qualified.
 
+    - ``QPDFObjectHandle`` and all object helper classes are now explicitly convertible
+      to ``QPDFObjGen``, and therefore can be passed as parameter where a ``QPDFObjGen``
+      is required. Redundant overloaded methods have been removed.
+
+    - All object helper classes are now explicitly convertible to ``QPDFObjectHandle``.
+
   - Build Changes
 
     - If ``POINTERHOLDER_TRANSITION`` is not defined, define it to
@@ -70,12 +108,26 @@ more detail.
       ``PointerHolder`` will have to explicitly include it rather than
       relying on other headers to bring it along.
 
+  - Other Changes
+
+    - The internal implementation of objects has been extensively refactored, using
+      std::variant to eliminate one level of indirection. This has saved one shared pointer
+      per object with some improvement both in runtime and memory usage. A new class
+      ``BaseHandle`` has been added as common base class of both ``QPDFObjectHandle``
+      and ``QPDFObjectHelper`` to provide common functionality appropriate for all
+      object-handle-like classes including e.g. the operator to convert to ``QPDFObjGen``.
+      ``BaseHandle`` is an implementation detail and not directly usable by library users.
+
+    - There has also been significant refactoring of how qpdf internally iterates over
+      arrays and dictionaries.
+
+
 11.10.1: February 15, 2025
   - Build fixes
 
-    - Fix incorrect detection of zopfli
+    - Fix incorrect detection of zopfli.
 
-    - Recognize cygwin perl as Windows when running test suite
+    - Recognize cygwin perl as Windows when running test suite.
 
 11.10.0: February 8, 2025
   - Bug fixes


Reviews:
user: login: jberkenbilt
body: You didn't ask for my review, but I thought I'd review it anyway. This is a good level of detail, including for the internal changes.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T19:41:11Z
user: login: m-holger
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T23:40:48Z

Review comments:
diff_hunk: @@ -63,7 +63,7 @@ class Pl_QPDFTokenizer;
 class QPDFMatrix;
 class QPDFParser;
 
-class QPDFObjectHandle final: public qpdf::BaseHandle
path: include/qpdf/QPDFObjectHandle.hh
user: login: jberkenbilt
body: No object, but I'm just curious as to why. I don't have a strong opinion about whether it should or shouldn't be final.
created_at: 2025-03-05T19:37:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,3 +1,6 @@
+.. _ticket: https://issues.qpdf.org
path: manual/release-notes.rst
user: login: jberkenbilt
body: huh, didn't know you could do that.
created_at: 2025-03-05T19:38:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,13 +44,42 @@ more detail.
     - ``QIntC.hh`` contained the typo ``substract`` in function names,
       which has been fixed to ``subtract``.
 
+    - The protected ``QPDFObjectHelper::oh`` data member has been replaced with
+      the new accessor method ``QPDFObjectHelper::oh()``.
+
+    - Except for abstract classes and the exceptions listed below, sub-classing of
path: manual/release-notes.rst
user: login: jberkenbilt
body: Oh, that's why. Good call.
created_at: 2025-03-05T19:39:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,13 +44,42 @@ more detail.
     - ``QIntC.hh`` contained the typo ``substract`` in function names,
       which has been fixed to ``subtract``.
 
+    - The protected ``QPDFObjectHelper::oh`` data member has been replaced with
+      the new accessor method ``QPDFObjectHelper::oh()``.
+
+    - Except for abstract classes and the exceptions listed below, sub-classing of
+      qpdf classes is not supported. These classes were never designed to be used as a
+      base class and will be made final in version 13. If you have a use case for
+      extending one of these classes, please open a ticket_.
+
+      Exceptions:
+
+      - ``QPDFDocumentHelper``
+      - ``QPDFObjectHelper``
+
+    - Upcasting to ``QPDFObjectHelper`` and ``QPDFDocumentHelper`` is not supported. Their
+      destructors will be made protected in version 13.
+
+    - Catching of logic errors thrown as the result of using an uninitialized
+      ``QPDFObjectHandle`` is not supported. In version 13 uninitialized object handles
+      will be treated as immutable `shared null`_ objects. Using them will no longer throw
+      any logic errors, but may where appropriate generate type warnings or exceptions.
+
 .. _r12-0-0-deprecate:
 
     - The following are believed to be not in use and have been deprecated.
-      If you are relying on them please open a `ticket <https://issues.qpdf.org>`__:
+      If you are relying on them please open a ticket_.
 
       - All ``QPDFTokenizer`` push-mode methods.
 
+  - CLI breaking Changes
+
+    - To support the future introduction of sub-commands, the use of filenames without
+      extension and path element as the first argument is no longer supported, and the
+      result may change in the future. For example, ``qpdf check out.pdf`` currently
+      copies the file ``check`` to ``out.pdf`` but may in future check ``out.pdf``.
+      Use ``qpdf ./check out.pdf`` or ``qpdf -- check out.pdf`` instead.
path: manual/release-notes.rst
user: login: jberkenbilt
body: Should we warn for this?
created_at: 2025-03-05T19:40:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,13 +44,42 @@ more detail.
     - ``QIntC.hh`` contained the typo ``substract`` in function names,
       which has been fixed to ``subtract``.
 
+    - The protected ``QPDFObjectHelper::oh`` data member has been replaced with
+      the new accessor method ``QPDFObjectHelper::oh()``.
+
+    - Except for abstract classes and the exceptions listed below, sub-classing of
+      qpdf classes is not supported. These classes were never designed to be used as a
+      base class and will be made final in version 13. If you have a use case for
+      extending one of these classes, please open a ticket_.
+
+      Exceptions:
+
+      - ``QPDFDocumentHelper``
+      - ``QPDFObjectHelper``
+
+    - Upcasting to ``QPDFObjectHelper`` and ``QPDFDocumentHelper`` is not supported. Their
+      destructors will be made protected in version 13.
+
+    - Catching of logic errors thrown as the result of using an uninitialized
+      ``QPDFObjectHandle`` is not supported. In version 13 uninitialized object handles
+      will be treated as immutable `shared null`_ objects. Using them will no longer throw
+      any logic errors, but may where appropriate generate type warnings or exceptions.
+
 .. _r12-0-0-deprecate:
 
     - The following are believed to be not in use and have been deprecated.
-      If you are relying on them please open a `ticket <https://issues.qpdf.org>`__:
+      If you are relying on them please open a ticket_.
 
       - All ``QPDFTokenizer`` push-mode methods.
 
+  - CLI breaking Changes
+
+    - To support the future introduction of sub-commands, the use of filenames without
+      extension and path element as the first argument is no longer supported, and the
+      result may change in the future. For example, ``qpdf check out.pdf`` currently
+      copies the file ``check`` to ``out.pdf`` but may in future check ``out.pdf``.
+      Use ``qpdf ./check out.pdf`` or ``qpdf -- check out.pdf`` instead.
path: manual/release-notes.rst
user: login: m-holger
body: Probably only for names that are likely to clash with sub commands.

I don't thinks there are many pdf files out there without extension and probably far fewer that are likely to clash. In any case, I don't think its urgent. I can't see much happening on this before 13. 
created_at: 2025-03-05T23:40:48Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-05T13:33:25Z
body: ## [Codecov](https://app.codecov.io/gh/qpdf/qpdf/pull/1381?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=qpdf) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 93.33%. Comparing base [(`00ad6f5`)](https://app.codecov.io/gh/qpdf/qpdf/commit/00ad6f555bf9244a918420da5baad2a8cbf724e6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=qpdf) to head [(`b4fe4c3`)](https://app.codecov.io/gh/qpdf/qpdf/commit/b4fe4c376a88a24ea8e50a8f41907627079565bc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=qpdf).
> Report is 201 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1381      +/-   ##
==========================================
- Coverage   93.34%   93.33%   -0.01%     
==========================================
  Files         278      278              
  Lines       33611    33601      -10     
  Branches     4176     4174       -2     
==========================================
- Hits        31374    31362      -12     
- Misses       2237     2239       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/qpdf/qpdf/pull/1381?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=qpdf).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=qpdf).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: jberkenbilt
created_at: 2025-03-05T19:41:39Z
body: > You didn't ask for my review, but I thought I'd review it anyway. This is a good level of detail, including for the internal changes.

Oh, you did ask for my review. :-)
author_association: CONTRIBUTOR