def expiration(self) -> Optional[Expiration]: """Calculates expiration data from which the expiration date can be calculated. See help information for the resulting Expiration model. """ if "PCT" in self.appl_id: raise NotImplementedError( "Expiration date not supported for PCT Applications") if not self.patent_number: return None expiration_data = dict() term_parents = [ p for p in self.parent_continuity if p.relationship not in [ "Claims Priority from Provisional Application", "is a Reissue of" ] ] if term_parents: term_parent = sorted(term_parents, key=lambda x: x.parent_app_filing_date)[0] relationship = term_parent.relationship parent_filing_date = term_parent.parent_app_filing_date parent_appl_id = term_parent.parent_appl_id else: relationship = "self" parent_appl_id = self.appl_id parent_filing_date = self.app_filing_date expiration_data["parent_appl_id"] = parent_appl_id expiration_data["parent_app_filing_date"] = parent_filing_date expiration_data["parent_relationship"] = relationship expiration_data["initial_term"] = parent_filing_date + relativedelta( years=20) # type: ignore expiration_data[ "pta_or_pte"] = self.pta_pte_summary.total_days if self.pta_pte_summary else 0 # type: ignore expiration_data[ "extended_term"] = expiration_data["initial_term"] + relativedelta( days=expiration_data["pta_or_pte"]) # type: ignore transactions = self.transactions try: disclaimer = next(t for t in transactions if t.code == "DIST") expiration_data["terminal_disclaimer_filed"] = True except StopIteration: expiration_data["terminal_disclaimer_filed"] = False return Expiration(**expiration_data) # type: ignore assignments = one_to_many("patent_client.uspto.assignment.Assignment", appl_id="appl_id") """Related Assignments from the Assignments API""" trials = one_to_many("patent_client.uspto.ptab.PtabProceeding", appl_id="appl_id") """Related PtabProceedings for this application"""
class InpadocPriorityClaim(Inpadoc): children = one_to_many( "patent_client.epo.inpadoc.model.Inpadoc", priority_claim="num" ) biblio = one_to_one( "patent_client.epo.inpadoc.model.InpadocBiblio", application="num" )
class PtabProceeding(Model): """A PTAB Proceeding - e.g. IPR/CBM/DER Trial, Patent Appeal, Interference, etc. All fields are query-able. Date ranges can be formed by inserting "from" or "to" on a query for a date range. """ __manager__ = "patent_client.uspto.ptab.manager.PtabProceedingManager" subproceeding_type_category: str proceeding_number: str proceeding_status_category: str proceeding_type_category: str # Party Information appl_id: str = field(repr=False) respondent_party_name: str = field(default=None) petitioner_counsel_name: Optional[str] = field(default=None, repr=False) petitioner_party_name: Optional[str] = field(default=None, repr=False) respondent_counsel_name: Optional[str] = field(default=None, repr=False) respondent_patent_owner_name: Optional[str] = field(default=None, repr=False) # Application Information inventor: Optional[str] = field(default=None, repr=False) patent_number: Optional[str] = field(default=None, repr=False) respondent_technology_center_number: Optional[str] = field(default=None, repr=False) respondent_grant_date: Optional[datetime.date] = field(default=None, repr=False) accorded_filing_date: Optional[datetime.date] = field(default=None, repr=False) decision_date: Optional[datetime.date] = field(default=None, repr=False) institution_decision_date: Optional[datetime.date] = field(default=None, repr=False) proceeding_filing_date: Optional[datetime.date] = field(default=None, repr=False) documents = one_to_many("patent_client.uspto.ptab.PtabDocument", proceeding_number="proceeding_number") """Documents associated with the Proceeding""" decisions = one_to_many("patent_client.uspto.ptab.PtabDecision", proceeding_number="proceeding_number") """Decisions associated with the Proceeding""" us_application = one_to_one("patent_client.uspto.peds.Application", appl_id="appl_id") """The US Application provided by PEDS associated with the Proceeding"""
class ITCInvestigation(Model): __manager__ = "patent_client.usitc.manager.ITCInvestigationManager" number: str phase: str status: str title: str type: str docket_number: str = dc.field(default=None) documents = one_to_many("patent_client.ITCDocument", investigation_number="number")
class PublishedApplication(Publication): __manager__ = "patent_client.uspto.fulltext.published_application.manager.PublishedApplicationManager" forward_citations = one_to_many( "patent_client.uspto.fulltext.patent.model.Patent", referenced_by="publication_number", ) images = one_to_one( "patent_client.uspto.fulltext.published_application.model.PublishedApplicationImage", publication_number="publication_number", ) def __repr__(self): return f"{self.__class__.__name__}(publication_number={self.publication_number}, publication_date={self.publication_date.isoformat()}, title={self.title})"
class ITCDocument(Model): __manager__ = "patent_client.usitc.manager.ITCDocumentManager" id: int investigation_number: str type: str title: str security: str filing_party: str filed_by: str filed_on_behalf_of: str action_jacket_control_number: str memorandum_control_number: str date: dt.date last_modified: dt.date investigation = one_to_one("patent_client.ITCInvestigation", investigation_number="investigation_number") attachments = one_to_many("patent_client.ITCAttachment", document_id="id")
class USApplication(Model): """ US Application ============== This object wraps a US Application obtained from the Patent Examination Data System (https://peds.uspto.gov) ------------------------- To Fetch a US Application ------------------------- The main way to create a US Application is by querying the US Application manager at USApplication.objects USApplication.objects.filter(query) -> obtains multiple matching applications USApplication.objects.get(query) -> obtains a single matching application, errors if more than one is retreived The query can either be a single number, which is treated like an application number, or a keyword argument: USApplication.objects.get("15123456") -> Retreives US Application # 15123456 USApplication.objects.get(patent_number="6103599") -> Retreives the US Application which issued as US Patent 6103599 All arguments can be specified multiple times: USApplication.objects.get("15123456", "15123457") -> Retreives US Applications 15123456 and 15123457 USApplication.objects.get(patent_number=['6103599', '6103600']) -> Retreives the US Applications which issued as US Patents 6103599 and 6103600 NOTE: All keyword arguments are repeated by placing them in a list, but application numbers can be repeated as non-keyword arguments Date queries are made as strings in ISO format - YYYY-MM-DD (e.g. 2019-02-01 for Feb. 1, 2019) The complete list of available query fields is at USApplication.objects.fields -------------- Using the Data -------------- Data retreived from the US Patent Examination Data System is populated as attributes on the US Application object. A complete list of available fields is at USApplication.attrs. All the data can be retreived as a Python dictionary by calling USApplication.dict() There are also several composite data types available from a US Application, including: app.transaction_history -> list of transactions (filings, USPTO actions, etc.) involving the application app.children -> list of child applications app.parents -> list of parent applications app.pta_pte_history -> Patent Term Adjustment / Extension Event History app.pta_pte_summary -> Patent Term Adjustment / Extension Results, including total term extension app.correspondent -> Contact information for prosecuting law firm app.attorneys -> List of attorneys authorized to take action in the case app.expiration -> Patent Expiration Data (earliest non-provisional US parent + 20 years + extension and a flag for the presnce of a Terminal Disclaimer) Each of these also attaches data as attributes to the objects, and implements a .dict() method. ------------ Related Data ------------ A US Application is also linked to other resources avaialble through patent_client, including: app.trials -> list of PTAB trials involving this application app.inpadoc -> list to corresponding INPADOC objects (1 for each publication) HINT: inpadoc family can be found at app.inpadoc[0].family app.assignments -> list of assignments that mention this application Also, related US Applications can be obtained through their relationship: app.children[0].application -> a new USApplication object for the first child. """ objects = USApplicationManager() trials = one_to_many("patent_client.PtabTrial", patent_number="patent_number") inpadoc = one_to_many("patent_client.Inpadoc", number="appl_id") assignments = one_to_many("patent_client.Assignment", appl_id="appl_id") attrs = [ 'appl_id', 'applicants', 'app_filing_date', 'app_exam_name', 'inventors', 'app_early_pub_number', 'app_early_pub_date', 'app_location', 'app_grp_art_number', 'patent_number', 'patent_issue_date', 'app_status', 'app_status_date', 'patent_title', 'app_attr_dock_number', 'first_inventor_file', 'app_type', 'app_cust_number', 'app_cls_sub_cls', 'corr_addr_cust_no', 'app_entity_status', 'app_confr_number', 'transaction_history', 'children', 'parents', 'foreign_priority_applications', 'pta_pte_history', 'pta_pte_summary', 'correspondent', 'attorneys' ] @property def publication(self): if self.patent_number: return "US" + self.patent_number else: return self.app_early_pub_number @property def expiration(self): expiration_data = dict() term_parents = [ p for p in self.parents if p.relationship not in [ 'Claims Priority from Provisional Application', 'is a Reissue of' ] ] if term_parents: term_parent = sorted(term_parents, key=lambda x: x.filing_date)[0] else: term_parent = self expiration_data['parent_appl_id'] = term_parent.appl_id expiration_data['parent_app_filing_date'] = term_parent.app_filing_date expiration_data['parent_relationship'] = getattr( term_parent, 'relationship', 'self') expiration_data[ '20_year_term'] = term_parent.app_filing_date + relativedelta( years=20) expiration_data['pta_or_pte'] = self.pta_pte_summary.total_days expiration_data['extended_term'] = expiration_data[ '20_year_term'] + relativedelta(days=expiration_data['pta_or_pte']) transactions = self.transaction_history try: disclaimer = next(t for t in transactions if t.code == 'DIST') expiration_data['terminal_disclaimer_filed'] = True except StopIteration: expiration_data['terminal_disclaimer_filed'] = False return expiration_data @property def transaction_history(self): return list( sorted((Transaction(d) for d in self.data.get('transactions', list())), key=lambda x: x.date)) @property def children(self): return [ Relationship(d, base_app=self) for d in self.data.get('child_continuity', list()) ] @property def parents(self): return [ Relationship(d, base_app=self) for d in self.data.get('parent_continuity', list()) ] @property def foreign_priority_applications(self): return [ ForeignPriority(d) for d in self.data.get('foreign_priority', list()) ] @property def pta_pte_history(self): return list( sorted((PtaPteHistory(d) for d in self.data.get('pta_pte_tran_history', list())), key=lambda x: x.number)) @property def pta_pte_summary(self): return PtaPteSummary(self.data) @property def correspondent(self): return Correspondent(self.data) @property def attorneys(self): return list(Attorney(d) for d in self.data.get('attrny_addr', list())) def __repr__(self): return f"<USApplication(appl_id={self.appl_id})>"
class Assignment(Model): """ Assignments =========== This object wraps the USPTO Assignment API (https://assignments.uspto.gov) ---------------------- To Fetch an Assignment ---------------------- The main way to create an Assignment is by querying the Assignment manager at Assignment.objects Assignment.objects.filter(query) -> obtains multiple matching applications Assignment.objects.get(query) -> obtains a single matching application, errors if more than one is retreived The query can either be a single number, which is treated as a reel/frame number (e.g. "123-1321"), or a keyword. Available query types are: patent_number, appl_id (application #), app_early_pub_number (publication #), assignee, assignor, pct_number (PCT application #), correspondent, reel_frame -------------- Using the Data -------------- An Assignment object has the following properties: id (reel/frame #) attorney_dock_num conveyance_text last_update_date page_count recorded_date correspondent assignees assignors properties Additionally, the original assignment document can be downloaded to the working directory by calling: assignment.download() ------------ Related Data ------------ An Assignment is also linked to other resources available through patent_client. A list of all assigned applications is available at: assignment.us_applications Additionally, each property entry in properties links to the corresponding application at: assignment.properties[0].us_application """ primary_key = "reel_frame" attrs = [ "id", "attorney_dock_num", "conveyance_text", "last_update_date", "page_count", "recorded_date", "correspondent", "assignors", "assignees", "properties", "image_url", ] objects = AssignmentManager() us_applications = one_to_many("patent_client.USApplication", appl_id="appl_num") def __repr__(self): return f"<Assignment(id={self.id})>" @property def properties(self): data = self.data properties = list() if isinstance(data['appl_num'], list): for i in range(len(data["appl_num"])): properties.append({ "appl_id": data["appl_num"][i], "app_filing_date": data["filing_date"][i], "patent_number": data["pat_num"][i], "pct_number": data["pct_num"][i], "intl_publ_date": datetime.datetime.strptime(data["intl_publ_date"][i], "%Y-%m-%d").date() if data["intl_publ_date"][i] else None, "intl_reg_num": data["intl_reg_num"][i], "app_early_pub_date": datetime.datetime.strptime(data["publ_date"][i], "%Y-%m-%d").date() if data["publ_date"][i] else None, "app_early_pub_number": data["publ_num"][i], "patent_issue_date": data["issue_date"][i], "patent_title": data["invention_title"][i], "patent_title_lang": data["invention_title_lang"][i], "inventors": data["inventors"][i], }) else: properties.append({ "appl_id": data["appl_num"], "app_filing_date": data["filing_date"], "patent_number": data["pat_num"], "pct_number": data["pct_num"], "intl_publ_date": data["intl_publ_date"] if data["intl_publ_date"] else None, "intl_reg_num": data["intl_reg_num"], "app_early_pub_date": data["publ_date"] if data["publ_date"] else None, "app_early_pub_number": data["publ_num"], "patent_issue_date": data["issue_date"], "patent_title": data["invention_title"], "patent_title_lang": data["invention_title_lang"], "inventors": data["inventors"], }) return [Property(p) for p in properties] @property def correspondent(self): data = self.data correspondent_keys = filter(lambda x: "corr_" in x and "size" not in x, data.keys()) return repartition({k: data[k] for k in correspondent_keys})[0] @property def assignees(self): data = self.data assignee_keys = filter( lambda x: "pat_assignee_" in x and "size" not in x, data.keys()) return repartition({k: data[k] for k in assignee_keys}) @property def assignors(self): data = self.data assignor_keys = filter( lambda x: "pat_assignor_" in x and "size" not in x, data.keys()) return repartition({k: data[k] for k in assignor_keys}) def download(self): response = session.get(self.image_url, stream=True) with open(f"{self.id}.pdf", "wb") as f: f.write(response.raw.read())
class USApplication(Model): __manager__ = "patent_client.uspto.peds.manager.USApplicationManager" appl_id: str = field(compare=True) patent_title: Optional[str] = None app_status: Optional[str] = field(default=None, repr=True) inventors: Optional[List[str]] = field(default=None, repr=False) app_filing_date: Optional[datetime.date] = field(default=None, repr=False) app_location: Optional[str] = field(default=None, repr=False) first_inventor_file: Optional[str] = field(default=None, repr=False) app_type: Optional[str] = field(default=None, repr=False) app_entity_status: Optional[str] = field(default=None, repr=False) app_confr_number: Optional[str] = field(default=None, repr=False) applicants: List[Applicant] = field(default_factory=list, repr=False) app_status_date: Optional[datetime.date] = field(default=None, repr=False) app_cls_sub_cls: Optional[str] = field(default=None, repr=False) app_grp_art_number: Optional[str] = field(default=None, repr=False) corr_addr_cust_no: Optional[str] = field(default=None, repr=False) app_cust_number: Optional[str] = field(default=None, repr=False) app_attr_dock_number: Optional[str] = field(default=None, repr=False) patent_number: Optional[str] = field(default=None, repr=False) patent_issue_date: Optional[datetime.date] = field(default=None, repr=False) app_early_pub_number: Optional[str] = field(default=None, repr=False) app_early_pub_date: Optional[datetime.date] = field(default=None, repr=False) app_exam_name: Optional[str] = field(default=None, repr=False) wipo_early_pub_number: Optional[str] = field(default=None, repr=False) wipo_early_pub_date: Optional[datetime.date] = field(default=None, repr=False) transactions: List[Transaction] = field(default_factory=list, repr=False) child_continuity: ListManager[Relationship] = field( default_factory=ListManager.empty, repr=False) parent_continuity: ListManager[Relationship] = field( default_factory=ListManager.empty, repr=False) pta_pte_tran_history: List[PtaPteHistory] = field(default_factory=list, repr=False) pta_pte_summary: Optional[PtaPteSummary] = field(default=None, repr=False) correspondent: Optional[Correspondent] = field(default=None, repr=False) attorneys: List[Attorney] = field(default_factory=list, repr=False) foreign_priority: List[ForeignPriority] = field(default_factory=list, repr=False) documents = one_to_many("patent_client.uspto.peds.model.Document", appl_id="appl_id") @property def continuity(self) -> QuerySet: """Returns a complete set of parents, self, and children""" return QuerySet([ self.child_continuity.values_list("child", flat=True), [ self, ], self.parent_continuity.values_list("parent", flat=True), ]) def __hash__(self): return hash(self.appl_id) @property def kind(self) -> str: """Differentiates provisional, PCT, and nonprovisional applications""" if "PCT" in self.appl_id: return "PCT" if self.appl_id[0] == "6": return "Provisional" return "Nonprovisional" @property def priority_date(self) -> datetime.date: """Attempts to return the priority date of the application, calculated as the earliest application filing date among the application's parents, or its own filing date if it has no parents """ if not self.parent_continuity: return self.app_filing_date else: return sorted(p.parent_app_filing_date for p in self.parent_continuity)[0] @property def expiration(self) -> Optional[Expiration]: """Calculates expiration data from which the expiration date can be calculated. See help information for the resulting Expiration model. """ if "PCT" in self.appl_id: raise NotImplementedError( "Expiration date not supported for PCT Applications") if not self.patent_number: return None expiration_data = dict() term_parents = [ p for p in self.parent_continuity if p.relationship not in [ "Claims Priority from Provisional Application", "is a Reissue of" ] ] if term_parents: term_parent = sorted(term_parents, key=lambda x: x.parent_app_filing_date)[0] relationship = term_parent.relationship parent_filing_date = term_parent.parent_app_filing_date parent_appl_id = term_parent.parent_appl_id else: relationship = "self" parent_appl_id = self.appl_id parent_filing_date = self.app_filing_date expiration_data["parent_appl_id"] = parent_appl_id expiration_data["parent_app_filing_date"] = parent_filing_date expiration_data["parent_relationship"] = relationship expiration_data["initial_term"] = parent_filing_date + relativedelta( years=20) # type: ignore expiration_data[ "pta_or_pte"] = self.pta_pte_summary.total_days if self.pta_pte_summary else 0 # type: ignore expiration_data[ "extended_term"] = expiration_data["initial_term"] + relativedelta( days=expiration_data["pta_or_pte"]) # type: ignore transactions = self.transactions try: disclaimer = next(t for t in transactions if t.code == "DIST") expiration_data["terminal_disclaimer_filed"] = True except StopIteration: expiration_data["terminal_disclaimer_filed"] = False return Expiration(**expiration_data) # type: ignore assignments = one_to_many("patent_client.uspto.assignment.Assignment", appl_id="appl_id") """Related Assignments from the Assignments API""" trials = one_to_many("patent_client.uspto.ptab.PtabProceeding", appl_id="appl_id") """Related PtabProceedings for this application""" patent = one_to_one("patent_client.uspto.fulltext.Patent", publication_number="patent_number") """Fulltext Patent - If Available""" @property def publication_number(self): return self.app_early_pub_number[2:-2] publication = one_to_one( "patent_client.uspto.fulltext.PublishedApplication", publication_number="publication_number", )
class PtabTrial(Model): """ Ptab Trial ========== This object wraps the PTAB's public API (https://ptabdata.uspto.gov) --------------------- To Fetch a PTAB Trial --------------------- The main way to create a PtabTrial is by querying the PtabTrial manager at PtabTrial.objects PtabTrial.objects.filter(query) -> obtains multiple matching applications PtabTrial.objects.get(query) -> obtains a single matching application, errors if more than one is retreived The query can either be a single number, which is treated as a trial number, or a keyword argument: PtabTrial.objects.get('IPR2016-00831') -> Retreives a single trial PtabTrial.objects.filter(patent_number='6103599') -> retreives all PTAB trials involving US Patent Number 6103599 A complete list of query fields is available at PtabTrial.objects.query_fields -------------- Using the Data -------------- A PtabTrial object has the following attributes: trial_number application_number patent_number petitioner_party_name patent_owner_name inventor_name prosecution_status filing_date accorded_filing_date institution_decision_date last_modified_datetime A PtabTrial also has access to the related documents, available at trial.documents ------------ Related Data ------------ A PtabTrial is also linked to other resources avaialble through patent_client, including: trial.us_application -> application which granted as the challenged patent """ objects = PtabTrialManager() attrs = [ "trial_number", "application_number", "patent_number", "petitioner_party_name", "patent_owner_name", "inventor_name", "prosecution_status", "filing_date", "accorded_filing_date", "institution_decision_date", "last_modified_datetime", "documents", ] us_application = one_to_one( "patent_client.USApplication", appl_id="application_number" ) documents = one_to_many("patent_client.PtabDocument", trial_number="trial_number") def __repr__(self): return f"<PtabTrial(trial_number={self.trial_number})>"