示例#1
0
 def test_scan_missing(self):
     (srcdir, mediadir, tmpdir) = self._setup_test_data()
     try:
         rows = 0
         photoman._find_and_archive_photos(srcdir, mediadir, True, 'foo')
         rep = media_common.Repository()
         rep.open(os.path.join(mediadir))
         rows = self._get_row_count(rep)
         rep.close()
         os.remove(
             os.path.join(mediadir, 'photos/2012/07_July/gnexus 160.jpg'))
         photoman._scan_missing_photos(mediadir)
         rep = media_common.Repository()
         rep.open(os.path.join(mediadir))
         self.assertEquals(rows - 1, self._get_row_count(rep))
         cur = rep.con.cursor()
         filepath = os.path.join(mediadir,
                                 'photos/2012/07_July/gnexus 160.jpg')
         rows = cur.execute(
             '''
     select id FROM photos WHERE archive_path = ?''', [filepath])
         self.assertEquals(None, rows.fetchone())
         rep.close()
     finally:
         shutil.rmtree(tmpdir)
示例#2
0
 def test_query_all(self):
     (srcdir, mediadir, tmpdir) = self._setup_test_data()
     try:
         photoman._find_and_archive_photos(srcdir, mediadir, True, 'foo')
         rep = media_common.Repository()
         rep.open(mediadir)
         cur = rep.con.cursor()
         cur.execute('''
     select id, archive_path FROM photos''')
         rows = 0
         for row in cur:
             rows += 1
         self.assertEquals(5, rows)
         cur = rep.con.cursor()
         ids = [1, 5]
         cur.execute(
             ' DELETE from photos where id in (' +
             ','.join('?' * len(ids)) + ')', ids)
         cur.execute('''
     select id, archive_path FROM photos''')
         rows = 0
         for row in cur:
             rows += 1
         self.assertEquals(3, rows)
         rep.close()
     finally:
         shutil.rmtree(tmpdir)
示例#3
0
 def test_close(self):
     rep = media_common.Repository()
     connection = MagicMock()
     rep.con = connection
     rep.close()
     self.assertEquals(None, rep.con, 'expect connection removed')
     self.assertEquals(call.commit(), connection.mock_calls[0])
     self.assertEquals(call.close(), connection.mock_calls[1])
示例#4
0
 def test_remove(self):
     rep = media_common.Repository()
     rep.con = MagicMock()
     execute = rep.con.cursor.return_value.execute
     photo = MagicMock()
     photo.md5 = 42
     rep.remove(photo)
     execute.assert_called_with(ANY, [42])
示例#5
0
 def test_add_or_update(self):
     rep = media_common.Repository()
     photo = Mock()
     rep.con = Mock()
     rep.con.cursor.return_value.lastrowid = 42
     self.assertEquals(42, rep.add_or_update(photo))
     self.assertTrue(rep.con.cursor.called)
     self.assertTrue(rep.con.cursor.return_value.execute.called)
     self.assertTrue(rep.con.commit.called)
示例#6
0
def _scan_missing_photos(lib_base_dir):
  """Removes photos from the repository that don't exist in the archive"""
  rep = media_common.Repository()
  try:
    rep.open(lib_base_dir)
    missing_files = []
    for (db_id, filepath) in rep.iter_all_photos():
      if not os.path.isfile(filepath):
        logging.warning('The photo %s was deleted from the ' +
                        'archive unexpectedly. It will be removed from ' +
                        'the database.', filepath)
        missing_files.append(db_id)
    rep.remove_photos(missing_files)
  finally:
    rep.close()
示例#7
0
 def test_remove_photos(self):
     rep = media_common.Repository()
     rep.con = MagicMock()
     execute = rep.con.cursor.return_value.execute
     rep.remove_photos([1, 4])
     execute.assert_called_with(ANY, [1, 4])
示例#8
0
 def test_lookup_hash(self):
     rep = media_common.Repository()
     rep.con = MagicMock()
     fetch_mock = rep.con.cursor.return_value.execute.return_value.fetchone
     fetch_mock.return_value = (42, '/tmp/foo')
     self.assertEquals('/tmp/foo', rep.lookup_hash('bar')[1])
示例#9
0
 def _execute_tester(self, method):
     rep = media_common.Repository()
     rep.con = MagicMock()
     rep.con.cursor.return_value.execute.return_value = [1, 4]
     self.assertEquals(rep.con.cursor.return_value, method(rep))
     self.assertTrue(rep.con.cursor.return_value.execute.called)
示例#10
0
 def test_tree_setup(self, mkdir):
     media_common.Repository()._tree_setup('/tmp/foo')
     self.assertEquals(2, mkdir.call_count)
示例#11
0
 def setUp(self):
     self.rep = media_common.Repository()
     pass
示例#12
0
 def test_init_db(self):
     rep = media_common.Repository()
     cur = Mock()
     rep._init_db(cur)
     self.assertTrue(cur.execute.called)
示例#13
0
 def test_get_db_name(self):
     rep = media_common.Repository()
     self.assertEquals('media.db', rep._get_db_name())
示例#14
0
 def test_lookup_hash_not_found(self):
     rep = media_common.Repository()
     rep.con = MagicMock()
     fetch_mock = rep.con.cursor.return_value.execute.return_value.fetchone
     fetch_mock.return_value = None
     self.assertEquals(None, rep.lookup_hash('bar'))
示例#15
0
def _find_and_archive_photos(search_dir,
                             lib_base_dir,
                             delete_source_on_success,
                             group_name):
  """Sets up or opens a media library and adds new photos
  to the library and its database.
  
  The source image files will be deleted if --del_src is
  specified.
  """
  

  rep = media_common.Repository()
  rep.open(lib_base_dir)
  paths = os.walk(search_dir)
  results = []
  group_id = media_common.get_group_id(group_name)
  files_to_delete = []
  archive_count = 0
  for (dirpath, dirnames, filenames) in paths:
    for filename in filenames:
      path = os.path.join(dirpath, filename)
      if os.path.isfile(path):
        photo = media_common.Photo(path)
        photo.load_metadata()
        db_result = rep.lookup_hash(photo.md5)
        if (db_result is not None
            and os.path.abspath(db_result[1]) == os.path.abspath(path)):
          logging.info('Found existing archived photo %s, ignoring',
                       db_result[1])
        elif (db_result is not None
            and os.path.isfile(db_result[1])
            and delete_source_on_success):
          # file is a duplicate and the original is still around
          logging.info('Deleting the source file %s, which is a ' +
                       'duplicate of existing file %s',
                       photo.source_path, db_result[1])
          os.remove(photo.source_path)
        elif (db_result is not None
              and os.path.isfile(db_result[1])):
          # same as above, but client didn't request deletion
          logging.info('Ignoring the source file %s, which is a ' +
                       'duplicate of existing file %s',
                       photo.source_path, db_result[1])
        elif db_result is not None:
          # file was deleted from archive, remove it from repository
          logging.info('Photo %s was deleted from the archive, replacing' +
                       ' it with the new one.', db_result[1])
          if (_archive_photo(photo, lib_base_dir, rep, group_id) and
              delete_source_on_success):
            files_to_delete.append(photo.source_path)
        else:
          archive_count += 1
          if (_archive_photo(photo, lib_base_dir, rep, group_id) and
              delete_source_on_success):
            files_to_delete.append(photo.source_path)
      else:
        logging.warning('Found a non-file when looking for photos: %s, ' +
                        'it will not be modified', path)

  rep.close()
  for filepath in files_to_delete:
    os.remove(filepath)
  logging.info('Successfully completed archiving %d files', archive_count)
示例#16
0
gflags.DEFINE_string(
    'group_name', '',
    'The name of the group to use' + ' for the daemon process')
gflags.DEFINE_string('user_name', '',
                     'The name of the user to use' + ' for the daemon process')
gflags.DEFINE_string('media_dir', None, 'Directory of media library')
gflags.DEFINE_boolean('daemon', True, 'Run the server as a daemon')

gflags.MarkFlagAsRequired('media_dir')
gflags.MarkFlagAsRequired('group_name')
gflags.MarkFlagAsRequired('user_name')

FLAGS = gflags.FLAGS

repository = media_common.Repository()


def run_server(lib_base_dir):
    repository.open(lib_base_dir)
    logging.info('opened repository at %s', lib_base_dir)
    server = SimpleXMLRPCServer(('192.168.1.27', 9333), logRequests=True)
    server.register_function(check_file_hash)
    try:
        print 'Use Control-C to exit'
        server.serve_forever()
    except KeyboardInterrupt:
        print 'Exiting'


def check_file_hash(hash):
示例#17
0
 def test_iter_all_photos(self):
     rep = media_common.Repository()
     rep.con = MagicMock()
     rep.con.cursor.return_value.execute.return_value = [1, 4]
     self.assertEquals(rep.con.cursor.return_value, rep.iter_all_photos())
     self.assertTrue(rep.con.cursor.return_value.execute.called)