anxwritter 1.0.0__tar.gz

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 (75) hide show
  1. anxwritter-1.0.0/.gitignore +42 -0
  2. anxwritter-1.0.0/LICENSE +21 -0
  3. anxwritter-1.0.0/NOTICE.md +37 -0
  4. anxwritter-1.0.0/PKG-INFO +163 -0
  5. anxwritter-1.0.0/README.md +129 -0
  6. anxwritter-1.0.0/anxwritter/__init__.py +93 -0
  7. anxwritter-1.0.0/anxwritter/_i2_interop.py +102 -0
  8. anxwritter-1.0.0/anxwritter/builder.py +2573 -0
  9. anxwritter-1.0.0/anxwritter/chart.py +1810 -0
  10. anxwritter-1.0.0/anxwritter/cli.py +357 -0
  11. anxwritter-1.0.0/anxwritter/colors.py +118 -0
  12. anxwritter-1.0.0/anxwritter/entities.py +318 -0
  13. anxwritter-1.0.0/anxwritter/enums.py +212 -0
  14. anxwritter-1.0.0/anxwritter/errors.py +91 -0
  15. anxwritter-1.0.0/anxwritter/models.py +731 -0
  16. anxwritter-1.0.0/anxwritter/resolved.py +135 -0
  17. anxwritter-1.0.0/anxwritter/semantic.py +216 -0
  18. anxwritter-1.0.0/anxwritter/timezones.json +124 -0
  19. anxwritter-1.0.0/anxwritter/timing.py +53 -0
  20. anxwritter-1.0.0/anxwritter/transforms.py +447 -0
  21. anxwritter-1.0.0/anxwritter/utils.py +125 -0
  22. anxwritter-1.0.0/anxwritter/validation.py +1248 -0
  23. anxwritter-1.0.0/docs/getting-started.md +83 -0
  24. anxwritter-1.0.0/docs/guide/analyst-guide.md +1151 -0
  25. anxwritter-1.0.0/docs/guide/yaml-json-guide.md +1111 -0
  26. anxwritter-1.0.0/docs/reference/attributes.md +219 -0
  27. anxwritter-1.0.0/docs/reference/cards-and-grades.md +203 -0
  28. anxwritter-1.0.0/docs/reference/cli.md +142 -0
  29. anxwritter-1.0.0/docs/reference/constructors.md +260 -0
  30. anxwritter-1.0.0/docs/reference/datetime-and-timezones.md +355 -0
  31. anxwritter-1.0.0/docs/reference/entities.md +196 -0
  32. anxwritter-1.0.0/docs/reference/links.md +196 -0
  33. anxwritter-1.0.0/docs/reference/semantic-types.md +224 -0
  34. anxwritter-1.0.0/docs/reference/settings.md +302 -0
  35. anxwritter-1.0.0/docs/reference/validation.md +98 -0
  36. anxwritter-1.0.0/docs/reference/visual-styling.md +373 -0
  37. anxwritter-1.0.0/examples/config.json +149 -0
  38. anxwritter-1.0.0/examples/config.yaml +296 -0
  39. anxwritter-1.0.0/examples/data.json +144 -0
  40. anxwritter-1.0.0/examples/data.yaml +131 -0
  41. anxwritter-1.0.0/examples/investigation_chart.py +236 -0
  42. anxwritter-1.0.0/pyproject.toml +108 -0
  43. anxwritter-1.0.0/tests/__init__.py +0 -0
  44. anxwritter-1.0.0/tests/fixtures/__init__.py +0 -0
  45. anxwritter-1.0.0/tests/fixtures/equivalence_specs.py +559 -0
  46. anxwritter-1.0.0/tests/fixtures/invalid_specs.py +233 -0
  47. anxwritter-1.0.0/tests/fixtures/strategies.py +223 -0
  48. anxwritter-1.0.0/tests/helpers/__init__.py +0 -0
  49. anxwritter-1.0.0/tests/helpers/chart_equivalence.py +232 -0
  50. anxwritter-1.0.0/tests/test_attribute_class_type.py +267 -0
  51. anxwritter-1.0.0/tests/test_audit_gaps.py +819 -0
  52. anxwritter-1.0.0/tests/test_chart_build.py +1241 -0
  53. anxwritter-1.0.0/tests/test_cli.py +255 -0
  54. anxwritter-1.0.0/tests/test_colors.py +95 -0
  55. anxwritter-1.0.0/tests/test_config.py +555 -0
  56. anxwritter-1.0.0/tests/test_config_roundtrip.py +277 -0
  57. anxwritter-1.0.0/tests/test_constructors.py +1121 -0
  58. anxwritter-1.0.0/tests/test_dataclass_fields.py +418 -0
  59. anxwritter-1.0.0/tests/test_datetime_format.py +256 -0
  60. anxwritter-1.0.0/tests/test_determinism.py +128 -0
  61. anxwritter-1.0.0/tests/test_entities.py +259 -0
  62. anxwritter-1.0.0/tests/test_enum_aliases.py +222 -0
  63. anxwritter-1.0.0/tests/test_enums.py +51 -0
  64. anxwritter-1.0.0/tests/test_error_completeness.py +151 -0
  65. anxwritter-1.0.0/tests/test_examples_smoke.py +60 -0
  66. anxwritter-1.0.0/tests/test_geo_map.py +512 -0
  67. anxwritter-1.0.0/tests/test_input_equivalence.py +564 -0
  68. anxwritter-1.0.0/tests/test_perf_scale.py +115 -0
  69. anxwritter-1.0.0/tests/test_properties.py +112 -0
  70. anxwritter-1.0.0/tests/test_settings.py +60 -0
  71. anxwritter-1.0.0/tests/test_utils.py +149 -0
  72. anxwritter-1.0.0/tests/test_validation.py +388 -0
  73. anxwritter-1.0.0/tests/test_validation_equivalence.py +138 -0
  74. anxwritter-1.0.0/tests/test_yaml_user_input.py +561 -0
  75. anxwritter-1.0.0/uv.lock +286 -0
@@ -0,0 +1,42 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ .hypothesis/
12
+
13
+ # Build artifacts
14
+ /dist/
15
+ /build/
16
+ /.build/
17
+
18
+ # Environments
19
+ .venv/
20
+ .venv-*/
21
+
22
+ # IDE / editor
23
+ .idea/
24
+ .vscode/
25
+ .claude/
26
+ .run/
27
+ *.swp
28
+ *.swo
29
+ *~
30
+
31
+ # OS
32
+ .DS_Store
33
+ Thumbs.db
34
+
35
+ # Sandbox
36
+ .sbx/
37
+
38
+ # Scratch / output
39
+ /output/
40
+ *.log
41
+ *.orig
42
+ *.rej
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 gustavo-gkmi (https://github.com/gustavo-gkmi)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,37 @@
1
+ # NOTICE
2
+
3
+ anxwritter is an independent, MIT-licensed Python library for writing
4
+ i2 Analyst's Notebook Exchange (`.anx`) files. It is not affiliated
5
+ with, endorsed by, or sponsored by the makers of i2 Analyst's Notebook
6
+ (past or present: IBM, i2 Group Limited, i2 Limited, N.Harris Computer
7
+ Corporation, Harris Computer Corporation, Constellation Software Inc.)
8
+ or by Esri, Microsoft, or Google.
9
+
10
+ ## Format identifiers reproduced for interoperability
11
+
12
+ To produce structurally valid `.anx` files, this library embeds nine
13
+ functional identifiers required by ANB:
14
+
15
+ - 6 abstract-root GUIDs required by the `lcx:LibraryCatalogue` schema
16
+ - 3 geo-map property GUIDs (Latitude, Longitude, Grid Reference)
17
+ required by ANB's Esri Maps subsystem
18
+ - the LCX XML namespace string `http://www.i2group.com/Schemas/2001-12-07/LCXSchema`
19
+
20
+ These are functional format anchors, not creative content, reproduced
21
+ solely for interoperability.
22
+
23
+ ## What is *not* included
24
+
25
+ anxwritter ships **none** of the following from i2/N.Harris/IBM ANB:
26
+ XML schemas (XSDs/XSLs), icon catalogues or image files,
27
+ standard-library semantic-type definitions, palette definitions,
28
+ compiled binaries, DLLs, `.ant` files, help text, or error messages.
29
+
30
+ All such content must be supplied by the user via their own `entity_types`,
31
+ `link_types`, `attribute_classes`, and `semantic_*` declarations.
32
+
33
+ ## Trademarks
34
+
35
+ "i2", "i2 Analyst's Notebook", "ANB", "Esri", "Esri Maps",
36
+ "Microsoft", and "Google" are trademarks of their respective owners.
37
+ Referenced for nominative use only.
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.4
2
+ Name: anxwritter
3
+ Version: 1.0.0
4
+ Summary: Write i2 Analyst's Notebook Exchange (.anx) files from Python, JSON, or YAML
5
+ Project-URL: Repository, https://github.com/gustavo-gkmi/anxwritter
6
+ Project-URL: Issues, https://github.com/gustavo-gkmi/anxwritter/issues
7
+ Author: gustavo-gkmi
8
+ License: MIT
9
+ License-File: LICENSE
10
+ License-File: NOTICE.md
11
+ Keywords: analyst-notebook,anb,anx,chart,i2,intelligence,law-enforcement,link-analysis,xml
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Other Audience
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: loguru>=0.7
27
+ Provides-Extra: dev
28
+ Requires-Dist: hypothesis>=6.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Requires-Dist: pyyaml>=6.0; extra == 'dev'
31
+ Provides-Extra: yaml
32
+ Requires-Dist: pyyaml>=6.0; extra == 'yaml'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # anxwritter
36
+
37
+ Write i2 Analyst's Notebook Exchange (`.anx`) files from Python, JSON, or YAML.
38
+
39
+ Output files open directly in i2 ANB 9+ via **File > Open** — no import wizard, no intermediate CSV. The `.anx` file embeds the entire chart as XML.
40
+
41
+ > This project is independent and not affiliated with, endorsed by, or sponsored by the makers of i2 Analyst's Notebook — past or present — including IBM, i2 Group Limited, i2 Limited, N.Harris Computer Corporation, Harris Computer Corporation, or Constellation Software Inc. — nor by Esri, Microsoft, or Google. "i2", "i2 Analyst's Notebook", "ANB", "Esri", "Esri Maps", "Microsoft", and "Google" are trademarks of their respective owners and are referenced here solely to identify the file format and the tools this library interoperates with (nominative use).
42
+ >
43
+ > To produce structurally valid `.anx` files, this library embeds nine format identifiers: six abstract-root GUIDs required by the `lcx:LibraryCatalogue` schema and three geo-map property GUIDs required by ANB's Esri Maps subsystem. These are functional tokens (format anchors), not creative content, reproduced for interoperability purposes. The library ships nothing else from i2's type system — no standard-library types, no icon catalog, no palette definitions. All of that content stays in the user's licensed ANB installation and must be supplied by the user.
44
+ >
45
+ > This design is intentional: organisations are free to define their own default semantic types, palettes, icon mappings, link types, and attribute classes.
46
+
47
+ ---
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ # As a library — import in your own code
53
+ pip install anxwritter
54
+
55
+ # With YAML support (optional)
56
+ pip install anxwritter[yaml]
57
+
58
+ # As a command-line tool only (isolated venv, no env conflicts)
59
+ pipx install anxwritter
60
+ ```
61
+
62
+ With [uv](https://docs.astral.sh/uv/):
63
+
64
+ ```bash
65
+ # Add to a uv-managed project
66
+ uv add anxwritter
67
+ uv add 'anxwritter[yaml]' # with YAML support
68
+
69
+ # Install globally as a CLI tool
70
+ uv tool install anxwritter
71
+
72
+ # One-off run without installing
73
+ uvx anxwritter chart.yaml -o my_chart.anx
74
+ ```
75
+
76
+ Requires Python 3.10+.
77
+
78
+ > Want a standalone executable? `pip install pyinstaller` (or `nuitka`) and
79
+ > point it at `anxwritter/cli.py`. anxwritter does not ship pre-built binaries.
80
+
81
+ ---
82
+
83
+ ## Quick example
84
+
85
+ ```python
86
+ from anxwritter import ANXChart
87
+
88
+ chart = ANXChart()
89
+
90
+ chart.add_icon(id='Alice', type='Person', color='Blue')
91
+ chart.add_icon(id='Bob', type='Person', color='Red')
92
+
93
+ chart.add_link(
94
+ from_id='Alice', to_id='Bob',
95
+ type='Telephone Call', arrow='->',
96
+ date='2024-01-15',
97
+ )
98
+
99
+ chart.to_anx('output/my_chart')
100
+ ```
101
+
102
+ This writes `output/my_chart.anx`. Open it in ANB.
103
+
104
+ ### YAML + CLI
105
+
106
+ ```yaml
107
+ # chart.yaml
108
+ entities:
109
+ icons:
110
+ - { id: Alice, type: Person, color: Blue }
111
+ - { id: Bob, type: Person, color: Red }
112
+ links:
113
+ - { from_id: Alice, to_id: Bob, type: Telephone Call, arrow: '->', date: '2024-01-15' }
114
+ ```
115
+
116
+ ```bash
117
+ anxwritter chart.yaml -o output/my_chart.anx
118
+ ```
119
+
120
+ ---
121
+
122
+ ## What's in the box
123
+
124
+ - **Typed dataclass API** — `Icon`, `Box`, `Circle`, `ThemeLine`, `EventFrame`, `TextBlock`, `Label`, `Link`, `Card`
125
+ - **Three input forms** — Python objects, JSON, or YAML; all paths produce identical output
126
+ - **Org-level config files** — separate entity types, link types, attribute classes, palettes from per-chart data; layered configs supported
127
+ - **Auto-layout** — circle, grid, or random placement; manual `x`/`y` always wins
128
+ - **Geographic positioning** — map entity attributes to lat/lon for canvas layout and/or ANB Esri Maps
129
+ - **Auto-coloring** — distribute HSV hues across entities; matching link colors
130
+ - **Validation** — collects every error in one pass before writing the file
131
+ - **Semantic types** — full `lcx:LibraryCatalogue` support with custom type extension
132
+ - **CLI** — `anxwritter [--config org.yaml ...] data.{json,yaml} -o out.anx`
133
+
134
+ ---
135
+
136
+ ## Customize everything ANB exposes
137
+
138
+ No fixed catalog — every configurable surface in ANB is yours to define:
139
+
140
+ - **Entity types & link types** — names, icons, colors, shading, semantic-type bindings
141
+ - **Attribute classes** — type, prefix/suffix, decimals, font, merge behavior, icons, visibility
142
+ - **Palettes** — your own "Insert from Palette" panels with grouped types and pre-filled attribute entries
143
+ - **Legend** — 8 item types (icon, link, line, font, text, attribute, timezone, icon-frame) with full styling
144
+ - **Colors** — 40 named, hex, COLORREF, or auto-distributed HSV with link colors that follow the entity
145
+ - **Strengths, grades, source types, datetime formats, semantic types** — all configurable
146
+
147
+ Define your defaults once in `config.yaml`, layer overrides on top, reuse across every chart.
148
+
149
+ ---
150
+
151
+ ## Documentation
152
+
153
+ - [Getting started](docs/getting-started.md) — install, first chart, where to go next
154
+ - [Analyst guide](docs/guide/analyst-guide.md) — every feature via practical examples
155
+ - [Reference docs](docs/reference/) — field-by-field API reference
156
+
157
+ ---
158
+
159
+ ## License
160
+
161
+ MIT — see [LICENSE](LICENSE). Copyright (c) 2024-2026 [gustavo-gkmi](https://github.com/gustavo-gkmi).
162
+
163
+ > Developed with the help of AI coding assistants.
@@ -0,0 +1,129 @@
1
+ # anxwritter
2
+
3
+ Write i2 Analyst's Notebook Exchange (`.anx`) files from Python, JSON, or YAML.
4
+
5
+ Output files open directly in i2 ANB 9+ via **File > Open** — no import wizard, no intermediate CSV. The `.anx` file embeds the entire chart as XML.
6
+
7
+ > This project is independent and not affiliated with, endorsed by, or sponsored by the makers of i2 Analyst's Notebook — past or present — including IBM, i2 Group Limited, i2 Limited, N.Harris Computer Corporation, Harris Computer Corporation, or Constellation Software Inc. — nor by Esri, Microsoft, or Google. "i2", "i2 Analyst's Notebook", "ANB", "Esri", "Esri Maps", "Microsoft", and "Google" are trademarks of their respective owners and are referenced here solely to identify the file format and the tools this library interoperates with (nominative use).
8
+ >
9
+ > To produce structurally valid `.anx` files, this library embeds nine format identifiers: six abstract-root GUIDs required by the `lcx:LibraryCatalogue` schema and three geo-map property GUIDs required by ANB's Esri Maps subsystem. These are functional tokens (format anchors), not creative content, reproduced for interoperability purposes. The library ships nothing else from i2's type system — no standard-library types, no icon catalog, no palette definitions. All of that content stays in the user's licensed ANB installation and must be supplied by the user.
10
+ >
11
+ > This design is intentional: organisations are free to define their own default semantic types, palettes, icon mappings, link types, and attribute classes.
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ # As a library — import in your own code
19
+ pip install anxwritter
20
+
21
+ # With YAML support (optional)
22
+ pip install anxwritter[yaml]
23
+
24
+ # As a command-line tool only (isolated venv, no env conflicts)
25
+ pipx install anxwritter
26
+ ```
27
+
28
+ With [uv](https://docs.astral.sh/uv/):
29
+
30
+ ```bash
31
+ # Add to a uv-managed project
32
+ uv add anxwritter
33
+ uv add 'anxwritter[yaml]' # with YAML support
34
+
35
+ # Install globally as a CLI tool
36
+ uv tool install anxwritter
37
+
38
+ # One-off run without installing
39
+ uvx anxwritter chart.yaml -o my_chart.anx
40
+ ```
41
+
42
+ Requires Python 3.10+.
43
+
44
+ > Want a standalone executable? `pip install pyinstaller` (or `nuitka`) and
45
+ > point it at `anxwritter/cli.py`. anxwritter does not ship pre-built binaries.
46
+
47
+ ---
48
+
49
+ ## Quick example
50
+
51
+ ```python
52
+ from anxwritter import ANXChart
53
+
54
+ chart = ANXChart()
55
+
56
+ chart.add_icon(id='Alice', type='Person', color='Blue')
57
+ chart.add_icon(id='Bob', type='Person', color='Red')
58
+
59
+ chart.add_link(
60
+ from_id='Alice', to_id='Bob',
61
+ type='Telephone Call', arrow='->',
62
+ date='2024-01-15',
63
+ )
64
+
65
+ chart.to_anx('output/my_chart')
66
+ ```
67
+
68
+ This writes `output/my_chart.anx`. Open it in ANB.
69
+
70
+ ### YAML + CLI
71
+
72
+ ```yaml
73
+ # chart.yaml
74
+ entities:
75
+ icons:
76
+ - { id: Alice, type: Person, color: Blue }
77
+ - { id: Bob, type: Person, color: Red }
78
+ links:
79
+ - { from_id: Alice, to_id: Bob, type: Telephone Call, arrow: '->', date: '2024-01-15' }
80
+ ```
81
+
82
+ ```bash
83
+ anxwritter chart.yaml -o output/my_chart.anx
84
+ ```
85
+
86
+ ---
87
+
88
+ ## What's in the box
89
+
90
+ - **Typed dataclass API** — `Icon`, `Box`, `Circle`, `ThemeLine`, `EventFrame`, `TextBlock`, `Label`, `Link`, `Card`
91
+ - **Three input forms** — Python objects, JSON, or YAML; all paths produce identical output
92
+ - **Org-level config files** — separate entity types, link types, attribute classes, palettes from per-chart data; layered configs supported
93
+ - **Auto-layout** — circle, grid, or random placement; manual `x`/`y` always wins
94
+ - **Geographic positioning** — map entity attributes to lat/lon for canvas layout and/or ANB Esri Maps
95
+ - **Auto-coloring** — distribute HSV hues across entities; matching link colors
96
+ - **Validation** — collects every error in one pass before writing the file
97
+ - **Semantic types** — full `lcx:LibraryCatalogue` support with custom type extension
98
+ - **CLI** — `anxwritter [--config org.yaml ...] data.{json,yaml} -o out.anx`
99
+
100
+ ---
101
+
102
+ ## Customize everything ANB exposes
103
+
104
+ No fixed catalog — every configurable surface in ANB is yours to define:
105
+
106
+ - **Entity types & link types** — names, icons, colors, shading, semantic-type bindings
107
+ - **Attribute classes** — type, prefix/suffix, decimals, font, merge behavior, icons, visibility
108
+ - **Palettes** — your own "Insert from Palette" panels with grouped types and pre-filled attribute entries
109
+ - **Legend** — 8 item types (icon, link, line, font, text, attribute, timezone, icon-frame) with full styling
110
+ - **Colors** — 40 named, hex, COLORREF, or auto-distributed HSV with link colors that follow the entity
111
+ - **Strengths, grades, source types, datetime formats, semantic types** — all configurable
112
+
113
+ Define your defaults once in `config.yaml`, layer overrides on top, reuse across every chart.
114
+
115
+ ---
116
+
117
+ ## Documentation
118
+
119
+ - [Getting started](docs/getting-started.md) — install, first chart, where to go next
120
+ - [Analyst guide](docs/guide/analyst-guide.md) — every feature via practical examples
121
+ - [Reference docs](docs/reference/) — field-by-field API reference
122
+
123
+ ---
124
+
125
+ ## License
126
+
127
+ MIT — see [LICENSE](LICENSE). Copyright (c) 2024-2026 [gustavo-gkmi](https://github.com/gustavo-gkmi).
128
+
129
+ > Developed with the help of AI coding assistants.
@@ -0,0 +1,93 @@
1
+ """
2
+ anxwritter — Convert typed Python objects to i2 Analyst's Notebook Exchange (.anx) files.
3
+
4
+ Quick start
5
+ -----------
6
+ ::
7
+
8
+ from anxwritter import ANXChart
9
+
10
+ chart = ANXChart()
11
+
12
+ chart.add_icon(id='Alice', type='Person', color='Blue',
13
+ attributes={'phone': '555-0001'})
14
+ chart.add_icon(id='Bob', type='Person')
15
+
16
+ chart.add_link(from_id='Alice', to_id='Bob', type='Call',
17
+ arrow='->', date='2024-01-15',
18
+ attributes={'duration': 120})
19
+
20
+ chart.to_anx('output/my_chart') # writes output/my_chart.anx
21
+ """
22
+
23
+ from importlib.metadata import version, metadata, PackageNotFoundError
24
+
25
+ from loguru import logger
26
+
27
+ from .chart import ANXChart
28
+ from .errors import ANXValidationError, ErrorType
29
+ from .colors import NAMED_COLORS, color_to_colorref, rgb_to_colorref
30
+ from .enums import VALID_SHADING_COLORS, MergeBehaviour, DotStyle, Enlargement, AttributeType, Multiplicity, ThemeWiring, ArrowStyle, Representation, LegendItemType, Color
31
+ from .entities import Icon, Box, Circle, ThemeLine, EventFrame, TextBlock, Label
32
+ from .models import (
33
+ Card, Link, AttributeClass, Strength, LegendItem, EntityType, LinkType,
34
+ Palette, PaletteAttributeEntry, DateTimeFormat,
35
+ SemanticEntity, SemanticLink, SemanticProperty,
36
+ Font, Frame, Show, TimeZone, CustomProperty,
37
+ GradeCollection, StrengthCollection,
38
+ Settings, ChartCfg, ViewCfg, GridCfg, WiringCfg, LinksCfg, TimeCfg,
39
+ SummaryCfg, LegendCfg, ExtraCfg, GeoMapCfg,
40
+ )
41
+
42
+ try:
43
+ __version__ = version("anxwritter")
44
+ _meta = metadata("anxwritter")
45
+ __repo_url__ = ""
46
+ for val in _meta.get_all("Project-URL") or []:
47
+ label, url = val.split(", ", 1)
48
+ if label == "Repository":
49
+ __repo_url__ = url
50
+ break
51
+ except PackageNotFoundError:
52
+ __version__ = "0.0.0"
53
+ __repo_url__ = ""
54
+
55
+ logger.disable("anxwritter")
56
+
57
+ __all__ = [
58
+ # Version
59
+ '__version__',
60
+ # Main class
61
+ 'ANXChart',
62
+ 'ANXValidationError',
63
+ 'ErrorType',
64
+ # Entity classes
65
+ 'Icon', 'Box', 'Circle', 'ThemeLine', 'EventFrame', 'TextBlock', 'Label',
66
+ # Chart item classes
67
+ 'Card', 'Link', 'AttributeClass', 'Strength', 'LegendItem',
68
+ 'GradeCollection', 'StrengthCollection',
69
+ 'EntityType', 'LinkType',
70
+ 'Palette', 'PaletteAttributeEntry',
71
+ 'DateTimeFormat',
72
+ 'SemanticEntity', 'SemanticLink', 'SemanticProperty',
73
+ # Settings dataclasses
74
+ 'Font', 'Frame', 'Show', 'TimeZone', 'CustomProperty', 'Settings',
75
+ 'ChartCfg', 'ViewCfg', 'GridCfg', 'WiringCfg', 'LinksCfg', 'TimeCfg',
76
+ 'SummaryCfg', 'LegendCfg', 'ExtraCfg', 'GeoMapCfg',
77
+ # Enums
78
+ 'MergeBehaviour',
79
+ 'DotStyle',
80
+ 'Enlargement',
81
+ 'AttributeType',
82
+ 'Multiplicity',
83
+ 'ThemeWiring',
84
+ 'ArrowStyle',
85
+ 'Representation',
86
+ 'LegendItemType',
87
+ 'Color',
88
+ # Color helpers
89
+ 'VALID_SHADING_COLORS',
90
+ 'NAMED_COLORS',
91
+ 'color_to_colorref',
92
+ 'rgb_to_colorref',
93
+ ]
@@ -0,0 +1,102 @@
1
+ """
2
+ _i2_interop.py — Minimum interoperability constants for the ANX format.
3
+
4
+ This module contains the only i2-derived identifiers this library ships:
5
+
6
+ * Six abstract-root GUIDs required by ANB's ``lcx:LibraryCatalogue`` schema.
7
+ Every semantic type chain must terminate at one of these roots; they are
8
+ structural anchors, not content.
9
+
10
+ * Three geo-map property GUIDs required by ANB's Esri Maps subsystem to
11
+ recognise Latitude/Longitude attributes for geographic rendering.
12
+
13
+ These nine identifiers are the absolute minimum needed to write a structurally
14
+ valid ANX file with semantic types. This library intentionally ships nothing
15
+ else from i2's type system — no standard-library types (Person, Vehicle,
16
+ Phone Call…), no icon catalog, no palette definitions. All of that content
17
+ belongs to the user's licensed ANB installation and must be supplied by the
18
+ user via config files or ``.ant``/``.anx`` reference files.
19
+
20
+ This design is intentional: it leaves organisations free to define their own
21
+ default semantic types, palettes, icon mappings, link types, and attribute
22
+ classes — either independently of i2's standard library or layered on top of
23
+ it using types extracted from their own ANB installation.
24
+
25
+ These nine identifiers are functional tokens (format anchors), not creative
26
+ works, reproduced under the interoperability doctrine
27
+ (EU Directive 2009/24/EC Art. 6).
28
+ """
29
+ from __future__ import annotations
30
+
31
+ from typing import Dict, Set
32
+
33
+
34
+ # ── Group 1: abstract root GUIDs ─────────────────────────────────────────────
35
+
36
+ #: i2 abstract root for every entity type. Parent of any user-defined
37
+ #: ``kind_of: Entity`` chain. Required by ANB schema.
38
+ ROOT_ENTITY = 'guid3669EC21-8E41-438A-AA1A-26B477C15BE0'
39
+
40
+ #: i2 abstract root for every link type. Parent of any user-defined
41
+ #: ``kind_of: Link`` chain. Required by ANB schema.
42
+ ROOT_LINK = 'guidC9E54967-BBBF-494B-8348-B9D524F500FD'
43
+
44
+ #: i2 abstract root for text-typed semantic properties.
45
+ ROOT_ABSTRACT_TEXT = 'guid9A224CCF-28F7-4c55-9F14-9E820A0B1631'
46
+
47
+ #: i2 abstract root for numeric-typed semantic properties. Also the indirect
48
+ #: ancestor of the geo-map ``Grid Reference`` / ``Latitude`` / ``Longitude``
49
+ #: property tree.
50
+ ROOT_ABSTRACT_NUM = 'guid6D676796-915D-487f-B384-73503C988ABE'
51
+
52
+ #: i2 abstract root for datetime-typed semantic properties.
53
+ ROOT_ABSTRACT_DT = 'guid6684F871-B607-4ffb-80E8-480535CB44FC'
54
+
55
+ #: i2 abstract root for flag/boolean semantic properties.
56
+ ROOT_ABSTRACT_FLAG = 'guid74F2A516-2F49-4282-989F-F4A468656FF0'
57
+
58
+ #: All six abstract roots.
59
+ ROOTS: Set[str] = {
60
+ ROOT_ENTITY, ROOT_LINK,
61
+ ROOT_ABSTRACT_TEXT, ROOT_ABSTRACT_NUM,
62
+ ROOT_ABSTRACT_DT, ROOT_ABSTRACT_FLAG,
63
+ }
64
+
65
+ #: Type-tree roots (entity + link). Used to distinguish from property roots
66
+ #: when populating the catalogue's type vs. property lookups.
67
+ TYPE_ROOTS: Set[str] = {ROOT_ENTITY, ROOT_LINK}
68
+
69
+ #: Property-tree roots (text/number/datetime/flag).
70
+ PROPERTY_ROOTS: Set[str] = {
71
+ ROOT_ABSTRACT_TEXT, ROOT_ABSTRACT_NUM,
72
+ ROOT_ABSTRACT_DT, ROOT_ABSTRACT_FLAG,
73
+ }
74
+
75
+ #: Display name for each root, emitted as the ``<TypeName>`` /
76
+ #: ``<PropertyName>`` of root catalogue entries.
77
+ ROOT_NAMES: Dict[str, str] = {
78
+ ROOT_ENTITY: 'Entity',
79
+ ROOT_LINK: 'Link',
80
+ ROOT_ABSTRACT_TEXT: 'Abstract Text',
81
+ ROOT_ABSTRACT_NUM: 'Abstract Number',
82
+ ROOT_ABSTRACT_DT: 'Abstract Date & Time',
83
+ ROOT_ABSTRACT_FLAG: 'Abstract Flag',
84
+ }
85
+
86
+
87
+ # ── Group 2: geo-map property GUIDs ──────────────────────────────────────────
88
+
89
+ #: i2 standard "Latitude" semantic property GUID. Required for ANB's Esri
90
+ #: Maps subsystem to recognise a Latitude attribute for geographic rendering.
91
+ #: Used only when ``geo_map.mode`` is ``'latlon'`` or ``'both'``.
92
+ LATITUDE_GUID = 'guid5304A03B-FE47-4406-91E7-0D49EC8409A6'
93
+
94
+ #: i2 standard "Longitude" semantic property GUID. Paired with
95
+ #: :data:`LATITUDE_GUID`.
96
+ LONGITUDE_GUID = 'guid14BCA0EC-D67A-4A67-BC36-CFF650FD77A9'
97
+
98
+ #: i2 standard "Grid Reference" semantic property GUID. Parent of Latitude
99
+ #: and Longitude in the property tree (chains up to ``Abstract Number``).
100
+ #: Required because Latitude/Longitude need a non-abstract parent to be
101
+ #: valid in the catalogue chain.
102
+ GRID_REFERENCE_GUID = 'guid7E0F705E-3D39-4E6E-B6C1-5E72B8C573DA'