Skip to content

Commit e8bfb01

Browse files
regebroLennart Regebro
andauthored
Updated schema to 1.2.0 (#12)
* Updated schema to 1.2.0 * Preparing release 1.2.0b1 * Back to development: 1.2.0b2 * There are new files in the OCF Zip (#13) Co-authored-by: Lennart Regebro <lennart.regebro@fidelity.com> * Updated CHANGES.txt * Preparing release 1.2.0b2 * Back to development: 1.2.0b3 * Make it possible to pass in data into the Captable constructor (#14) * When saving, exclude_unset doesn't always behave as expected So we remove exclude_unset, which will increase the size of the output, but that's not big deal. * Make it possible to pass in data into the Captable constructor --------- Co-authored-by: Lennart Regebro <lennart.regebro@fidelity.com> * Preparing release 1.2.0b3 * Back to development: 1.2.0b4 --------- Co-authored-by: Lennart Regebro <lennart.regebro@fidelity.com>
1 parent 6217dec commit e8bfb01

191 files changed

Lines changed: 1526 additions & 391 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.txt

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
Changes
22
=======
33

4-
1.2.0 (unreleased)
5-
------------------
4+
1.2.0b4 (unreleased)
5+
--------------------
66

77
- Nothing changed yet.
88

99

10+
1.2.0b3 (2025-04-17)
11+
--------------------
12+
13+
- Now includes default values when saving, making the OCF files larger.
14+
15+
- It's now possible to pass in the data to the Captable object when
16+
creating it, instead of adding the data to the attribute lists later.
17+
18+
19+
1.2.0b2 (2025-02-04)
20+
--------------------
21+
22+
- Added the new files to the format.
23+
24+
25+
1.2.0b1 (2025-01-10)
26+
--------------------
27+
28+
- Updated schema to 1.2.0
29+
30+
1031
1.1.0 (2025-01-09)
1132
------------------
1233

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ ifndef NO_VENV
77
bin_dir := $(root_dir)/ve/bin/
88
python_exe := $(bin_dir)python3
99
endif
10-
git_source := https://github.com/Open-Cap-Table-Coalition/Open-Cap-Format-OCF.git
11-
git_branch := release-v1.1.0
10+
git_source := https://github.com/regebro/Open-Cap-Format-OCF.git
11+
git_branch := lregebro-v1.2.0
1212

1313
all: devenv fetch build
1414

docs/source/using.rst

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,12 @@ but you then need to create ``File`` objects for each file, with dummy md5 hashe
4646
... id="d6c49a5a-257d-4b41-9f1d-073a77dfe719",
4747
... name={"legal_name": "Person Y"},
4848
... stakeholder_type="INDIVIDUAL",
49-
... comments=[],
5049
... )
5150
... )
5251

5352
>>> cap.transactions.append(
54-
... api.PlanSecurityIssuance(
55-
... object_type="TX_PLAN_SECURITY_ISSUANCE",
53+
... api.EquityCompensationIssuance(
54+
... object_type="TX_EQUITY_COMPENSATION_ISSUANCE",
5655
... stock_plan_id="test",
5756
... id="Success OPTION",
5857
... custom_id="test",
@@ -65,9 +64,24 @@ but you then need to create ``File`` objects for each file, with dummy md5 hashe
6564
... security_id="",
6665
... date="2022-12-12",
6766
... security_law_exemptions=[],
67+
... expiration_date=None,
6868
... )
6969
... )
7070

71+
It is also possible to create the list of objects first, and pass them in to the
72+
Captable constructor::
73+
74+
>>> sh_list = [
75+
... api.Stakeholder(
76+
... object_type="STAKEHOLDER",
77+
... id="'917efd77a370-d1f9-14b4-d752-a5a94c6d",
78+
... name={"legal_name": "Person X"},
79+
... stakeholder_type="INDIVIDUAL",
80+
... )
81+
... }
82+
83+
>>> cap2 = Captable(stakeholders=sh_list)
84+
7185
And once you have filled in all the lists with all the information, you save
7286
the captable:
7387

@@ -101,13 +115,8 @@ A captable will then be created and Python objects will be stored in it.
101115
'pyocf example docs'
102116

103117
>>> cap.stakeholders # doctest: +NORMALIZE_WHITESPACE
104-
[Stakeholder(id='d6c49a5a-257d-4b41-9f1d-073a77dfe719', comments=[],
105-
object_type='STAKEHOLDER', name=Name(legal_name='Person Y', first_name=None,
106-
last_name=None), stakeholder_type=<StakeholderType.ENUM_INDIVIDUAL:
107-
'INDIVIDUAL'>, issuer_assigned_id=None, current_relationship=None,
108-
primary_contact=None, addresses=None, tax_ids=None),
109-
Stakeholder(id='d6c49a5a-257d-4b41-9f1d-073a77dfe719', comments=[],
118+
[Stakeholder(id='d6c49a5a-257d-4b41-9f1d-073a77dfe719', comments=None,
110119
object_type='STAKEHOLDER', name=Name(legal_name='Person Y', first_name=None,
111120
last_name=None), stakeholder_type=<StakeholderType.ENUM_INDIVIDUAL:
112121
'INDIVIDUAL'>, issuer_assigned_id=None, current_relationship=None,
113-
primary_contact=None, addresses=None, tax_ids=None)]
122+
primary_contact=None, contact_info=None, addresses=None, tax_ids=None)]

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = pyocf
3-
version = 1.2.0.dev0
3+
version = 1.2.0b4.dev0
44
description = Open Captable Format objects and parser
55
long_description = file: README.rst, CONTRIBUTORS.txt, CHANGES.txt
66
classifiers =

src/pyocf/api.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pyocf.enums.accrualperiodtype import AccrualPeriodType
77
from pyocf.enums.addresstype import AddressType
88
from pyocf.enums.allocationtype import AllocationType
9+
from pyocf.enums.authorizedshares import AuthorizedShares
910
from pyocf.enums.compensationtype import CompensationType
1011
from pyocf.enums.compoundingtype import CompoundingType
1112
from pyocf.enums.conversionmechanismtype import ConversionMechanismType
@@ -22,6 +23,7 @@
2223
from pyocf.enums.parentsecuritytype import ParentSecurityType
2324
from pyocf.enums.periodtype import PeriodType
2425
from pyocf.enums.phonetype import PhoneType
26+
from pyocf.enums.quantitysourcetype import QuantitySourceType
2527
from pyocf.enums.roundingtype import RoundingType
2628
from pyocf.enums.stakeholderrelationshiptype import StakeholderRelationshipType
2729
from pyocf.enums.stakeholdertype import StakeholderType
@@ -31,9 +33,12 @@
3133
StockPlanCancellationBehaviorType,
3234
)
3335
from pyocf.enums.terminationwindowtype import TerminationWindowType
36+
from pyocf.enums.valuationbasedformulatype import ValuationBasedFormulaType
3437
from pyocf.enums.valuationtype import ValuationType
3538
from pyocf.enums.vestingdayofmonth import VestingDayOfMonth
3639
from pyocf.enums.vestingtriggertype import VestingTriggerType
40+
from pyocf.files.documentsfile import DocumentsFile
41+
from pyocf.files.financingsfile import FinancingsFile
3742
from pyocf.files.ocfmanifestfile import OCFManifestFile
3843
from pyocf.files.stakeholdersfile import StakeholdersFile
3944
from pyocf.files.stockclassesfile import StockClassesFile
@@ -42,6 +47,8 @@
4247
from pyocf.files.transactionsfile import TransactionsFile
4348
from pyocf.files.valuationsfile import ValuationsFile
4449
from pyocf.files.vestingtermsfile import VestingTermsFile
50+
from pyocf.objects.document import Document
51+
from pyocf.objects.financing import Financing
4552
from pyocf.objects.issuer import Issuer
4653
from pyocf.objects.stakeholder import Stakeholder
4754
from pyocf.objects.stockclass import StockClass
@@ -58,6 +65,9 @@
5865
)
5966
from pyocf.objects.transactions.acceptance.stockacceptance import StockAcceptance
6067
from pyocf.objects.transactions.acceptance.warrantacceptance import WarrantAcceptance
68+
from pyocf.objects.transactions.adjustment.issuerauthorizedsharesadjustment import (
69+
IssuerAuthorizedSharesAdjustment,
70+
)
6171
from pyocf.objects.transactions.adjustment.stockclassauthorizedsharesadjustment import (
6272
StockClassAuthorizedSharesAdjustment,
6373
)
@@ -142,6 +152,7 @@
142152
from pyocf.primitives.objects.transactions.conversion.conversion import Conversion
143153
from pyocf.primitives.objects.transactions.exercise.exercise import Exercise
144154
from pyocf.primitives.objects.transactions.issuance.issuance import Issuance
155+
from pyocf.primitives.objects.transactions.issuertransaction import IssuerTransaction
145156
from pyocf.primitives.objects.transactions.reissuance.reissuance import Reissuance
146157
from pyocf.primitives.objects.transactions.release.release import Release
147158
from pyocf.primitives.objects.transactions.repurchase.repurchase import Repurchase
@@ -194,6 +205,12 @@
194205
from pyocf.types.conversion_mechanisms.safeconversionmechanism import (
195206
SAFEConversionMechanism,
196207
)
208+
from pyocf.types.conversion_mechanisms.sharepricebasedconversionmechanism import (
209+
SharePriceBasedConversionMechanism,
210+
)
211+
from pyocf.types.conversion_mechanisms.valuationbasedconversionmechanism import (
212+
ValuationBasedConversionMechanism,
213+
)
197214
from pyocf.types.conversion_rights.convertibleconversionright import (
198215
ConvertibleConversionRight,
199216
)
@@ -230,6 +247,7 @@
230247
from pyocf.types.monetary import Monetary
231248
from pyocf.types.name import Name
232249
from pyocf.types.numeric import Numeric
250+
from pyocf.types.objectreference import ObjectReference
233251
from pyocf.types.percentage import Percentage
234252
from pyocf.types.phone import Phone
235253
from pyocf.types.ratio import Ratio
@@ -238,6 +256,7 @@
238256
from pyocf.types.stockparent import StockParent
239257
from pyocf.types.taxid import TaxID
240258
from pyocf.types.terminationwindow import TerminationWindow
259+
from pyocf.types.vesting import Vesting
241260
from pyocf.types.vesting.vestingcondition import VestingCondition
242261
from pyocf.types.vesting.vestingconditionportion import VestingConditionPortion
243262
from pyocf.types.vesting.vestingeventtrigger import VestingEventTrigger
@@ -257,6 +276,7 @@
257276
Address,
258277
AddressType,
259278
AllocationType,
279+
AuthorizedShares,
260280
AutomaticConversionOnConditionTrigger,
261281
AutomaticConversionOnDateTrigger,
262282
Cancellation,
@@ -288,6 +308,8 @@
288308
CustomConversionMechanism,
289309
Date,
290310
DayCountType,
311+
Document,
312+
DocumentsFile,
291313
ElectiveConversionAtWillTrigger,
292314
ElectiveConversionInDateRangeTrigger,
293315
ElectiveConversionOnConditionTrigger,
@@ -304,18 +326,23 @@
304326
File,
305327
FileObject,
306328
FileType,
329+
Financing,
330+
FinancingsFile,
307331
FixedAmountConversionMechanism,
308332
InterestPayoutType,
309333
InterestRate,
310334
Issuance,
311335
Issuer,
336+
IssuerAuthorizedSharesAdjustment,
337+
IssuerTransaction,
312338
Md5,
313339
Monetary,
314340
Name,
315341
NoteConversionMechanism,
316342
Numeric,
317343
OCFManifestFile,
318344
Object,
345+
ObjectReference,
319346
ObjectType,
320347
OptionType,
321348
ParentSecurityType,
@@ -331,6 +358,7 @@
331358
PlanSecurityRelease,
332359
PlanSecurityRetraction,
333360
PlanSecurityTransfer,
361+
QuantitySourceType,
334362
Ratio,
335363
RatioConversionMechanism,
336364
Reissuance,
@@ -343,6 +371,7 @@
343371
SecurityExemption,
344372
SecurityTransaction,
345373
ShareNumberRange,
374+
SharePriceBasedConversionMechanism,
346375
Stakeholder,
347376
StakeholderRelationshipType,
348377
StakeholderType,
@@ -381,8 +410,11 @@
381410
Transfer,
382411
UnspecifiedConversionTrigger,
383412
Valuation,
413+
ValuationBasedConversionMechanism,
414+
ValuationBasedFormulaType,
384415
ValuationType,
385416
ValuationsFile,
417+
Vesting,
386418
VestingAcceleration,
387419
VestingCondition,
388420
VestingConditionPortion,

src/pyocf/captable.py

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import pathlib
99
import zipfile
1010

11+
from pyocf.files import documentsfile
12+
from pyocf.files import financingsfile
1113
from pyocf.files import ocfmanifestfile
1214
from pyocf.files import stakeholdersfile
1315
from pyocf.files import stockclassesfile
@@ -16,6 +18,8 @@
1618
from pyocf.files import transactionsfile
1719
from pyocf.files import valuationsfile
1820
from pyocf.files import vestingtermsfile
21+
from pyocf.objects.document import Document
22+
from pyocf.objects.financing import Financing
1923
from pyocf.objects.stakeholder import Stakeholder
2024
from pyocf.objects.stockclass import StockClass
2125
from pyocf.objects.stocklegendtemplate import StockLegendTemplate
@@ -26,25 +30,53 @@
2630
from pyocf.types import file
2731

2832
FILEMAP = [
29-
("stock_plans", stockplansfile.StockPlansFile),
30-
("stock_legend_templates", stocklegendtemplatesfile.StockLegendTemplatesFile),
33+
("documents", documentsfile.DocumentsFile),
34+
("financings", financingsfile.FinancingsFile),
35+
("stakeholders", stakeholdersfile.StakeholdersFile),
3136
("stock_classes", stockclassesfile.StockClassesFile),
32-
("vesting_terms", vestingtermsfile.VestingTermsFile),
33-
("valuations", valuationsfile.ValuationsFile),
37+
("stock_legend_templates", stocklegendtemplatesfile.StockLegendTemplatesFile),
38+
("stock_plans", stockplansfile.StockPlansFile),
3439
("transactions", transactionsfile.TransactionsFile),
35-
("stakeholders", stakeholdersfile.StakeholdersFile),
40+
("valuations", valuationsfile.ValuationsFile),
41+
("vesting_terms", vestingtermsfile.VestingTermsFile),
3642
]
3743

3844

3945
class Captable:
40-
manifest: ocfmanifestfile.OCFManifestFile = None
41-
stock_plans: list[StockPlan] = []
42-
stock_legend_templates: list[StockLegendTemplate] = []
43-
stock_classes: list[StockClass] = []
44-
vesting_terms: list[VestingTerms] = []
45-
valuations: list[Valuation] = []
46-
transactions: list[Transaction] = []
47-
stakeholders: list[Stakeholder] = []
46+
manifest: ocfmanifestfile.OCFManifestFile
47+
documents: list[Document]
48+
financings: list[Financing]
49+
stakeholders: list[Stakeholder]
50+
stock_classes: list[StockClass]
51+
stock_legend_templates: list[StockLegendTemplate]
52+
stock_plans: list[StockPlan]
53+
transactions: list[Transaction]
54+
valuations: list[Valuation]
55+
vesting_terms: list[VestingTerms]
56+
57+
def __init__(
58+
self,
59+
manifest: ocfmanifestfile.OCFManifestFile = None,
60+
documents: list[Document] = None,
61+
financings: list[Financing] = None,
62+
stakeholders: list[Stakeholder] = None,
63+
stock_classes: list[StockClass] = None,
64+
stock_legend_templates: list[StockLegendTemplate] = None,
65+
stock_plans: list[StockPlan] = None,
66+
transactions: list[Transaction] = None,
67+
valuations: list[Valuation] = None,
68+
vesting_terms: list[VestingTerms] = None,
69+
):
70+
self.manifest = manifest
71+
self.documents = documents or []
72+
self.financings = financings or []
73+
self.stakeholders = stakeholders or []
74+
self.stock_classes = stock_classes or []
75+
self.stock_legend_templates = stock_legend_templates or []
76+
self.stock_plans = stock_plans or []
77+
self.transactions = transactions or []
78+
self.valuations = valuations or []
79+
self.vesting_terms = vesting_terms or []
4880

4981
@classmethod
5082
def load(cls, location):
@@ -82,7 +114,10 @@ def file_factory(p):
82114
return open(pathlib.Path(basedir, p))
83115

84116
for filetype, filecls in FILEMAP:
85-
for fileob in getattr(captable.manifest, filetype + "_files"):
117+
fileobjs = getattr(captable.manifest, filetype + "_files")
118+
if fileobjs is None:
119+
continue
120+
for fileob in fileobjs:
86121
infile = file_factory(fileob.filepath)
87122
items = filecls(**json.load(infile)).items
88123
getattr(captable, filetype).extend(items)
@@ -92,7 +127,7 @@ def file_factory(p):
92127
def _save_ocf_files(self, manifest_path, issuer, file_factory, pretty):
93128
if issuer is None and self.manifest is None:
94129
raise ValueError(
95-
"You must specify an issuer, either by passing the value to the"
130+
"You must specify an issuer, either by passing the value to the "
96131
"save method, or by creating a Manifest."
97132
)
98133

@@ -104,6 +139,8 @@ def _save_ocf_files(self, manifest_path, issuer, file_factory, pretty):
104139
if self.manifest:
105140
# Check if there is a different filename in the manifest:
106141
ocffilename = getattr(self.manifest, filetype + "_files", [])
142+
if ocffilename is None:
143+
continue
107144
if len(ocffilename) >= 1:
108145
ocffilename = ocffilename[0].filepath
109146

@@ -112,7 +149,7 @@ def _save_ocf_files(self, manifest_path, issuer, file_factory, pretty):
112149

113150
with file_factory(ocffilename) as ocffile:
114151
itemfile = fileob(items=getattr(self, filetype))
115-
jsonstr = itemfile.json(exclude_unset=True)
152+
jsonstr = itemfile.model_dump_json()
116153
if pretty:
117154
jsonstr = json.dumps(json.loads(jsonstr), indent=4)
118155
jsonstr = jsonstr.encode("UTF-8")
@@ -143,7 +180,7 @@ def _save_ocf_files(self, manifest_path, issuer, file_factory, pretty):
143180
self.manifest = ocfmanifestfile.OCFManifestFile(**manifest_data)
144181

145182
with file_factory(manifest_path) as ocffile:
146-
jsonstr = self.manifest.json()
183+
jsonstr = self.manifest.model_dump_json()
147184
if pretty:
148185
jsonstr = json.dumps(json.loads(jsonstr), indent=4)
149186
ocffile.write(jsonstr.encode("UTF-8"))

0 commit comments

Comments
 (0)