mpcontribs-client 5.10.1__py3-none-any.whl → 5.10.2__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.
@@ -20,7 +20,7 @@ from math import isclose
20
20
  from semantic_version import Version
21
21
  from requests.exceptions import RequestException
22
22
  from bson.objectid import ObjectId
23
- from typing import Union, Type, List
23
+ from typing import Union, Type, Optional
24
24
  from tqdm.auto import tqdm
25
25
  from hashlib import md5
26
26
  from pathlib import Path
@@ -297,7 +297,7 @@ def _response_hook(resp, *args, **kwargs):
297
297
  def _chunk_by_size(items, max_size=0.95 * MAX_BYTES):
298
298
  buffer, buffer_size = [], 0
299
299
 
300
- for idx, item in enumerate(items):
300
+ for item in items:
301
301
  item_size = _compress(item)[0]
302
302
 
303
303
  if buffer_size + item_size <= max_size:
@@ -466,7 +466,7 @@ class Structure(PmgStructure):
466
466
  class Attachment(dict):
467
467
  """Wrapper class around dict to handle attachments"""
468
468
 
469
- def decode(self) -> str:
469
+ def decode(self) -> bytes:
470
470
  """Decode base64-encoded content of attachment"""
471
471
  return b64decode(self["content"], validate=True)
472
472
 
@@ -478,7 +478,7 @@ class Attachment(dict):
478
478
 
479
479
  return unpacked
480
480
 
481
- def write(self, outdir: Union[str, Path] = None) -> Path:
481
+ def write(self, outdir: Optional[Union[str, Path]] = None) -> Path:
482
482
  """Write attachment to file using its name
483
483
 
484
484
  Args:
@@ -490,7 +490,7 @@ class Attachment(dict):
490
490
  path.write_bytes(content)
491
491
  return path
492
492
 
493
- def display(self, outdir: Union[str, Path] = None):
493
+ def display(self, outdir: Optional[Union[str, Path]] = None):
494
494
  """Display Image/FileLink for attachment if in IPython/Jupyter
495
495
 
496
496
  Args:
@@ -761,7 +761,7 @@ def _expand_params(protocol, host, version, projects_json, apikey=None):
761
761
  columns = {"string": [], "number": []}
762
762
  projects = ujson.loads(projects_json)
763
763
  query = {"project__in": ",".join(projects)}
764
- query["_fields"] = ["columns"]
764
+ query["_fields"] = "columns"
765
765
  url = f"{protocol}://{host}"
766
766
  http_client = RequestsClient()
767
767
  http_client.session.headers["Content-Type"] = "application/json"
@@ -870,11 +870,11 @@ class Client(SwaggerClient):
870
870
 
871
871
  def __init__(
872
872
  self,
873
- apikey: str = None,
874
- headers: dict = None,
875
- host: str = None,
876
- project: str = None,
877
- session: requests.Session = None,
873
+ apikey: Optional[str] = None,
874
+ headers: Optional[dict] = None,
875
+ host: Optional[str] = None,
876
+ project: Optional[str] = None,
877
+ session: Optional[requests.Session] = None,
878
878
  ):
879
879
  """Initialize the client - only reloads API spec from server as needed
880
880
 
@@ -966,7 +966,7 @@ class Client(SwaggerClient):
966
966
 
967
967
  def _get_per_page_default_max(
968
968
  self, op: str = "query", resource: str = "contributions"
969
- ) -> int:
969
+ ) -> tuple[int, int]:
970
970
  attr = f"{op}{resource.capitalize()}"
971
971
  resource = self.swagger_spec.resources[resource]
972
972
  param_spec = getattr(resource, attr).params["per_page"].param_spec
@@ -988,7 +988,7 @@ class Client(SwaggerClient):
988
988
  op: str = "query",
989
989
  resource: str = "contributions",
990
990
  pages: int = -1,
991
- ) -> List[dict]:
991
+ ) -> list[dict]:
992
992
  """Avoid URI too long errors"""
993
993
  pp_default, pp_max = self._get_per_page_default_max(op=op, resource=resource)
994
994
  per_page = (
@@ -1047,7 +1047,7 @@ class Client(SwaggerClient):
1047
1047
  params: dict,
1048
1048
  rel_url: str = "contributions",
1049
1049
  op: str = "query",
1050
- data: dict = None,
1050
+ data: Optional[dict] = None,
1051
1051
  ):
1052
1052
  rname = rel_url.split("/", 1)[0]
1053
1053
  resource = self.swagger_spec.resources[rname]
@@ -1065,7 +1065,9 @@ class Client(SwaggerClient):
1065
1065
  return future
1066
1066
 
1067
1067
  def available_query_params(
1068
- self, startswith: tuple = None, resource: str = "contributions"
1068
+ self,
1069
+ startswith: Optional[tuple] = None,
1070
+ resource: str = "contributions",
1069
1071
  ) -> list:
1070
1072
  resources = self.swagger_spec.resources
1071
1073
  resource_obj = resources.get(resource)
@@ -1081,7 +1083,9 @@ class Client(SwaggerClient):
1081
1083
 
1082
1084
  return [param for param in params if param.startswith(startswith)]
1083
1085
 
1084
- def get_project(self, name: str = None, fields: list = None) -> Type[Dict]:
1086
+ def get_project(
1087
+ self, name: Optional[str] = None, fields: Optional[list] = None
1088
+ ) -> Dict:
1085
1089
  """Retrieve a project entry
1086
1090
 
1087
1091
  Args:
@@ -1099,12 +1103,12 @@ class Client(SwaggerClient):
1099
1103
 
1100
1104
  def query_projects(
1101
1105
  self,
1102
- query: dict = None,
1103
- term: str = None,
1104
- fields: list = None,
1105
- sort: str = None,
1106
+ query: Optional[dict] = None,
1107
+ term: Optional[str] = None,
1108
+ fields: Optional[list] = None,
1109
+ sort: Optional[str] = None,
1106
1110
  timeout: int = -1,
1107
- ) -> List[dict]:
1111
+ ) -> list[dict]:
1108
1112
  """Query projects by query and/or term (Atlas Search)
1109
1113
 
1110
1114
  See `client.available_query_params(resource="projects")` for keyword arguments used in
@@ -1206,7 +1210,7 @@ class Client(SwaggerClient):
1206
1210
  else:
1207
1211
  raise MPContribsClientError(resp)
1208
1212
 
1209
- def update_project(self, update: dict, name: str = None):
1213
+ def update_project(self, update: dict, name: Optional[str] = None):
1210
1214
  """Update project info
1211
1215
 
1212
1216
  Args:
@@ -1272,7 +1276,7 @@ class Client(SwaggerClient):
1272
1276
  else:
1273
1277
  raise MPContribsClientError(error)
1274
1278
 
1275
- def delete_project(self, name: str = None):
1279
+ def delete_project(self, name: Optional[str] = None):
1276
1280
  """Delete a project
1277
1281
 
1278
1282
  Args:
@@ -1291,7 +1295,7 @@ class Client(SwaggerClient):
1291
1295
  if resp and "error" in resp:
1292
1296
  raise MPContribsClientError(resp["error"])
1293
1297
 
1294
- def get_contribution(self, cid: str, fields: list = None) -> Type[Dict]:
1298
+ def get_contribution(self, cid: str, fields: Optional[list] = None) -> Dict:
1295
1299
  """Retrieve a contribution
1296
1300
 
1297
1301
  Args:
@@ -1305,7 +1309,7 @@ class Client(SwaggerClient):
1305
1309
  self.contributions.getContributionById(pk=cid, _fields=fields).result()
1306
1310
  )
1307
1311
 
1308
- def get_table(self, tid_or_md5: str) -> Type[Table]:
1312
+ def get_table(self, tid_or_md5: str) -> Table:
1309
1313
  """Retrieve full Pandas DataFrame for a table
1310
1314
 
1311
1315
  Args:
@@ -1347,7 +1351,7 @@ class Client(SwaggerClient):
1347
1351
 
1348
1352
  return Table.from_dict(table)
1349
1353
 
1350
- def get_structure(self, sid_or_md5: str) -> Type[Structure]:
1354
+ def get_structure(self, sid_or_md5: str) -> Structure:
1351
1355
  """Retrieve pymatgen structure
1352
1356
 
1353
1357
  Args:
@@ -1375,7 +1379,7 @@ class Client(SwaggerClient):
1375
1379
  resp = self.structures.getStructureById(pk=sid, _fields=fields).result()
1376
1380
  return Structure.from_dict(resp)
1377
1381
 
1378
- def get_attachment(self, aid_or_md5: str) -> Type[Attachment]:
1382
+ def get_attachment(self, aid_or_md5: str) -> Attachment:
1379
1383
  """Retrieve an attachment
1380
1384
 
1381
1385
  Args:
@@ -1403,7 +1407,9 @@ class Client(SwaggerClient):
1403
1407
  self.attachments.getAttachmentById(pk=aid, _fields=["_all"]).result()
1404
1408
  )
1405
1409
 
1406
- def init_columns(self, columns: dict = None, name: str = None) -> dict:
1410
+ def init_columns(
1411
+ self, columns: Optional[dict] = None, name: Optional[str] = None
1412
+ ) -> dict:
1407
1413
  """initialize columns for a project to set their order and desired units
1408
1414
 
1409
1415
  The `columns` field of a project tracks the minima and maxima of each `data` field
@@ -1560,7 +1566,7 @@ class Client(SwaggerClient):
1560
1566
 
1561
1567
  return self.projects.updateProjectByName(pk=name, project=payload).result()
1562
1568
 
1563
- def delete_contributions(self, query: dict = None, timeout: int = -1):
1569
+ def delete_contributions(self, query: Optional[dict] = None, timeout: int = -1):
1564
1570
  """Remove all contributions for a query
1565
1571
 
1566
1572
  Args:
@@ -1594,7 +1600,7 @@ class Client(SwaggerClient):
1594
1600
  _run_futures(futures, total=total, timeout=timeout)
1595
1601
  left, _ = self.get_totals(query=query)
1596
1602
  deleted = total - left
1597
- self.init_columns()
1603
+ self.init_columns(name=query["project"])
1598
1604
  self._reinit()
1599
1605
  toc = time.perf_counter()
1600
1606
  dt = (toc - tic) / 60
@@ -1607,7 +1613,7 @@ class Client(SwaggerClient):
1607
1613
 
1608
1614
  def get_totals(
1609
1615
  self,
1610
- query: dict = None,
1616
+ query: Optional[dict] = None,
1611
1617
  timeout: int = -1,
1612
1618
  resource: str = "contributions",
1613
1619
  op: str = "query",
@@ -1648,11 +1654,11 @@ class Client(SwaggerClient):
1648
1654
 
1649
1655
  return result["total_count"], result["total_pages"]
1650
1656
 
1651
- def count(self, query: dict = None) -> int:
1657
+ def count(self, query: Optional[dict] = None) -> int:
1652
1658
  """shortcut for get_totals()"""
1653
1659
  return self.get_totals(query=query)[0]
1654
1660
 
1655
- def get_unique_identifiers_flags(self, query: dict = None) -> dict:
1661
+ def get_unique_identifiers_flags(self, query: Optional[dict] = None) -> dict:
1656
1662
  """Retrieve values for `unique_identifiers` flags.
1657
1663
 
1658
1664
  See `client.available_query_params(resource="projects")` for available query parameters.
@@ -1672,10 +1678,10 @@ class Client(SwaggerClient):
1672
1678
 
1673
1679
  def get_all_ids(
1674
1680
  self,
1675
- query: dict = None,
1676
- include: List[str] = None,
1681
+ query: Optional[dict] = None,
1682
+ include: Optional[list[str]] = None,
1677
1683
  timeout: int = -1,
1678
- data_id_fields: dict = None,
1684
+ data_id_fields: Optional[dict] = None,
1679
1685
  fmt: str = "sets",
1680
1686
  op: str = "query",
1681
1687
  ) -> dict:
@@ -1830,12 +1836,12 @@ class Client(SwaggerClient):
1830
1836
 
1831
1837
  def query_contributions(
1832
1838
  self,
1833
- query: dict = None,
1834
- fields: list = None,
1835
- sort: str = None,
1839
+ query: Optional[dict] = None,
1840
+ fields: Optional[list] = None,
1841
+ sort: Optional[str] = None,
1836
1842
  paginate: bool = False,
1837
1843
  timeout: int = -1,
1838
- ) -> List[dict]:
1844
+ ) -> dict:
1839
1845
  """Query contributions
1840
1846
 
1841
1847
  See `client.available_query_params()` for keyword arguments used in query.
@@ -1886,7 +1892,7 @@ class Client(SwaggerClient):
1886
1892
  return ret
1887
1893
 
1888
1894
  def update_contributions(
1889
- self, data: dict, query: dict = None, timeout: int = -1
1895
+ self, data: dict, query: Optional[dict] = None, timeout: int = -1
1890
1896
  ) -> dict:
1891
1897
  """Apply the same update to all contributions in a project (matching query)
1892
1898
 
@@ -1898,7 +1904,7 @@ class Client(SwaggerClient):
1898
1904
  timeout (int): cancel remaining requests if timeout exceeded (in seconds)
1899
1905
  """
1900
1906
  if not data:
1901
- return "Nothing to update."
1907
+ raise MPContribsClientError("Nothing to update.")
1902
1908
 
1903
1909
  tic = time.perf_counter()
1904
1910
  valid, error = self._is_valid_payload("Contribution", data)
@@ -1912,27 +1918,28 @@ class Client(SwaggerClient):
1912
1918
 
1913
1919
  query = query or {}
1914
1920
 
1915
- if not self.project and (not query or "project" not in query):
1916
- raise MPContribsClientError(
1917
- "initialize client with project, or include project in query!"
1918
- )
1919
-
1920
- if "project" in query and self.project != query["project"]:
1921
- raise MPContribsClientError(
1922
- f"client initialized with different project {self.project}!"
1923
- )
1921
+ if self.project:
1922
+ if "project" in query and self.project != query["project"]:
1923
+ raise MPContribsClientError(
1924
+ f"client initialized with different project {self.project}!"
1925
+ )
1926
+ query["project"] = self.project
1927
+ else:
1928
+ if not query or "project" not in query:
1929
+ raise MPContribsClientError(
1930
+ "initialize client with project, or include project in query!"
1931
+ )
1924
1932
 
1925
- query["project"] = self.project
1926
- cids = list(self.get_all_ids(query).get(self.project, {}).get("ids", set()))
1933
+ name = query["project"]
1934
+ cids = list(self.get_all_ids(query).get(name, {}).get("ids", set()))
1927
1935
 
1928
1936
  if not cids:
1929
- logger.info(f"There aren't any contributions to update for {self.project}")
1930
- return
1937
+ raise MPContribsClientError(
1938
+ f"There aren't any contributions to update for {name}"
1939
+ )
1931
1940
 
1932
1941
  # get current list of data columns to decide if swagger reload is needed
1933
- resp = self.projects.getProjectByName(
1934
- pk=self.project, _fields=["columns"]
1935
- ).result()
1942
+ resp = self.projects.getProjectByName(pk=name, _fields=["columns"]).result()
1936
1943
  old_paths = set(c["path"] for c in resp["columns"])
1937
1944
 
1938
1945
  total = len(cids)
@@ -1947,20 +1954,18 @@ class Client(SwaggerClient):
1947
1954
  updated = sum(resp["count"] for _, resp in responses.items())
1948
1955
 
1949
1956
  if updated:
1950
- resp = self.projects.getProjectByName(
1951
- pk=self.project, _fields=["columns"]
1952
- ).result()
1957
+ resp = self.projects.getProjectByName(pk=name, _fields=["columns"]).result()
1953
1958
  new_paths = set(c["path"] for c in resp["columns"])
1954
1959
 
1955
1960
  if new_paths != old_paths:
1956
- self.init_columns()
1961
+ self.init_columns(name=name)
1957
1962
  self._reinit()
1958
1963
 
1959
1964
  toc = time.perf_counter()
1960
1965
  return {"updated": updated, "total": total, "seconds_elapsed": toc - tic}
1961
1966
 
1962
1967
  def make_public(
1963
- self, query: dict = None, recursive: bool = False, timeout: int = -1
1968
+ self, query: Optional[dict] = None, recursive: bool = False, timeout: int = -1
1964
1969
  ) -> dict:
1965
1970
  """Publish a project and optionally its contributions
1966
1971
 
@@ -1973,7 +1978,7 @@ class Client(SwaggerClient):
1973
1978
  )
1974
1979
 
1975
1980
  def make_private(
1976
- self, query: dict = None, recursive: bool = False, timeout: int = -1
1981
+ self, query: Optional[dict] = None, recursive: bool = False, timeout: int = -1
1977
1982
  ) -> dict:
1978
1983
  """Make a project and optionally its contributions private
1979
1984
 
@@ -1988,7 +1993,7 @@ class Client(SwaggerClient):
1988
1993
  def _set_is_public(
1989
1994
  self,
1990
1995
  is_public: bool,
1991
- query: dict = None,
1996
+ query: Optional[dict] = None,
1992
1997
  recursive: bool = False,
1993
1998
  timeout: int = -1,
1994
1999
  ) -> dict:
@@ -2040,7 +2045,7 @@ class Client(SwaggerClient):
2040
2045
  if recursive:
2041
2046
  query = query or {}
2042
2047
  query["is_public"] = not is_public
2043
- ret["contributions"] = self.updateContributions(
2048
+ ret["contributions"] = self.update_contributions(
2044
2049
  {"is_public": is_public}, query=query, timeout=timeout
2045
2050
  )
2046
2051
 
@@ -2048,7 +2053,7 @@ class Client(SwaggerClient):
2048
2053
 
2049
2054
  def submit_contributions(
2050
2055
  self,
2051
- contributions: List[dict],
2056
+ contributions: list[dict],
2052
2057
  ignore_dupes: bool = False,
2053
2058
  timeout: int = -1,
2054
2059
  skip_dupe_check: bool = False,
@@ -2250,6 +2255,8 @@ class Client(SwaggerClient):
2250
2255
  element = Attachment.from_file(element)
2251
2256
 
2252
2257
  dct = {k: element[k] for k in ["mime", "content"]}
2258
+ else:
2259
+ raise MPContribsClientError("This should never happen")
2253
2260
 
2254
2261
  digest = get_md5(dct)
2255
2262
 
@@ -2406,11 +2413,11 @@ class Client(SwaggerClient):
2406
2413
  logger.info(
2407
2414
  f"{project_name}: resubmit failed contributions manually"
2408
2415
  )
2416
+ self.init_columns(name=project_name)
2409
2417
 
2418
+ self._reinit()
2410
2419
  toc = time.perf_counter()
2411
2420
  dt = (toc - tic) / 60
2412
- self.init_columns()
2413
- self._reinit()
2414
2421
  logger.info(
2415
2422
  f"It took {dt:.1f}min to submit {total_processed}/{total} contributions."
2416
2423
  )
@@ -2419,12 +2426,12 @@ class Client(SwaggerClient):
2419
2426
 
2420
2427
  def download_contributions(
2421
2428
  self,
2422
- query: dict = None,
2429
+ query: Optional[dict] = None,
2423
2430
  outdir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR,
2424
2431
  overwrite: bool = False,
2425
- include: List[str] = None,
2432
+ include: Optional[list[str]] = None,
2426
2433
  timeout: int = -1,
2427
- ) -> int:
2434
+ ) -> list:
2428
2435
  """Download a list of contributions as .json.gz file(s)
2429
2436
 
2430
2437
  Args:
@@ -2446,7 +2453,7 @@ class Client(SwaggerClient):
2446
2453
  if include and not components:
2447
2454
  raise MPContribsClientError(f"`include` must be subset of {COMPONENTS}!")
2448
2455
 
2449
- all_ids = self.get_all_ids(query, include=components, timeout=timeout)
2456
+ all_ids = self.get_all_ids(query, include=list(components), timeout=timeout)
2450
2457
  fmt = query.get("format", "json")
2451
2458
  contributions, components_loaded = [], defaultdict(dict)
2452
2459
 
@@ -2520,12 +2527,12 @@ class Client(SwaggerClient):
2520
2527
 
2521
2528
  def download_structures(
2522
2529
  self,
2523
- ids: List[str],
2530
+ ids: list[str],
2524
2531
  outdir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR,
2525
2532
  overwrite: bool = False,
2526
2533
  timeout: int = -1,
2527
2534
  fmt: str = "json",
2528
- ) -> Path:
2535
+ ) -> list[Path]:
2529
2536
  """Download a list of structures as a .json.gz file
2530
2537
 
2531
2538
  Args:
@@ -2549,12 +2556,12 @@ class Client(SwaggerClient):
2549
2556
 
2550
2557
  def download_tables(
2551
2558
  self,
2552
- ids: List[str],
2559
+ ids: list[str],
2553
2560
  outdir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR,
2554
2561
  overwrite: bool = False,
2555
2562
  timeout: int = -1,
2556
2563
  fmt: str = "json",
2557
- ) -> Path:
2564
+ ) -> list[Path]:
2558
2565
  """Download a list of tables as a .json.gz file
2559
2566
 
2560
2567
  Args:
@@ -2578,12 +2585,12 @@ class Client(SwaggerClient):
2578
2585
 
2579
2586
  def download_attachments(
2580
2587
  self,
2581
- ids: List[str],
2588
+ ids: list[str],
2582
2589
  outdir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR,
2583
2590
  overwrite: bool = False,
2584
2591
  timeout: int = -1,
2585
2592
  fmt: str = "json",
2586
- ) -> Path:
2593
+ ) -> list[Path]:
2587
2594
  """Download a list of attachments as a .json.gz file
2588
2595
 
2589
2596
  Args:
@@ -2608,12 +2615,12 @@ class Client(SwaggerClient):
2608
2615
  def _download_resource(
2609
2616
  self,
2610
2617
  resource: str,
2611
- ids: List[str],
2618
+ ids: list[str],
2612
2619
  outdir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR,
2613
2620
  overwrite: bool = False,
2614
2621
  timeout: int = -1,
2615
2622
  fmt: str = "json",
2616
- ) -> Path:
2623
+ ) -> list[Path]:
2617
2624
  """Helper to download a list of resources as .json.gz file
2618
2625
 
2619
2626
  Args:
@@ -2625,7 +2632,7 @@ class Client(SwaggerClient):
2625
2632
  fmt: download format - "json" or "csv"
2626
2633
 
2627
2634
  Returns:
2628
- tuple (paths of output files, objects per path / per_page)
2635
+ list of paths to output files
2629
2636
  """
2630
2637
  resources = ["contributions"] + COMPONENTS
2631
2638
  if resource not in resources:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mpcontribs-client
3
- Version: 5.10.1
3
+ Version: 5.10.2
4
4
  Summary: client library for MPContribs API
5
5
  Home-page: https://github.com/materialsproject/MPContribs/tree/master/mpcontribs-client
6
6
  Author: Patrick Huck
@@ -0,0 +1,6 @@
1
+ mpcontribs/client/__init__.py,sha256=i3_utKfv1fC0V02L0U-ZYDgz98p6we3t-rMqllRzsbc,97589
2
+ mpcontribs_client-5.10.2.dist-info/LICENSE,sha256=5tG0Niaqw2hnuyZZYkRXLSnfVrZA47COwduU_6caPLM,1074
3
+ mpcontribs_client-5.10.2.dist-info/METADATA,sha256=3nW4oolxr1LwtRLFJ-PTF7FoVgxz9hQkOlrT5e9QWVk,2776
4
+ mpcontribs_client-5.10.2.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
5
+ mpcontribs_client-5.10.2.dist-info/top_level.txt,sha256=t8R5L_Dg9oDQMh2gyRFdZGnrzZsr7OjCBTrhTcmimC8,11
6
+ mpcontribs_client-5.10.2.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- mpcontribs/client/__init__.py,sha256=SmVQBVOTWRYfX-rUXEP1gdPkJANxWdTDUP5c679yRSU,97012
2
- mpcontribs_client-5.10.1.dist-info/LICENSE,sha256=5tG0Niaqw2hnuyZZYkRXLSnfVrZA47COwduU_6caPLM,1074
3
- mpcontribs_client-5.10.1.dist-info/METADATA,sha256=vsvzgHYxTxXppTw3ZaCu7mJU4HAmmvOgKZdwv3ijg-o,2776
4
- mpcontribs_client-5.10.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
5
- mpcontribs_client-5.10.1.dist-info/top_level.txt,sha256=t8R5L_Dg9oDQMh2gyRFdZGnrzZsr7OjCBTrhTcmimC8,11
6
- mpcontribs_client-5.10.1.dist-info/RECORD,,