focus-data-toolkit 0.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. focus_data_toolkit/__init__.py +69 -0
  2. focus_data_toolkit/__main__.py +6 -0
  3. focus_data_toolkit/_version.py +8 -0
  4. focus_data_toolkit/cli.py +968 -0
  5. focus_data_toolkit/context/__init__.py +88 -0
  6. focus_data_toolkit/context/billing.py +54 -0
  7. focus_data_toolkit/context/provider.py +90 -0
  8. focus_data_toolkit/convert/__init__.py +708 -0
  9. focus_data_toolkit/convert/billing_period.py +65 -0
  10. focus_data_toolkit/convert/contract_applied.py +235 -0
  11. focus_data_toolkit/convert/contract_commitment.py +182 -0
  12. focus_data_toolkit/convert/cost_and_usage.py +179 -0
  13. focus_data_toolkit/convert/detect.py +39 -0
  14. focus_data_toolkit/convert/invoice_detail.py +199 -0
  15. focus_data_toolkit/convert/streaming.py +1030 -0
  16. focus_data_toolkit/errors.py +145 -0
  17. focus_data_toolkit/focus_json.py +68 -0
  18. focus_data_toolkit/generators/__init__.py +61 -0
  19. focus_data_toolkit/generators/_shim.py +43 -0
  20. focus_data_toolkit/generators/engine/__init__.py +14 -0
  21. focus_data_toolkit/generators/engine/context.py +12 -0
  22. focus_data_toolkit/generators/engine/determinism.py +117 -0
  23. focus_data_toolkit/generators/engine/json_focus.py +63 -0
  24. focus_data_toolkit/generators/engine/ladder.py +71 -0
  25. focus_data_toolkit/generators/engine/scenarios_core.py +380 -0
  26. focus_data_toolkit/generators/engine/serialize.py +151 -0
  27. focus_data_toolkit/generators/generate_aws_focus_1_2.py +19 -0
  28. focus_data_toolkit/generators/generate_aws_focus_1_3.py +20 -0
  29. focus_data_toolkit/generators/generate_azure_focus_1_2.py +17 -0
  30. focus_data_toolkit/generators/generate_azure_focus_1_3.py +17 -0
  31. focus_data_toolkit/generators/generate_gcp_focus_1_2.py +17 -0
  32. focus_data_toolkit/generators/generate_gcp_focus_1_3.py +17 -0
  33. focus_data_toolkit/generators/providers/__init__.py +29 -0
  34. focus_data_toolkit/generators/providers/aws.py +186 -0
  35. focus_data_toolkit/generators/providers/azure.py +191 -0
  36. focus_data_toolkit/generators/providers/gcp.py +194 -0
  37. focus_data_toolkit/generators/providers/profile.py +123 -0
  38. focus_data_toolkit/generators/scenarios.py +178 -0
  39. focus_data_toolkit/generators/versions/__init__.py +17 -0
  40. focus_data_toolkit/generators/versions/adapter.py +41 -0
  41. focus_data_toolkit/generators/versions/v1_2.py +111 -0
  42. focus_data_toolkit/generators/versions/v1_3.py +154 -0
  43. focus_data_toolkit/io/__init__.py +1 -0
  44. focus_data_toolkit/io/atomic_writer.py +462 -0
  45. focus_data_toolkit/io/csv_io.py +128 -0
  46. focus_data_toolkit/io/parquet_io.py +528 -0
  47. focus_data_toolkit/io/records.py +92 -0
  48. focus_data_toolkit/io/row_source.py +117 -0
  49. focus_data_toolkit/lifecycle.py +342 -0
  50. focus_data_toolkit/manifest.py +114 -0
  51. focus_data_toolkit/model/__init__.py +43 -0
  52. focus_data_toolkit/model/capabilities.py +66 -0
  53. focus_data_toolkit/model/focus_1_4_decimal_scale.json +10 -0
  54. focus_data_toolkit/model/focus_1_4_model.json +1913 -0
  55. focus_data_toolkit/model/focus_1_4_servicesubcategory.json +84 -0
  56. focus_data_toolkit/model/focus_json_keys.py +112 -0
  57. focus_data_toolkit/model/iso_4217_currencies.json +23 -0
  58. focus_data_toolkit/model/json_schema_check.py +205 -0
  59. focus_data_toolkit/model/json_schemas/allocatedmethoddetailsobjectschema.json +82 -0
  60. focus_data_toolkit/model/json_schemas/commitmentprogrameligibilitydetailsobjectschema.json +41 -0
  61. focus_data_toolkit/model/json_schemas/contractappliedobjectschema.json +104 -0
  62. focus_data_toolkit/model/json_schemas/contractcommitmentapplicabilityobjectschema.json +290 -0
  63. focus_data_toolkit/model/json_schemas/json_schemas_provenance.json +38 -0
  64. focus_data_toolkit/model/model_provenance.json +58 -0
  65. focus_data_toolkit/model/validator.py +498 -0
  66. focus_data_toolkit/modes.py +18 -0
  67. focus_data_toolkit/official_validator.py +61 -0
  68. focus_data_toolkit/progress.py +89 -0
  69. focus_data_toolkit/provenance.py +106 -0
  70. focus_data_toolkit/py.typed +1 -0
  71. focus_data_toolkit/runtime.py +243 -0
  72. focus_data_toolkit/schema/__init__.py +17 -0
  73. focus_data_toolkit/schema/detection.py +274 -0
  74. focus_data_toolkit/schema/registry.py +127 -0
  75. focus_data_toolkit/storage/__init__.py +1 -0
  76. focus_data_toolkit/storage/external_index.py +99 -0
  77. focus_data_toolkit/storage/spill.py +150 -0
  78. focus_data_toolkit/studio/__init__.py +19 -0
  79. focus_data_toolkit/studio/app.py +467 -0
  80. focus_data_toolkit/studio/config.py +42 -0
  81. focus_data_toolkit/studio/frontend/app.js +214 -0
  82. focus_data_toolkit/studio/frontend/index.html +101 -0
  83. focus_data_toolkit/studio/frontend/style.css +60 -0
  84. focus_data_toolkit/studio/jobs.py +142 -0
  85. focus_data_toolkit/studio/preview.py +32 -0
  86. focus_data_toolkit/studio/security.py +125 -0
  87. focus_data_toolkit/studio/server.py +71 -0
  88. focus_data_toolkit/supplement/__init__.py +50 -0
  89. focus_data_toolkit/supplement/adapters/__init__.py +21 -0
  90. focus_data_toolkit/supplement/adapters/adapters_provenance.json +39 -0
  91. focus_data_toolkit/supplement/adapters/aws_invoice_summary.json +24 -0
  92. focus_data_toolkit/supplement/adapters/aws_savings_plans.json +31 -0
  93. focus_data_toolkit/supplement/adapters/azure_invoice.json +25 -0
  94. focus_data_toolkit/supplement/adapters/gcp_compute_commitments.json +28 -0
  95. focus_data_toolkit/supplement/adapters/registry.py +215 -0
  96. focus_data_toolkit/supplement/apply.py +318 -0
  97. focus_data_toolkit/supplement/gaps.py +219 -0
  98. focus_data_toolkit/supplement/kinds.py +118 -0
  99. focus_data_toolkit/supplement/loader.py +409 -0
  100. focus_data_toolkit/supplement/spec.py +74 -0
  101. focus_data_toolkit/supplement/validate.py +215 -0
  102. focus_data_toolkit/validate/__init__.py +15 -0
  103. focus_data_toolkit/validate/allocation.py +333 -0
  104. focus_data_toolkit/validate/bundle.py +254 -0
  105. focus_data_toolkit/validate/codes.py +93 -0
  106. focus_data_toolkit/validate/corrections.py +245 -0
  107. focus_data_toolkit/validate/reconciliation.py +98 -0
  108. focus_data_toolkit/validate/referential.py +289 -0
  109. focus_data_toolkit-0.11.0.dist-info/METADATA +519 -0
  110. focus_data_toolkit-0.11.0.dist-info/RECORD +116 -0
  111. focus_data_toolkit-0.11.0.dist-info/WHEEL +5 -0
  112. focus_data_toolkit-0.11.0.dist-info/entry_points.txt +2 -0
  113. focus_data_toolkit-0.11.0.dist-info/licenses/LICENSE +21 -0
  114. focus_data_toolkit-0.11.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +156 -0
  115. focus_data_toolkit-0.11.0.dist-info/licenses/NOTICE +60 -0
  116. focus_data_toolkit-0.11.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,290 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://focus.finops.org/schemas/contractcommitmentapplicabilityobject.json",
4
+ "title": "Contract Commitment Applicability Object",
5
+ "description": "Schema for validating the Contract Commitment Applicability column JSON object structure in FOCUS datasets",
6
+ "type": "object",
7
+ "$defs": {
8
+ "ApplicabilityObject": {
9
+ "type": "object",
10
+ "properties": {
11
+ "Cost": {
12
+ "type": "number",
13
+ "description": "Percentage applicable to ContractCommitmentCost",
14
+ "minimum": 0.0,
15
+ "maximum": 1.0,
16
+ "default": 1.0
17
+ },
18
+ "Usage": {
19
+ "type": "number",
20
+ "description": "Percentage applicable to ContractCommitmentQuantity",
21
+ "minimum": 0.0,
22
+ "maximum": 1.0,
23
+ "default": 1.0
24
+ }
25
+ },
26
+ "additionalProperties": false
27
+ },
28
+ "ApplicabilityRule": {
29
+ "type": "object",
30
+ "required": [
31
+ "Dimension",
32
+ "Operator",
33
+ "Values"
34
+ ],
35
+ "properties": {
36
+ "Dimension": {
37
+ "type": "string",
38
+ "description": "A valid FOCUS Column Name"
39
+ },
40
+ "Operator": {
41
+ "type": "string",
42
+ "description": "The comparison logic to apply",
43
+ "enum": [
44
+ "In",
45
+ "NotIn",
46
+ "StartsWith",
47
+ "NotStartsWith",
48
+ "Contains",
49
+ "NotContains",
50
+ "EndsWith",
51
+ "Exists",
52
+ "DoesNotExist"
53
+ ]
54
+ },
55
+ "Values": {
56
+ "type": "array",
57
+ "description": "List of strings to compare",
58
+ "items": {
59
+ "type": "string"
60
+ },
61
+ "minItems": 1
62
+ },
63
+ "Applicability": {
64
+ "$ref": "#/$defs/ApplicabilityObject",
65
+ "description": "Optional rule-level applicability that overrides top-level"
66
+ }
67
+ },
68
+ "allOf": [
69
+ {
70
+ "description": "Wildcard constraint: If '*' is used, it must be the only value and Operator must be compatible.",
71
+ "if": {
72
+ "properties": {
73
+ "Values": {
74
+ "contains": {
75
+ "const": "*"
76
+ }
77
+ }
78
+ }
79
+ },
80
+ "then": {
81
+ "properties": {
82
+ "Values": {
83
+ "maxItems": 1
84
+ },
85
+ "Operator": {
86
+ "enum": [
87
+ "In",
88
+ "Contains",
89
+ "Exists",
90
+ "DoesNotExist"
91
+ ]
92
+ }
93
+ }
94
+ }
95
+ },
96
+ {
97
+ "description": "Existence Logic: Exists/DoesNotExist operators require the specific wildcard value.",
98
+ "if": {
99
+ "properties": {
100
+ "Operator": {
101
+ "enum": [
102
+ "Exists",
103
+ "DoesNotExist"
104
+ ]
105
+ }
106
+ }
107
+ },
108
+ "then": {
109
+ "properties": {
110
+ "Values": {
111
+ "items": {
112
+ "const": "*"
113
+ },
114
+ "maxItems": 1
115
+ }
116
+ }
117
+ }
118
+ }
119
+ ],
120
+ "additionalProperties": false
121
+ }
122
+ },
123
+ "properties": {
124
+ "IsGlobalScope": {
125
+ "type": "boolean",
126
+ "description": "If true, commitment applies to all entities",
127
+ "default": false
128
+ },
129
+ "IsComplexScope": {
130
+ "type": "boolean",
131
+ "description": "If true, applicability logic exceeds schema capabilities",
132
+ "default": false
133
+ },
134
+ "Applicability": {
135
+ "$ref": "#/$defs/ApplicabilityObject",
136
+ "description": "Top-level fractional mapping for metrics"
137
+ },
138
+ "InclusionOperator": {
139
+ "type": "string",
140
+ "description": "Logical operator for Inclusions array",
141
+ "enum": [
142
+ "And",
143
+ "Or"
144
+ ]
145
+ },
146
+ "Inclusions": {
147
+ "type": "array",
148
+ "description": "List of rules defining the applicability boundary",
149
+ "items": {
150
+ "$ref": "#/$defs/ApplicabilityRule"
151
+ }
152
+ },
153
+ "ExclusionOperator": {
154
+ "type": "string",
155
+ "description": "Logical operator for Exclusions array",
156
+ "enum": [
157
+ "And",
158
+ "Or"
159
+ ]
160
+ },
161
+ "Exclusions": {
162
+ "type": "array",
163
+ "description": "List of rules defining entities to exclude",
164
+ "items": {
165
+ "$ref": "#/$defs/ApplicabilityRule"
166
+ },
167
+ "minItems": 1
168
+ }
169
+ },
170
+ "allOf": [
171
+ {
172
+ "description": "IsGlobalScope and IsComplexScope cannot both be true simultaneously.",
173
+ "not": {
174
+ "required": [
175
+ "IsGlobalScope",
176
+ "IsComplexScope"
177
+ ],
178
+ "properties": {
179
+ "IsGlobalScope": {
180
+ "const": true
181
+ },
182
+ "IsComplexScope": {
183
+ "const": true
184
+ }
185
+ }
186
+ }
187
+ },
188
+ {
189
+ "description": "If IsGlobalScope is true, Inclusions must be empty or omitted.",
190
+ "if": {
191
+ "properties": {
192
+ "IsGlobalScope": {
193
+ "const": true
194
+ }
195
+ },
196
+ "required": [
197
+ "IsGlobalScope"
198
+ ]
199
+ },
200
+ "then": {
201
+ "properties": {
202
+ "Inclusions": {
203
+ "maxItems": 0
204
+ },
205
+ "InclusionOperator": false
206
+ }
207
+ }
208
+ },
209
+ {
210
+ "description": "If IsComplexScope is true, Inclusions must be empty or omitted.",
211
+ "if": {
212
+ "properties": {
213
+ "IsComplexScope": {
214
+ "const": true
215
+ }
216
+ },
217
+ "required": [
218
+ "IsComplexScope"
219
+ ]
220
+ },
221
+ "then": {
222
+ "properties": {
223
+ "Inclusions": {
224
+ "maxItems": 0
225
+ },
226
+ "InclusionOperator": false
227
+ }
228
+ }
229
+ },
230
+ {
231
+ "description": "If neither Global nor Complex scope is active, Inclusions and InclusionOperator are required.",
232
+ "if": {
233
+ "not": {
234
+ "anyOf": [
235
+ {
236
+ "properties": {
237
+ "IsGlobalScope": {
238
+ "const": true
239
+ }
240
+ },
241
+ "required": [
242
+ "IsGlobalScope"
243
+ ]
244
+ },
245
+ {
246
+ "properties": {
247
+ "IsComplexScope": {
248
+ "const": true
249
+ }
250
+ },
251
+ "required": [
252
+ "IsComplexScope"
253
+ ]
254
+ }
255
+ ]
256
+ }
257
+ },
258
+ "then": {
259
+ "required": [
260
+ "InclusionOperator",
261
+ "Inclusions"
262
+ ],
263
+ "properties": {
264
+ "Inclusions": {
265
+ "minItems": 1
266
+ }
267
+ }
268
+ }
269
+ },
270
+ {
271
+ "description": "If Exclusions are present, ExclusionOperator is required.",
272
+ "if": {
273
+ "required": [
274
+ "Exclusions"
275
+ ]
276
+ },
277
+ "then": {
278
+ "required": [
279
+ "ExclusionOperator"
280
+ ]
281
+ }
282
+ }
283
+ ],
284
+ "patternProperties": {
285
+ "^x_[A-Z][a-zA-Z0-9]*$": {
286
+ "description": "Custom data generator-defined properties prefixed with x_ in PascalCase format"
287
+ }
288
+ },
289
+ "additionalProperties": false
290
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "description": "Provenance of the vendored official FOCUS JSON object schemas.",
3
+ "source_repository": "https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec",
4
+ "source_ref": "v1.4",
5
+ "license": "CC-BY-4.0",
6
+ "attribution": "FinOps Open Cost and Usage Specification (FOCUS), (c) FinOps Foundation. Schemas vendored verbatim from the specification repository.",
7
+ "retrieved": "2026-07-17",
8
+ "files": [
9
+ {
10
+ "file": "contractappliedobjectschema.json",
11
+ "source_path": "specification/schemas/datasets/cost_and_usage/contractappliedobjectschema.json",
12
+ "column": "ContractApplied",
13
+ "sha256": "26ad380f89c12b414f36822fb4f12786e4eacfb0d00ac4781a84752483a5d73e",
14
+ "bytes": 4352
15
+ },
16
+ {
17
+ "file": "allocatedmethoddetailsobjectschema.json",
18
+ "source_path": "specification/schemas/datasets/cost_and_usage/allocatedmethoddetailsobjectschema.json",
19
+ "column": "AllocatedMethodDetails",
20
+ "sha256": "0f552469954433c04a51ad18561e4b85e13787570cda4a4cc5a733a39214d8fd",
21
+ "bytes": 3250
22
+ },
23
+ {
24
+ "file": "commitmentprogrameligibilitydetailsobjectschema.json",
25
+ "source_path": "specification/schemas/datasets/cost_and_usage/commitmentprogrameligibilitydetailsobjectschema.json",
26
+ "column": "CommitmentProgramEligibilityDetails",
27
+ "sha256": "0cc2fc4bfc3a720754591c017a5899d214f78d630167a16e99c2875cb91de576",
28
+ "bytes": 1647
29
+ },
30
+ {
31
+ "file": "contractcommitmentapplicabilityobjectschema.json",
32
+ "source_path": "specification/schemas/datasets/contract_commitment/contractcommitmentapplicabilityobjectschema.json",
33
+ "column": "ContractCommitmentApplicability",
34
+ "sha256": "6c396aa5ac0ccfed1bfb1c464d6698684520554aca50dca3258307ff779a565b",
35
+ "bytes": 7143
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/guymano/focus-data-toolkit/main/schema/model_provenance.schema.json",
3
+ "schema_version": "1.0",
4
+ "focus_version": "1.4",
5
+ "provenance_status": "complete",
6
+ "description": "Provenance for the committed FOCUS 1.4 machine-readable model (focus_1_4_model.json). The JSON is a deterministic extraction of the FinOps Foundation FOCUS 1.4 Data Model and is the artifact of record for this package.",
7
+ "source": {
8
+ "name": "FinOps FOCUS 1.4 Data Model workbook",
9
+ "publisher": "FinOps Foundation",
10
+ "homepage": "https://focus.finops.org",
11
+ "repository": "https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec",
12
+ "license": "CC-BY-4.0",
13
+ "license_verified": true,
14
+ "license_reference": "https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/blob/main/license.md",
15
+ "artifact": "FOCUS 1.4 Data Model workbook (spreadsheet), downloaded from https://focus.finops.org; not redistributed in this repository",
16
+ "artifact_sha256": "39b3e3347e902a484cad180ead6fcb5a96b70cc76391c9af1916911a25a68005",
17
+ "artifact_retrieved": "2026-07-18"
18
+ },
19
+ "supplements": [
20
+ {
21
+ "path": "src/focus_data_toolkit/model/focus_1_4_servicesubcategory.json",
22
+ "sha256": "8532467093bedd1e228a82f07c782d8b29286de75d0a79bccbf896debd867f64",
23
+ "description": "ServiceSubcategory -> parent Category map, transcribed from the FOCUS v1.4 specification; an input to the extractor."
24
+ }
25
+ ],
26
+ "generator": {
27
+ "script": "tools/extract_focus_1_4_model.py",
28
+ "script_sha256": "4fc4c8d6f30f3b3045c7f6afcc46b81ebbb44d800e63993246878374d4ee9403",
29
+ "command": "python tools/extract_focus_1_4_model.py <focus_1_4_data_model.xlsx>",
30
+ "runtime": "Dev-time only; requires openpyxl. Neither the runtime package nor the test suite imports openpyxl — the committed JSON is the artifact of record.",
31
+ "serialization": "json.dumps(model, indent=2, sort_keys=True) + trailing newline; UTF-8. Deterministic: identical (workbook, supplement, generator) reproduce identical output bytes."
32
+ },
33
+ "output": {
34
+ "path": "src/focus_data_toolkit/model/focus_1_4_model.json",
35
+ "sha256": "8b006e1a36bc9678fef6b79c847654f914ea7abe25c827478aa44ee1d15b214b",
36
+ "bytes": 64971,
37
+ "focus_version": "1.4",
38
+ "datasets": {
39
+ "Cost and Usage": 65,
40
+ "Billing Period": 6,
41
+ "Contract Commitment": 30,
42
+ "Invoice Detail": 22
43
+ }
44
+ },
45
+ "reproducibility": {
46
+ "byte_for_byte": "The committed output is byte-reproducible by re-running the pinned generator on the same source workbook: the serialization is deterministic (sorted keys, fixed indent, UTF-8, trailing newline).",
47
+ "verifiable_in_ci": [
48
+ "output.sha256 matches the committed focus_1_4_model.json",
49
+ "generator.script_sha256 matches the committed extractor",
50
+ "supplements[].sha256 match the committed supplement files"
51
+ ],
52
+ "limitation": "None for the model chain: the source workbook is hashed (source.artifact_sha256) and the committed output was reproduced byte-for-byte from it by the pinned extractor at completion time. The workbook itself is still not redistributed; obtain it from the FinOps Foundation and verify it against source.artifact_sha256."
53
+ },
54
+ "attribution": "FOCUS(TM) is a trademark of the FinOps Foundation. The FOCUS specification and data model are (c) the FinOps Foundation and are licensed CC-BY-4.0. The committed model JSON and this provenance file are a derivative work distributed under CC-BY-4.0 with attribution. This project is an independent community toolkit and is not endorsed by the FinOps Foundation.",
55
+ "notes": [
56
+ "provenance_status was set to 'complete' by scripts/verify_model_provenance.py --complete: the source workbook was hashed and the committed model was reproduced byte-for-byte from it with the pinned extractor."
57
+ ]
58
+ }