1 from optparse
import make_option
2 from itertools
import count
3 from functools
import partial
4 from collections
import Counter
6 from django
.core
.management
.base
import BaseCommand
8 from mygpo
.utils
import progress
9 from mygpo
.db
.couchdb
import bulk_save_retry
10 from mygpo
.db
.couchdb
.episode_state
import episode_states_count
, \
11 get_nth_episode_state
, get_duplicate_episode_states
14 class Command(BaseCommand
):
15 """ Merge duplicate EpisodeUserState documents """
17 option_list
= BaseCommand
.option_list
+ (
18 make_option('--skip', action
='store', type=int, dest
='skip', default
=0,
19 help="Number of states to skip"),
22 def handle(self
, *args
, **options
):
24 skip
= options
.get('skip')
25 total
= episode_states_count()
33 first
= get_nth_episode_state(n
)
36 states
= get_duplicate_episode_states(first
.user
, first
.episode
)
39 # we don't want to delete this one
42 assert len(states
) == l1
-1
45 updater
= get_updater(states
)
47 obj_funs
= [(first
, updater
)] + [(state
, do_delete
) for state
in states
]
49 bulk_save_retry(obj_funs
)
51 merged
= len(states
)-1
52 actions
['merged'] += merged
55 status_str
= ', '.join('%s: %d' % x
for x
in actions
.items())
56 progress(n
+1, total
, status_str
)
59 def get_updater(states
):
67 actions
.union(set(state
.actions
))
68 settings
.update(state
.settings
)
69 merged_ids
.union(set(state
.merged_ids
+ [state
._id
]))
70 chapters
.union(set(state
.chapters
))
72 return partial(do_update
, list(actions
), settings
, list(merged_ids
), list(chapters
))
75 def do_update(actions
, settings
, merged_ids
, chapters
, state
):
76 state
.add_actions(actions
)
77 # overwrite settings in old_state with state's settings
78 state
.settings
= settings
.update(state
.settings
or {})
79 state
.merged_ids
= list(set(state
.merged_ids
+ merged_ids
))
80 state
.chapters
= list(set(state
.chapters
+ chapters
))
85 # remove all attributes
86 for attr
in filter(lambda n
: not n
.startswith('_'), dir(state
)):
89 except AttributeError: