Releases: codingatty/Plumage-py
V1.4.0 ("Experiment IV")
Summary of new features
- USPTO API key support
- Pauses between TSDR calls to comply with PTO policy
- TSDR calls now default to requests for ST.96-format XML files
- New unbound method
GetMetainfo()
- New reporting: trademark classes and first-use dates
- Minimum Python release supported is Python 3.6. Python 2 is no longer supported
Details
USPTO API key support
The USPTO recently instituted a requirement that calls to TSDR must specify an API key. There is no charge for the API key, but you must register with the USPTO to obtain one. Calls without specifying an API key will fail as 401 Not Authorized. To set the API key, use the SetAPIKey(key)
prior to any call (such as getTSDRInfo
or getXMLData
) that calls TSDR.
For example:
t = plumage.TSDRReq()
t.SetAPIKey("32characterAPIKeyYouGotFromTheUSPTO")
t.getTSDRInfo("75181334", "s")
Pauses between TSDR calls to comply with PTO policy
By default, there is now a one-second delay between TSDR calls. I was going to add this delay in any event, to prevent an inadvertent denial-of-service attack on the TSDR servers. However, it's become even more essential now that the PTO has implemented the API key approach. As part of the new API key requirement, the PTO limits TSDR calls to 60 calls per minute for XML fetches; more than 60 calls per minute results in an error. By inserting a one-second pause between each call, Plumage ensures keeping within the PTO-enforced limit.
The length of the delay can be modified by calling SetIntervalTime()
, and can be eliminated entirely by using SetIntervalTime(0)
. Be aware that if the delay is shortened or eliminated, calls in excess of USPTO policy will be rejected by the server.
This approach to complying with the PTO's constraints may change in the next release. See the Additional comments section, below.
TSDR calls now default to requests for ST.96-format XML files
By default, TSDR queries are now for XML files; specifically, ST.96-format. Prior to 1.4.0, the default was for a zip file. Zip files contain some additional data, most notably image files that correspond to the published trademark specimen. However, the USPTO's restriction for zip files is significantly tighter than its restriction for XML text files: it only allows 4 zip files per minute, compared to 60 XML files per minute. In order to allow for more calls, XML is now the default.
If you require image data, you can still request zip format by calling the setPTOFormat
method. If making successive calls, you should change from the default one-second pause between TSDR calls to a fifteen-second pause to avoid having excessive calls rejected:
t = plumage.TSDRReq()
t.SetAPIKey("32characterAPIKeyYouGotFromTheUSPTO")
t.SetIntervalTime(15)
t.setPTOFormat("zip")
t.getTSDRInfo("75181334", "s")
New unbound method GetMetainfo()
The new method method GetMetainfo()
is available to obtain metainfo about the library and environment without instantiating a TSDRReq
object and without invoking a TSDR call.
Example:
metainfo = plumage.TSDRReq.GetMetainfo()
print(metainfo["MetaInfoLibraryVersion"])
will print:
1.4.0
New reporting: trademark classes and first-use dates
This release incorporates XSL transforms from Plumage-XSL V1.4.0. Plumage-XSL V1.4.0 reports additional information about trademark classes (both international and domestic) as well as first-use dates. See the Plumage-XSL V1.4.0 release notes for details.
For example, the following code fetches application no. 76/044,902 (the trademark "Python" for the Python programming language) and prints the class number and goods & services information for the first-listed international class; and the first-use date for the first of the documented use dates (in the PTO-supplied formats, YYYYMMDD):
t = plumage.TSDRReq()
t.setAPIKey("api-key")
t.getTSDRInfo("76044902", "s")
print("Registration no.: ", t.TSDRData.TSDRSingle["RegistrationNumber"])
print("Mark text: ", t.TSDRData.TSDRSingle["MarkVerbalElementText"])
international_class_list = t.TSDRData.TSDRMulti["InternationalClassDescriptionList"]
first_ic = international_class_list[0]
print("Class: ", first_ic["InternationalClassNumber"])
print("G&S:", first_ic["GoodsServicesDescription"])
use_date_list = t.TSDRData.TSDRMulti["FirstUseDateList"]
first_ud = use_date_list[0]
print("Class: ", first_ud["NiceClassNumber"])
print("First use:", first_ud["FirstUseDateNumber"])
print("First use in commerce:", first_ud["FirstUseInCommerceDate"])
prints:
Registration no.: 2824281
Mark text: PYTHON
Class: 009
G&S: Computer programs and downloadable computer programs that implement an object-oriented computer programming language
Class: 009
First use: 19951013
First use in commerce: 19951013
Minimum Python release supported is Python 3.6; Python 2 is no longer supported
Python 2 was sunset on January 1, 2020, more than a year ago. I no longer even have it installed, so would not be able to test with Python 2. This seemed like a good time to drop Python 2 support.
At least the unit tests require Python 3.6 (specifically, the timespec
argument in datetime.isoformat()
), so Python 3.6 should be considered the minimum required release level.
Additional comments
Future of complying with PTO timing constraints
As mentioned above, the USPTO imposes a constraint of 60 queries per minute for XML retrieval. This is addressed by pausing to ensure that at least one second elapses between each query, thereby keeping queries to at most 60 in one minute.
Plumage tries to limit the delays. The first call is not delayed at all. On subsequent calls, the delay is shortened or eliminated if possible. For example. if the calling program makes a TDSR call, then spends a half-second processing the data from the call before making a second TSDR call, the subsequent call will be delayed only a half-second. If more than a second is spent between calls, no additional pause is added at all.
However, this does impede the throughput of small bursts. For example, if you need to make only 15 queries, it is fully compliant with the PTO constraints to make those 15 queries immediately, and it would likely take only about 5 seconds. 15 queries in 5 seconds complies with the PTO's "no more than 60 queries in one minute" constraint. However, the current approach will take 14 seconds: 15 calls, with up to a one-second delay between each call (the initial call is not delayed at all).
I'm considering other approaches that would allow better throughput for short bursts of fewer than 60 queries. In the interest of getting the API key support (and the concomitant timing compliance) out in a timely manner, I went with the current approach; but I may revisit it in the future release, hopefully in a not-too-incompatible way.
Development environment
This release was developed and tested using Python 3.8.6 (at least 3.6 required) and lxml 4.6.2.
V1.3.0 ("Delius")
Changes in this release
- Support for Python 3; specifically, tested on Python 2.7.14 and Python 3.6.4
- Development environment upgraded to lxml 4.2.0
Because the only change in this release is to support Python 3, there is no corresponding release 1.3.0 for
Plumage-dotnet, which remains at V1.2.0.
V1.2.0 ("Cloudbusting")
Changes in this release
Major
- API change: single-instance values and multiple-instance values are broken into two data fields (see API change, below)
- XSL relaxation (see XSL relaxation, below)
Minor
- Now uses Plumage-XSL V1.1.1 for underlying XSL transform (for SPDX support)
- Now uses Software Package Data Exchange (SPDX) license identifier
- Self-test removed in favor of unit testing
API change
In release V1.1.0 and earlier, both single-instance attributes and multiple-instance attributes were kept in a single dictionary named TSDRMap
. Examples of single-instance attributes are the application serial number (ApplicationNumber
), the filing date (ApplicationDate
), and its current status (MarkCurrentStatusExternalDescriptionText
). Examples of multiple-instance attributes are prosecution events and assignments (kept in the lists MarkEventList
and AssignmentList
, respectively); these entries are lists of dictionaries, each dictionary representing one prosecution event or assignment.
This required program logic to recognize the type of entry by its key; if it ended in "List", the entry was to be treated as a list of dictionaries; otherwise as a string. This was awkward even in Python, and is especially ungainly in strongly-typed implementations such as the C# Plumage-dotnet implementation, which required storing the materials as generic objects and casting them as required, losing the benefits of typing. While the problem was more pronounced in strongly-typed languages, it's a bit annoying in Python, too, and in the interest of keeping the interfaces consistent, I'm revising the API in both implementations.
In this release, the prior mixed-content dictionary TSDRMap
is replaced by a new object TSDRData
, which now contains two dictionaries: TSDRSingle
for single-valued attributes, and TSDRMulti
for multi-valued attributes. In addition, the TSDRMapIsValid
flag is moved into the TSDRData
object.
The following snippet demonstrates the changes.
V1.1.0 and older:
t = plumage.TSDRReq()
t.getTSDRInfo("2564831", "r") # get info on reg. no 2,564,831
if t.TSDRMapIsValid:
print "Application serial no: ", t.TSDRMap["ApplicationNumber"]
event_list = t.TSDRMap["MarkEventList"]
most_recent_event = event_list[0]
print "Most recent event: ", most_recent_event["MarkEventDescription"]
V1.2.0:
t = plumage.TSDRReq()
t.getTSDRInfo("2564831", "r") # get info on reg. no 2,564,831
if t.TSDRData.TSDRMapIsValid:
print "Application serial no: ", t.TSDRData.TSDRSingle["ApplicationNumber"]
event_list = t.TSDRData.TSDRMulti["MarkEventList"]
most_recent_event = event_list[0]
print "Most recent event: ", most_recent_event["MarkEventDescription"]
Also, for consistency with the change from the TSDRMap
dictionary to the TSDRData
object , as well as consistency with other method names, the getTSDRMap
and resetTSDRMap
method have been renamed to getTSDRData
and resetTSDRData
, respectively.
XSL relaxation
Prior to this release, the CSV produced by the XSL transform could have no blank or empty lines. This made constructing a usable XSL file burdensome and made the XSL file itself more clutterful. With this release, the XSLT can produce blank or empty lines, and they will be stripped out as part of building the CSV information. The lines are removed as part of building the TSDRReq.CSVData
member.
V1.1.0 ("The Big Sky")
- Support for ST.96 V 2.2.1 (adopted by the US PTO on May 6, 2016)
- Added diagnostic where older ST.96 1-D3 is encountered
- small bug fix from Plumage V1.0.1
V1.0.0 ("And Dream of Sheep")
Initial formal release of Plumage-py, a Python implementation of Plumage. This is essentially the release I've been using for about a year; just formalizing the release.
Note: ST96.XSL targets ST.96 1_D3. On May 6, 2016, the PTO changed to ST.96 V2.2.1. Support for V2.2.1 is in test and will be added in V1.1.0. In the meantime, ST.66 format continues to work unchanged, and as ST.66 is the format included in the ZIP file (the default), temporary loss of ST.96 support is non-critical.