annet 0.8__py3-none-any.whl → 0.10__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.

Potentially problematic release.


This version of annet might be problematic. Click here for more details.

annet/annlib/jsontools.py CHANGED
@@ -106,7 +106,7 @@ def apply_acl_filters(content: Dict[str, Any], filters: List[str]) -> Dict[str,
106
106
  patch = jsonpatch.JsonPatch([{"op": "add", "path": f, "value": part}])
107
107
  result = patch.apply(result)
108
108
  except jsonpointer.JsonPointerException:
109
- # no value found in new_fragment by the pointer, skip the ACL item
109
+ # no value found in content by the pointer, skip the ACL item
110
110
  continue
111
111
 
112
112
  return result
annet/gen.py CHANGED
@@ -216,6 +216,7 @@ def _old_new_per_device(ctx: OldNewDeviceContext, device: Device, filterer: Filt
216
216
 
217
217
  new_files = {}
218
218
  safe_new_files = {}
219
+ safe_new_json_fragment_files = {}
219
220
  if not ctx.no_new:
220
221
  if device in ctx.fetched_packages:
221
222
  if ctx.args.required_packages_check:
@@ -238,23 +239,34 @@ def _old_new_per_device(ctx: OldNewDeviceContext, device: Device, filterer: Filt
238
239
  new_files = res.new_files()
239
240
  new_json_fragment_files = res.new_json_fragment_files(old_json_fragment_files)
240
241
 
241
- if ctx.args.acl_safe:
242
- safe_new_files = res.new_files(safe=True)
242
+ filters: List[str] = []
243
+ filters_text = build_filter_text(filterer, device, ctx.stdin, ctx.args, ctx.config)
244
+ if filters_text:
245
+ filters = filters_text.split("\n")
243
246
 
244
- filters = build_filter_text(filterer, device, ctx.stdin, ctx.args, ctx.config).split("\n")
247
+ for file_name in new_json_fragment_files:
248
+ new_json_fragment_files = _update_json_config(
249
+ new_json_fragment_files,
250
+ file_name,
251
+ jsontools.apply_acl_filters(new_json_fragment_files[file_name][0], filters)
252
+ )
253
+ for file_name in old_json_fragment_files:
254
+ old_json_fragment_files = _update_json_config(
255
+ old_json_fragment_files,
256
+ file_name,
257
+ jsontools.apply_acl_filters(old_json_fragment_files[file_name][0], filters)
258
+ )
245
259
 
246
- for file_name in new_json_fragment_files:
247
- new_json_fragment_files = _update_json_config(
248
- new_json_fragment_files,
249
- file_name,
250
- jsontools.apply_acl_filters(new_json_fragment_files[file_name][0], filters)
251
- )
252
- for file_name in old_json_fragment_files:
253
- old_json_fragment_files = _update_json_config(
254
- old_json_fragment_files,
255
- file_name,
256
- jsontools.apply_acl_filters(old_json_fragment_files[file_name][0], filters)
257
- )
260
+ if ctx.args.acl_safe:
261
+ safe_new_files = res.new_files(safe=True)
262
+ safe_new_json_fragment_files = res.new_json_fragment_files(old_json_fragment_files, safe=True)
263
+ if filters:
264
+ for file_name in safe_new_json_fragment_files:
265
+ safe_new_json_fragment_files = _update_json_config(
266
+ safe_new_json_fragment_files,
267
+ file_name,
268
+ jsontools.apply_acl_filters(safe_new_json_fragment_files[file_name][0], filters)
269
+ )
258
270
 
259
271
  if ctx.args.profile:
260
272
  perf = res.perf_mesures()
@@ -281,6 +293,7 @@ def _old_new_per_device(ctx: OldNewDeviceContext, device: Device, filterer: Filt
281
293
  safe_old=safe_old,
282
294
  safe_new=safe_new,
283
295
  safe_new_files=safe_new_files,
296
+ safe_new_json_fragment_files=safe_new_json_fragment_files,
284
297
  filter_acl_rules=filter_acl_rules,
285
298
  )
286
299
 
@@ -180,9 +180,8 @@ class RunGeneratorResult:
180
180
  def new_json_fragment_files(
181
181
  self,
182
182
  old_files: Dict[str, Optional[str]],
183
- safe: bool = False, # pylint: disable=unused-argument
183
+ safe: bool = False,
184
184
  ) -> Dict[str, Tuple[Any, Optional[str]]]:
185
- # TODO: safe
186
185
  files: Dict[str, Tuple[Any, Optional[str]]] = {}
187
186
  reload_prios: Dict[str, int] = {}
188
187
  for generator_result in self.json_fragment_results.values():
@@ -194,7 +193,12 @@ class RunGeneratorResult:
194
193
  files[filepath] = ({}, None)
195
194
  previous_config: Dict[str, Any] = files[filepath][0]
196
195
  new_fragment = generator_result.config
197
- new_config = jsontools.apply_json_fragment(previous_config, new_fragment, generator_result.acl)
196
+
197
+ if safe:
198
+ new_config = jsontools.apply_json_fragment(previous_config, new_fragment, generator_result.acl_safe)
199
+ else:
200
+ new_config = jsontools.apply_json_fragment(previous_config, new_fragment, generator_result.acl)
201
+
198
202
  if filepath in reload_prios and reload_prios[filepath] > generator_result.reload_prio:
199
203
  _, reload_cmd = files[filepath]
200
204
  else:
@@ -496,18 +500,24 @@ def _run_json_fragment_generator(
496
500
  logger = get_logger(generator=_make_generator_ctx(gen))
497
501
  if not gen.supports_device(device):
498
502
  logger.info("generator %s is not supported for device %s", gen, device.hostname)
503
+ return
499
504
 
500
505
  path = gen.path(device)
501
506
  if not path:
502
507
  raise RuntimeError("json fragment generator should return non-empty path")
503
508
 
504
509
  acl_item_or_list_of_items = gen.acl(device)
510
+ safe_acl_item_or_list_of_items = gen.acl_safe(device)
505
511
  if not acl_item_or_list_of_items:
506
512
  raise RuntimeError("json fragment generator should return non-empty acl")
507
513
  if isinstance(acl_item_or_list_of_items, list):
508
514
  acl = acl_item_or_list_of_items
509
515
  else:
510
516
  acl = [acl_item_or_list_of_items]
517
+ if isinstance(safe_acl_item_or_list_of_items, list):
518
+ acl_safe = safe_acl_item_or_list_of_items
519
+ else:
520
+ acl_safe = [safe_acl_item_or_list_of_items]
511
521
 
512
522
  logger.info("Generating JSON_FRAGMENT ...")
513
523
  with GeneratorPerfMesurer(gen, storage) as pm:
@@ -518,10 +528,10 @@ def _run_json_fragment_generator(
518
528
  tags=gen.TAGS,
519
529
  path=path,
520
530
  acl=acl,
531
+ acl_safe=acl_safe,
521
532
  config=config,
522
533
  reload=reload_cmds,
523
534
  perf=pm.last_result,
524
- is_safe=gen.is_safe(device),
525
535
  reload_prio=gen.reload_prio,
526
536
  )
527
537
 
@@ -935,14 +945,17 @@ class JSONFragment(TreeGenerator):
935
945
  """
936
946
  raise NotImplementedError("Required ACL for JSON_FRAGMENT generator")
937
947
 
948
+ def acl_safe(self, device: Device) -> Union[str, List[str]]:
949
+ """
950
+ Restrict the generator to a specified safe ACL using JSON Pointer syntax.
951
+
952
+ Expected ACL to be a list of strings, but a single string is also allowed.
953
+ """
954
+ raise NotImplementedError("Required ACL for JSON_FRAGMENT generator")
955
+
938
956
  def run(self, device: Device):
939
957
  raise NotImplementedError
940
958
 
941
- # pylint: disable=unused-argument
942
- def is_safe(self, device: Device) -> bool:
943
- """Output gen results when --acl-safe flag is used"""
944
- return False
945
-
946
959
  def get_reload_cmds(self, device: Device) -> str:
947
960
  ret = self.reload(device) or ""
948
961
  return ret
annet/types.py CHANGED
@@ -126,20 +126,20 @@ class GeneratorJSONFragmentResult:
126
126
  tags: List[str],
127
127
  path: str,
128
128
  acl: List[str],
129
+ acl_safe: List[str],
129
130
  config: Dict[str, Any],
130
131
  reload: str,
131
132
  perf: GeneratorPerf,
132
- is_safe: bool,
133
133
  reload_prio: int,
134
134
  ):
135
135
  self.name = name
136
136
  self.tags = tags
137
137
  self.path = path
138
138
  self.acl = acl
139
+ self.acl_safe = acl_safe
139
140
  self.config = config
140
141
  self.reload = reload
141
142
  self.perf = perf
142
- self.is_safe = is_safe
143
143
  self.reload_prio = reload_prio
144
144
 
145
145
 
@@ -171,6 +171,7 @@ class OldNewResult:
171
171
  safe_old=None,
172
172
  safe_new=None,
173
173
  safe_new_files=None,
174
+ safe_new_json_fragment_files=None,
174
175
  filter_acl_rules=None
175
176
  ):
176
177
  self.device: Device = device
@@ -193,6 +194,7 @@ class OldNewResult:
193
194
  self.safe_old: MutableMapping = safe_old if safe_old else OrderedDict()
194
195
  self.safe_new: MutableMapping = safe_new if safe_new else OrderedDict()
195
196
  self.safe_new_files: MutableMapping = safe_new_files if safe_new_files else {}
197
+ self.safe_new_json_fragment_files: MutableMapping = safe_new_json_fragment_files or {}
196
198
 
197
199
  self.filter_acl_rules: Optional[MutableMapping] = filter_acl_rules
198
200
 
@@ -221,5 +223,7 @@ class OldNewResult:
221
223
  return self.new_files
222
224
 
223
225
  def get_new_file_fragments(self, safe: bool = False) -> Dict[str, Tuple[Any, Optional[str]]]: # pylint: disable=unused-argument
224
- # TODO: safe
226
+ if safe:
227
+ return self.safe_new_json_fragment_files
228
+
225
229
  return self.new_json_fragment_files
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annet
3
- Version: 0.8
3
+ Version: 0.10
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -8,7 +8,7 @@ annet/deploy.py,sha256=B8E0P_VvCrS2URjFvgmUiIkHp95g7pAWfmT34igaDeo,18893
8
8
  annet/diff.py,sha256=zLcaCnb4lZRUb7frpH1CstQ3kacRcCblZs1uLG8J5lk,3391
9
9
  annet/executor.py,sha256=bw7COJNtssuxIqbQehlHYJnkdUeYvvL8WO5B-c67XE0,19040
10
10
  annet/filtering.py,sha256=F4ZKUCU3Yb1RlL2zKdyHtVUaWPzjWF4vWyMcdygKNYk,852
11
- annet/gen.py,sha256=MI82tdc-r3leiyp4Oa35PBsrfj0jNKdbASRnQ8Rk39g,32336
11
+ annet/gen.py,sha256=FFIzfDudMihS824wmTPMuFTOWRwn0EZac-VxITrlyTw,33068
12
12
  annet/hardware.py,sha256=HYPDfji_GdRn5S0_0fl4rvM7byOY9aHxG6VMAtsLaxE,1090
13
13
  annet/implicit.py,sha256=QigK4uoxvrFho2h9yFjOq1d9rLsC5xFlAU4bKkCuMWk,5139
14
14
  annet/lib.py,sha256=zQIfNBg7fAAk2BHbHAqy_McAiXhz0RqpBAcfdU-6pAA,3742
@@ -20,7 +20,7 @@ annet/storage.py,sha256=V1AQDGxaAEKC5EXOcPy2DqglR_sUdp3l_AS_2c1CFfA,2299
20
20
  annet/tabparser.py,sha256=ZjiI43ZVbrpMVR8qNbTbNh_U3oZ26VDc_2Y9wkkDkYA,874
21
21
  annet/text_term_format.py,sha256=CHb6viv45vmYl-SK1A1vyPHGhaEni6jVybBusaQnct8,2813
22
22
  annet/tracing.py,sha256=ndpM-au1c88uBBpOuH_z52qWZL773edYozNyys_wA68,4044
23
- annet/types.py,sha256=f0iwSJGSQ7GvWeXgXqBCoxzYNezMa4YASQEHJzWUrWU,6962
23
+ annet/types.py,sha256=wT1z1DM-hcjfHizmLxAe9aUi4uhuQ13POiV_MTygUJM,7158
24
24
  annet/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  annet/adapters/netbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  annet/adapters/netbox/provider.py,sha256=OM7Hq2vnMHNVBfubJvx2qJlMYm3VvKhomdLMNO8YnLQ,1024
@@ -44,7 +44,7 @@ annet/annlib/command.py,sha256=uuBddMQphtn8P5MO5kzIa8_QrtMns-k05VeKv1bcAuA,1043
44
44
  annet/annlib/diff.py,sha256=UPt3kYFQdQdVVy3ePYzNHPAxMVmHxCrCnZnMCV6ou2Q,4587
45
45
  annet/annlib/errors.py,sha256=jBcSFzY6Vj-FxR__vqjFm-87AwYQ0xHuAopTirii5AU,287
46
46
  annet/annlib/filter_acl.py,sha256=0w1VF6WcONiTYTQh0yWi6_j9rCTc_kMLAUMr0hbdkNU,7203
47
- annet/annlib/jsontools.py,sha256=TJazOP-1njwbGN7iIz8oGYgWPdry4XfKLjpzNYxdvjg,3364
47
+ annet/annlib/jsontools.py,sha256=_astuRFlt4KlDrneAbuL-HWt1ceu0pWp13skGoV0k-c,3359
48
48
  annet/annlib/lib.py,sha256=eJ4hcVuQ6pdYBzLs4YKCHFtq45idOfZCYp92XfF7_QI,15317
49
49
  annet/annlib/output.py,sha256=_SjJ6G6bejvnTKqNHw6xeio0FT9oO3OIkLaOC3cEga4,7569
50
50
  annet/annlib/patching.py,sha256=Gh8uUjFyYND9TJBBQH-DH6-AwFiiR-dXVXOisMS7elg,19784
@@ -68,7 +68,7 @@ annet/annlib/rulebook/common.py,sha256=9kCZwZpsH5UliF2OzaN9nLs2eLlz_d__4L7_oZ3Sr
68
68
  annet/api/__init__.py,sha256=VooP9u9f6e8vF7FPUE-r0JAGqCjck9-2b0dVNWAtoLM,33752
69
69
  annet/configs/context.yml,sha256=nt4QnzYzrG2hqmaWOUsab2wgFl-CXmFSzbto6rqqFt4,291
70
70
  annet/configs/logging.yaml,sha256=Hu42lRK248dssp9TgkbHCaZNl0E6f4IChGb0XaQnTVo,970
71
- annet/generators/__init__.py,sha256=iOTaIfTQfGoExmSAzqt1RSWP7V1O_pEkuqvjnsEjBkQ,34476
71
+ annet/generators/__init__.py,sha256=0aswTm4MD_DWas0iwQQI8DaGX1iRQYHXHg6sl8549CI,34979
72
72
  annet/generators/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  annet/generators/common/initial.py,sha256=XI7uWLMuLrHC-uXm38oRbM1YVuELAvMHLZFHM9x5IF8,1229
74
74
  annet/rulebook/__init__.py,sha256=14IpOfTbeJtre7JKrfXVYiH0qAXsUSOL7AatUFmSQs0,3847
@@ -120,10 +120,10 @@ annet/rulebook/texts/routeros.rul,sha256=ipfxjj0mjFef6IsUlupqx4BY_Je_OUb8u_U1019
120
120
  annet_generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
121
  annet_generators/example/__init__.py,sha256=zVd8_DrXuOASrNzg2Ab94rPyvJff83L-_HppDFxnUjM,228
122
122
  annet_generators/example/lldp.py,sha256=68CLrK7vxTQQy9XIBxtywuEdBNlIlfXGYj8_wYWs5UI,1146
123
- annet-0.8.dist-info/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
124
- annet-0.8.dist-info/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
125
- annet-0.8.dist-info/METADATA,sha256=biTv9OtMLS-HnbvanEbTm3B-tYG9SGFV-TSQCtem7cE,691
126
- annet-0.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
127
- annet-0.8.dist-info/entry_points.txt,sha256=yHimujIzR2bwNIbb--MTs_GpXiAve89Egpu2LlgTEkg,119
128
- annet-0.8.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
129
- annet-0.8.dist-info/RECORD,,
123
+ annet-0.10.dist-info/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
124
+ annet-0.10.dist-info/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
125
+ annet-0.10.dist-info/METADATA,sha256=wUvxu4XGIQ0tSRIwoetdSNG45tkxpO70zPAngL0NN5Y,692
126
+ annet-0.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
127
+ annet-0.10.dist-info/entry_points.txt,sha256=yHimujIzR2bwNIbb--MTs_GpXiAve89Egpu2LlgTEkg,119
128
+ annet-0.10.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
129
+ annet-0.10.dist-info/RECORD,,
File without changes
File without changes
File without changes