Skip to content

Commit

Permalink
Merge pull request #16 from vixen-project/copy-project
Browse files Browse the repository at this point in the history
Add support to copy a project.
  • Loading branch information
prabhuramachandran committed Jan 24, 2018
2 parents 4bcfe5c + a484eb6 commit fb05797
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 20 deletions.
3 changes: 3 additions & 0 deletions vixen/html/vixen_ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ <h3>Available Projects</h3>
v-bind:id="'view-' + index">View</button>
<button v-on:click="busy_call(ui, 'edit', project)"
v-bind:id="'edit-' + index">Edit</button>
<button v-on:click="busy_call(ui, 'copy_project', project)"
v-bind:id="'copy-' + index"
title="Copies project config but not the data.">Copy</button>
<button v-on:click="remove_project(project)"
v-bind:id="'remove-' + index">Remove</button>
</li>
Expand Down
48 changes: 29 additions & 19 deletions vixen/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,16 @@ def update_tags(self, new_tags):

self._query_parser = self._make_query_parser()

def copy(self):
"""Make a copy of this project. This does not copy the data but only
the tags, extensions and the other settings of the project.
"""
name = self.name + ' copy'
p = Project(name=name)
traits = ['description', 'extensions', 'path', 'processors', 'tags']
p.copy_traits(self, traits, copy='deep')
return p

# #### CRUD interface to the data ####

def update(self, media_data, tags=None):
Expand Down Expand Up @@ -324,25 +334,6 @@ def remove(self, relpaths):
self._replace_with_last_record(index, last)
self._delete_record(last, relpath)

def _replace_with_last_record(self, index, last):
_data = self._data
_tag_data = self._tag_data
for key in MediaData._fields:
_data[key][index] = _data[key][last]
for key in self._tag_data:
_tag_data[key][index] = _tag_data[key][last]
last_relpath = _data['relpath'][last]
self._relpath2index[last_relpath] = index

def _delete_record(self, index, relpath):
for key in MediaData._fields:
del self._data[key][index]
for key in self._tag_data:
del self._tag_data[key][index]
if relpath in self._media:
del self._media[relpath]
del self._relpath2index[relpath]

def has_media(self, relpath):
"""Returns True if the media data is available.
"""
Expand Down Expand Up @@ -701,6 +692,25 @@ def _read_version1_media(self, media):
self._tag_data = tag_data
self._relpath2index = relpath2index

def _delete_record(self, index, relpath):
for key in MediaData._fields:
del self._data[key][index]
for key in self._tag_data:
del self._tag_data[key][index]
if relpath in self._media:
del self._media[relpath]
del self._relpath2index[relpath]

def _replace_with_last_record(self, index, last):
_data = self._data
_tag_data = self._tag_data
for key in MediaData._fields:
_data[key][index] = _data[key][last]
for key in self._tag_data:
_tag_data[key][index] = _tag_data[key][last]
last_relpath = _data['relpath'][last]
self._relpath2index[last_relpath] = index

def _save_as_v1(self, fp):
"""Save copy to specified path.
Expand Down
38 changes: 38 additions & 0 deletions vixen/tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from vixen.tests.test_directory import make_data, create_dummy_file
from vixen.project import Project, TagInfo, get_non_existing_filename, INT
from vixen.processor import CommandFactory

if sys.version_info >= (3, 0):
import csv
Expand Down Expand Up @@ -90,6 +91,43 @@ def test_project_scan_works(self):
self.assertEqual(len(m.tags), 1)
self.assertIn('completed', m.tags)

def test_project_copy_does_not_copy_data(self):
# Given
tags = [TagInfo(name='completed', type='bool'),
TagInfo(name='comment', type='string')]
p = Project(name='test', path=self.root,
extensions=['.txt', '.py'], tags=tags)
cf = CommandFactory(dest=self.root,
input_extension='.py',
output_extension='.rst',
command='echo $input $output')
p.processors = [cf]
p.scan()

# When
p1 = p.copy()

# Then
self.assertEqual(p.number_of_files, 5)
self.assertEqual(p1.number_of_files, 0)
self.assertEqual(p1.name, p.name + ' copy')
self.assertEqual(p1.path, p.path)
tag_info = [(x.name, x.type) for x in p.tags]
tag_info1 = [(x.name, x.type) for x in p1.tags]
self.assertEqual(tag_info, tag_info1)
self.assertEqual(p1.extensions, p.extensions)
self.assertEqual(len(p1._relpath2index), 0)
self.assertEqual(len(p1.processors), len(p.processors))
self.assertEqual(p1.processors[0].trait_get(),
p.processors[0].trait_get())

# When
p.tags[0].type = 'int'

# Then
# This just checks that p1's tags are not a reference to p's.
self.assertEqual(p1.tags[0].type, 'bool')

def test_load_should_restore_saved_state(self):
# Given
p = Project(name='test', description='Test', path=self.root)
Expand Down
36 changes: 35 additions & 1 deletion vixen/tests/test_vixen.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import vixen
from vixen.processor import PythonFunctionFactory
from vixen.project import Project
from vixen.project import Project, TagInfo
from vixen.vixen import VixenUI, Vixen, UIErrorHandler, is_valid_tag
from vixen.vixen_ui import get_html, get_html_file

Expand Down Expand Up @@ -453,6 +453,40 @@ def test_add_remove_project_works(self):
# Then
self.assertEqual(len(vixen.projects), 0)

def test_copy_project_works(self):
# Setup

# Create a new project, scan it, save it and re-load it for the test.
ui = VixenUI()
vixen = ui.vixen
ui.add_project()

p = vixen.projects[-1]
p.add_tags([TagInfo(name='sometag', type='text')])
p.path = self.root
p.scan()
p.save()
vixen.save()
self.assertEqual(len(vixen.projects), 1)

# Given
ui = VixenUI()
vixen = ui.vixen
self.assertEqual(len(vixen.projects), 1)

# When
ui.copy_project(vixen.projects[0])

# Then
self.assertEqual(len(vixen.projects), 2)
p = vixen.projects[-1]
self.assertEqual(p.name, 'Project1 copy')
self.assertEqual(len(p.tags), 2)
self.assertEqual(p.tags[0].name, 'completed')
self.assertEqual(p.tags[0].type, 'bool')
self.assertEqual(p.tags[1].name, 'sometag')
self.assertEqual(p.tags[1].type, 'text')

def test_search_string_updates_search_completed(self):
# Given
ui = VixenUI()
Expand Down
9 changes: 9 additions & 0 deletions vixen/vixen.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,15 @@ def add_project(self):
self.editor.project = p
logger.info('Added project %s', name)

def copy_project(self, project):
name = project.name
logger.info('Copying project: %s', name)
if exists(project.save_file) and project.number_of_files == 0:
project.load()
p1 = project.copy()
self.vixen.add(p1)
self.editor.project = p1

def save(self):
with self.busy():
if self.mode == 'edit':
Expand Down

0 comments on commit fb05797

Please sign in to comment.