Skip to main content
ADrobkov
Known Participant
November 14, 2019
Answered

photo:addKeyword( keyword ) by several photos

  • November 14, 2019
  • 6 replies
  • 1378 views

Hello! Faced with such a problem. The value of metadata trying to make keywords.

If one photo is selected, then everything works out correctly.. But if you choose 2 or more photos, the error falls out  "Внутренняя ошибка: assertion failed!" 

 

 

local photos = catalog.targetPhotos
local countPhotos = #photos
local keywords = catalog:getKeywords()
local keywordCategory
for k, keyword in ipairs(keywords) do
	if  keyword:getName() == "PERSON" then
		keywordCategory = keyword
	end
end
for i, photo in ipairs(photos) do
	local participant = photo:getFormattedMetadata("licensor") or ""
	local participantCount = #participant
	keywordPerson = catalog:createKeyword( photo:getFormattedMetadata ("licensor")[1].LicensorName, nil, false, keywordCategory, true )
	photo:addKeyword( keywordPerson )
end

 

 

Tell me what I'm missing. Like in a loop should run through all the photos. Metadata in the same way inserts...

This topic has been closed for replies.
Correct answer johnrellis

"On every action generated its step history, otkatyvaemyy on CTRL+Z. And this means, that if I wrong suddenly call its script on 500 photo, then me 500 times press CTRL+Z."

 

I think the workaround is to use a more complicated method of doing this that avoids calling catalog:createKeyword() with returnExisting = true, which I think is the cause of the problem:

 

1. Loop over the photos and build a table that maps LicensorName to existing LrKeyword objects.  Also build an array of LicensorNames that don't currently have keywords.

 

2. Inside catalog:withWriteAccessDo(), first create the keywords for the LicensorNames that currently don't have them, updating the table that maps LicensorName to LrKeyword as you go.  Then loop through all the photos, assigning the keywords to photos (using that table).

 

I have a plugin that uses this method without any issues.

 

6 replies

johnrellis
Legend
November 16, 2019

"But the following error falls out: "Assertion failed: packed". What am I doing wrong here?"

 

Don't know, but try using a separate catalog:withWriteAccessDo() for creating the smart collection.

johnrellis
johnrellisCorrect answer
Legend
November 16, 2019

"On every action generated its step history, otkatyvaemyy on CTRL+Z. And this means, that if I wrong suddenly call its script on 500 photo, then me 500 times press CTRL+Z."

 

I think the workaround is to use a more complicated method of doing this that avoids calling catalog:createKeyword() with returnExisting = true, which I think is the cause of the problem:

 

1. Loop over the photos and build a table that maps LicensorName to existing LrKeyword objects.  Also build an array of LicensorNames that don't currently have keywords.

 

2. Inside catalog:withWriteAccessDo(), first create the keywords for the LicensorNames that currently don't have them, updating the table that maps LicensorName to LrKeyword as you go.  Then loop through all the photos, assigning the keywords to photos (using that table).

 

I have a plugin that uses this method without any issues.

 

johnrellis
Legend
November 16, 2019

I also got the "assertion failed" when I used two photos with the same LicensorName.  Below is a version that works correctly in that case. The problem seems to be calling catalog:createKeyword() more than once in a single invocation of catalog:withWriteAccessDo().   I don't know why that causes problems, but rewriting the code to do only one call to catalog:createKeyword() inside catalog:withWriteAccessDo() avoids the problem.

 

local Require = require 'Require'.path ("../common").reload ()
local Debug = require 'Debug'.init ()
require 'strict'

local LrApplication = import "LrApplication"
local LrProgressScope = import "LrProgressScope"
local LrTasks = import "LrTasks"

local catalog = LrApplication.activeCatalog ()

function showDialog(context)
    local props = LrBinding.makePropertyTable(context)
    local fillFormat = props.fillFormat
    prefs.fillFormat = fillFormat
    updateFill(fillFormat)
end

function updateFill(fillFormat)
    LrTasks.startAsyncTask(function()
        local photos = catalog.targetPhotos
        local countPhotos = #photos
        local ProgressBar = LrProgressScope({
            title = "Инициализация данных об участниках для " .. 
            tostring(countPhotos) .. " файла(ов)"})
        local keywords = catalog:getKeywords()
        local keywordCategory
        for k, keyword in ipairs(keywords) do
            if  keyword:getName() == "PERSON" then
                keywordCategory = keyword
            end
        end
        for i, photo in ipairs(photos) do
            local participant = photo:getFormattedMetadata("licensor") or ""
            local participantCount = #participant
            for j = 1, participantCount do
                catalog:withWriteAccessDo("&Инициализация данных об участниках", 
                function()
                    local keywordPerson = catalog:createKeyword( 
                      photo:getFormattedMetadata ("licensor")[j].LicensorName, 
                      nil, false, keywordCategory, true )
                    photo:addKeyword( keywordPerson )
                end)
            end      
        ProgressBar:setPortionComplete( i, countPhotos )
        end
        ProgressBar:done()
    end)
end

updateFill (nil)
ADrobkov
ADrobkovAuthor
Known Participant
November 16, 2019

Yes, thank you! This helps to avoid the problem! But creates another problem. On every action generated its step history, otkatyvaemyy on CTRL+Z. And this means, that if I wrong suddenly call its script on 500 photo, then me 500 times press CTRL+Z.

johnrellis
Legend
November 15, 2019

"In my case, the "LrKeyword" object should return, and False is returned ((("

 

Not sure what might going on.  I ran this slightly modified script with two photos selected, and it created two keywords under PERSON with names corresponding to the Licensor Name fields in the metadata. 

 

Try saving this exact script to a file and running it, using File > Plug-in Extras > Debugging Toolkit > Debug Script:

local Require = require 'Require'.path ("../common").reload ()
local Debug = require 'Debug'.init ()
require 'strict'

local LrApplication = import "LrApplication"
local LrProgressScope = import "LrProgressScope"
local LrTasks = import "LrTasks"

local catalog = LrApplication.activeCatalog ()

function showDialog(context)
  local props = LrBinding.makePropertyTable(context)
    local fillFormat = props.fillFormat
    prefs.fillFormat = fillFormat
    updateFill(fillFormat)
end

function updateFill(fillFormat)
  LrTasks.startAsyncTask(function()
    catalog:withWriteAccessDo("&Инициализация данных об участниках", function()
      local photos = catalog.targetPhotos
      local countPhotos = #photos
      local ProgressBar = LrProgressScope({
        title = "Инициализация данных об участниках для " .. 
          tostring(countPhotos) .. " файла(ов)"
      })
      local keywords = catalog:getKeywords()
      local keywordCategory
      for k, keyword in ipairs(keywords) do
        if  keyword:getName() == "PERSON" then
          keywordCategory = keyword
        end
      end
      for i, photo in ipairs(photos) do
        local participant = photo:getFormattedMetadata("licensor") or ""
        local participantCount = #participant
        for j = 1, participantCount do
        local keywordPerson = catalog:createKeyword( 
          photo:getFormattedMetadata ("licensor")[j].LicensorName, 
          nil, false, keywordCategory, true )
        photo:addKeyword( keywordPerson )
        end      
        ProgressBar:setPortionComplete(i, countPhotos)
      end
      ProgressBar:done()
    end)
  end)
end

updateFill (nil)

   

ADrobkov
ADrobkovAuthor
Known Participant
November 15, 2019

Still the same(((

Are the values in the Licensor Name the same? I do.

If I perform on one, then everything is correct!

johnrellis
Legend
November 15, 2019

It's not readily apparent where the "assertion failed" is coming from.   You'll have to insert logging print statements (see the SDK Guide) or use a debugger (e.g. my Debugging Toolkit or ZeroBrane IDE) to narrow down exactly where it's failing.

 

[Use the reply button under the first post to ensure replies sort properly.]

ADrobkov
ADrobkovAuthor
Known Participant
November 15, 2019

Thanks for the hint! Installed your plugin and found this error... The variable "keyword Person" on the first photo had an object inside, and on the second photo it was false...

Only until I understood why...

ADrobkov
ADrobkovAuthor
Known Participant
November 15, 2019

 

Return value

(LrKeyword) The new keyword object, or false if a keyword already exists with the same name and parent, assuming that 'returnExisting' is not specified or false. If 'returnExisting' is true and the keyword with the same name and parent already exists, that keyword object will be returned.

Judging by the description in the SDK, when passed "return Existing = true", false cannot be returned...

keywordPerson = catalog:createKeyword( photo:getFormattedMetadata ("licensor")[c].LicensorName, nil, false, keywordCategory, true )

In my case, the "LrKeyword" object should return, and False is returned (((

 

johnrellis
Legend
November 14, 2019

I see a couple of things:

local participant = photo:getFormattedMetadata("licensor") or ""

 If the photo doesn't have any "licensor" metadata, then "participant" gets assigned the empty string, and then the following statements try to index "participant" as an array. You'll need to check for a nil value for "licensor".

 

photo:addKeyword( keywordPerson )

photo:addKeyword() needs to be called inside a call to catalog:withWriteAccessDo().

ADrobkov
ADrobkovAuthor
Known Participant
November 14, 2019

To be honest, I am not a programmer and do not understand what "catalog:with Write Access Do" means, but the description for "photo:set Raw Metadata( key, value)" says the same. And setRawMetadata works for me...