mreg-cli 1.8.2__tar.gz → 1.9.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 (121) hide show
  1. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/.github/workflows/publish.yml +3 -3
  2. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/.github/workflows/test.yml +15 -11
  3. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/CHANGELOG.md +24 -0
  4. mreg_cli-1.9.0/CLAUDE.md +152 -0
  5. mreg_cli-1.9.0/PKG-INFO +575 -0
  6. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/docker-compose.yml +1 -1
  7. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/run_testsuite_and_record_V2.sh +14 -5
  8. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/testsuite +2 -0
  9. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/testsuite-result.json +3143 -2205
  10. mreg_cli-1.9.0/mreg_cli/_version.py +24 -0
  11. mreg_cli-1.9.0/mreg_cli/choices.py +19 -0
  12. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/cli.py +29 -19
  13. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/cache.py +21 -24
  14. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/dhcp.py +3 -2
  15. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/group.py +35 -7
  16. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/help.py +23 -7
  17. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/a_aaaa.py +8 -5
  18. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/bacnet.py +4 -2
  19. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/cname.py +6 -3
  20. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/core.py +156 -46
  21. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/rr.py +40 -27
  22. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/label.py +5 -2
  23. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/logging.py +0 -1
  24. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/network.py +45 -20
  25. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/permission.py +3 -2
  26. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/policy.py +25 -18
  27. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/root.py +3 -2
  28. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/zone.py +20 -4
  29. mreg_cli-1.9.0/mreg_cli/exceptions.py +287 -0
  30. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/main.py +34 -9
  31. mreg_cli-1.9.0/mreg_cli/output/__init__.py +166 -0
  32. mreg_cli-1.9.0/mreg_cli/output/base.py +58 -0
  33. mreg_cli-1.9.0/mreg_cli/output/cache.py +17 -0
  34. mreg_cli-1.9.0/mreg_cli/output/group.py +119 -0
  35. mreg_cli-1.9.0/mreg_cli/output/history.py +90 -0
  36. mreg_cli-1.9.0/mreg_cli/output/host.py +686 -0
  37. mreg_cli-1.9.0/mreg_cli/output/meta.py +109 -0
  38. mreg_cli-1.9.0/mreg_cli/output/network.py +276 -0
  39. mreg_cli-1.9.0/mreg_cli/output/policy.py +269 -0
  40. mreg_cli-1.9.0/mreg_cli/output/zone.py +91 -0
  41. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/outputmanager.py +10 -16
  42. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/types.py +7 -44
  43. mreg_cli-1.9.0/mreg_cli/utilities/api.py +125 -0
  44. mreg_cli-1.9.0/mreg_cli.egg-info/PKG-INFO +575 -0
  45. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli.egg-info/SOURCES.txt +14 -14
  46. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli.egg-info/requires.txt +1 -2
  47. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/pyproject.toml +8 -5
  48. mreg_cli-1.9.0/tests/api/test_client.py +33 -0
  49. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/commands/test_host.py +64 -1
  50. mreg_cli-1.9.0/tests/conftest.py +70 -0
  51. mreg_cli-1.9.0/tests/test_exceptions.py +164 -0
  52. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_prompt.py +3 -2
  53. mreg_cli-1.9.0/tests/utils.py +6 -0
  54. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tox.ini +1 -2
  55. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/uv.lock +185 -212
  56. mreg_cli-1.8.2/PKG-INFO +0 -1252
  57. mreg_cli-1.8.2/ci/run_testsuite_and_record.sh +0 -46
  58. mreg_cli-1.8.2/mreg_cli/_version.py +0 -34
  59. mreg_cli-1.8.2/mreg_cli/api/__init__.py +0 -7
  60. mreg_cli-1.8.2/mreg_cli/api/abstracts.py +0 -513
  61. mreg_cli-1.8.2/mreg_cli/api/endpoints.py +0 -147
  62. mreg_cli-1.8.2/mreg_cli/api/errors.py +0 -91
  63. mreg_cli-1.8.2/mreg_cli/api/fields.py +0 -172
  64. mreg_cli-1.8.2/mreg_cli/api/history.py +0 -153
  65. mreg_cli-1.8.2/mreg_cli/api/models.py +0 -4653
  66. mreg_cli-1.8.2/mreg_cli/cache.py +0 -333
  67. mreg_cli-1.8.2/mreg_cli/exceptions.py +0 -318
  68. mreg_cli-1.8.2/mreg_cli/utilities/api.py +0 -657
  69. mreg_cli-1.8.2/mreg_cli.egg-info/PKG-INFO +0 -1252
  70. mreg_cli-1.8.2/tests/api/test_fields.py +0 -270
  71. mreg_cli-1.8.2/tests/api/test_models.py +0 -218
  72. mreg_cli-1.8.2/tests/conftest.py +0 -76
  73. mreg_cli-1.8.2/tests/test_cache.py +0 -151
  74. mreg_cli-1.8.2/tests/test_exceptions.py +0 -174
  75. mreg_cli-1.8.2/tests/utilities/__init__.py +0 -0
  76. mreg_cli-1.8.2/tests/utilities/test_api.py +0 -291
  77. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/.gitignore +0 -0
  78. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/.markdownlint.json +0 -0
  79. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/AUTHORS +0 -0
  80. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/CONTRIBUTING +0 -0
  81. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/LICENSE +0 -0
  82. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/README.md +0 -0
  83. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/Dockerfile +0 -0
  84. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/ci/diff.py +0 -0
  85. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/data/mreg-cli.conf +0 -0
  86. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/__about__.py +0 -0
  87. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/__init__.py +0 -0
  88. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/__main__.py +0 -0
  89. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/__init__.py +0 -0
  90. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/base.py +0 -0
  91. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host.py +0 -0
  92. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/host_submodules/__init__.py +0 -0
  93. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/recording.py +0 -0
  94. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/commands/registry.py +0 -0
  95. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/config.py +0 -0
  96. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/dirs.py +0 -0
  97. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/errorbuilder.py +0 -0
  98. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/help_formatter.py +0 -0
  99. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/log.py +0 -0
  100. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/prompt.py +0 -0
  101. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/py.typed +0 -0
  102. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/tags.txt +0 -0
  103. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/tokenfile.py +0 -0
  104. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/utilities/__init__.py +0 -0
  105. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/utilities/fs.py +0 -0
  106. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/utilities/shared.py +0 -0
  107. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli/utilities/validators.py +0 -0
  108. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli.egg-info/dependency_links.txt +0 -0
  109. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli.egg-info/entry_points.txt +0 -0
  110. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/mreg_cli.egg-info/top_level.txt +0 -0
  111. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/run.py +0 -0
  112. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/setup.cfg +0 -0
  113. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/__init__.py +0 -0
  114. {mreg_cli-1.8.2/tests/api → mreg_cli-1.9.0/tests/commands}/__init__.py +0 -0
  115. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_config.py +0 -0
  116. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_errorbuilder.py +0 -0
  117. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_outputmanager.py +0 -0
  118. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_tokenfile.py +0 -0
  119. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/test_types.py +0 -0
  120. {mreg_cli-1.8.2/tests/commands → mreg_cli-1.9.0/tests/utilities}/__init__.py +0 -0
  121. {mreg_cli-1.8.2 → mreg_cli-1.9.0}/tests/utilities/test_fs.py +0 -0
@@ -8,9 +8,6 @@ on:
8
8
  concurrency:
9
9
  group: build-mreg-cli-${{ github.head_ref }}
10
10
 
11
- env:
12
- UV_FROZEN: 1
13
-
14
11
  jobs:
15
12
  build_pypi:
16
13
  name: Build wheels and source distribution
@@ -82,6 +79,9 @@ jobs:
82
79
  - name: Set up Python ${{ matrix.python-version }}
83
80
  run: uv python install ${{ matrix.python-version }}
84
81
 
82
+ - name: Add repo directory to git safe.directory
83
+ run: git config --global --add safe.directory /__w/mreg-cli/mreg-cli
84
+
85
85
  - name: Install build dependencies
86
86
  run: uv sync --group ci
87
87
 
@@ -1,7 +1,11 @@
1
- on: [push, pull_request]
2
-
3
- env:
4
- UV_FROZEN: 1
1
+ on:
2
+ push:
3
+ pull_request:
4
+ workflow_dispatch:
5
+ inputs:
6
+ mreg_image:
7
+ description: "MREG Docker image to use for testing"
8
+ required: false
5
9
 
6
10
  name: CI
7
11
  jobs:
@@ -12,9 +16,9 @@ jobs:
12
16
  matrix:
13
17
  os: [ubuntu-22.04]
14
18
  python-version:
15
- - '3.11'
16
- - '3.12'
17
- - '3.13'
19
+ - "3.11"
20
+ - "3.12"
21
+ - "3.13"
18
22
  env:
19
23
  # Disable colors and formatting in Rich console output
20
24
  TERM: dumb
@@ -22,7 +26,7 @@ jobs:
22
26
  - name: Checkout
23
27
  uses: actions/checkout@v4
24
28
  - name: Test and compare api calls
25
- run: ci/run_testsuite_and_record_V2.sh ${{ matrix.python-version }}
29
+ run: ci/run_testsuite_and_record_V2.sh ${{ matrix.python-version }} ${{ github.event.inputs.mreg_image }}
26
30
 
27
31
  tox:
28
32
  name: tox
@@ -51,8 +55,8 @@ jobs:
51
55
  - uses: actions/checkout@v4
52
56
  - uses: DavidAnson/markdownlint-cli2-action@v18
53
57
  with:
54
- config: '.markdownlint.json'
55
- globs: '**/*.md'
58
+ config: ".markdownlint.json"
59
+ globs: "**/*.md"
56
60
 
57
61
  unit:
58
62
  name: Unit tests
@@ -63,7 +67,7 @@ jobs:
63
67
  python-version:
64
68
  - "3.11"
65
69
  - "3.12"
66
- - '3.13'
70
+ - "3.13"
67
71
  steps:
68
72
  - uses: actions/checkout@v4
69
73
  - name: Install uv
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  <!-- ## Unreleased -->
9
9
 
10
+ ## [1.9.0](https://github.com/unioslo/mreg-cli/releases/tag/1.9.0) - 2026-04-14
11
+
12
+ ### Changed
13
+
14
+ - Now uses `mreg-api` package for all API interactions. All API code has been stripped out of `mreg-cli`.
15
+
16
+ ### Fixed
17
+
18
+ - `host remove` printing success messages for associated record removal when host deletion failed and no records were actually deleted.
19
+
20
+ ## [1.8.3](https://github.com/unioslo/mreg-cli/releases/tag/1.8.3) - 2026-02-03
21
+
22
+ ### Added
23
+
24
+ - `host add_contact <host> <contact> [<contact> ...]` command to add one or more contacts to a host.
25
+ - `host remove_contact <host> <contact> [<contact> ...]` command to remove one or more contacts from a host.
26
+ - `host unset_contact <host> [-force]` command to remove all contacts from a host.
27
+ - `network community_list -sort <name|global>` option to sort communities by name or global name (defaults to name).
28
+
29
+ ### Changed
30
+
31
+ - `host set_contact <host> <contact> [<contact> ...]` command now accepts multiple contacts to set at once, replacing all existing contacts.
32
+ - `host add -contact` option now accepts multiple arguments.
33
+
10
34
  ## [1.8.2](https://github.com/unioslo/mreg-cli/releases/tag/1.8.2) - 2026-01-06
11
35
 
12
36
  <!-- NOTE: 1.8.1 skipped in changelog due to Github release issues that required creating a separate 1.8.1 release for PyPI. -->
@@ -0,0 +1,152 @@
1
+ # mreg-cli Architecture
2
+
3
+ ## Overview
4
+
5
+ This CLI uses `mreg_api` for data models and API operations, with presentation logic handled by standalone output functions in `mreg_cli.output`.
6
+
7
+ ### Module Structure
8
+
9
+ ```text
10
+ mreg_cli/
11
+ ├── output/ # Presentation logic
12
+ │ ├── __init__.py # Re-exports all output functions
13
+ │ ├── base.py # Shared utilities (timestamps, TTL)
14
+ │ ├── zone.py # Zone, delegation, nameserver output
15
+ │ ├── host.py # Host, IP, CNAME, TXT, MX, SRV, etc.
16
+ │ ├── network.py # Network, community, policy output
17
+ │ ├── policy.py # Role, atom, label, permission output
18
+ │ ├── group.py # HostGroup output
19
+ │ └── meta.py # UserInfo, ServerVersion, HealthInfo
20
+ │
21
+ ├── commands/ # Command handlers (use mreg_api.models + mreg_cli.output)
22
+ │ └── ...
23
+ │
24
+ ├── exceptions.py # CLI exception classes and handling functions
25
+ └── outputmanager.py # Low-level output formatting
26
+ ```
27
+
28
+ ## Usage Examples
29
+
30
+ Commands use `mreg_api.models` for data operations and `mreg_cli.output` for presentation:
31
+
32
+ ```python
33
+ # mreg_cli/commands/zone.py
34
+ from mreg_api.models import Zone
35
+ from mreg_cli.output import output_zone
36
+
37
+ def zone_info(args):
38
+ zone = Zone.get_zone_or_raise(args.name)
39
+ output_zone(zone) # Standalone function
40
+ ```
41
+
42
+ <details>
43
+ <summary><strong>Output Function Reference</strong></summary>
44
+
45
+ ### Zone (`mreg_cli.output.zone`)
46
+
47
+ - `output_zone(zone, padding=20)` - Single zone
48
+ - `output_zones(zones)` - List of zones
49
+ - `output_nameservers(nameservers, padding=20)` - Zone nameservers
50
+ - `output_delegations(zone, padding=20)` - Zone delegations
51
+
52
+ ### Host (`mreg_cli.output.host`)
53
+
54
+ - `output_host(host, names=False, traverse_hostgroups=False)` - Single host
55
+ - `output_hosts(hosts, names=False, traverse_hostgroups=False)` - Multiple hosts
56
+ - `output_hostlist(hostlist)` - HostList result
57
+ - `output_ipaddresses(ips, padding=14, names=False)` - IP addresses
58
+ - `output_cnames(cnames, host=None, padding=14)` - CNAME records
59
+ - `output_mxs(mxs, padding=14)` - MX records
60
+ - `output_txts(txts, padding=14)` - TXT records
61
+ - `output_srvs(srvs, padding=14)` - SRV records
62
+ - `output_naptrs(naptrs, padding=14)` - NAPTR records
63
+ - `output_sshfps(sshfps, padding=14)` - SSHFP records
64
+ - `output_ptr_overrides(ptrs, padding=14)` - PTR overrides
65
+ - `output_hinfo(hinfo, padding=14)` - HINFO record
66
+ - `output_location(loc, padding=14)` - LOC record
67
+ - `output_bacnetids(bacnetids)` - BACnet IDs
68
+
69
+ ### Network (`mreg_cli.output.network`)
70
+
71
+ - `output_network(network, padding=25)` - Single network
72
+ - `output_networks(networks, padding=25)` - Multiple networks
73
+ - `output_unused_addresses(network, padding=25)` - Unused IPs
74
+ - `output_used_addresses(network, padding=46)` - Used IPs with hosts
75
+ - `output_excluded_ranges(excluded_ranges, padding=32)` - Excluded ranges
76
+ - `output_community(community, padding=14, show_hosts=True)` - Single community
77
+ - `output_communities(communities, padding=14, show_hosts=True, sort=NAME)` - Multiple communities
78
+ - `output_network_policy(policy)` - Network policy
79
+ - `output_network_policy_attributes(attributes, padding=20)` - Policy attributes
80
+
81
+ ### Policy (`mreg_cli.output.policy`)
82
+
83
+ - `output_role(role, padding=14)` - Single role
84
+ - `output_roles(roles, padding=14)` - Multiple roles (single line)
85
+ - `output_roles_table(roles, padding=14)` - Roles as table
86
+ - `output_role_hosts(role, padding=14, exclude_roles=None)` - Role's hosts
87
+ - `output_role_atoms(role, padding=14)` - Role's atoms
88
+ - `output_atom(atom, padding=14)` - Single atom
89
+ - `output_atoms(atoms, padding=14)` - Multiple atoms (single line)
90
+ - `output_atoms_lines(atoms, padding=20)` - Atoms (one per line)
91
+ - `output_label(label, padding=14)` - Label with roles/permissions
92
+ - `output_permissions(permissions, indent=4)` - Permissions table
93
+
94
+ ### Group (`mreg_cli.output.group`)
95
+
96
+ - `output_hostgroup(hostgroup, padding=14)` - Single hostgroup
97
+ - `output_hostgroups(hostgroups, padding=14, multiline=False)` - Multiple hostgroups
98
+ - `output_hostgroup_members(hostgroup, expand=False)` - Group members
99
+
100
+ ### Meta (`mreg_cli.output.meta`)
101
+
102
+ - `output_user_info(user, django=False)` - User information
103
+ - `output_user_permissions(permissions)` - User permissions
104
+ - `output_server_version(version)` - Server version
105
+ - `output_server_libraries(libraries, indent=4)` - Server libraries
106
+ - `output_health_info(health)` - Health information
107
+
108
+ ### Base (`mreg_cli.output.base`)
109
+
110
+ - `output_timestamps(obj, padding=14)` - Created/updated timestamps
111
+ - `output_ttl(obj, label="TTL", field="ttl", padding=14)` - TTL value
112
+
113
+ </details>
114
+
115
+ ## Known Issues
116
+
117
+ 1. **Circular imports**: Some functions use local imports to avoid circular dependencies between output modules.
118
+
119
+ 2. **Type protocol mismatches**: `Role` and `Atom` have `created_at` as computed properties rather than direct fields, causing protocol mismatches with `HasTimestamps`.
120
+
121
+ ## Exception Handling
122
+
123
+ Exception handling uses standalone functions in `mreg_cli.exceptions`.
124
+ This allows uniform handling of exceptions from both `mreg_cli` and `mreg_api`.
125
+
126
+ ### Exception Classes
127
+
128
+ Exception classes in `mreg_cli.exceptions` are pure data containers with no output methods:
129
+
130
+ ```text
131
+ CliException (base)
132
+ ├── CliError (non-recoverable errors, displayed in red)
133
+ │ ├── CreateError, PatchError, DeleteError, GetError
134
+ │ ├── InternalError, FileError, ValidationError, LoginFailedError
135
+ └── CliWarning (recoverable, displayed in italics)
136
+ ├── APIError (has response attribute), UnexpectedDataError
137
+ ├── EntityNotFound, EntityAlreadyExists, MultipleEntitiesFound
138
+ ├── TooManyResults, NoHistoryFound, ForceMissing
139
+ └── IPNetworkWarning and subclasses
140
+ ```
141
+
142
+ ### Exception Handling Locations
143
+
144
+ - `mreg_cli/cli.py` - Main command parsing catches and handles exceptions
145
+ - `mreg_cli/main.py` - Entry point handles login and REPL exceptions
146
+ - `mreg_cli/utilities/api.py` - Authentication-related exception handling
147
+
148
+ ## Future Work
149
+
150
+ ### Caching
151
+
152
+ The cache code was copied to `mreg_api` but has not been implemented in that module. Implementing caching should be the **last priority** once the final API design of both packages is clear.