Modify

Opened 9 years ago

Closed 9 years ago

#12430 closed defect (fixed)

Can't get XMLRPC server.ticket.update() to modify tickets

Reported by: anonymous Owned by: osimons
Priority: normal Component: XmlRpcPlugin
Severity: normal Keywords: XmlRpc
Cc: Trac Release: 1.0

Description (last modified by Ryan J Ollos)

I am attempting to synchronize my trac tickets with an external database. I need to use the ticket.update() function to modify tickets as they are changed in the database.

I am attempting this with a simple example:

p = xmlrpclib.ServerProxy(trac_server % (user_name, password))

ticketNumber = p.ticket.get(92)
about = p.ticket.update(
        int('92'),
        {"reporter": "bumpudj",
         "keywords": "",
         "version": "4.0.0",
         "component": "D2D",
         "owner": "bumpudj",
         "type": "defect",
         "resolve": "Not yet resolved",
         "milestone": "D2D_Sync_Issues",
         "requestor": "",
         "status": "",
         "collective": 6.1,
         "d2d_id": '12',
         "action": "resolve",
         "action_resolve_resolve_resolution": "fixed",
         "_ts":ticketNumber[3]["_ts"]
         })

However, I am getting the following error:

Fault: <Fault 1: "''dict' object has no attribute 'strip'' while executing 'ticket.update()'">

What is the correct syntax for this function?

Attachments (5)

versions_plugins.PNG (98.8 KB) - added by anonymous 9 years ago.
trac_log.PNG (139.1 KB) - added by anonymous 9 years ago.
trac.log (49.3 KB) - added by anonymous 9 years ago.
about_trac.pdf (139.3 KB) - added by Geert 9 years ago.
rpcfail.log (6.0 KB) - added by Geert 9 years ago.

Download all attachments as: .zip

Change History (33)

comment:1 Changed 9 years ago by anonymous

Here's the traceback:

Traceback (most recent call last):
  File "P:/D2D Sync/Test Elements/Update a trac ticket.py", line 58, in <module>
    "_ts":ticketNumber[3]["_ts"]
  File "C:\Python27\lib\xmlrpclib.py", line 1240, in __call__
    return self.__send(self.__name, args)
  File "C:\Python27\lib\xmlrpclib.py", line 1599, in __request
    verbose=self.__verbose
  File "C:\Python27\lib\xmlrpclib.py", line 1280, in request
    return self.single_request(host, handler, request_body, verbose)
  File "C:\Python27\lib\xmlrpclib.py", line 1313, in single_request
    return self.parse_response(response)
  File "C:\Python27\lib\xmlrpclib.py", line 1490, in parse_response
    return u.close()
  File "C:\Python27\lib\xmlrpclib.py", line 799, in close
    raise Fault(**self._stack[0])
Fault: <Fault 1: "''dict' object has no attribute 'strip'' while executing 'ticket.update()'">
Last edited 9 years ago by osimons (previous) (diff)

comment:2 Changed 9 years ago by osimons

Have you looked at the functional tests? Various tests that do update here: source:/xmlrpcplugin/trunk/tracrpc/tests/ticket.py

comment:3 Changed 9 years ago by anonymous

Yes, when I try to run:

  def test_update_time_same(self):
315         # Unrestricted old-style update (to be removed soon)
316         tid = self.admin.ticket.create('test_update_time_same', '...', {})
317         tid, created, modified, attrs = self.admin.ticket.get(tid)
318         ts = attrs['_ts']
319         self.admin.ticket.update(tid, "comment1",
320                     {'_ts': ts})
321         self.admin.ticket.delete(tid)
322
323         # Update with 'action' to test new-style update.
324         tid = self.admin.ticket.create('test_update_time_same', '...', {})
325         tid, created, modified, attrs = self.admin.ticket.get(tid)
326         ts = attrs['_ts'][[BR]]
327         self.admin.ticket.update(tid, "comment1",
328                     {'_ts': ts, 'action': 'leave'})
329         self.admin.ticket.delete(tid)

I get the following error:

Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    p.ticket.update(tid, "comment1", {'_ts': ts, 'action': 'leave'})
  File "C:\Python27\lib\xmlrpclib.py", line 1240, in __call__
    return self.__send(self.__name, args)
  File "C:\Python27\lib\xmlrpclib.py", line 1599, in __request
    verbose=self.__verbose
  File "C:\Python27\lib\xmlrpclib.py", line 1280, in request
    return self.single_request(host, handler, request_body, verbose)
  File "C:\Python27\lib\xmlrpclib.py", line 1313, in single_request
    return self.parse_response(response)
  File "C:\Python27\lib\xmlrpclib.py", line 1490, in parse_response
    return u.close()
  File "C:\Python27\lib\xmlrpclib.py", line 799, in close
    raise Fault(**self._stack[0])
Fault: <Fault 1: "'Sorry, can not save your changes. This ticket has been modified by someone else since you started' while executing 'ticket.update()'">
Last edited 9 years ago by Ryan J Ollos (previous) (diff)

comment:4 Changed 9 years ago by anonymous

The confusion is related to the ['_ts'] parameter. Perhaps you can give me a simple example.

comment:5 Changed 9 years ago by osimons

The 'ts' parameter is passed to you as part of ticket.get(). You just return it exactly as you got it. The purpose is of course to tell the API the time-origin of the data you are now providing updated values for in order to avoid overwriting any changes that happens between you reading the data and updating it again.

comment:6 Changed 9 years ago by anonymous

That's exactly what I'm doing here:

p = xmlrpclib.ServerProxy(trac_server % (user_name, password))
tid, created, modified, attrs = p.ticket.get(92)
about = p.ticket.update(
        tid,
        'comment1',
        {"version": "4.0.1",
         "action": 'leave',
         "_ts":attrs['_ts']
         })

Yet it still gives me the error:

Fault: <Fault 1: "'Sorry, can not save your changes. 
This ticket has been modified by someone else since you started' while executing 'ticket.update()'">

comment:7 Changed 9 years ago by osimons

As TRAC_ADMIN, could you please visit "About Trac" in your local installation and copy & paste your versions for Trac, dependencies and plugins?

Changed 9 years ago by anonymous

Attachment: versions_plugins.PNG added

comment:8 Changed 9 years ago by anonymous

Last edited 9 years ago by Ryan J Ollos (previous) (diff)

comment:9 Changed 9 years ago by osimons

If possible for testing, could you disable a few of the ticket-related plugins and see if any of them interfere with RPC handling? Some I know work fine, so of particular interest for disable are these plugins: blackmagictickettweaks, tracdynamicfields, tracsubticketsplugin, tracticketchainedfields.

I don't know the details of these, but from their names they look to be plugins that could possibly modify request input/output and ticket state handling during processing.

Your code sample should work, and the plugin functional tests pass with similar code also for Trac 1.0. Turning on Trac debug logging (wiki:TracLogging) could perhaps also provide some clues?

comment:10 Changed 9 years ago by anonymous

In the case that one of those plugins is interfering is there any workaround that I can employ in order to keep those plugins and be able to use xmlrpc as well? Disabling the time stamp requirement perhaps?

comment:11 Changed 9 years ago by anonymous

Also, with all of those plugins disabled, the problem remains. Must they be deleted from their listed file locations to completely eliminate anything that may be happening in the code or should it be enough to simply have them disabled?

comment:12 Changed 9 years ago by anonymous

Would it be helpful for you to see the log?

comment:13 Changed 9 years ago by osimons

Let's have a look at the debug log. If you could stop the server, move the current trac.log out of the way, start server and make 1 x ticket.get request & 1 x ticket.update to provoke the error, and then stop the server again. This new log should hopefully contain the lifecycle of relevant code loading and request handling.

Changed 9 years ago by anonymous

Attachment: trac_log.PNG added

comment:14 Changed 9 years ago by anonymous

I can't stop the server, but I believe I have a snip that contains the lifecycle of the error.

Last edited 9 years ago by Ryan J Ollos (previous) (diff)

comment:15 Changed 9 years ago by osimons

Please upload the actual log file, don't screenshot it...

Changed 9 years ago by anonymous

Attachment: trac.log added

comment:16 Changed 9 years ago by osimons

Your call to ticket.update looks like this:

2015-07-06 12:59:43,997 Trac[xml_rpc] DEBUG: RPC(xml) call by 'bumpudj', method 'ticket.update' with args: (97, 'comment1', {'action': 'leave', 'version': '4.0.1', '_ts': '2015-07-06 15:10:07.725000+00:00'})

An example call from my last test suite run looks like this

2015-06-24 23:00:03,320 Trac[xml_rpc] DEBUG: RPC(xml) call by 'admin', method 'ticket.update' with args: (1, 'comment1', {'action': 'leave', '_ts': '1435179603283924'})

Notice format of _ts where you have the string '2015-07-06 15:10:07.725000+00:00' I have '1435179603283924' (which is actually the stringified ticket change timestamp as stored in the database). It is the exact same string I get in the preceding ticket.get (abbreviated for clarity):

... DEBUG: RPC(xml) 'ticket.get' result: [1, ..., {..., '_ts': '1435179603283924', ...}]

comment:17 Changed 9 years ago by anonymous

Very good. My timestamp from ticket.get reads: (Abbreviated for clarity)

...DEBUG: RPC(xml) 'ticket.get' result: [97,...  {..., '_ts': '2015-07-06 15:10:07.725000+00:00', ...}]

Which is the same format of _ts as in my ticket.update that you sited:

2015-07-06 12:59:43,997 Trac[xml_rpc] DEBUG: RPC(xml) call by 'bumpudj', method 'ticket.update' with args: (97, 'comment1', {'action': 'leave', 'version': '4.0.1', '_ts': '2015-07-06 15:10:07.725000+00:00'})

I am confused as to what you are suggesting is the solution to the problem? My log included:

DEBUG: RPC(xml) 'ticket.get' result: [97, datetime.datetime(2015, 7, 6, 15, 10, 7, 725000, tzinfo=<FixedOffset "UTC" 0:00:00>)

Unless you removed it, I do not believe your test suite includes:

datetime.datetime(2015, 7, 24, ..., tzinf0=<FixedOffset...>)

You're suggesting that I change the format of my timestamps? How would I change the format to match yours when I am passing _ts exactly how I am receiving it?

comment:18 in reply to:  17 Changed 9 years ago by osimons

Replying to anonymous:

2015-07-06 12:59:43,997 Trac[xml_rpc] DEBUG: RPC(xml) call by 'bumpudj', method 'ticket.update' with args: (97, 'comment1', {'action': 'leave', 'version': '4.0.1', '_ts': '2015-07-06 15:10:07.725000+00:00'})

I am confused as to what you are suggesting is the solution to the problem?

You're suggesting that I change the format of my timestamps? How would I change the format to match yours when I am passing _ts exactly how I am receiving it?

I have not been suggesting a solution to the problem. I merely specified how the timestamp should look in an attempt to uncover the problem. Now we know. Something somehow makes your timestamps like '_ts': '2015-07-06 15:10:07.725000+00:00' when they should look look like '_ts': '1435179603283924'. The code handling the ticket.update call expects the microseconds timestamp when it compares received value with value stored in the database.

I have no idea why this happens on your installation. The symptom shows up in RPC calls, but I'm not yet convinced that it is actually a problem with the RPC code itself. However, if you can repoduce it in a "clean room" installation that would aid in troubleshooting – a separate Trac with just RPC plugin installed. A virtualenv on the same machine would be great (same OS, same Python):

$ cd /path/to/testarea
$ virtualenv rpc-12430
$ cd rpc-12430
$ source bin/activate
(rpc-12430)$ pip install Trac==1.0
(rpc-12430)$ easy_install -Z -U http://trac-hacks.org/svn/xmlrpcplugin/trunk
(rpc-12430)$ trac-admin testproject initenv                     # accept defaults
(rpc-12430)$ trac-admin testproject config set components tracrpc.* enabled  # enable plugin
(rpc-12430)$ trac-admin testproject permission add anonymous TRAC_ADMIN      # ignore permission issues
(rpc-12430)$ trac-admin testproject config set logging log_type file         # enable logging
(rpc-12430)$ trac-admin testproject config set logging log_level DEBUG       # debug level
(rpc-12430)$ tracd --port=8999 testproject                      # start server

You should not be able to browse to the site at http://127.0.0.1:8999/testproject, and use http://127.0.0.1:8999/testproject/rpc for RPC access. Create a ticket through a browser, and then use RPC as before to do ticket.get and ticket.update while keeping an eye on '_ts'.

$ python
>>> import xmlrpclib
>>> p = xmlrpclib.ServerProxy('http://127.0.0.1:8999/testproject/rpc')
>>> p.ticket.get(1)
[1,
 <DateTime '20150707T20:48:06' at 10a120d40>,
 <DateTime '20150707T20:48:06' at 10a120d88>,
 {'_ts': '1436302086554388',
  'cc': '',
   ...

Check logs:

$ grep '_ts' testproject/log/trac.log

comment:19 Changed 9 years ago by anonymous

Would it be possible to force the timestamp to be an acceptable time? Would the ticket.update() function accept a value for '_ts' that is in the future?

For example if the current time is '2015-07-06 15:10:07.725000+00:00', could I add 100 seconds so that the function recieves '2015-07-06 15:11:47.725000+00:00'?

In this case, it would be impossible for tickets to have been modified between ticket.get() and ticket.update()

comment:20 Changed 9 years ago by anonymous

Or can you give me a different version of the plugin which is not so strict regarding timestamps or tell me where I can modify the code to circumnavigate this error?

The way I am using this function, it is extremely unlikely (perhaps impossible) that a ticket would be modified between the ticket.get() and ticket.update() functions.

In summary:

For my application, this protection does more harm than good.

comment:21 Changed 9 years ago by anonymous

A couple of things to note: Avoiding this is already a feature of Trac trac:#11489 & trac:#7145

And apparently you can override the warning by pressing submit twice: http://www.gossamer-threads.com/lists/trac/users/51313

How would I do this through XmlRpc.

Also noteworthy is that I do not have Agilo.

Last edited 9 years ago by Ryan J Ollos (previous) (diff)

comment:22 Changed 9 years ago by anonymous

Trac 1.0 is incompatible with xmlrpc 1.1.2. After updating xmlrpc, the function works as expected.

comment:23 Changed 9 years ago by osimons

So I can close ticket with worksforme resolution based on latest version (1.1.4)?

Last edited 9 years ago by Ryan J Ollos (previous) (diff)

comment:24 Changed 9 years ago by anonymous

Yes

comment:25 Changed 9 years ago by osimons

Resolution: worksforme
Status: newclosed

All right. Thanks.

comment:26 Changed 9 years ago by Geert

Resolution: worksforme
Status: closedreopened

I have the same problem with Trac 1.0 and xmlrpc 1.1.4.

If I get a ticket, modify it and update it I get fault

xmlrpclib.Fault: <Fault 1: "''datetime.datetime' object has no attribute 'strip'' while executing 'ticket.update()'">

See attachments.

Changed 9 years ago by Geert

Attachment: about_trac.pdf added

Changed 9 years ago by Geert

Attachment: rpcfail.log added

comment:27 Changed 9 years ago by Ryan J Ollos

Description: modified (diff)

comment:28 Changed 9 years ago by osimons

Resolution: fixed
Status: reopenedclosed

In 15032:

XmlRpcPlugin: Never try to update ticket 'time' and 'changetime' fields. Closes #12430.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain osimons.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.