Make the in-memory NPV cubes constructible from Python (#354) - #355
Open
dazivo wants to merge 1 commit into
Open
Make the in-memory NPV cubes constructible from Python (#354)#355dazivo wants to merge 1 commit into
dazivo wants to merge 1 commit into
Conversation
…k#354) SinglePrecisionInMemoryCubeN and DoublePrecisionInMemoryCubeN raised "No constructor defined - class is abstract" on construction, on the released 1.8.15.0 and 1.8.16.0 wheels alike. Since NPVCube and AggregationScenarioData are abstract by design and JointNPVCube only joins existing cubes, no NPV cube could be built from Python at all. The InMemoryCubeOpt overrides in orea_cube.i did not textually match the base's pure virtuals as the SWIG parser sees them, for two independent reasons: - getT0/get dropped the base's `= 0` default argument. SWIG expands a pure virtual with a default into one required signature per arity, so an override without the default satisfies only the full-arity form. - the parameters were spelled QuantLib::Size/QuantLib::Real, which the SWIG parser cannot resolve: the `using QuantLib::Size` that would bridge them to the declared `typedef size_t Size` sits inside a %{ %} block the parser never sees (the same visibility mechanism as OpenSourceRisk#351). Either mismatch alone keeps the class abstract; SWIG then treats the pure virtuals as unimplemented and drops the constructors. Spell the overrides exactly like the base -- bare Size/Real, with the base's default repeated on getT0/get -- and declare %feature("compactdefaultargs") for getT0/get on NPVCube and InMemoryCubeOpt. The feature is load-bearing: without it SWIG emits a reduced-arity call like cube->getT0(i) for the default-argument overload, which does not compile, because the C++ overrides do not repeat the base's default and default arguments are resolved against the static type. It has to be declared for base and overrides alike, and before both classes, or the abstract check stops matching them. Verified by building the bindings and running them in a debian trixie container (clang 19, swig 4.3, apt boost): both classes construct, values round-trip through set/get at either arity, and overload dispatch on a base-typed NPVCube proxy (index vs trade id, with and without the depth argument) resolves correctly. The accompanying test constructs both precisions and round-trips values through set/get; it fails with the abstract-class AttributeError against both released wheels.
dazivo
force-pushed
the
fix/inmemory-cube-swig-abstract
branch
from
August 18, 2026 18:08
78b25fe to
39108fd
Compare
This was referenced Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #354.
SinglePrecisionInMemoryCubeNandDoublePrecisionInMemoryCubeNraisedAttributeError: No constructor defined - class is abstracton construction, on the released 1.8.15.0 and 1.8.16.0 wheels alike. SinceNPVCubeandAggregationScenarioDataare abstract by design andJointNPVCubeonly joins existing cubes, no NPV cube could be built from Python at all.The
InMemoryCubeOptoverrides inorea_cube.idid not textually match the base's pure virtuals as the SWIG parser sees them, for two independent reasons:getT0/getdropped the base's= 0default argument. SWIG expands a pure virtual with a default into one required signature per arity, so an override without the default satisfies only the full-arity form.QuantLib::Size/QuantLib::Real, which the SWIG parser cannot resolve: theusing QuantLib::Sizethat would bridge them to the declaredtypedef size_t Sizesits inside a%{ %}block the parser never sees (the same visibility mechanism as Python bindings: getCube/setCube declare different shared_ptr spellings, so in-memory cube reuse raises TypeError (regression in 1.8.16.0) #351).Either mismatch alone keeps the class abstract (verified by bisection in a minimal SWIG module, table in #354); SWIG then treats the pure virtuals as unimplemented and drops the constructors.
The fix spells the overrides exactly like the base — bare
Size/Real, with the base's default repeated ongetT0/get— and declares%feature("compactdefaultargs")forgetT0/getonNPVCubeandInMemoryCubeOpt. The feature is load-bearing: without it SWIG emits a reduced-arity call likecube->getT0(i)for the default-argument overload, which does not compile, because the C++ overrides do not repeat the base's default and default arguments are resolved against the static type. It has to be declared for base and overrides alike, and before both classes, or the abstract check stops matching them.Verified by building the bindings and running them in a debian trixie container (clang 19, swig 4.3, apt boost): both classes construct, values round-trip through
set/getat either arity, and overload dispatch on a base-typedNPVCubeproxy (index vs trade id, with and without the depth argument) resolves correctly. Warning profile unchanged, independent of the #353 alias fix (verified with and without it applied).The accompanying test constructs both precisions and round-trips values through
set/get; it fails with the abstract-classAttributeErroragainst both released wheels.