python-re3data-v2 0.1.0__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.
@@ -0,0 +1,564 @@
1
+ """API resources for the /repository/{id} endpoint (v40, schema 4.0).
2
+
3
+ Typed models mirroring the `re3data.org Metadata Schema for the Description of
4
+ Research Data Repositories, Version 4.0 (August 2023)
5
+ <https://doi.org/10.48440/re3.014>`_. The authoritative XSD is served at
6
+ https://schema.re3data.org/4-0/re3dataV4-0.xsd.
7
+
8
+ Design notes:
9
+
10
+ - Dataclass field names intentionally mirror the XML element/attribute names
11
+ (camelCase), so ``dataclasses.asdict`` reproduces the document structure
12
+ with XML-style keys, matching the dict contract established by the original
13
+ python-re3data library.
14
+ - Elements carrying text plus attributes (e.g. ``repositoryName`` with a
15
+ ``language`` attribute) are modelled as ``{"value": ..., "language": ...}``.
16
+ - Vocabulary fields are typed as plain ``str`` instead of enums. Schema 4.0
17
+ data has already shown drift against the XSD vocabularies (the upstream API
18
+ team keeps extending values); parsing therefore never fails on unknown
19
+ values. The controlled vocabularies are exported as reference enums below
20
+ for callers that want to compare against known values.
21
+ - Dates (``entryDate``, ``lastUpdate``, ...) are parsed to ``datetime.date``
22
+ and serialized back to ISO-8601 strings.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from dataclasses import dataclass, field
28
+ from datetime import date
29
+ from enum import StrEnum
30
+
31
+ __NAMESPACE__ = "http://www.re3data.org/schema/4-0"
32
+
33
+
34
+ # ------------------------------------------------------------------------------
35
+ # Reference vocabularies (schema 4.0 simpleTypes)
36
+ # ------------------------------------------------------------------------------
37
+
38
+
39
+ class RepositoryType(StrEnum):
40
+ """Repository types (schema 4.0: 6 values, up from 3 in schema 2-2)."""
41
+
42
+ DISCIPLINARY = "disciplinary"
43
+ GOVERNMENTAL = "governmental"
44
+ INSTITUTIONAL = "institutional"
45
+ MULTIDISCIPLINARY = "multidisciplinary"
46
+ PROJECT_RELATED = "project-related"
47
+ OTHER = "other"
48
+
49
+
50
+ class ProviderType(StrEnum):
51
+ DATA_PROVIDER = "dataProvider"
52
+ SERVICE_PROVIDER = "serviceProvider"
53
+
54
+
55
+ class DatabaseAccessType(StrEnum):
56
+ OPEN = "open"
57
+ RESTRICTED = "restricted"
58
+ CLOSED = "closed"
59
+
60
+
61
+ class DatabaseAccessRestriction(StrEnum):
62
+ FEE_REQUIRED = "feeRequired"
63
+ REGISTRATION = "registration"
64
+
65
+
66
+ class DataAccessType(StrEnum):
67
+ OPEN = "open"
68
+ EMBARGOED = "embargoed"
69
+ RESTRICTED = "restricted"
70
+ CLOSED = "closed"
71
+
72
+
73
+ class DataAccessRestriction(StrEnum):
74
+ FEE_REQUIRED = "feeRequired"
75
+ INSTITUTIONAL_MEMBERSHIP = "institutionalMembership"
76
+ REGISTRATION = "registration"
77
+
78
+
79
+ class DataUploadType(StrEnum):
80
+ OPEN = "open"
81
+ RESTRICTED = "restricted"
82
+ CLOSED = "closed"
83
+
84
+
85
+ class DataUploadRestriction(StrEnum):
86
+ FEE_REQUIRED = "feeRequired"
87
+ INSTITUTIONAL_MEMBERSHIP = "institutionalMembership"
88
+ REGISTRATION = "registration"
89
+ STORAGE_LIMIT = "storageLimit"
90
+
91
+
92
+ class InstitutionType(StrEnum):
93
+ COMMERCIAL = "commercial"
94
+ NON_PROFIT = "non-profit"
95
+
96
+
97
+ class ResponsibilityType(StrEnum):
98
+ """Institution responsibility types (schema 4.0 dropped "sponsoring")."""
99
+
100
+ FUNDING = "funding"
101
+ GENERAL = "general"
102
+ TECHNICAL = "technical"
103
+
104
+
105
+ class RelatedRepositoryType(StrEnum):
106
+ PREDECESSOR = "predecessor"
107
+ SUCCESSOR = "successor"
108
+
109
+
110
+ class YesNo(StrEnum):
111
+ YES = "yes"
112
+ NO = "no"
113
+
114
+
115
+ # ------------------------------------------------------------------------------
116
+ # Leaf wrapper elements
117
+ # ------------------------------------------------------------------------------
118
+
119
+
120
+ @dataclass(slots=True)
121
+ class Identifiers:
122
+ """Wrapper of the persistent identifiers of the repository.
123
+
124
+ Attributes:
125
+ re3data: The re3data identifier, e.g. "r3d100012417".
126
+ doi: The re3data DOI, e.g. "https://doi.org/10.17616/R34F41".
127
+ """
128
+
129
+ re3data: str | None = None
130
+ doi: str | None = None
131
+
132
+
133
+ @dataclass(slots=True)
134
+ class RepositoryName:
135
+ """The full name of the repository, with an optional language attribute."""
136
+
137
+ value: str = ""
138
+ language: str | None = None
139
+
140
+
141
+ @dataclass(slots=True)
142
+ class AdditionalName:
143
+ """The alternative name or acronym of the repository."""
144
+
145
+ value: str = ""
146
+ language: str | None = None
147
+
148
+
149
+ @dataclass(slots=True)
150
+ class Description:
151
+ """A textual description of the repository (primary language is English)."""
152
+
153
+ value: str = ""
154
+ language: str | None = None
155
+
156
+
157
+ @dataclass(slots=True)
158
+ class RepositoryIdentifier:
159
+ """A globally unique identifier referring to the repository.
160
+
161
+ Attributes:
162
+ repositoryIdentifierType: The type of the identifier, e.g. "DOI", "ROR".
163
+ repositoryIdentifierValue: The identifier value, usually a URL.
164
+ """
165
+
166
+ repositoryIdentifierType: str | None = None
167
+ repositoryIdentifierValue: str | None = None
168
+
169
+
170
+ @dataclass(slots=True)
171
+ class RepositoryContact:
172
+ """Contact information of the repository.
173
+
174
+ New in schema 4.0: a wrapper element instead of a plain string.
175
+
176
+ Attributes:
177
+ repositoryContactInformation: An email address or contact form URL.
178
+ repositoryContactType: Optional type of the contact information.
179
+ """
180
+
181
+ repositoryContactInformation: str | None = None
182
+ repositoryContactType: str | None = None
183
+
184
+
185
+ @dataclass(slots=True)
186
+ class EndDate:
187
+ """Date details when the repository went offline or stopped ingesting.
188
+
189
+ New in schema 4.0: the closed/offline flags replace the former date value.
190
+ """
191
+
192
+ closed: bool = False
193
+ offline: bool = False
194
+
195
+
196
+ @dataclass(slots=True)
197
+ class RelatedRepository:
198
+ """A related (predecessor/successor) repository. New in schema 4.0."""
199
+
200
+ relatedRepositoryId: str | None = None
201
+ relatedRepositoryType: str | None = None
202
+
203
+
204
+ @dataclass(slots=True)
205
+ class Subject:
206
+ """A subject of the repository, based on the DFG classification.
207
+
208
+ New in schema 4.0: subjects are identified by ``subjectId`` (e.g. "11204")
209
+ instead of the former free text ("11204 Business Administration").
210
+
211
+ Attributes:
212
+ subjectId: The DFG subject identifier, e.g. "11204".
213
+ subjectName: The DFG subject name, e.g. "Business Administration".
214
+ subjectScheme: The subject scheme attribute, e.g. "DFG".
215
+ """
216
+
217
+ subjectId: str | None = None
218
+ subjectName: str | None = None
219
+ subjectScheme: str | None = None
220
+
221
+
222
+ @dataclass(slots=True)
223
+ class ContentType:
224
+ """A content type available in the repository, based on COAR resource types.
225
+
226
+ New in schema 4.0: content types moved from the former "parse" text list
227
+ to COAR resource type URIs.
228
+
229
+ Attributes:
230
+ contentTypeId: The COAR resource type URI.
231
+ contentTypeName: The COAR resource type name, e.g. "dataset".
232
+ contentTypeScheme: The content type scheme attribute, e.g. "COAR".
233
+ """
234
+
235
+ contentTypeId: str | None = None
236
+ contentTypeName: str | None = None
237
+ contentTypeScheme: str | None = None
238
+
239
+
240
+ @dataclass(slots=True)
241
+ class InstitutionName:
242
+ """The name of an institution, with an optional language attribute."""
243
+
244
+ value: str = ""
245
+ language: str | None = None
246
+
247
+
248
+ @dataclass(slots=True)
249
+ class InstitutionAdditionalName:
250
+ """The alternative name of an institution."""
251
+
252
+ value: str = ""
253
+ language: str | None = None
254
+
255
+
256
+ @dataclass(slots=True)
257
+ class InstitutionIdentifier:
258
+ """An identifier of an institution.
259
+
260
+ New in schema 4.0: structured type/url pair instead of a plain string.
261
+
262
+ Attributes:
263
+ institutionIdentifierType: e.g. "ROR", "RRID".
264
+ institutionIdentifierUrl: e.g. "https://ror.org/02jx3x895".
265
+ """
266
+
267
+ institutionIdentifierType: str | None = None
268
+ institutionIdentifierUrl: str | None = None
269
+
270
+
271
+ @dataclass(slots=True)
272
+ class Institution:
273
+ """An institution responsible for funding, creating and/or running the repository.
274
+
275
+ Attributes:
276
+ institutionName: The name of the institution.
277
+ institutionAdditionalName: Alternative names of the institution.
278
+ institutionCountry: The country of the institution (ISO 3166-1 alpha-3).
279
+ responsibilityType: The types of responsibility, e.g. "funding".
280
+ institutionType: The type of institution, e.g. "non-profit".
281
+ institutionUrl: The URL of the institution.
282
+ institutionIdentifier: Identifiers of the institution.
283
+ responsibilityStartDate: Start of the responsibility (new in 4.0).
284
+ responsibilityEndDate: End of the responsibility (new in 4.0).
285
+ """
286
+
287
+ institutionName: InstitutionName | None = None
288
+ institutionAdditionalName: list[InstitutionAdditionalName] = field(default_factory=list)
289
+ institutionCountry: str | None = None
290
+ responsibilityType: list[str] = field(default_factory=list)
291
+ institutionType: str | None = None
292
+ institutionUrl: str | None = None
293
+ institutionIdentifier: list[InstitutionIdentifier] = field(default_factory=list)
294
+ responsibilityStartDate: date | None = None
295
+ responsibilityEndDate: date | None = None
296
+
297
+
298
+ @dataclass(slots=True)
299
+ class Policy:
300
+ """A policy of the repository, e.g. a data policy."""
301
+
302
+ policyName: str | None = None
303
+ policyUrl: str | None = None
304
+
305
+
306
+ @dataclass(slots=True)
307
+ class FunderIdentifier:
308
+ """An identifier of a funder. New in schema 4.0."""
309
+
310
+ funderIdentifierType: str | None = None
311
+ funderIdentifierValue: str | None = None
312
+
313
+
314
+ @dataclass(slots=True)
315
+ class FundingInformation:
316
+ """Funding information of the repository. New in schema 4.0.
317
+
318
+ Attributes:
319
+ funderName: The name of the funder.
320
+ funderIdentifier: Identifiers of the funder.
321
+ grantIdentifier: The identifier of the grant.
322
+ """
323
+
324
+ funderName: str | None = None
325
+ funderIdentifier: list[FunderIdentifier] = field(default_factory=list)
326
+ grantIdentifier: str | None = None
327
+
328
+
329
+ @dataclass(slots=True)
330
+ class DatabaseAccess:
331
+ """The access restrictions of the repository database (wrapper element)."""
332
+
333
+ databaseAccessType: str | None = None
334
+ databaseAccessRestriction: list[str] = field(default_factory=list)
335
+
336
+
337
+ @dataclass(slots=True)
338
+ class DatabaseLicense:
339
+ """The license of the repository database."""
340
+
341
+ databaseLicenseName: str | None = None
342
+ databaseLicenseUrl: str | None = None
343
+
344
+
345
+ @dataclass(slots=True)
346
+ class DataAccess:
347
+ """The access restrictions of the data (wrapper element)."""
348
+
349
+ dataAccessType: str | None = None
350
+ dataAccessRestriction: list[str] = field(default_factory=list)
351
+
352
+
353
+ @dataclass(slots=True)
354
+ class DataLicense:
355
+ """The license of the data available in the repository."""
356
+
357
+ dataLicenseName: str | None = None
358
+ dataLicenseUrl: str | None = None
359
+
360
+
361
+ @dataclass(slots=True)
362
+ class DataUpload:
363
+ """The upload restrictions of the repository (wrapper element)."""
364
+
365
+ dataUploadType: str | None = None
366
+ dataUploadRestriction: list[str] = field(default_factory=list)
367
+
368
+
369
+ @dataclass(slots=True)
370
+ class DataUploadLicense:
371
+ """The license for data upload."""
372
+
373
+ dataUploadLicenseName: str | None = None
374
+ dataUploadLicenseUrl: str | None = None
375
+
376
+
377
+ @dataclass(slots=True)
378
+ class Api:
379
+ """An API provided by the repository.
380
+
381
+ New in schema 4.0: ``apiUrl`` is a dedicated child element (formerly the
382
+ element text) and ``apiDocumentation`` was added.
383
+
384
+ Attributes:
385
+ apiType: The type of the API, e.g. "OAI-PMH", "REST".
386
+ apiUrl: The URL of the API.
387
+ apiDocumentation: URL or text pointing to the API documentation.
388
+ """
389
+
390
+ apiType: str | None = None
391
+ apiUrl: str | None = None
392
+ apiDocumentation: str | None = None
393
+
394
+
395
+ @dataclass(slots=True)
396
+ class QualityManagementMeasure:
397
+ """A quality management measure. New in schema 4.0."""
398
+
399
+ qualityManagementMeasureName: str | None = None
400
+ qualityManagementMeasureUrl: str | None = None
401
+
402
+
403
+ @dataclass(slots=True)
404
+ class QualityManagement:
405
+ """Quality management information.
406
+
407
+ New in schema 4.0: a wrapper with an explicit status and measures,
408
+ replacing the former yes/no/unknown element.
409
+ """
410
+
411
+ qualityManagementStatus: str | None = None
412
+ qualityManagementMeasure: list[QualityManagementMeasure] = field(default_factory=list)
413
+
414
+
415
+ @dataclass(slots=True)
416
+ class Certificate:
417
+ """A certificate, seal or standard the repository complies with.
418
+
419
+ New in schema 4.0: structured name/dates/url instead of a plain enum value.
420
+ """
421
+
422
+ certificateName: str | None = None
423
+ certificateStartDate: date | None = None
424
+ certificateEndDate: date | None = None
425
+ certificateUrl: str | None = None
426
+ certificateWidget: str | None = None
427
+
428
+
429
+ @dataclass(slots=True)
430
+ class Profile:
431
+ """A profile the repository complies with, e.g. "Helmholtz Association". New in schema 4.0."""
432
+
433
+ profileName: str | None = None
434
+ profileUrl: str | None = None
435
+
436
+
437
+ @dataclass(slots=True)
438
+ class MetadataStandard:
439
+ """A metadata standard the repository adheres to."""
440
+
441
+ metadataStandardName: str | None = None
442
+ metadataStandardUrl: str | None = None
443
+
444
+
445
+ @dataclass(slots=True)
446
+ class Syndication:
447
+ """An alerting service provided by the repository, e.g. RSS."""
448
+
449
+ syndicationType: str | None = None
450
+ syndicationUrl: str | None = None
451
+
452
+
453
+ # ------------------------------------------------------------------------------
454
+ # Repository and root element
455
+ # ------------------------------------------------------------------------------
456
+
457
+
458
+ @dataclass(slots=True)
459
+ class Repository:
460
+ """A research data repository described with the re3data schema 4.0.
461
+
462
+ Attributes:
463
+ identifiers: The persistent identifiers (re3data id and DOI).
464
+ repositoryName: The full name of the repository.
465
+ additionalName: Alternative names or acronyms of the repository.
466
+ repositoryUrl: The URL referencing the repository.
467
+ repositoryIdentifier: Identifiers referring to the repository.
468
+ description: Textual descriptions of the repository.
469
+ repositoryContact: Contact information of the repository.
470
+ type: The types of the repository.
471
+ size: The number of items contained in the repository.
472
+ startDate: The releasing date of the repository.
473
+ endDate: Details if the repository went offline.
474
+ relatedRepository: Predecessor/successor repositories.
475
+ repositoryLanguage: The user interface languages of the repository.
476
+ subject: The subjects of the repository (DFG classification).
477
+ missionStatementUrl: URL of the mission statement.
478
+ contentType: The types of resources available (COAR resource types).
479
+ providerType: The types of provider.
480
+ keyword: English keywords describing the subject focus.
481
+ institution: The institutions responsible for the repository.
482
+ policy: Policies of the repository.
483
+ fundingInformation: Funding information of the repository.
484
+ databaseAccess: The database access restrictions.
485
+ databaseLicense: The database licenses.
486
+ dataAccess: The data access restrictions.
487
+ dataLicense: The licenses of the data.
488
+ dataUpload: The data upload restrictions.
489
+ dataUploadLicense: The licenses for data upload.
490
+ software: The software used to run the repository.
491
+ versioning: Whether the repository supports versioning ("yes"/"no").
492
+ api: The APIs provided by the repository.
493
+ pidSystem: The persistent identifier systems used.
494
+ citationReference: Citation references (new in 4.0).
495
+ metrics: Metrics in use, e.g. "Altmetric" (new in 4.0).
496
+ citationGuidelineUrl: URL describing how to cite the research data.
497
+ aidSystem: The author identifier systems used.
498
+ enhancedPublication: Whether publications and data are interlinked.
499
+ qualityManagement: Quality management information.
500
+ certificate: Certificates, seals or standards complied with.
501
+ profile: Profiles complied with (new in 4.0).
502
+ metadataStandard: Metadata standards adhered to.
503
+ syndication: Alerting services of the repository.
504
+ remarks: Additional remarks.
505
+ entryDate: The date the repository was indexed in re3data.org.
506
+ lastUpdate: The date the metadata was last updated.
507
+ """
508
+
509
+ identifiers: Identifiers | None = None
510
+ repositoryName: RepositoryName | None = None
511
+ additionalName: list[AdditionalName] = field(default_factory=list)
512
+ repositoryUrl: str | None = None
513
+ repositoryIdentifier: list[RepositoryIdentifier] = field(default_factory=list)
514
+ description: list[Description] = field(default_factory=list)
515
+ repositoryContact: list[RepositoryContact] = field(default_factory=list)
516
+ type: list[str] = field(default_factory=list)
517
+ size: str | None = None
518
+ startDate: date | None = None
519
+ endDate: EndDate | None = None
520
+ relatedRepository: list[RelatedRepository] = field(default_factory=list)
521
+ repositoryLanguage: list[str] = field(default_factory=list)
522
+ subject: list[Subject] = field(default_factory=list)
523
+ missionStatementUrl: str | None = None
524
+ contentType: list[ContentType] = field(default_factory=list)
525
+ providerType: list[str] = field(default_factory=list)
526
+ keyword: list[str] = field(default_factory=list)
527
+ institution: list[Institution] = field(default_factory=list)
528
+ policy: list[Policy] = field(default_factory=list)
529
+ fundingInformation: list[FundingInformation] = field(default_factory=list)
530
+ databaseAccess: DatabaseAccess | None = None
531
+ databaseLicense: list[DatabaseLicense] = field(default_factory=list)
532
+ dataAccess: list[DataAccess] = field(default_factory=list)
533
+ dataLicense: list[DataLicense] = field(default_factory=list)
534
+ dataUpload: list[DataUpload] = field(default_factory=list)
535
+ dataUploadLicense: list[DataUploadLicense] = field(default_factory=list)
536
+ software: list[str] = field(default_factory=list)
537
+ versioning: str | None = None
538
+ api: list[Api] = field(default_factory=list)
539
+ pidSystem: list[str] = field(default_factory=list)
540
+ citationReference: list[str] = field(default_factory=list)
541
+ metrics: list[str] = field(default_factory=list)
542
+ citationGuidelineUrl: str | None = None
543
+ aidSystem: list[str] = field(default_factory=list)
544
+ enhancedPublication: str | None = None
545
+ qualityManagement: QualityManagement | None = None
546
+ certificate: list[Certificate] = field(default_factory=list)
547
+ profile: list[Profile] = field(default_factory=list)
548
+ metadataStandard: list[MetadataStandard] = field(default_factory=list)
549
+ syndication: list[Syndication] = field(default_factory=list)
550
+ remarks: str | None = None
551
+ entryDate: date | None = None
552
+ lastUpdate: date | None = None
553
+
554
+ @property
555
+ def id(self) -> str | None:
556
+ """The re3data identifier of the repository."""
557
+ return self.identifiers.re3data if self.identifiers else None
558
+
559
+
560
+ @dataclass(slots=True)
561
+ class Re3Data:
562
+ """The root element of a repository detail response."""
563
+
564
+ repository: list[Repository] = field(default_factory=list)
@@ -0,0 +1,66 @@
1
+ """API resources for the /repositories endpoint (v40).
2
+
3
+ The list endpoint returns a HATEOAS-style index document:
4
+
5
+ .. code-block:: xml
6
+
7
+ <list>
8
+ <repository>
9
+ <id>r3d100012417</id>
10
+ <doi>https://doi.org/10.17616/R34F41</doi>
11
+ <name>UCL Discovery</name>
12
+ <link href="https://www.re3data.org/api/v40/repository/r3d100012417" rel="self" />
13
+ </repository>
14
+ </list>
15
+
16
+ Note: compared to the deprecated beta API, the v40 list additionally includes
17
+ the repository ``name``.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from dataclasses import dataclass, field
23
+
24
+ __NAMESPACE__ = "http://www.re3data.org/schema/4-0"
25
+
26
+
27
+ @dataclass(slots=True)
28
+ class Link:
29
+ """A hyperlink pointing to a repository resource.
30
+
31
+ Attributes:
32
+ href: The URL of the linked resource.
33
+ rel: The relation type of the link, e.g. "self".
34
+ """
35
+
36
+ href: str | None = None
37
+ rel: str | None = None
38
+
39
+
40
+ @dataclass(slots=True)
41
+ class RepositorySummary:
42
+ """A single repository entry of the list endpoint.
43
+
44
+ Attributes:
45
+ id: The re3data identifier of the repository, e.g. "r3d100012417".
46
+ doi: The DOI of the repository.
47
+ name: The name of the repository.
48
+ link: A hyperlink to the repository detail resource.
49
+ """
50
+
51
+ id: str | None = None
52
+ doi: str | None = None
53
+ name: str | None = None
54
+ link: Link | None = None
55
+
56
+ @property
57
+ def href(self) -> str | None:
58
+ """The URL of the detail resource, derived from the link element."""
59
+ return self.link.href if self.link else None
60
+
61
+
62
+ @dataclass(slots=True)
63
+ class RepositoryList:
64
+ """The root element of the list endpoint response."""
65
+
66
+ repository: list[RepositorySummary] = field(default_factory=list)
re3data/_response.py ADDED
@@ -0,0 +1,34 @@
1
+ """A structured representation of responses from the re3data API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+ import httpx
8
+
9
+
10
+ @dataclass(slots=True)
11
+ class Response:
12
+ """A response received from the re3data API, encapsulating the HTTP response.
13
+
14
+ Attributes:
15
+ url: The URL of the request.
16
+ status_code: The HTTP status code of the response.
17
+ headers: The response headers.
18
+ text: The raw XML response text.
19
+ """
20
+
21
+ url: httpx.URL
22
+ status_code: httpx.codes
23
+ headers: httpx.Headers = field(repr=False)
24
+ text: str = field(repr=False)
25
+
26
+
27
+ def _build_response(http_response: httpx.Response) -> Response:
28
+ """Build a :class:`Response` object from an ``httpx.Response``."""
29
+ return Response(
30
+ url=http_response.url,
31
+ status_code=httpx.codes(http_response.status_code),
32
+ headers=http_response.headers,
33
+ text=http_response.text,
34
+ )