Skip to content

[FEAT] Deprecate development in Triangle constructor - #1401

Open
henrydingliu wants to merge 16 commits into
casact:mainfrom
henrydingliu:feature/deprecate_development_in_constructor
Open

henrydingliu wants to merge 16 commits into
casact:mainfrom
henrydingliu:feature/deprecate_development_in_constructor

Conversation

@henrydingliu

@henrydingliu henrydingliu commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

Summary of Changes

Uses the newly minted deprecation decorator to deprecate the development argument to valuation and age.

wording changes to the decorator warning

replace all instances of development in triangle declaration in the codebase. will replace all instances in docs in a later PR

changed the stacklevel for dask deprecation warning in order to pass test

Related GitHub Issue(s)

Refers #1193

AI/LLM Usage

A lot of small changes scatters over the repo. Only used AI to triage the previously failing dask test

Additional Context for Reviewers

this PR exclusively changes a triangle declaration like this

    df = pd.DataFrame(
        data={
            "origin": [2022, 2022, 2023],
            "development": [2022, 2023, 2023],
            "reported": [78000, 222000, 78000],
        }
    )
    tri_from_df = cl.Triangle(
        data=df,
        origin="origin",
        development="development",
        columns=["reported"],
        cumulative=True,
    )

to this

    df = pd.DataFrame(
        data={
            "origin": [2022, 2022, 2023],
            "development": [2022, 2023, 2023],
            "reported": [78000, 222000, 78000],
        }
    )
    tri_from_df = cl.Triangle(
        data=df,
        origin="origin",
        valuation="development",
        columns=["reported"],
        cumulative=True,
    )

the Triangle.development and Triangle.valuation properties are unaffected.

bifurcating valuation and age is technically an API change. however, age support for Development was only added very recently in #1229.

Submitter's Checklist

  • I have reviewed and am adhering to the standards outlined in the project Governing Doc.
  • The PR subject title summarizes the changes, with one proper prefix ([FIX], [FEAT], [DOCS], [TST], [CHORE], or [BRK]).
  • I am a human (not a bot), and this PR form is written by a human.

Reviewer's Checklist

  • The implementation addresses the associated issue(s).
  • The implementation is appropriate, maintainable, and follows ARCHITECTURE.md.
  • PR subject title has the proper prefix and the subject is appropriate.
  • Relevant issue(s) are linked.
  • AI/LLM usage is disclosed and appropriate.
  • Documentation and tests are appropriate.
  • CI tests passed, or any failures are acceptable.
  • Leave a comment with the final recommendation (e.g. approve as is, request a secondary review, or flag an area for more review).

Note

Medium Risk
Touches the core Triangle construction API and changes how age vs valuation columns are specified, though legacy kwargs remain with warnings until v2.0.

Overview
Renames the primary Triangle / read_csv constructor kwargs from development and development_format to valuation and valuation_format, with _deprecated_rename_argument on Triangle.__init__ and read_csv so old names still work but emit FutureWarnings targeted for removal in v2.0. The rename decorator’s messages now say the old name is deprecated and will be removed (including “soon” when no version).

Splits development timing into two explicit inputs: valuation for date-like valuation columns and a new age kwarg for month-based development ages (mutually exclusive; specifying both raises). Age handling moves out of datetime inference (allow_age removed from _to_datetime); numeric columns passed only via valuation no longer auto-interpret as age.

Repo-wide call sites (tests, doctest examples, load_sample manifest, internal Triangle builds) switch to valuation=… while often keeping the same underlying column name (e.g. valuation="development"). Docs gain an age-based construction example. Dask backend deprecation stacklevel is bumped so warnings still point at user code through the new decorators.

Reviewed by Cursor Bugbot for commit 3408771. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Pyright Type Completeness

View the full pyright --verifytypes output for this commit

Project (full chainladder package, at this PR's head): 15.6% of exported symbols fully typed (223 / 1428)

Known Ambiguous Unknown Total
Project (head) 223 108 1097 1428

Other symbols referenced but not exported by chainladder: 13

Known Ambiguous Unknown Total
Other (head) 3 1 9 13

Symbols without documentation:

  • Functions without docstring: 326
  • Functions without default param: 0
  • Classes without docstring: 8

Patch (exported symbols added or changed by this PR): 100.0% fully typed (4 / 4); 2 no longer exported

Known Ambiguous Unknown Total
Patch 4 0 0 4
Patch symbol details
Symbol Status Change
chainladder.core.tests.test_triangle.test_1d_annual_valuation_date1 ✅ known new
chainladder.core.tests.test_triangle.test_1d_monthly_valuation_date2 ✅ known new
chainladder.core.tests.test_triangle.test_declare_w_both_valuation_age_raises ✅ known new
chainladder.core.tests.test_triangle.test_feed_age_into_valuation_raises ✅ known new
chainladder.core.tests.test_triangle.test_1d_annual_valuation_date — no longer exported (was ✅ known)
chainladder.core.tests.test_triangle.test_1d_monthly_valuation_date — no longer exported (was ✅ known)

@henrydingliu
henrydingliu marked this pull request as draft September 18, 2026 05:35

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread chainladder/utils/utility_functions.py
Comment thread chainladder/core/triangle.py Outdated
Comment thread chainladder/core/triangle.py
Comment thread chainladder/core/base.py
@codecov

codecov Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.11%. Comparing base (08ded05) to head (3408771).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1401      +/-   ##
==========================================
+ Coverage   94.06%   94.11%   +0.04%     
==========================================
  Files          96       96              
  Lines        5765     5773       +8     
  Branches      722      722              
==========================================
+ Hits         5423     5433      +10     
+ Misses        221      220       -1     
+ Partials      121      120       -1     
Flag Coverage Δ
unittests 94.11% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread chainladder/core/triangle.py
@henrydingliu
henrydingliu marked this pull request as ready for review September 18, 2026 06:05
@henrydingliu

Copy link
Copy Markdown
Member Author

Major API update. Will need review from two codeowners.

@henrydingliu henrydingliu changed the title [FEAT] Deprecate development in constructor [FEAT] Deprecate development in Triangle constructor Sep 18, 2026
@genedan

genedan commented Sep 18, 2026

Copy link
Copy Markdown
Member

I have some clarifying questions (since actuarial lingo varies a lot):

  • Why is the development parameter a misnomer?
  • Will the development axis still refer to the 12, 24, 36, etc. that we see at the top of the triangle?
  • Will the valuation axis (used in trend) still refer to the diagonals?

@henrydingliu

henrydingliu commented Sep 18, 2026 •

Copy link
Copy Markdown
Member Author

Why is the development parameter a misnomer?

after constructing the triangle, the triangle.development property refers to the development age. the triangle.valuation virtual column is the "as of" date. this is inconsistent with the development argument, which could only take "as of" dates till very recently. so it's less of actuarial dialect between different shops, more of an internal consistency within the package

will add some notes to the PR summary

Will the development axis still refer to the 12, 24, 36, etc. that we see at the top of the triangle?

this will not change. only the declaration is change.

Will the valuation axis (used in trend) still refer to the diagonals?

yes

Comment thread chainladder/core/base.py
Comment thread chainladder/utils/data/_manifest.py
Comment thread chainladder/utils/data/_manifest.py
Comment thread chainladder/utils/utility_functions.py
Comment thread chainladder/_config/deprecation.py Outdated
Comment on lines +292 to +296
message = f"'{old_name}' has been deprecated in favor of '{new_name}' and will be removed"
if version:
message += f" in {version}"
else:
message += " soon"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the message can be improved, maybe:

"The function has been deprecated since 0.11.0, and will be removed in a future version" or something like that. Do we want to commit to something will be deprecated ON a specific version? The timing could be hard to manage.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think we said we want the deprecation cycle to be at least 3 months long

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah completely open to wordsmithing here. will let gene propose something since i already butchered his original message.

the overall intent is, assuming we are aligned. we are gonna deprecate this name (either function or arg), you can still use it for now, till this new version.

i have been tying deprecation to versions. but also open to tying to date.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had commented earlier on #1027, but I think the 3 month thing needs to be revised in favor of deprecating by version. Historically we haven't been so good at committing to a specific release date, but we have been pretty good at releasing once we've closed out enough tickets. @henrydingliu's comment about copying pandas works for me. They do at least 2 minor releases which would work for me.

array_backend: str = None,
pattern=False,
trailing: bool = True,
age: Optional[str | list] = None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the order of these parameters, but not sure what is best, my proposal:

self
data
origin
origin_format
valuation
valuation_format
age
index
columns
cumulative
trailing
pattern
array_backend

Hopefully I didn't miss any

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah cursor screams at you if you don't put age at the end. basically, someone who passes parameters by position would get messed up if we put age earlier up the argument list.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh... I see, but that's only if you use the implied order right? Ok I hate it but I guess we can't do much about it.

Do you think people often use the implied parameters ordering without explicitly saying what is what?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean, in general the best practice guides tell you to not use positional arguments for anything with more than a couple of arguments. i actually wouldn't mind at all if we did reorder.

this is why we need multiple codeowners to review a major API change :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we reach 2.0.0 before we ever reach 1.5?

@kennethshsu

Copy link
Copy Markdown
Member

I think this is going to be my favorite PR in a long time.

@genedan does what @henrydingliu make sense? This is one of those things that had bothered me a lot. development is to describe how old, not when, and valuation is a better way to describe "when", and age is the better way to describe how old.

@genedan

genedan commented Sep 18, 2026

Copy link
Copy Markdown
Member

I'm in agreement, I'll put in the review soon.

@genedan

genedan commented Sep 19, 2026

Copy link
Copy Markdown
Member

What do you think of having the deprecation version being optional? I'm leaning towards making it a mandatory parameter. If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

@henrydingliu

Copy link
Copy Markdown
Member Author

What do you think of having the deprecation version being optional? I'm leaning towards making it a mandatory parameter. If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

do you think other contributors will be comfortable naming versions? we can always recommend a version during PR review

@kennethshsu

Copy link
Copy Markdown
Member

What do you think of having the deprecation version being optional? I'm leaning towards making it a mandatory parameter. If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

I think we should announce when it began being deprecated, and just say we will remove it in a future version, then just follow the governing doc and leave it for 3 months min after it's been released.

So basically, "this function is deprecated on v0.x.0, and will be removed in an upcoming release, use ____ instead". That way we have reasonable documentation on when deprecation began, and it is also easy to just check the time requirement. Thoughts?

@henrydingliu

Copy link
Copy Markdown
Member Author

What do you think of having the deprecation version being optional? I'm leaning towards making it a mandatory parameter. If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

I think we should announce when it began being deprecated, and just say we will remove it in a future version, then just follow the governing doc and leave it for 3 months min after it's been released.

So basically, "this function is deprecated on v0.x.0, and will be removed in an upcoming release, use ____ instead". That way we have reasonable documentation on when deprecation began, and it is also easy to just check the time requirement. Thoughts?

Did you comment in the right PR? we are not deprecating a function here.

@kennethshsu

Copy link
Copy Markdown
Member

Bad wording on my part, but my point is the same, it should say something like

"development is deprecated on v0.x.0, and will be removed in an upcoming release, use valuation instead."

My point is that we just announce when something will begin being deprecated, without saying when the end of life is.

@kennethshsu

kennethshsu commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

But it should be mandatory, basically I agree with what @genedan proposed.

If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

@henrydingliu

henrydingliu commented Sep 22, 2026 •

Copy link
Copy Markdown
Member Author

Bad wording on my part, but my point is the same, it should say something like

"development is deprecated on v0.x.0, and will be removed in an upcoming release, use valuation instead."

My point is that we just announce when something will begin being deprecated, without saying when the end of life is.

But it should be mandatory, basically I agree with what @genedan proposed.

If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

to be clear, you just said two conflicting things.

earlier you said, do not promise a version where it's removed

here you just said, you agree with gene, whose question was whether we need to make the removal version mandatory

@kennethshsu

Copy link
Copy Markdown
Member

Bad wording on my part, but my point is the same, it should say something like
"development is deprecated on v0.x.0, and will be removed in an upcoming release, use valuation instead."
My point is that we just announce when something will begin being deprecated, without saying when the end of life is.

But it should be mandatory, basically I agree with what @genedan proposed.

If we don't assign a version number, it's going to be harder to track down and schedule features for removal.

to be clear, you just said two conflicting things.

earlier you said, do not promise a version where it's removed

here you just said, you agree with gene, whose question was whether we need to make the removal version mandatory

I meant we document when something is beginning to be deprecated, and no need to document when it will be deprecated, so use

"development is deprecated on vX, and will be removed in an upcoming release, use valuation instead."

instead of

"development will be deprecated on vY,, use valuation instead."

See here.

@henrydingliu

Copy link
Copy Markdown
Member Author

okay. say you are a user of this package. and you get a deprecation warning like this. what exactly is the value of knowing when a deprecation was first introduced?

@kennethshsu

Copy link
Copy Markdown
Member

okay. say you are a user of this package. and you get a deprecation warning like this. what exactly is the value of knowing when a deprecation was first introduced?

To know when it began? I.e. you've been warned since ____. I'm not saying it's more valuable than knowing "this function will no longer work by this date" but it is easier for us maintainers to keep track. It's a good balance between keeping the users informed but without overburdening ourselves with promising a date that we must keep to.

@henrydingliu

Copy link
Copy Markdown
Member Author

To know when it began? I.e. you've been warned since ____.

dude, that's so passive aggressive. do you not hear it?

but it is easier for us maintainers to keep track

we shouldn't be relying on warning messages to keep track. a centralized list somewhere on the repo is much more effective.

@kennethshsu

Copy link
Copy Markdown
Member

To know when it began? I.e. you've been warned since ____.

dude, that's so passive aggressive. do you not hear it?

Well you asked and I answered lol. I also think a bit of passive aggressiveness here isn't a bad thing? We want to warn the user to basically migrate before they complain? All jokes aside, what do you not like about this?

but it is easier for us maintainers to keep track

we shouldn't be relying on warning messages to keep track. a centralized list somewhere on the repo is much more effective.

That's a fair point, but it does mean we will need to maintain another list, which isn't bad I think.

Let me reply and add more context in the other thread.

Comment thread chainladder/_config/deprecation.py Outdated
Comment thread chainladder/core/triangle.py
@genedan

genedan commented Sep 24, 2026

Copy link
Copy Markdown
Member

I'm good with the syntax, I only just need an example of supplying ages because I've never actually seen that used before and it would be good to have an example of that in the Triangle docstring.

For the deprecation though we do need to iron out some details in the policy on #1027 .

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2ffb953. Configure here.

Comment thread chainladder/utils/data/_manifest.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants