class Relationship(Model): parent_appl_id: str child_appl_id: str relationship: str child_app_filing_date: Optional[datetime.date] = None parent_app_filing_date: Optional[datetime.date] = None parent = one_to_one("patent_client.uspto.peds.USApplication", appl_id="parent_appl_id") child = one_to_one("patent_client.uspto.peds.USApplication", appl_id="child_appl_id")
class Inpadoc(Model): __manager__ = "patent_client.epo.inpadoc.manager.InpadocManager" number: str doc_type: str kind_code: typing.Optional[str] = None country: typing.Optional[str] = None family_id: typing.Optional[str] = None date: typing.Optional[dt.date] = None biblio = one_to_one( "patent_client.epo.inpadoc.model.InpadocBiblio", publication="num" ) claims = lookup_claims() description = lookup_description() family = lookup_family() @property def num(self): return f"{self.country}{self.number}{self.kind_code}" @property def us_application(self): klass = getattr( importlib.import_module("patent_client.uspto.peds.model"), "USApplication" ) if self.kind_code == "A1": pub_num = ( self.country + self.number[:4] + self.number[4:].rjust(7, "0") + self.kind_code ) return klass.objects.get(app_early_pub_number=pub_num) else: return klass.objects.get(patent_number=self.number)
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 ITCAttachment(Model): __manager__ = "patent_client.usitc.manager.ITCAttachmentManager" id: int document_id: int title: str file_size: int file_name: str pages: int created_date: dt.date last_modified_date: dt.date document = one_to_one("patent_client.ITCDocument", id="document_id") @property def download_url(self): return f"https://edis.usitc.gov/data/download/{self.document_id}/{self.id}" def download(self, file_obj=None): *_, ext = self.file_name.split(".") if file_obj is None: file_obj = tempfile.NamedTemporaryFile(suffix=ext) response = session.get(self.download_url, stream=True) with file_obj.open("wb") as f: for chunk in response.iter_content(1024): f.write(chunk) return file_obj
class PublicationResult(Model): publication_number: str title: str publication = one_to_one( "patent_client.uspto.fulltext.base.model.Publication", publication_number="publication_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 Inpadoc(Model): objects = InpadocManager() full_text = one_to_one("patent_client.epo_ops.models.InpadocFullText", doc_db="doc_db") us_application = one_to_one("patent_client.USApplication", appl_id="original_application_number") def __repr__(self): return f"<Inpadoc(publication={self.publication})>" @property def legal(self): if not hasattr(self, "_legal"): data = inpadoc_connector.legal(self.doc_db) self._legal = data return self._legal @property def images(self): if not hasattr(self, "_images"): data = inpadoc_connector.images(self.doc_db) data["doc_db"] = self.doc_db self._images = InpadocImages(data) return self._images @property def family(self): for doc_db in inpadoc_connector.family(self.doc_db): yield Inpadoc(inpadoc_connector.bib_data(doc_db)[0]) @property def specification(self): return self.full_text.description @property def claims(self): return self.full_text.claims
class PtabDocument(Model): __manager__ = "patent_client.uspto.ptab.manager.PtabDocumentManager" document_identifier: str = field(repr=False) document_category: str document_type_name: str document_number: int document_name: str document_filing_date: datetime.date proceeding_number: str = field(repr=False) proceeding_type_category: str = field(repr=False) title: Optional[str] = None proceeding = one_to_one("patent_client.uspto.ptab.PtabProceeding", proceeding_number="proceeding_number") """The PTAB proceeding associated with the document"""
class Publication(Model): __manager__ = "patent_client.uspto.fulltext.base.manager.FullTextManager" publication_number: str kind_code: str publication_date: str title: str description: str abstract: str claims: str appl_id: str filing_date: datetime.date family_id: str = None pct_filing_date: datetime.date = None pct_number: str = None national_stage_entry_date: datetime.date = None foreign_priority: "List[ForeignPriority]" = field(default_factory=list) inventors: list = field(default_factory=list) applicants: list = field(default_factory=list) assignees: list = field(default_factory=list) examiner: str = None agent: str = None related_us_applications: "List[RelatedPatentDocument]" = field( default_factory=list) prior_publications: "List[PriorPublication]" = field(default_factory=list) cpc_classes: "List[CpcClass]" = field(default_factory=list) intl_classes: "List[CpcClass]" = field(default_factory=list) us_classes: "List[USClass]" = field(default_factory=list) field_of_search: "List[USClass]" = field(default_factory=list) us_references: "List[USReference]" = field(default_factory=list) foreign_references: "List[ForeignReference]" = field(default_factory=list) npl_references: "List[NPLReference]" = field(default_factory=list) def __repr__(self): return f"{self.__class__.__name__}(publication_number={self.publication_number}, publication_date={self.publication_date.isoformat()}, title={self.title})" @property def parsed_claims(self): return ClaimsParser().parse(self.claims) application = one_to_one("patent_client.uspto.peds.model.USApplication", appl_id="appl_id")
class Property(Model): attrs = [ "appl_id", "app_filing_date", "pct_number", "intl_publ_date", "app_early_pub_number", "app_early_pub_date", "patent_number", "patent_title", "inventors", "patent_issue_date", ] primary_key = "appl_id" us_application = one_to_one("patent_client.USApplication", appl_id="appl_id")
class PtabDecision(Model): __manager__ = "patent_client.uspto.ptab.manager.PtabDecisionManager" proceeding_number: str board_rulings: List[str] decision_type_category: str document_identifier: str document_name: str identifier: str subdecision_type_category: str issue_type: Optional[str] = None object_uu_id: Optional[str] = None petitioner_technology_center_number: Optional[str] = None proceeding = one_to_one("patent_client.uspto.ptab.PtabProceeding", proceeding_number="proceeding_number") """The PTAB proceeding associated with the document"""
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 Property(Model): invention_title: str inventors: str # Numbers appl_id: str pct_num: str intl_reg_num: str publ_num: str pat_num: str # Dates filing_date: datetime.date intl_publ_date: datetime.date issue_date: datetime.date publ_date: datetime.date us_application = one_to_one("patent_client.USApplication", appl_id="appl_id") """A USApplication object related to the property"""
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 Document(Model): __manager__ = "patent_client.uspto.peds.manager.DocumentManager" base_url = "https://ped.uspto.gov/api/queries/cms/" access_level_category: str appl_id: str category: str code: str description: str identifier: str mail_room_date: datetime.date page_count: int url: Optional[str] = None application = one_to_one("patent_client.uspto.peds.model.USApplication", appl_id="appl_id") def __repr__(self): return f"Document(appl_id={self.appl_id}, mail_room_date={self.mail_room_date}, description={self.description})" def download(self, path=".", include_appl_id=True): if str(path)[-4:].lower() == ".pdf": # If we've been given a specific filename, use it out_file = Path(path) elif include_appl_id: out_file = ( Path(path) / f"{self.appl_id} - {self.mail_room_date} - {self.code} - {self.description[:40]}.pdf" ) else: out_file = ( Path(path) / f"{self.mail_room_date} - {self.code} - {self.description[:40]}.pdf" ) with session.get(self.base_url + self.url, stream=True) as r: r.raise_for_status() with out_file.open("wb") as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) return out_file
class Relationship(Model): application = one_to_one("patent_client.USApplication", appl_id='appl_id') attrs = [ 'appl_id', 'filing_date', 'patent_number', 'status', 'relationship', 'related_to_appl_id' ] def __init__(self, *args, **kwargs): super(Relationship, self).__init__(*args, **kwargs) data = self.data self.related_to_appl_id = data.get('application_number_text', None) self.appl_id = data['claim_application_number_text'] self.related_to_appl_id = kwargs['base_app'].appl_id self.app_filing_date = data['filing_date'] self.patent_number = data.get('patent_number_text', None) or None self.status = data.get('application_status', None) self.relationship = data['application_status_description'].replace( 'This application ', '') #self.aia = data['aia_indicator'] == 'Y' # XML data does not include the AIA indicator def __repr__(self): return f"<Relationship(appl_id={self.appl_id}, relationship={self.relationship})>"
class PublishedApplicationResult(PublicationResult): publication = one_to_one( "patent_client.uspto.fulltext.published_application.model.PublishedApplication", publication_number="publication_number", )
class InpadocApplication(Inpadoc): biblio = one_to_one( "patent_client.epo.inpadoc.model.InpadocBiblio", application="num" )
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})>"
class PatentResult(PublicationResult): publication = one_to_one( "patent_client.uspto.fulltext.patent.model.Patent", publication_number="publication_number", )
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 PtabDocument(Model): """ Ptab Document ========== This object wraps documents obtained from PTAB's public API (https://ptabdata.uspto.gov) --------------------- To Fetch a PTAB Document --------------------- There are two ways to get a PTAB Document. First, you can fetch a PtabTrial, and then get a list of document objects: PtabTrial.objects.get('IPR2016-00831').documents -> a list of Ptab Document objects Or, you can search and filter for specific documents by various critera (e.g. date ranges, filing party, etc.) PtabDocumemt.objects.filter(trial_number='IPR2016-00831', filing_party='board') -> retreives all documents from Trial IPR2016-00831 filed by the Board A complete list of query fields is available at PtabDocument.objects.query_fields -------------- Using the Data -------------- A PtabTrial object has the following attributes: trial_number size_in_bytes filing_party filing_datetime last_modified_datetime document_number title media_type id type A PtabTrial also has access to the trial object it is associated with at document.trial A document can also be downloaded to your working directory by running document.download() """ objects = PtabDocumentManager() attrs = [ "trial_number", "size_in_bytes", "filing_party", "filing_datetime", "last_modified_datetime", "document_number", "title", "media_type", "id", "type", ] trial = one_to_one("patent_client.PtabTrial", trial_number="trial_number") def download(self, path="."): url = self.links[1]["href"] extension = mimetypes.guess_extension(self.media_type) base_name = self.title.replace("/", "_") + extension cdir = os.path.join(CACHE_DIR, self.trial_number) os.makedirs(cdir, exist_ok=True) cname = os.path.join(cdir, base_name) oname = os.path.join(path, base_name) if not os.path.exists(cname): response = session.get(url, stream=True) with open(cname, "wb") as f: for chunk in response.iter_content(1024): f.write(chunk) shutil.copy(cname, oname) def __repr__(self): return f"<PtabDocument(title={self.title})>"