wipo-gbd-transformation 1.1.46__py3-none-any.whl → 1.1.59__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wipo-gbd-transformation might be problematic. Click here for more details.

Files changed (139) hide show
  1. gbdtransformation/brands/attm/template.yml +1 -2
  2. gbdtransformation/brands/bgtm/template.yml +1 -1
  3. gbdtransformation/brands/catm/filters.py +2 -1
  4. gbdtransformation/brands/catm/template.yml +10 -6
  5. gbdtransformation/brands/chtm/filters.py +159 -181
  6. gbdtransformation/brands/chtm/schema +79 -91
  7. gbdtransformation/brands/chtm/template.yml +97 -106
  8. gbdtransformation/brands/eetm/template.yml +1 -1
  9. gbdtransformation/brands/emtm/template.yml +1 -1
  10. gbdtransformation/brands/estm/template.yml +1 -1
  11. gbdtransformation/brands/frtm/template.yml +1 -1
  12. gbdtransformation/brands/gdtm/__init__.py +5 -0
  13. gbdtransformation/brands/gdtm/filters.py +61 -0
  14. gbdtransformation/brands/gdtm/schema +87 -0
  15. gbdtransformation/brands/gdtm/template.yml +1 -0
  16. gbdtransformation/brands/gdtm/tests/__init__.py +0 -0
  17. gbdtransformation/brands/istm/filters.py +21 -11
  18. gbdtransformation/brands/istm/template.yml +1 -1
  19. gbdtransformation/brands/krtm/template.yml +1 -1
  20. gbdtransformation/brands/lktm/__init__.py +5 -0
  21. gbdtransformation/brands/lktm/filters.py +83 -0
  22. gbdtransformation/brands/lktm/schema +87 -0
  23. gbdtransformation/brands/lktm/template.yml +1 -0
  24. gbdtransformation/brands/lktm/tests/__init__.py +0 -0
  25. gbdtransformation/brands/natm/__init__.py +2 -3
  26. gbdtransformation/brands/natm/filters.py +8 -2
  27. gbdtransformation/brands/notm/__init__.py +5 -0
  28. gbdtransformation/brands/notm/filters.py +113 -0
  29. gbdtransformation/brands/notm/template.yml +152 -0
  30. gbdtransformation/brands/nztm/template.yml +1 -1
  31. gbdtransformation/brands/pgtm/filters.py +1 -0
  32. gbdtransformation/brands/phtm/schema +79 -50
  33. gbdtransformation/brands/phtm/schema.classic +50 -0
  34. gbdtransformation/brands/phtm/template.classic.yml +102 -0
  35. gbdtransformation/brands/phtm/template.yml +1 -102
  36. gbdtransformation/brands/qatm/__init__.py +5 -0
  37. gbdtransformation/brands/qatm/filters.py +81 -0
  38. gbdtransformation/brands/qatm/schema +87 -0
  39. gbdtransformation/brands/qatm/template.yml +1 -0
  40. gbdtransformation/brands/qatm/tests/__init__.py +0 -0
  41. gbdtransformation/brands/sgtm/filters.py +1 -0
  42. gbdtransformation/brands/sgtm/template.trademark.yml +2 -2
  43. gbdtransformation/brands/ustm/template.yml +1 -1
  44. gbdtransformation/brands/vctm/__init__.py +5 -0
  45. gbdtransformation/brands/vctm/filters.py +75 -0
  46. gbdtransformation/brands/vctm/schema +87 -0
  47. gbdtransformation/brands/vctm/template.yml +1 -0
  48. gbdtransformation/brands/vctm/tests/__init__.py +0 -0
  49. gbdtransformation/brands/vntm/filters.py +1 -3
  50. gbdtransformation/brands/xxxx/template.yml +1 -1
  51. gbdtransformation/designs/__init__.py +8 -0
  52. gbdtransformation/designs/alid/__init__.py +1 -1
  53. gbdtransformation/designs/alid/filters.py +14 -1
  54. gbdtransformation/designs/bnid/__init__.py +5 -0
  55. gbdtransformation/designs/bnid/filters.py +61 -0
  56. gbdtransformation/designs/bnid/schema +80 -0
  57. gbdtransformation/designs/bnid/template.yml +1 -0
  58. gbdtransformation/designs/bwid/__init__.py +6 -0
  59. gbdtransformation/designs/bwid/filters.py +64 -0
  60. gbdtransformation/designs/bwid/schema +101 -0
  61. gbdtransformation/designs/bwid/template.yml +1 -0
  62. gbdtransformation/designs/crid/__init__.py +5 -0
  63. gbdtransformation/designs/crid/filters.py +63 -0
  64. gbdtransformation/designs/crid/schema +94 -0
  65. gbdtransformation/designs/crid/template.yml +1 -0
  66. gbdtransformation/designs/cuid/__init__.py +5 -0
  67. gbdtransformation/designs/cuid/filters.py +60 -0
  68. gbdtransformation/designs/cuid/schema +98 -0
  69. gbdtransformation/designs/cuid/template.yml +1 -0
  70. gbdtransformation/designs/egid/__init__.py +5 -0
  71. gbdtransformation/designs/egid/filters.py +62 -0
  72. gbdtransformation/designs/egid/schema +82 -0
  73. gbdtransformation/designs/egid/template.yml +1 -0
  74. gbdtransformation/designs/filters.py +73 -0
  75. gbdtransformation/designs/idid/__init__.py +5 -0
  76. gbdtransformation/designs/idid/filters.py +67 -0
  77. gbdtransformation/designs/idid/schema +102 -0
  78. gbdtransformation/designs/idid/template.yml +1 -0
  79. gbdtransformation/designs/ipas/filters.py +84 -2
  80. gbdtransformation/designs/ipas/template.yml +90 -79
  81. gbdtransformation/designs/joid/__init__.py +6 -0
  82. gbdtransformation/designs/joid/filters.py +62 -0
  83. gbdtransformation/designs/joid/schema +97 -0
  84. gbdtransformation/designs/joid/template.yml +1 -0
  85. gbdtransformation/designs/keid/__init__.py +5 -0
  86. gbdtransformation/designs/keid/filters.py +62 -0
  87. gbdtransformation/designs/keid/schema +99 -0
  88. gbdtransformation/designs/keid/template.yml +1 -0
  89. gbdtransformation/designs/khid/__init__.py +5 -0
  90. gbdtransformation/designs/khid/filters.py +63 -0
  91. gbdtransformation/designs/khid/schema +100 -0
  92. gbdtransformation/designs/khid/template.yml +1 -0
  93. gbdtransformation/designs/laid/__init__.py +5 -0
  94. gbdtransformation/designs/laid/filters.py +61 -0
  95. gbdtransformation/designs/laid/schema +94 -0
  96. gbdtransformation/designs/laid/template.yml +1 -0
  97. gbdtransformation/designs/mnid/__init__.py +6 -0
  98. gbdtransformation/designs/mnid/filters.py +62 -0
  99. gbdtransformation/designs/mnid/schema +98 -0
  100. gbdtransformation/designs/mnid/template.yml +1 -0
  101. gbdtransformation/designs/myid/__init__.py +5 -0
  102. gbdtransformation/designs/myid/filters.py +60 -0
  103. gbdtransformation/designs/myid/schema +95 -0
  104. gbdtransformation/designs/myid/template.yml +1 -0
  105. gbdtransformation/designs/phid/__init__.py +5 -0
  106. gbdtransformation/designs/phid/filters.py +70 -0
  107. gbdtransformation/designs/phid/schema +95 -0
  108. gbdtransformation/designs/phid/template.yml +1 -0
  109. gbdtransformation/designs/sgid/__init__.py +6 -0
  110. gbdtransformation/designs/sgid/filters.py +66 -0
  111. gbdtransformation/designs/sgid/schema +115 -0
  112. gbdtransformation/designs/sgid/template.yml +1 -0
  113. gbdtransformation/designs/thid/__init__.py +4 -0
  114. gbdtransformation/designs/thid/filters.py +64 -0
  115. gbdtransformation/designs/thid/schema +98 -0
  116. gbdtransformation/designs/thid/template.yml +1 -0
  117. gbdtransformation/designs/tnid/__init__.py +5 -0
  118. gbdtransformation/designs/tnid/filters.py +66 -0
  119. gbdtransformation/designs/tnid/schema +96 -0
  120. gbdtransformation/designs/tnid/template.yml +1 -0
  121. gbdtransformation/designs/vnid/__init__.py +5 -0
  122. gbdtransformation/designs/vnid/filters.py +62 -0
  123. gbdtransformation/designs/vnid/schema +97 -0
  124. gbdtransformation/designs/vnid/template.yml +1 -0
  125. gbdtransformation/designs/woid/__init__.py +2 -0
  126. gbdtransformation/designs/woid/filters.py +372 -0
  127. gbdtransformation/designs/woid/schema +592 -0
  128. gbdtransformation/designs/woid/template.yml +516 -0
  129. gbdtransformation/designs/xxid/template.yml +331 -119
  130. gbdtransformation/execs-nico.py +709 -0
  131. gbdtransformation/execs.py +55 -4
  132. gbdtransformation/gbd-transform.exec.tgz +0 -0
  133. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/METADATA +4 -1
  134. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/RECORD +139 -39
  135. wipo_gbd_transformation-1.1.59.dist-info/SOURCES_Stefans-Mac-Studio.local_Sep-18-063455-2024_Conflict.txt +690 -0
  136. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/entry_points.txt +1 -0
  137. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/LICENSE.md +0 -0
  138. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/WHEEL +0 -0
  139. {wipo_gbd_transformation-1.1.46.dist-info → wipo_gbd_transformation-1.1.59.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,62 @@
1
+ # standard gbd definitions
2
+ import gbdtransformation.designs.ipas.filters as ipas
3
+
4
+
5
+ # namespaces defined in XML and to be ignored in procecssing
6
+ ignore_namespace = [
7
+ 'http://www.wipo.int/standards/XMLSchema/designs',
8
+ 'http://www.wipo.int/standards/XMLSchema/wo-designs'
9
+ ]
10
+ def get_appdate(appdate, appnum):
11
+ return appnum.split('-')[-2]
12
+
13
+ def get_designs_count(design, header):
14
+ return '1'
15
+
16
+ def get_designs_pos(design, header):
17
+ return '1'
18
+
19
+ def translate_kind(desgin, header):
20
+ code = header.TransactionCode.lower()
21
+ subcode = header.TransactionSubCode.lower()
22
+ if code == 'industrial design':
23
+ return 'Industrial Design'
24
+ raise Exception('Type "%s" "%s" is not mapped.' % (code, subcode))
25
+
26
+ def translate_status(design):
27
+ status = design.DesignCurrentStatusCode
28
+ if status in ['181', '486']:
29
+ return 'Unknown'
30
+ return ipas.translate_status(status)
31
+
32
+
33
+ def get_registration_nb(design, idstatus):
34
+ if design.RegistrationNumber:
35
+ return design.RegistrationNumber
36
+
37
+ return None
38
+
39
+
40
+ def get_expiry_date(design, idstatus):
41
+ return ipas.get_expiry_date(design, idstatus)
42
+
43
+ def get_registration_date(design, idstatus):
44
+ return ipas.get_registration_date(design, idstatus)
45
+
46
+ def is_international(header):
47
+ return False
48
+
49
+ def get_ir_refnum(appnum):
50
+ return appnum
51
+
52
+ def select_earliest_date(publications):
53
+ return ipas.select_earliest_date(publications)
54
+
55
+ def deduplicate_publication_dates(publications):
56
+ return ipas.deduplicate_publication_dates(publications)
57
+
58
+ def deduplicate_classes(classes):
59
+ return ipas.deduplicate_classes(classes)
60
+
61
+ def deduplicate_publications(publications):
62
+ return ipas.deduplicate_publications(publications)
@@ -0,0 +1,97 @@
1
+ /Transaction
2
+ __/DesignTransactionBody
3
+ ____/TransactionContentDetails
4
+ ______/TransactionCode
5
+ ______/TransactionData
6
+ ________/DesignApplicationDetails
7
+ __________/DesignApplication
8
+ ____________/ApplicantDetails
9
+ ______________/ApplicantKey
10
+ ____________/DesignApplicationDate
11
+ ____________/DesignApplicationLanguageCode
12
+ ____________/DesignApplicationNumber
13
+ ____________/DesignDetails
14
+ ______________/Design
15
+ ________________/ApplicantDetails
16
+ __________________/Applicant
17
+ ____________________/ApplicantAddressBook
18
+ ______________________/FormattedNameAddress
19
+ ________________________/Address
20
+ __________________________/AddressCountryCode
21
+ __________________________/FreeFormatAddress
22
+ ____________________________/FreeFormatAddressLine
23
+ ________________________/Name
24
+ __________________________/FreeFormatName
25
+ ____________________________/FreeFormatNameDetails
26
+ ______________________________/FreeFormatNameLine
27
+ ______________________________/FreeFormatNameLine[@languageCode=vi]
28
+ ________________/DesignCurrentStatusCode
29
+ ________________/DesignCurrentStatusDate
30
+ ________________/DesignDescription
31
+ ________________/DesignEventDetails
32
+ __________________/DesignEvent
33
+ ____________________/DesignEventCode
34
+ ____________________/DesignEventDate
35
+ ____________________/OfficeSpecificDesignEventName
36
+ ________________/DesignIdentifier
37
+ ________________/DesignRepresentationSheetDetails
38
+ __________________/DesignRepresentationSheet
39
+ ____________________/RepresentationSheetFilename
40
+ ________________/DesignSpecimenDetails
41
+ __________________/DesignSpecimen
42
+ ____________________/SpecimenDescription
43
+ ____________________/SpecimenDescription[@languageCode=vi]
44
+ ____________________/SpecimenDescription[@languageCode=vn]
45
+ ____________________/SpecimenIdentifier
46
+ ________________/DesignTitle
47
+ ________________/DesignTitle[@languageCode=vi]
48
+ ________________/DesignTitle[@sequenceNumber=1]
49
+ ________________/DesignerDetails
50
+ __________________/Designer
51
+ ____________________/DesignerAddressBook
52
+ ______________________/FormattedNameAddress
53
+ ________________________/Address
54
+ __________________________/AddressCountryCode
55
+ __________________________/FreeFormatAddress
56
+ ____________________________/FreeFormatAddressLine
57
+ ________________________/Name
58
+ __________________________/FreeFormatName
59
+ ____________________________/FreeFormatNameDetails
60
+ ______________________________/FreeFormatNameLine
61
+ ______________________________/FreeFormatNameLine[@languageCode=vi]
62
+ ________________/ExpiryDate
63
+ ________________/IndicationProductDetails
64
+ __________________/IndicationProduct
65
+ ____________________/ClassDescriptionDetails
66
+ ______________________/ClassDescription
67
+ ________________________/ClassNumber
68
+ ________________________/ProductDescription
69
+ ____________________/ClassificationKindCode
70
+ ____________________/ClassificationVersion
71
+ ________________/PriorityDetails
72
+ __________________/Priority
73
+ ____________________/PriorityCountryCode
74
+ ____________________/PriorityDate
75
+ ____________________/PriorityNumber
76
+ ________________/PublicationDetails
77
+ __________________/Publication
78
+ ____________________/PublicationDate
79
+ ____________________/PublicationIdentifier
80
+ ________________/RegistrationDate
81
+ ________________/RegistrationNumber
82
+ ________________/RepresentativeDetails
83
+ __________________/Representative
84
+ ____________________/RepresentativeAddressBook
85
+ ______________________/FormattedNameAddress
86
+ ________________________/Address
87
+ __________________________/AddressCountryCode
88
+ __________________________/FreeFormatAddress
89
+ ____________________________/FreeFormatAddressLine
90
+ ________________________/Name
91
+ __________________________/FreeFormatName
92
+ ____________________________/FreeFormatNameDetails
93
+ ______________________________/FreeFormatNameLine
94
+ ______________________________/FreeFormatNameLine[@languageCode=vi]
95
+ ____________/RegistrationOfficeCode
96
+ ______/TransactionIdentifier
97
+ ______/TransactionSubCode
@@ -0,0 +1 @@
1
+ {% include "ipas/template.yml" %}
@@ -0,0 +1,2 @@
1
+ # instruction to render the output to JSON format
2
+ render = 'JSON'
@@ -0,0 +1,372 @@
1
+ # standard gdd definitions
2
+ from gbdtransformation.designs import kinds as std_kinds
3
+ from gbdtransformation.designs import status as std_status
4
+ from gbdtransformation.designs.filters import st13
5
+ from datetime import datetime, date
6
+ import json
7
+
8
+ # namespaces defined in XML and to be ignored in procecssing
9
+ ignore_namespace = [ "http://www.wipo.int/standards/XMLSchema/ST96/Design",
10
+ "http://www.wipo.int/standards/XMLSchema/ST96/Common" ]
11
+
12
+ # -------------------------------------------------------------
13
+ # data translation helpers:
14
+ # translate values from office interpretation to gbd equivalent
15
+ # -------------------------------------------------------------
16
+
17
+ def detectSealedDepositIndicator(HagueExpressTransaction):
18
+ return 'Open'
19
+
20
+ def cleanHagueAgreementActCategory(category):
21
+ return category.replace("Act", "") if category else None
22
+
23
+ def getExpiryDate(expiryDate, histories, designIdentifier=None, countryCode=None):
24
+ '''
25
+ Return last seen expiry date in the history events, if any
26
+ restricted to the identified design if specified
27
+ '''
28
+ #print("getExpiryDate")
29
+ #print(expiryDate)
30
+ #print(histories)
31
+
32
+ if histories == None or len(histories) == 0:
33
+ return expiryDate
34
+
35
+ if not isinstance(histories, list):
36
+ histories = [histories]
37
+
38
+ for history in histories:
39
+ if "HagueRenewal" in history:
40
+ if "ExpiryDate" in history.HagueRenewal:
41
+ if designIdentifier == None:
42
+ # no design restriction
43
+ expiryDate = history.HagueRenewal.ExpiryDate
44
+ else:
45
+ # is the design identifier in the list of affected designs?
46
+ if isAffectedDesignIdentifier(designIdentifier, history.HagueRenewal.AffectedDesign):
47
+ if countryCode == None:
48
+ expiryDate = history.HagueRenewal.ExpiryDate
49
+ else:
50
+ if isApplicableToCountry(countryCode, history.HagueRenewal):
51
+ expiryDate = history.HagueRenewal.ExpiryDate
52
+ return expiryDate
53
+
54
+ def getLastRenewalDate(histories, designIdentifier=None, countryCode=None):
55
+ '''
56
+ Return the renewal date if the last seen expiry date is in the history events
57
+ Renewal date can be restricted optionally by design identifier and country
58
+ '''
59
+ #print("getLastRenewalDate")
60
+
61
+ if histories == None or len(histories) == 0:
62
+ return None
63
+
64
+ if not isinstance(histories, list):
65
+ histories = [histories]
66
+
67
+ renewalDate = None
68
+ for history in histories:
69
+ if "HagueRenewal" in history:
70
+ if "ExpiryDate" in history.HagueRenewal:
71
+ if designIdentifier == None:
72
+ # no design restriction
73
+ renewalDate = history.HagueRenewal.RenewalDate
74
+ else:
75
+ # is the design identifier in the list of affected designs?
76
+ if isAffectedDesignIdentifier(designIdentifier, history.HagueRenewal.AffectedDesign):
77
+ if countryCode == None:
78
+ renewalDate = history.HagueRenewal.RenewalDate
79
+ else:
80
+ if isApplicableToCountry(countryCode, history.HagueRenewal):
81
+ renewalDate = history.HagueRenewal.RenewalDate
82
+ return renewalDate
83
+
84
+ def getRefusalDate(histories, designIdentifier=None, countryCode=None):
85
+ '''
86
+ Return refusal date, if any
87
+ Refusal datecan be restricted optionally by design identifier and country
88
+ '''
89
+ # check refusal
90
+ refusalDate = None
91
+ if histories != None:
92
+ for history in histories:
93
+ if "HagueRefusal" in history:
94
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueRefusal.AffectedDesign):
95
+ if countryCode == None or isApplicableToCountry(countryCode, history.HagueRefusal):
96
+ if "DecisionEffectiveDate" in history.HagueRefusal:
97
+ refusalDate = history.HagueRefusal.DecisionEffectiveDate
98
+ elif "DecisionDate" in history.HagueRefusal:
99
+ refusalDate = history.HagueRefusal.DecisionDate
100
+ return refusalDate
101
+
102
+ def build_person_name(name_struct):
103
+ first_name = None
104
+ if "FirstName" in name_struct:
105
+ first_name = name_struct.FirstName
106
+ last_name = None
107
+ if "LastName" in name_struct:
108
+ last_name = name_struct.LastName
109
+ if first_name is None and last_name is None:
110
+ return None
111
+ name = ""
112
+ if first_name is not None:
113
+ name += first_name
114
+ if last_name is not None:
115
+ name += " " + last_name.upper()
116
+ return name
117
+
118
+ def render_and_sort_views(viewBag):
119
+ views = []
120
+ for localViewKey in viewBag:
121
+ localView = viewBag[localViewKey]
122
+ #print(localView)
123
+ view = {}
124
+ if "ViewIdentifier" in localView:
125
+ rank = int(localView.ViewIdentifier)
126
+ localView["rank"] = rank
127
+ if "FileName" in localView:
128
+ name = localView.FileName
129
+ localView["name"] = name
130
+ if "ViewTypeCategory" in localView:
131
+ localType = localView.ViewTypeCategory
132
+ localView["type"] = localType
133
+ legends = []
134
+ if "ViewTypeTextBag" in localView:
135
+ for local_legend in localView.ViewTypeTextBag:
136
+ legend = {}
137
+ legend["languageCode"] = local_legend._languageCode
138
+ legend["legend"] = local_legend.__value
139
+ legends.append(legend)
140
+ if len(legends) > 0:
141
+ localView["legends"] = legends
142
+ return views
143
+
144
+ def format_address(address_lines):
145
+ address = ""
146
+ if not isinstance(address_lines, list):
147
+ address_lines = [address_lines]
148
+ for address_line in address_lines:
149
+ if address_line is not None and "__value" in address_line:
150
+ address += address_line.__value + ' \n'
151
+ if len(address) > 0:
152
+ return address.strip()
153
+ else:
154
+ return None
155
+
156
+ def format_complete_address(PostalStructuredAddress):
157
+ if PostalStructuredAddress == None:
158
+ return None
159
+ adr_lines = format_address(PostalStructuredAddress.AddressLineText)
160
+ address = []
161
+ if adr_lines:
162
+ address.append(adr_lines)
163
+ if PostalStructuredAddress.CityName:
164
+ address.append(PostalStructuredAddress.CityName.strip())
165
+ if PostalStructuredAddress.GeographicRegionName:
166
+ address.append(PostalStructuredAddress.GeographicRegionName.strip())
167
+ if PostalStructuredAddress.PostalCode:
168
+ address.append(PostalStructuredAddress.PostalCode.strip())
169
+ if PostalStructuredAddress.CountryCode:
170
+ address.append(PostalStructuredAddress.CountryCode.strip())
171
+ return ' '.join(address)
172
+
173
+ def getOfficeStatusDate(registrationDate, expiryDate, histories, designIdentifier, countryCode=None):
174
+ expiryDate = getExpiryDate(expiryDate, histories, designIdentifier)
175
+ grantedDate = None
176
+ if countryCode != None and histories != None:
177
+ # check possible renunciation including the particular country if specified
178
+ for history in histories:
179
+ if "HagueRenunciation" in history:
180
+ # is the design identifier in the list of affected designs?
181
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueRenunciation):
182
+ if "DesignatedCountryBag" in history.HagueRenunciation:
183
+ for designatedCountry in history.HagueRenunciation.DesignatedCountryBag.DesignatedCountry:
184
+ if isinstance(designatedCountry, str):
185
+ if history.HagueRenunciation.DesignatedCountryBag.DesignatedCountry.DesignatedCountryCode == countryCode:
186
+ history.HagueRenunciation.InternationalRecordingDate
187
+ elif designatedCountry.DesignatedCountryCode == countryCode:
188
+ return history.HagueRenunciation.InternationalRecordingDate
189
+
190
+ # to be tested: same for HagueLimitation, which is very similar to HagueRenunciation
191
+ if "HagueLimitation" in history:
192
+ # is the design identifier in the list of affected designs?
193
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueLimitation):
194
+ if "DesignatedCountryBag" in history.HagueLimitation:
195
+ for designatedCountry in history.HagueLimitation.DesignatedCountryBag.DesignatedCountry:
196
+ if isinstance(designatedCountry, str):
197
+ if history.HagueLimitation.DesignatedCountryBag.DesignatedCountry.DesignatedCountryCode == countryCode:
198
+ return history.HagueLimitation.InternationalRecordingDate
199
+ elif designatedCountry.DesignatedCountryCode == countryCode:
200
+ return history.HagueLimitation.InternationalRecordingDate
201
+
202
+ if "HagueGrantProtection" in history:
203
+ # is the design identifier in the list of affected designs?
204
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueGrantProtection.AffectedDesign):
205
+ if "RecordNotifyingOfficeCode" in history.HagueGrantProtection:
206
+ if history.HagueGrantProtection.RecordNotifyingOfficeCode == countryCode:
207
+ grantedDate = history.HagueGrantProtection.InternationalRecordingDate
208
+
209
+ # other events potentially impacting status:
210
+ # to check: HagueInvalidation, HagueMerger, however no occurance since 2018 data
211
+
212
+ refusalDate = getRefusalDate(histories, designIdentifier, countryCode)
213
+ # refusal is per designated countries, not just by design
214
+ if refusalDate != None and len(refusalDate) >= 0 and grantedDate is None:
215
+ return refusalDate
216
+
217
+ if grantedDate is not None:
218
+ registrationDate = grantedDate
219
+
220
+ if expiryDate == None or len(expiryDate) == 0:
221
+ return registrationDate
222
+
223
+ registrationDateObject = datetime.strptime(registrationDate, '%Y-%m-%d').date()
224
+ expiryDateObject = datetime.strptime(expiryDate, '%Y-%m-%d').date()
225
+
226
+ # the following gives the date of the last extension, if any
227
+ lastRenewalDate = getLastRenewalDate(histories, designIdentifier)
228
+ lastRenewalDateObject = datetime.strptime(expiryDate, '%Y-%m-%d').date()
229
+
230
+ if lastRenewalDateObject > registrationDateObject:
231
+ return lastRenewalDate
232
+ else:
233
+ return registrationDate
234
+
235
+ def getGbdStatus(registrationDate, expiryDate, histories, designIdentifier, countryCode=None):
236
+ # (Ended|Expired|Pending|Registered|Unknown)
237
+ # note: Ended is for every non-active cases except expired ones, so withdrawal, refusal,
238
+ # renunciation
239
+
240
+ # if we have specified a country, check if the country is not part of a renunciation,
241
+ # then the status would be Ended for all design following Hague XML schema explanations
242
+ grantedDate = None
243
+ if countryCode != None and histories != None:
244
+ for history in histories:
245
+ if "HagueRenunciation" in history:
246
+ # is the design identifier in the list of affected designs?
247
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueRenunciation):
248
+ if "DesignatedCountryBag" in history.HagueRenunciation:
249
+ for designatedCountry in history.HagueRenunciation.DesignatedCountryBag.DesignatedCountry:
250
+ if isinstance(designatedCountry, str):
251
+ if history.HagueRenunciation.DesignatedCountryBag.DesignatedCountry.DesignatedCountryCode == countryCode:
252
+ return "Ended"
253
+ elif designatedCountry.DesignatedCountryCode == countryCode:
254
+ return "Ended"
255
+
256
+ # to be tested: same for HagueLimitation, which is very similar to HagueRenunciation
257
+ if "HagueLimitation" in history:
258
+ # is the design identifier in the list of affected designs?
259
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueLimitation):
260
+ if "DesignatedCountryBag" in history.HagueLimitation:
261
+ for designatedCountry in history.HagueLimitation.DesignatedCountryBag.DesignatedCountry:
262
+ if isinstance(designatedCountry, str):
263
+ if history.HagueLimitation.DesignatedCountryBag.DesignatedCountry.DesignatedCountryCode == countryCode:
264
+ return "Ended"
265
+ elif designatedCountry.DesignatedCountryCode == countryCode:
266
+ return "Ended"
267
+
268
+ if "HagueGrantProtection" in history:
269
+ # is the design identifier in the list of affected designs?
270
+ if designIdentifier == None or isAffectedDesignIdentifier(designIdentifier, history.HagueGrantProtection.AffectedDesign):
271
+ if "RecordNotifyingOfficeCode" in history.HagueGrantProtection:
272
+ if history.HagueGrantProtection.RecordNotifyingOfficeCode == countryCode:
273
+ grantedDate = history.HagueGrantProtection.InternationalRecordingDate
274
+
275
+ # other events potentially impacting status:
276
+ # to check: HagueInvalidation, HagueMerger, however no occurance since 2018 data
277
+
278
+ # check refusal, refusal is per designated countries, not just by design
279
+ # unfortunately it seems that conditional refusal are encoded as refusal, so
280
+ # so we have to look for a follow-up grant to recover this problem
281
+ if countryCode != None:
282
+ refusalDate = getRefusalDate(histories, designIdentifier, countryCode)
283
+ if refusalDate != None and len(refusalDate)>0 and grantedDate is None:
284
+ return "Ended"
285
+
286
+ if grantedDate is not None:
287
+ registrationDate = grantedDate
288
+
289
+ if registrationDate == None or len(registrationDate) == 0:
290
+ return "Pending"
291
+
292
+ expiryDate = getExpiryDate(expiryDate, histories, designIdentifier, countryCode)
293
+ if expiryDate == None or len(expiryDate) == 0:
294
+ return "Registered"
295
+
296
+ try:
297
+ registrationDateObject = datetime.strptime(registrationDate, '%Y-%m-%d').date()
298
+ expiryDateObject = datetime.strptime(expiryDate, '%Y-%m-%d').date()
299
+ currentDate = date.today()
300
+
301
+ if expiryDateObject < currentDate:
302
+ return "Expired"
303
+ else:
304
+ return "Registered"
305
+ except Exception as e:
306
+ print("invalid date")
307
+ print(e)
308
+
309
+ return "Unknown"
310
+
311
+ def isAffectedDesignIdentifier(designIdentifier, affectedDesignBlock):
312
+ '''
313
+ Return True if the identified design is included in the affected design information
314
+ '''
315
+ if "AllDesignsIndicator" in affectedDesignBlock:
316
+ return True
317
+ elif "DesignIdentifierBag" in affectedDesignBlock:
318
+ affectedDesignIdentifiers = []
319
+ for identifier in affectedDesignBlock.DesignIdentifierBag.DesignIdentifier:
320
+ affectedDesignIdentifiers.append(identifier)
321
+ if designIdentifier in affectedDesignIdentifiers:
322
+ return True
323
+ else:
324
+ return False
325
+ return False
326
+
327
+ possibleEventsFromOffice = [ "HagueGrantProtection", "HagueRefusal" ]
328
+
329
+ def isApplicableToCountry(countryCode, hagueHistoryEvent):
330
+ '''
331
+ Return True if the history event is applicable to the provided country
332
+ '''
333
+ if hagueHistoryEvent is None:
334
+ return False
335
+
336
+ if "RecordNotifyingOfficeCode" in hagueHistoryEvent:
337
+ if hagueHistoryEvent.RecordNotifyingOfficeCode == countryCode:
338
+ return True
339
+ elif "DesignatedCountryBag" in hagueHistoryEvent:
340
+ if hagueHistoryEvent.DesignatedCountryBag is not None:
341
+ if "DesignatedCountry" in hagueHistoryEvent.DesignatedCountryBag:
342
+ for designatedCountry in hagueHistoryEvent.DesignatedCountryBag.DesignatedCountry:
343
+ if isinstance(designatedCountry, str):
344
+ if hagueHistoryEvent.DesignatedCountryBag.DesignatedCountry.DesignatedCountryCode == countryCode:
345
+ return True
346
+ elif designatedCountry.DesignatedCountryCode == countryCode:
347
+ return True
348
+ return False
349
+
350
+ """
351
+ Functions dedicated to Hague transaction history
352
+ """
353
+
354
+ transaction_header_elements = [ "HagueBulletinNumber", "PublicationDate" ]
355
+
356
+ def get_event_type(history):
357
+ for child in history:
358
+ if child.startswith("_"):
359
+ continue
360
+ if child not in transaction_header_elements:
361
+ return child
362
+ return None
363
+
364
+ def serialize(history):
365
+ #print(history)
366
+ jsonString = history.toJSON()
367
+ # keeping single quote in the JSON (even escaped) will fail when going back to yaml (yaml parsing error)
368
+ # so we need to use an alternative unicode for single quote.
369
+ jsonString = jsonString.replace("\'", "\u201A")
370
+ return json.loads(jsonString)
371
+
372
+