forked from urschrei/pyzotero
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.txt
756 lines (463 loc) · 25.5 KB
/
index.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
Description
===========
A Python wrapper for the `Zotero API <http:https://www.zotero.org/support/dev/server_api>`_. You'll require a user ID and access key, which can be set up `here <http:https://www.zotero.org/settings/keys/new>`_.
.. Pyzotero documentation master file, created by
sphinx-quickstart on Mon Jul 4 19:39:03 2011.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. py:module:: pyzotero.zotero
.. toctree::
:maxdepth: 2
Getting started (short version)
===============================
1. In a shell / prompt: ``pip install pyzotero``. Then:
.. _hello-world:
.. code-block:: python
:emphasize-lines: 1,2,3
from pyzotero import zotero
zot = zotero.Zotero(user_id, user_key)
items = zot.top(limit = 5)
# we have now retrieved the last five top-level items in our library
# we can print each item's item type and ID
for item in items:
print 'Item Type: %s | Key: %s' % (item['itemType'], item['key'])
2. Refer to the :ref:`read` and :ref:`write`.
Installation, testing, usage (longer version)
=============================================
============
Installation
============
Using `pip <http:https://www.pip-installer.org/en/latest/index.html>`_: ``pip install pyzotero``
From a local clone, if you wish to install Pyzotero from a specific branch:
.. code-block:: bash
git clone git:https://github.com/urschrei/pyzotero.git
cd pyzotero
git checkout dev
pip install .
Alternatively, download the latest stable version from https://github.com/urschrei/pyzotero/tags, and point pip at the zip file.
Example: ``pip install ~/Downloads/urschrei-pyzotero-v0.3-0-g04ff544.zip``
The Pyzotero source tarball is also available from `PyPI <http:https://pypi.python.org/pypi/Pyzotero>`_
The `feedparser <http:https://feedparser.org>`_ (>= 0.5.1) and `pytz <http:https://pypi.python.org/pypi/pytz/>`_ modules are required. They will be automatically installed when installing Pyzotero using pip.
Installation using ``easy_install`` may be successful, but is neither tested nor officially supported – pip is the preferred method.
===============================
Installing development versions
===============================
Pyzotero remains in development as of March 2012. Unstable development versions can be found on the `Github dev branch <https://github.com/urschrei/pyzotero/tree/dev>`_, and installed directly from there using pip: ``pip install -e git+https://github.com/urschrei/pyzotero.git@dev#egg=pyzotero``, or from the checked-out ``dev`` branch on a local clone, as in the example above.
=======
Testing
=======
Run ``tests.py`` in the pyzotero directory, or, using `Nose <http:https://readthedocs.org/docs/nose/en/latest/>`_, ``nosetests``. If you wish to see coverage statistics, run ``nosetests --with-coverage --cover-package=pyzotero``.
======================
Building Documentation
======================
If you wish to build Pyzotero's documentation for offline use, it can be built from the ``doc`` directory of a local git repo by running ``make`` followed by the desired output format(s) (``html``, ``epub``, ``latexpdf`` etc.)
See the `Sphinx documentation <http:https://sphinx.pocoo.org/tutorial.html#running-the-build>`_ for full details.
================
Reporting issues
================
If you encounter an error while using Pyzotero, please open an issue on its `Github issues page <https://github.com/urschrei/pyzotero/issues>`_.
=====================
General Usage
=====================
First, create a new Zotero instance:
.. py:class:: Zotero(userID, userKey)
:param str userID: a valid Zotero API user ID
:param str userKey: a valid Zotero API user key
Example:
.. code-block:: python
:emphasize-lines: 4
from pyzotero import zotero
zot = zotero.Zotero(123, ABC1234XYZ)
# we now have a Zotero object, zot, and access to all its methods
first_ten = zot.items(limit = 10)
# a list containing dicts of the ten most recently modified library items
.. _read:
Read API Methods
====================
**Note:** :ref:`search/request parameters <parameters>` inside square brackets are optional. Methods such as :py:meth:`Zotero.top()`, :py:meth:`Zotero.items()` etc. can be called with no additional parameters if you wish.
====================
Retrieving Items
====================
.. py:method:: Zotero.items([search/request parameters])
Returns Zotero library items
:rtype: list of dicts
.. py:method:: Zotero.top([search/request parameters])
Returns top-level Zotero library items
:rtype: list of dicts
.. py:method:: Zotero.trash([search/request parameters])
Returns library items from the user's trash
:rtype: list of dicts
.. py:method:: Zotero.item(itemID[, search/request parameters])
Returns a specific item
:param str itemID: a zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.children(itemID[, search/request parameters])
Returns the child items of a specific item
:param str itemID: a zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.tag_items(itemID[, search/request parameters])
Returns items for a specific tag
:param str itemID: a zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.group_items(groupID[, search/request parameters])
Returns items from a specific group
:param str groupID: a Zotero group ID
:rtype: list of dicts
.. py:method:: Zotero.group_trash(groupID[, search/request parameters])
Returns items from a specific group's trash
:param str groupID: a Zotero group ID
:rtype: list of dicts
.. py:method:: Zotero.group_top(groupID[, search/request parameters])
Returns top-level items from a specific group
:param str groupID: a Zotero group ID
:rtype: list of dicts
.. py:method:: Zotero.group_item(groupID, itemID[, search/request parameters])
Returns a specific item from a specific group
:param str groupID: a Zotero group ID
:param str itemID: a Zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.group_item_children(groupID, itemID[, search/request parameters])
Returns the child items of a specific item from a specific group
:param str groupID: a Zotero group ID
:param str itemID: a Zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.group_items_tag(groupID, tag[, search/request parameters])
Returns a specific group's items for a specific tag
:param str groupID: a Zotero group ID
:param str tag: a tag whose items you wish to return
:rtype: list of dicts
.. py:method:: Zotero.group_collection_items(groupID, collection ID[, search/request parameters])
Returns a specific collection's items from a specific group
:param str groupID: a Zotero group ID
:param str collectionID: a Zotero collection ID
:rtype: list of dicts
.. py:method:: Zotero.group_collection_item(groupID, collectionID, itemID[, search/request parameters])
Returns a specific collection's item from a specific group
:param str groupID: a Zotero group ID
:param str collectionID: a Zotero collection ID
:param str itemID: a Zotero item ID
:rtype: list of dicts
.. py:method:: Zotero.group_collection_top(groupID, collectionID[, search/request parameters])
Returns a specific collection's top-level items from a specific group
:param str groupID: a Zotero group ID
:param str groupID: a Zotero collection ID
:rtype: list of dicts
.. py:method:: Zotero.collection_items(collectionID[, search/request parameters])
Returns items from the specified collection
:param str collectionID: a Zotero collection ID
:rtype: list of dicts
.. py:method:: Zotero.get_subset(itemIDs[, search/request parameters])
Retrieve an arbitrary set of non-adjacent items. Limited to 50 items per call.
:param list itemIDs: a list of Zotero Item IDs
:rtype: list of dicts
.. _returned:
Example of returned data:
.. code-block:: python
[{'DOI': '',
'ISSN': '1747-1532',
'abstractNote': '',
'accessDate': '',
'archive': '',
'archiveLocation': '',
'callNumber': '',
'creators': [{'creatorType': 'author',
'firstName': 'T. J.',
'lastName': 'McIntyre'}],
'date': '2007',
'extra': '',
'issue': '',
'itemType': 'journalArticle',
'journalAbbreviation': '',
'language': '',
'libraryCatalog': 'Google Scholar',
'pages': '',
'publicationTitle': 'Journal of Intellectual Property Law & Practice',
'rights': '',
'series': '',
'seriesText': '',
'seriesTitle': '',
'shortTitle': 'Copyright in custom code',
'tags': [],
'title': 'Copyright in custom code: Who owns commissioned software?',
'updated': 'Mon, 14 Mar 2011 22:30:17 GMT',
'url': '',
'volume': ''}]
See :ref:`'Hello World' <hello-world>` example, above
=======================
Retrieving Collections
=======================
.. py:method:: Zotero.collections([search/request parameters])
Returns a user's collections
:rtype: list of dicts
.. py:method:: Zotero.collections_sub(collectionID[, search/request parameters])
Returns a sub-collection from a specific collection
:param str collectionID: a Zotero library collection ID
:rtype: list of dicts
.. py:method:: Zotero.group_collections(groupID[, search/request parameters])
Returns collections for a specific group
:param str groupID: a Zotero group ID
:rtype: list of dicts
.. py:method:: Zotero.group_collection(groupID, collectionID[, search/request parameters])
Returns a specific collection from a specific group
:param str groupID: a Zotero group ID
:param str collectionID: a Zotero collection ID
:rtype: list of dicts
Example of returned data:
.. code-block:: python
[{'key': 'PRMD6BGB', 'name': "A Midsummer Night's Dream"}]
==========================
Retrieving groups
==========================
.. py:method:: Zotero.groups([search/request parameters])
Retrieve the Zotero group data to which the current user key has access
:rtype: list of dicts
Example of returned data:
.. code-block:: python
[{u'description': u'%3Cp%3EBGerman+Cinema+and+related+literature.%3C%2Fp%3E',
u'fileEditing': u'none',
u'group_id': u'153',
u'hasImage': 1,
u'libraryEditing': u'admins',
u'libraryEnabled': 1,
u'libraryReading': u'all',
u'members': {u'0': 436,
u'1': 6972,
u'15': 499956,
u'16': 521307,
u'17': 619180},
u'name': u'German Cinema',
u'owner': 10421,
u'type': u'PublicOpen',
u'url': u''}]
===================
Retrieving Tags
===================
.. py:method:: Zotero.tags([search/request parameters])
Returns a user's tags
:rtype: list of strings
.. py:method:: Zotero.item_tags(itemID[, search/request parameters])
Returns tags from a specific item
:param str itemID: a valid Zotero library Item ID
:rtype: list of strings
.. py:method:: Zotero.group_tags(groupID[, search/request parameters])
Returns tags from a specific group
:param str groupID: a valid Zotero library group ID
:rtype: list of strings
.. py:method:: Zotero.group_item_tags(groupID, itemID[, search/request parameters])
Returns tags from a specific item from a specific group
:param str groupID: a valid Zotero library group ID
:param str itemID: a valid Zotero library Item ID
:rtype: list of strings
Example of returned data:
::
['Authority in literature', 'Errata']
=======================
The ``follow()`` method
=======================
This method (currently experimental) aims to make Pyzotero a little more RESTful. Following any Read API call which can retrieve **multiple items**, calling ``follow()`` will repeat that call, but for the next *x* number of items, where *x* is either a number set by the user for the original call, or 50 by default. Each subsequent call to ``follow()`` will extend the offset.
Example:
::
from pyzotero import zotero
zot = zotero.Zotero(user_id, user_key)
# only retrieve a single item
# this will retrieve the most recently added/modified top-level item
first_item = zot.top(limit=1)
# now we can start retrieving subsequent items
next_item = zot.follow()
third_item = zot.follow()
===========================
The ``everything()`` method
===========================
This method (currently experimental) will retrieve **all** library items specified by its argument: a valid Read API call which can retrieve multiple items..
Example:
::
from pyzotero import zotero
zot = zotero.Zotero(user_id, user_key)
# retrieve all top-level items
toplevel = zot.everything(zot.top())
The ``everything()`` method should work with all Pyzotero Read API calls which can return multiple items, but has not yet been extensively tested. `Feedback is welcomed <https://github.com/urschrei/pyzotero/issues>`_.
.. warning:: The ``follow()`` and ``everything()`` methods are only valid for methods which can return multiple library items. For instance, you cannot use ``follow()`` after an ``item()`` call.
======================
Retrieving item counts
======================
If you wish to retrieve item counts for subsets of a library, you can use the following methods:
.. py:method:: Zotero.num_items()
Returns the count of top-level items in the library
:rtype: int
.. py:method:: Zotero.num_collectionitems(collectionID)
Returns the count of items in the specified collection
:rtype: int
.. py:method:: Zotero.num_tagitems(tag)
Returns the count of items for the specified tag
:rtype: int
.. py:method:: Zotero.num_groupitems(groupID)
Returns the count of items in the specified group
:rtype: int
.. _parameters:
==============================================
Search / Request Parameters for Read API calls
==============================================
Additional parameters may be set on Read API methods **following any required parameters**, or set using the :py:meth:`Zotero.add_parameters()` method detailed below.
All parameters are optional. **You may also set a search term here, using the 'itemType', 'q', or 'tag' parameters**.
This area of the Zotero Read API is under heavy development as of early 2012, and may change frequently. See `the API documentation <http:https://www.zotero.org/support/dev/server_api/read_api#search_syntax>`_ for the most up-to-date details of search syntax usage and export format details.
.. py:method:: Zotero.add_parameters([format=None, itemKey=None, itemType=None, q=None, tag=None, limit=None, start=None, order=None, sort=None, [content=None[ ,style=None]]])
:param str format: only 'keys' is currently supported as an alternate format
:param str itemKey: A comma-separated list of item keys. Valid only for item requests. Up to 50 items can be specified in a single request.
:param str itemType: item type search
:param str q: a search term, which currently matches titles and individual creator fields
:param str tag: tag search
:param int limit: 1 – 99 or None
:param int start: 1 – total number of items in your library or None
:param str order: any one of the following: “dateAdded”, “dateModified”, “title”, “creator”, “type”, “date”, “publisher”, “publication”, “journalAbbreviation”, “language”, “accessDate”, “libraryCatalog”, “callNumber”, “rights”, “addedBy”, “numItems”
:param str sort: 'asc' or 'desc'
:param str content: 'bib', or one of the export formats (see below). If 'bib' is passed, you may also pass:
:param str style: Any valid CSL style in the Zotero style repository
:rtype: list of HTML strings or None
The following two examples produce the same result::
# set parameters on the call itself
z = zot.top(limit=7, start=3)
# set parameters using explicit method
zot.add_parameters(limit=7, start=3)
z = zot.top()
.. note::
Any parameters you set will be valid **for the next call only**. Any parameters set using ``add_parameters()`` will be overridden by parameters you pass in the call itself.
A note on the ``content`` and ``style`` parameters:
Example::
zot.add_parameters(content='bib', style='mla')
If these are set, the return value is a list of UTF-8 formatted HTML ``div`` elements, each containing an item:
``['<div class="csl-entry">(content)</div>', … ]``.
You may also set ``content='citation'`` if you wish to retrieve citations. Similar to ``bib``, the result will be a list of one or more HTML ``span`` elements.
If you select one of the available `export formats <http:https://www.zotero.org/support/dev/server_api/read_api#export_formats>`_ as the ``content`` parameter, pyzotero will in most cases return a list of unicode strings in the format you specified. The exception is the ``csljson`` format, which is parsed into a list of dicts. Please note that you must provide a ``limit`` parameter if you specify one of these export formats. Multiple simultaneous retrieval of particular formats, e.g. ``content="json,coins"`` is not currently supported.
If you set ``format='keys'``, a newline-delimited string containing item keys will be returned
.. _write:
Write API Methods
=================
=================
Item Methods
=================
.. py:method:: Zotero.item_types()
Returns a dict containing all available item types
:rtype: dict
.. py:method:: Zotero.item_fields()
Returns a dict of all available item fields
:rtype: dict
.. py:method:: Zotero.item_creator_types(itemtype)
Returns a dict of all valid creator types for the specified item type
:param str itemtype: a valid Zotero item type. A list of available item types can be obtained by the use of :py:meth:`item_types()`
:rtype: dict
.. py:method:: Zotero.creator_fields()
Returns a dict containing all localised creator fields
:rtype: dict
.. py:method:: Zotero.item_type_fields(itemtype)
Returns all valid fields for the specified item type
:param str itemtype: a valid Zotero item type. A list of available item types can be obtained by the use of :py:meth:`item_types()`
:rtype: list of dicts
.. py:method:: Zotero.item_template(itemtype)
Returns an item creation template for the specified item type
:param str itemtype: a valid Zotero item type. A list of available item types can be obtained by the use of :py:meth:`item_types()`
:rtype: dict
.. py:method:: Zotero.check_items(items)
Check whether items to be created on the server contain only valid keys. This method first creates a set of valid keys by calling :py:meth:`item_fields()`, then compares the user-created dicts to it. If any keys in the user-created dicts are unknown, a ``KeyError`` exception is raised, detailing the invalid fields.
:param list items: one or more dicts containing item data
:rtype: Boolean
.. py:method:: Zotero.create_items(items)
Create Zotero library items
:param list items: one or more dicts containing item data
:rtype: list of dicts
Returns a copy of the created item(s), if successful. Use of :py:meth:`item_template` is recommended in order to first obtain a dict with a structure which is known to be valid.
Before calling this method, the use of :py:meth:`check_items()` is encouraged, in order to confirm that the item to be created contains only valid fields.
Example:
.. code-block:: python
template = zot.item_template('book')
template['creators'][0]['firstName'] = 'Monty'
template['creators'][0]['lastName'] = 'Cantsin'
template['title'] = 'Maris Kundzins: A Life'
resp = zot.create_items([template])
If successful, ``resp`` will have the same structure as items retrieved with an :py:meth:`items()` call, e.g. a list of one or more dicts (see :ref:`Item Data <returned>`, above).
.. py:method:: Zotero.update_item(item)
Update an item in your library
:param dict item: a dict containing item data
:rtype: Boolean
Returns a copy of the updated item, if successful. Before calling this method, the use of :py:meth:`check_items()` is encouraged, in order to confirm that the item to be created contains only valid fields.
Example:
.. code-block:: python
i = zot.items()
# see above for example of returned item structure
# modify the latest item which was added to your library
i[0]['title'] = 'The Sheltering Sky'
i[0]['creators'][0]['firstName'] = 'Paul'
i[0]['creators'][0]['lastName'] = 'Bowles'
zot.update_item(i[0])
Deleting items:
.. py:method:: Zotero.delete_item(item)
Delete an item from your library
:param dict item: a dict containing item data. As in the previous example, you must first retrieve the item(s) you wish to delete, and pass it/them to the method one by one. Deletion of multiple items is most easily accomplished using e.g. a ``for`` loop.
:rtype: Boolean
Example:
.. code-block:: python
:emphasize-lines: 5
i = zot.items()
# only delete the last five items we added
to_delete = i[:5]
for d in to_delete:
zot.delete_item(d)
Adding tags:
.. py:method:: Zotero.add_tags(item, tag[, tag …])
Add one or more tags to an item, and update it on the server
:param dict item: a dict containing item data
:param string tag: the tag you'd like to add to the item
:rtype: list of dicts
Example:
.. code-block:: python
zot.add_parameters(limit=1)
z = zot.top()
# we've now retrieved the most recent top-level item
updated = zot.add_tags(z[0], 'tag1', 'tag2', 'tag3')
# updated now contains a representation of the updated server item
====================
Collection Methods
====================
.. py:method:: Zotero.create_collection(name)
Create a new collection in the Zotero library
:param dict name: dict containing the key ``name`` and the value of the new collection name you wish to create. May optionally contain a ``parent`` key, the value of which is the ID of an existing collection. If this is set, the collection will be created as a child of that collection.
:rtype: Boolean
.. py:method:: Zotero.addto_collection(collection, items)
Add the specified item(s) to the specified collection
:param str collection: a collection key
:param list items: list of one or more item dicts
:rtype: Boolean
Collection keys can be obtained by a call to :py:meth:`collections()` (see details above).
.. py:method:: Zotero.deletefrom_collection(collection, item)
Remove the specified item from the specified collection
:param str collection: a collection key
:param dict item: dict containing item data
:rtype: Boolean
See the :py:meth:`delete_item()` example for multiple-item removal.
.. py:method:: Zotero.update_collection(collection)
Update an existing collection name
:param dict collection: a dict containing collection data, previously retrieved using one of the Collections calls (e.g. :py:meth:`collections()`)
:rtype: Boolean
Example::
# get existing collections, which will return a list of dicts
c = zot.collections()
# rename the last collection created in the library
c[0]['name'] = 'Whither Digital Humanities?'
# update collection name on the server
zot.update_collection(c[0])
.. py:method:: Zotero.delete_collection(collection)
Delete a collection from the Zotero library
:param dict collection: a dict containing collection data, previously retrieved using one of the Collections calls (e.g. :py:meth:`collections()`)
:rtype: Boolean
See the :py:meth:`delete_item()` example for ways to delete multiple collections.
Notes
=====
All Read API methods return **lists** of **dicts** or, in the case of tag methods, **lists** of **strings**. Most Write API methods return either ``True`` if successful, or raise an error. See ``zotero_errors.py`` for a full listing of these.
.. warning:: URL parameters will supersede API calls which should return e.g. a single item: ``https://api.zotero.org/users/436/items/ABC?start=50&limit=10`` will return 10 items beginning at position 50, even though ``ABC`` does not exist. Be aware of this, and don't pass URL parameters which do not apply to a given API method. This is a limitation/foible of the Zotero API, and there's nothing I can do about it.
License
=======
Pyzotero is licensed under the `GNU GPL Version 3 <http:https://www.gnu.org/licenses/gpl.html>`_ license, in line with Zotero's own license. Details can be found in the file ``license.txt``.
Cat Picture
===========
This is The Grinch.
.. figure:: cat.png
*Orangecat*