Repository: borgbackup/borg

Issue:
fix Statistics.__add__
because the file_stats defaultdict can contain different keys, it must iterate over `union(self.keys(), other.keys())` when adding up stats values.

fix Statistics.__add__
because the file_stats defaultdict can contain different keys, it must iterate over `union(self.keys(), other.keys())` when adding up stats values.



Discussion:
Hi, can it be done by setting `stats.files_stats = self.files_stats` and then iterate the keys of `other.files_stats` and check if key is in `stats.files_stats`? If key is not present in the dictionary, create it. And finally `stats.files_stats[key] += other.files_stats[key]`.
@vhadzhiev something like that might work, but is too much effort and also a bit an asymmetric approach.

Just iterating over the union set of all keys is the symmetric approach and easier. 

https://docs.python.org/3.8/library/stdtypes.html#set

Guess it could be a one-liner using a dict comprehension. Note that you do not need to "check if key is in some dict", because both are defaultdict and defaulting to 0, which is neutral in a addition.
A very long one-liner here :)
`stats.files_stats = {key: (self.files_stats[key] + other.files_stats[key]) for key in self.files_stats.keys() | other.files_stats.keys()}`

I don't have much experience with defaultdicts, but as I read the docs, I really like it. The one-liner above will create normal dictionary. I also tested with another one-liner if the new dictionary can be initiated as defaultdict and it worked. 

`stats.files_stats = defaultdict(int, {key: (self.files_stats[key] + other.files_stats[key]) for key in self.files_stats.keys() | other.files_stats.keys()})`

Which one should be used if they are OK? Is it needed the new dictionary also to have the functionality of the defaultdict?
We need the lower one.

Could be a bit shorter via first doing:
```
st1, st2 = self.files_stats, other.files_stats
```
OK, 10x. I'll fix it tomorrow and will create pull request.  
Hi, can it be done by setting `stats.files_stats = self.files_stats` and then iterate the keys of `other.files_stats` and check if key is in `stats.files_stats`? If key is not present in the dictionary, create it. And finally `stats.files_stats[key] += other.files_stats[key]`.
@vhadzhiev something like that might work, but is too much effort and also a bit an asymmetric approach.

Just iterating over the union set of all keys is the symmetric approach and easier. 

https://docs.python.org/3.8/library/stdtypes.html#set

Guess it could be a one-liner using a dict comprehension. Note that you do not need to "check if key is in some dict", because both are defaultdict and defaulting to 0, which is neutral in a addition.
A very long one-liner here :)
`stats.files_stats = {key: (self.files_stats[key] + other.files_stats[key]) for key in self.files_stats.keys() | other.files_stats.keys()}`

I don't have much experience with defaultdicts, but as I read the docs, I really like it. The one-liner above will create normal dictionary. I also tested with another one-liner if the new dictionary can be initiated as defaultdict and it worked. 

`stats.files_stats = defaultdict(int, {key: (self.files_stats[key] + other.files_stats[key]) for key in self.files_stats.keys() | other.files_stats.keys()})`

Which one should be used if they are OK? Is it needed the new dictionary also to have the functionality of the defaultdict?
We need the lower one.

Could be a bit shorter via first doing:
```
st1, st2 = self.files_stats, other.files_stats
```
OK, 10x. I'll fix it tomorrow and will create pull request.  

Resolving patch:
diff --git a/src/borg/archive.py b/src/borg/archive.py
--- a/src/borg/archive.py
+++ b/src/borg/archive.py
@@ -79,8 +79,8 @@ def __add__(self, other):
         stats.nfiles = self.nfiles + other.nfiles
         stats.chunking_time = self.chunking_time + other.chunking_time
         stats.hashing_time = self.hashing_time + other.hashing_time
-        for key in other.files_stats:
-            stats.files_stats[key] = self.files_stats[key] + other.files_stats[key]
+        st1, st2 = self.files_stats, other.files_stats
+        stats.files_stats = defaultdict(int, {key: (st1[key] + st2[key]) for key in st1.keys() | st2.keys()})
 
         return stats
 


Test patch: