@@ -566,22 +566,74 @@ def update(
566
566
self .meta [metadata_fn ] = MetaFile (version , length , hashes )
567
567
568
568
569
+ class TargetFile :
570
+ """A container with information about a particilur target file.
571
+ Instances of TargetFile are used as values in a dictionary
572
+ called "targets" in Targets.
573
+
574
+ targets: A dictionary that contains information about target files::
575
+ {
576
+ 'target_file_path_1': <TargetFile INSTANCE_1>,
577
+ 'target_file_path_2': <TargetFile INSTANCE_2>,
578
+ ...
579
+ }
580
+ Attributes:
581
+ length: An integer indicating the length of the target file.
582
+ hashes: An dictionary containing hash algorithms and the
583
+ hashes resulted from applying them over the target file::
584
+ 'hashes': {
585
+ '<HASH ALGO 1>': '<TARGET FILE HASH 1>',
586
+ '<HASH ALGO 2>': '<TARGET FILE HASH 2>',
587
+ ...
588
+ }
589
+ custom: An optional dictionary which may include version numbers,
590
+ dependencies, or any other data that the application wants
591
+ to include to describe the target file::
592
+ 'custom': {
593
+ 'type': 'metadata',
594
+ 'file_permissions': '0644',
595
+ ...
596
+ } // optional
597
+
598
+ """
599
+
600
+ def __init__ (self , length : int , hashes : JsonDict ,
601
+ custom : Optional [JsonDict ] = None ) -> None :
602
+ self .length = length
603
+ self .hashes = hashes
604
+ self .custom = custom
605
+
606
+
607
+ def __eq__ (self , other : Any ) -> bool :
608
+ """Used to compare objects by their values instead of by their
609
+ addresses."""
610
+ if not isinstance (other , TargetFile ):
611
+ # don't attempt to compare against unrelated types
612
+ return NotImplemented
613
+
614
+ return self .length == other .length and \
615
+ self .hashes == other .hashes and \
616
+ self .custom == other .custom
617
+
618
+
619
+ def to_dict (self ) -> JsonDict :
620
+ """Returns the JSON-serializable dictionary representation of self. """
621
+ json_dict = {'length' : self .length , 'hashes' : self .hashes }
622
+
623
+ if self .custom is not None :
624
+ json_dict ['custom' ] = self .custom
625
+
626
+ return json_dict
627
+
628
+
569
629
class Targets (Signed ):
570
630
"""A container for the signed part of targets metadata.
571
631
572
632
Attributes:
573
633
targets: A dictionary that contains information about target files::
574
634
575
635
{
576
- '<TARGET FILE NAME>': {
577
- 'length': <TARGET FILE SIZE>,
578
- 'hashes': {
579
- '<HASH ALGO 1>': '<TARGET FILE HASH 1>',
580
- '<HASH ALGO 2>': '<TARGETS FILE HASH 2>',
581
- ...
582
- },
583
- 'custom': <CUSTOM OPAQUE DICT> // optional
584
- },
636
+ '<TARGET FILE NAME>': <TargetFile INSTANCE>,
585
637
...
586
638
}
587
639
@@ -628,22 +680,32 @@ def __init__(
628
680
expires : datetime , targets : JsonDict , delegations : JsonDict
629
681
) -> None :
630
682
super ().__init__ (_type , version , spec_version , expires )
631
- # TODO: Add class for meta
632
- self .targets = targets
683
+
684
+ self .targets = {}
685
+ for target_path , target_dict in targets .items ():
686
+ self .targets [target_path ] = TargetFile (target_dict ['length' ],
687
+ target_dict ['hashes' ], target_dict .get ('custom' ))
688
+
689
+ # TO DO: Add Key and Role classes
633
690
self .delegations = delegations
634
691
635
692
636
693
# Serialization.
637
694
def to_dict (self ) -> JsonDict :
638
695
"""Returns the JSON-serializable dictionary representation of self. """
639
696
json_dict = super ().to_dict ()
697
+ target_dict = {}
698
+ for target_path , target_file_obj in self .targets .items ():
699
+ target_dict [target_path ] = target_file_obj .to_dict ()
700
+
640
701
json_dict .update ({
641
- 'targets' : self . targets ,
702
+ 'targets' : target_dict ,
642
703
'delegations' : self .delegations ,
643
704
})
644
705
return json_dict
645
706
646
707
# Modification.
647
708
def update (self , filename : str , fileinfo : JsonDict ) -> None :
648
709
"""Assigns passed target file info to meta dict. """
649
- self .targets [filename ] = fileinfo
710
+ self .targets [filename ] = TargetFile (fileinfo ['length' ],
711
+ fileinfo ['hashes' ], fileinfo .get ('custom' ))
0 commit comments