mpcontribs-client 5.10.5rc0__py3-none-any.whl → 5.10.5rc1__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.
@@ -1,62 +1,62 @@
1
- import io
1
+ import functools
2
+ import gzip
2
3
  import importlib.metadata
3
- import sys
4
+ import io
5
+ import itertools
6
+ import logging
4
7
  import os
5
- import ujson
8
+ import sys
6
9
  import time
7
- import gzip
8
10
  import warnings
9
- import pandas as pd
10
- import numpy as np
11
- import plotly.io as pio
12
- import itertools
13
- import functools
14
- import requests
15
- import logging
16
-
11
+ from base64 import b64decode, b64encode, urlsafe_b64encode
12
+ from collections import defaultdict
13
+ from concurrent.futures import as_completed
14
+ from copy import deepcopy
15
+ from hashlib import md5
17
16
  from inspect import getfullargspec
18
17
  from math import isclose
19
- from requests.exceptions import RequestException
20
- from bson.objectid import ObjectId
21
- from typing import Type
22
- from tqdm.auto import tqdm
23
- from hashlib import md5
24
18
  from pathlib import Path
25
- from copy import deepcopy
26
- from filetype import guess
27
- from flatten_dict import flatten, unflatten
28
- from base64 import b64encode, b64decode, urlsafe_b64encode
19
+ from tempfile import gettempdir
20
+ from typing import Type
29
21
  from urllib.parse import urlparse
30
- from pyisemail import is_email
31
- from collections import defaultdict
32
- from pyisemail.diagnosis import BaseDiagnosis
33
- from swagger_spec_validator.common import SwaggerValidationError
34
- from jsonschema.exceptions import ValidationError
35
- from bravado_core.formatter import SwaggerFormat
22
+
23
+ import numpy as np
24
+ import pandas as pd
25
+ import plotly.io as pio
26
+ import requests
27
+ import ujson
28
+ from boltons.iterutils import remap
36
29
  from bravado.client import SwaggerClient
30
+ from bravado.config import bravado_config_from_config_dict
31
+ from bravado.exception import HTTPNotFound
37
32
  from bravado.requests_client import RequestsClient
38
33
  from bravado.swagger_model import Loader
39
- from bravado.config import bravado_config_from_config_dict
40
- from bravado_core.spec import Spec, build_api_serving_url, _identity
34
+ from bravado_core.formatter import SwaggerFormat
41
35
  from bravado_core.model import model_discovery
42
36
  from bravado_core.resource import build_resources
43
- from bravado.exception import HTTPNotFound
37
+ from bravado_core.spec import Spec, _identity, build_api_serving_url
44
38
  from bravado_core.validate import validate_object
45
- from json2html import Json2Html
46
- from IPython.display import display, HTML, Image, FileLink
47
- from boltons.iterutils import remap
48
- from pymatgen.core import Structure as PmgStructure
49
- from concurrent.futures import as_completed
50
- from requests_futures.sessions import FuturesSession
51
- from urllib3.util.retry import Retry
39
+ from bson.objectid import ObjectId
40
+ from cachetools import LRUCache, cached
41
+ from cachetools.keys import hashkey
42
+ from filetype import guess
52
43
  from filetype.types.archive import Gz
53
- from filetype.types.image import Jpeg, Png, Gif, Tiff
44
+ from filetype.types.image import Gif, Jpeg, Png, Tiff
45
+ from flatten_dict import flatten, unflatten
46
+ from IPython.display import HTML, FileLink, Image, display
47
+ from json2html import Json2Html
48
+ from jsonschema.exceptions import ValidationError
54
49
  from pint import UnitRegistry
55
50
  from pint.errors import DimensionalityError
56
- from tempfile import gettempdir
57
51
  from plotly.express._chart_types import line as line_chart
58
- from cachetools import cached, LRUCache
59
- from cachetools.keys import hashkey
52
+ from pyisemail import is_email
53
+ from pyisemail.diagnosis import BaseDiagnosis
54
+ from pymatgen.core import Structure as PmgStructure
55
+ from requests.exceptions import RequestException
56
+ from requests_futures.sessions import FuturesSession
57
+ from swagger_spec_validator.common import SwaggerValidationError
58
+ from tqdm.auto import tqdm
59
+ from urllib3.util.retry import Retry
60
60
 
61
61
  try:
62
62
  __version__ = importlib.metadata.version("mpcontribs-client")
@@ -1128,10 +1128,10 @@ class Client(SwaggerClient):
1128
1128
  Returns:
1129
1129
  List of projects
1130
1130
  """
1131
- query = query or {}
1131
+ q = deepcopy(query) or {}
1132
1132
 
1133
- if self.project or "name" in query:
1134
- return [self.get_project(name=query.get("name"), fields=fields)]
1133
+ if self.project or "name" in q:
1134
+ return [self.get_project(name=q.get("name"), fields=fields)]
1135
1135
 
1136
1136
  if term:
1137
1137
 
@@ -1148,41 +1148,78 @@ class Client(SwaggerClient):
1148
1148
  responses = _run_futures(
1149
1149
  [search_future(term)], timeout=timeout, disable=True
1150
1150
  )
1151
- query["name__in"] = responses["search"].get("result", [])
1151
+ q["name__in"] = responses["search"].get("result", [])
1152
1152
 
1153
1153
  if fields:
1154
- query["_fields"] = fields
1154
+ q["_fields"] = fields
1155
1155
  if sort:
1156
- query["_sort"] = sort
1156
+ q["_sort"] = sort
1157
1157
 
1158
- ret = self.projects.queryProjects(**query).result() # first page
1158
+ ret = self.projects.queryProjects(**q).result() # first page
1159
+ """
1160
+ 'ret' type:
1161
+ {
1162
+ "data": [
1163
+ ...
1164
+ ],
1165
+ "has_more": <bool>,
1166
+ "total_count": <int>,
1167
+ "total_pages": <int>
1168
+ }
1169
+ """
1159
1170
  total_count, total_pages = ret["total_count"], ret["total_pages"]
1160
1171
 
1161
1172
  if total_pages < 2:
1162
1173
  return ret["data"]
1163
1174
 
1164
- query.update(
1175
+ q.update(
1165
1176
  {
1166
- field: ",".join(query[field])
1177
+ field: ",".join(q[field])
1167
1178
  for field in ["name__in", "_fields"]
1168
- if field in query
1179
+ if field in q
1169
1180
  }
1170
1181
  )
1171
1182
 
1172
1183
  queries = []
1173
1184
 
1174
1185
  for page in range(2, total_pages + 1):
1175
- queries.append(deepcopy(query))
1186
+ queries.append(deepcopy(q))
1176
1187
  queries[-1]["page"] = page
1177
1188
 
1178
1189
  futures = [
1179
- self._get_future(i, q, rel_url="projects") for i, q in enumerate(queries)
1190
+ self._get_future(i, _q, rel_url="projects") for i, _q in enumerate(queries)
1180
1191
  ]
1181
1192
  responses = _run_futures(futures, total=total_count, timeout=timeout)
1193
+ """
1194
+ 'responses' type:
1195
+ {
1196
+ "0": {
1197
+ "result": {
1198
+ "data": [
1199
+ ...
1200
+ ],
1201
+ "has_more": <bool>,
1202
+ "total_count": <int>,
1203
+ "total_pages": <int>
1204
+ },
1205
+ "count": <int>
1206
+ },
1207
+ "1": ...
1208
+ }
1209
+ """
1182
1210
 
1183
- ret["data"].extend([resp["result"]["data"] for resp in responses.values()])
1184
-
1185
- return ret["data"]
1211
+ return list(
1212
+ itertools.chain.from_iterable(
1213
+ [
1214
+ ret["data"],
1215
+ itertools.chain.from_iterable(
1216
+ # did not hit early return, guaranteed
1217
+ # to have additional pages w/ data
1218
+ map(lambda x: x["result"]["data"], iter(responses.values()))
1219
+ ),
1220
+ ]
1221
+ )
1222
+ )
1186
1223
 
1187
1224
  def create_project(
1188
1225
  self, name: str, title: str, authors: str, description: str, url: str
@@ -1584,25 +1621,25 @@ class Client(SwaggerClient):
1584
1621
  )
1585
1622
 
1586
1623
  tic = time.perf_counter()
1587
- query = query or {}
1624
+ q = deepcopy(query) or {}
1588
1625
 
1589
1626
  if self.project:
1590
- query["project"] = self.project
1627
+ q["project"] = self.project
1591
1628
 
1592
- name = query["project"]
1593
- cids = list(self.get_all_ids(query).get(name, {}).get("ids", set()))
1629
+ name = q["project"]
1630
+ cids = list(self.get_all_ids(q).get(name, {}).get("ids", set()))
1594
1631
 
1595
1632
  if not cids:
1596
1633
  logger.info(f"There aren't any contributions to delete for {name}")
1597
1634
  return
1598
1635
 
1599
1636
  total = len(cids)
1600
- query = {"id__in": cids}
1601
- _, total_pages = self.get_totals(query=query)
1602
- queries = self._split_query(query, op="delete", pages=total_pages)
1603
- futures = [self._get_future(i, q, op="delete") for i, q in enumerate(queries)]
1637
+ id_query = {"id__in": cids}
1638
+ _, total_pages = self.get_totals(query=id_query)
1639
+ queries = self._split_query(id_query, op="delete", pages=total_pages)
1640
+ futures = [self._get_future(i, _q, op="delete") for i, _q in enumerate(queries)]
1604
1641
  _run_futures(futures, total=total, timeout=timeout)
1605
- left, _ = self.get_totals(query=query)
1642
+ left, _ = self.get_totals(query=id_query)
1606
1643
  deleted = total - left
1607
1644
  self.init_columns(name=name)
1608
1645
  self._reinit()
@@ -1638,16 +1675,16 @@ class Client(SwaggerClient):
1638
1675
  if op not in ops:
1639
1676
  raise MPContribsClientError(f"`op` has to be one of {ops}")
1640
1677
 
1641
- query = query or {}
1642
- if self.project and "project" not in query:
1643
- query["project"] = self.project
1678
+ q = deepcopy(query) or {}
1679
+ if self.project and "project" not in q:
1680
+ q["project"] = self.project
1644
1681
 
1645
1682
  skip_keys = {"per_page", "_fields", "format", "_sort"}
1646
- query = {k: v for k, v in query.items() if k not in skip_keys}
1647
- query["_fields"] = [] # only need totals -> explicitly request no fields
1648
- queries = self._split_query(query, resource=resource, op=op) # don't paginate
1683
+ q = {k: v for k, v in q.items() if k not in skip_keys}
1684
+ q["_fields"] = [] # only need totals -> explicitly request no fields
1685
+ queries = self._split_query(q, resource=resource, op=op) # don't paginate
1649
1686
  futures = [
1650
- self._get_future(i, q, rel_url=resource) for i, q in enumerate(queries)
1687
+ self._get_future(i, _q, rel_url=resource) for i, _q in enumerate(queries)
1651
1688
  ]
1652
1689
  responses = _run_futures(futures, timeout=timeout, desc="Totals")
1653
1690
 
@@ -1759,11 +1796,11 @@ class Client(SwaggerClient):
1759
1796
  )
1760
1797
 
1761
1798
  ret = {}
1762
- query = query or {}
1763
- if self.project and "project" not in query:
1764
- query["project"] = self.project
1799
+ q = deepcopy(query) or {}
1800
+ if self.project and "project" not in q:
1801
+ q["project"] = self.project
1765
1802
 
1766
- [query.pop(k, None) for k in ["page", "per_page", "_fields"]]
1803
+ [q.pop(k, None) for k in ["page", "per_page", "_fields"]]
1767
1804
  id_fields = {"project", "id", "identifier"}
1768
1805
 
1769
1806
  if data_id_fields:
@@ -1771,10 +1808,10 @@ class Client(SwaggerClient):
1771
1808
  f"data.{data_id_field}" for data_id_field in data_id_fields.values()
1772
1809
  )
1773
1810
 
1774
- query["_fields"] = list(id_fields | components)
1775
- _, total_pages = self.get_totals(query=query, timeout=timeout)
1776
- queries = self._split_query(query, op=op, pages=total_pages)
1777
- futures = [self._get_future(i, q) for i, q in enumerate(queries)]
1811
+ q["_fields"] = list(id_fields | components)
1812
+ _, total_pages = self.get_totals(query=q, timeout=timeout)
1813
+ queries = self._split_query(q, op=op, pages=total_pages)
1814
+ futures = [self._get_future(i, _q) for i, _q in enumerate(queries)]
1778
1815
  responses = _run_futures(futures, timeout=timeout, desc="Identifiers")
1779
1816
 
1780
1817
  for resp in responses.values():
@@ -1870,15 +1907,15 @@ class Client(SwaggerClient):
1870
1907
  Returns:
1871
1908
  List of contributions
1872
1909
  """
1873
- query = query or {}
1910
+ q: dict = deepcopy(query) or {}
1874
1911
 
1875
- if self.project and "project" not in query:
1876
- query["project"] = self.project
1912
+ if self.project and "project" not in q:
1913
+ q["project"] = self.project
1877
1914
 
1878
1915
  if paginate:
1879
1916
  cids = [
1880
1917
  idx
1881
- for v in self.get_all_ids(query).values()
1918
+ for v in self.get_all_ids(q).values()
1882
1919
  for idx in (v.get("ids") or [])
1883
1920
  ]
1884
1921
 
@@ -1889,17 +1926,26 @@ class Client(SwaggerClient):
1889
1926
  cids_query = {"id__in": cids, "_fields": fields, "_sort": sort}
1890
1927
  _, total_pages = self.get_totals(query=cids_query)
1891
1928
  queries = self._split_query(cids_query, pages=total_pages)
1892
- futures = [self._get_future(i, q) for i, q in enumerate(queries)]
1893
- responses = _run_futures(futures, total=total, timeout=timeout)
1894
- ret = {"total_count": 0, "data": []}
1895
-
1896
- for resp in responses.values():
1897
- result = resp["result"]
1898
- ret["data"].extend(result["data"])
1899
- ret["total_count"] += result["total_count"]
1929
+ futures = [self._get_future(i, _q) for i, _q in enumerate(queries)]
1930
+ responses = [
1931
+ resp
1932
+ for resp in _run_futures(futures, total=total, timeout=timeout).values()
1933
+ if resp.get("result")
1934
+ ]
1935
+ ret = {
1936
+ "total_count": sum(
1937
+ resp["result"].get("total_count", 0) for resp in responses
1938
+ ),
1939
+ "data": list(
1940
+ itertools.chain.from_iterable(
1941
+ [resp["result"].get("data", []) for resp in responses]
1942
+ )
1943
+ ),
1944
+ }
1945
+
1900
1946
  else:
1901
1947
  ret = self.contributions.queryContributions(
1902
- _fields=fields, _sort=sort, **query
1948
+ _fields=fields, _sort=sort, **q
1903
1949
  ).result()
1904
1950
 
1905
1951
  return ret
@@ -1925,22 +1971,22 @@ class Client(SwaggerClient):
1925
1971
  if "data" in data:
1926
1972
  self._is_serializable_dict(data["data"])
1927
1973
 
1928
- query = query or {}
1974
+ q = deepcopy(query) or {}
1929
1975
 
1930
1976
  if self.project:
1931
- if "project" in query and self.project != query["project"]:
1977
+ if "project" in q and self.project != q["project"]:
1932
1978
  raise MPContribsClientError(
1933
1979
  f"client initialized with different project {self.project}!"
1934
1980
  )
1935
- query["project"] = self.project
1981
+ q["project"] = self.project
1936
1982
  else:
1937
- if not query or "project" not in query:
1983
+ if not q or "project" not in q:
1938
1984
  raise MPContribsClientError(
1939
1985
  "initialize client with project, or include project in query!"
1940
1986
  )
1941
1987
 
1942
- name = query["project"]
1943
- cids = list(self.get_all_ids(query).get(name, {}).get("ids", set()))
1988
+ name = q["project"]
1989
+ cids = list(self.get_all_ids(q).get(name, {}).get("ids", set()))
1944
1990
 
1945
1991
  if not cids:
1946
1992
  raise MPContribsClientError(
@@ -1956,8 +2002,8 @@ class Client(SwaggerClient):
1956
2002
  _, total_pages = self.get_totals(query=cids_query)
1957
2003
  queries = self._split_query(cids_query, op="update", pages=total_pages)
1958
2004
  futures = [
1959
- self._get_future(i, q, op="update", data=data)
1960
- for i, q in enumerate(queries)
2005
+ self._get_future(i, _q, op="update", data=data)
2006
+ for i, _q in enumerate(queries)
1961
2007
  ]
1962
2008
  responses = _run_futures(futures, total=total, timeout=timeout)
1963
2009
  updated = sum(resp["count"] for _, resp in responses.items())
@@ -2019,23 +2065,23 @@ class Client(SwaggerClient):
2019
2065
  "initialize client with project, or include project in query!"
2020
2066
  )
2021
2067
 
2022
- query = query or {}
2068
+ q = deepcopy(query) or {}
2023
2069
 
2024
2070
  if self.project:
2025
- query["project"] = self.project
2071
+ q["project"] = self.project
2026
2072
 
2027
2073
  try:
2028
2074
  resp = self.projects.getProjectByName(
2029
- pk=query["project"], _fields=["is_public", "is_approved"]
2075
+ pk=q["project"], _fields=["is_public", "is_approved"]
2030
2076
  ).result()
2031
2077
  except HTTPNotFound:
2032
2078
  raise MPContribsClientError(
2033
- f"project `{query['project']}` not found or access denied!"
2079
+ f"project `{q['project']}` not found or access denied!"
2034
2080
  )
2035
2081
 
2036
2082
  if not recursive and resp["is_public"] == is_public:
2037
2083
  return {
2038
- "warning": f"`is_public` already set to {is_public} for `{query['project']}`."
2084
+ "warning": f"`is_public` already set to {is_public} for `{q['project']}`."
2039
2085
  }
2040
2086
 
2041
2087
  ret = {}
@@ -2043,19 +2089,19 @@ class Client(SwaggerClient):
2043
2089
  if resp["is_public"] != is_public:
2044
2090
  if is_public and not resp["is_approved"]:
2045
2091
  raise MPContribsClientError(
2046
- f"project `{query['project']}` is not approved yet!"
2092
+ f"project `{q['project']}` is not approved yet!"
2047
2093
  )
2048
2094
 
2049
2095
  resp = self.projects.updateProjectByName(
2050
- pk=query["project"], project={"is_public": is_public}
2096
+ pk=q["project"], project={"is_public": is_public}
2051
2097
  ).result()
2052
2098
  ret["published"] = resp["count"] == 1
2053
2099
 
2054
2100
  if recursive:
2055
- query = query or {}
2056
- query["is_public"] = not is_public
2101
+ q = deepcopy(query) or {}
2102
+ q["is_public"] = not is_public
2057
2103
  ret["contributions"] = self.update_contributions(
2058
- {"is_public": is_public}, query=query, timeout=timeout
2104
+ {"is_public": is_public}, query=q, timeout=timeout
2059
2105
  )
2060
2106
 
2061
2107
  return ret
@@ -2450,7 +2496,7 @@ class Client(SwaggerClient):
2450
2496
  Number of new downloads written to disk.
2451
2497
  """
2452
2498
  start = time.perf_counter()
2453
- query = query or {}
2499
+ q = deepcopy(query) or {}
2454
2500
  include = include or []
2455
2501
  outdir = Path(outdir) or Path(".")
2456
2502
  outdir.mkdir(parents=True, exist_ok=True)
@@ -2458,8 +2504,8 @@ class Client(SwaggerClient):
2458
2504
  if include and not components:
2459
2505
  raise MPContribsClientError(f"`include` must be subset of {COMPONENTS}!")
2460
2506
 
2461
- all_ids = self.get_all_ids(query, include=list(components), timeout=timeout)
2462
- fmt = query.get("format", "json")
2507
+ all_ids = self.get_all_ids(q, include=list(components), timeout=timeout)
2508
+ fmt = q.get("format", "json")
2463
2509
  contributions, components_loaded = [], defaultdict(dict)
2464
2510
 
2465
2511
  for name, values in all_ids.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mpcontribs-client
3
- Version: 5.10.5rc0
3
+ Version: 5.10.5rc1
4
4
  Summary: Client library for MPContribs API
5
5
  Author-email: Patrick Huck <phuck@lbl.gov>, The Materials Project <feedback@materialsproject.org>
6
6
  License-Expression: BSD-3-Clause-LBNL
@@ -0,0 +1,6 @@
1
+ mpcontribs/client/__init__.py,sha256=AwKIDzTg30ZMW97QxQZ1OCwJAFrXT3XMdRktgL356Jc,98456
2
+ mpcontribs_client-5.10.5rc1.dist-info/licenses/LICENSE,sha256=5tG0Niaqw2hnuyZZYkRXLSnfVrZA47COwduU_6caPLM,1074
3
+ mpcontribs_client-5.10.5rc1.dist-info/METADATA,sha256=APCeqCMlQLDEAEBwUYk6CFqHdawo-JDmCgz3VA9R8bg,1289
4
+ mpcontribs_client-5.10.5rc1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
5
+ mpcontribs_client-5.10.5rc1.dist-info/top_level.txt,sha256=t8R5L_Dg9oDQMh2gyRFdZGnrzZsr7OjCBTrhTcmimC8,11
6
+ mpcontribs_client-5.10.5rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +0,0 @@
1
- mpcontribs/client/__init__.py,sha256=YOv2KfnQK4T7rHp45XCudqzmv1C4EjeDcgH_VyAog1o,97366
2
- mpcontribs_client-5.10.5rc0.dist-info/licenses/LICENSE,sha256=5tG0Niaqw2hnuyZZYkRXLSnfVrZA47COwduU_6caPLM,1074
3
- mpcontribs_client-5.10.5rc0.dist-info/METADATA,sha256=1Mry_eGOJVD61aLEhjeElyA6geL9HRPIwb4aDydD8Ps,1289
4
- mpcontribs_client-5.10.5rc0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
5
- mpcontribs_client-5.10.5rc0.dist-info/top_level.txt,sha256=t8R5L_Dg9oDQMh2gyRFdZGnrzZsr7OjCBTrhTcmimC8,11
6
- mpcontribs_client-5.10.5rc0.dist-info/RECORD,,