python-materialsdb 0.3.0__tar.gz → 0.3.1__tar.gz
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.
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/PKG-INFO +1 -1
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/pyproject.toml +1 -1
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/cache.py +69 -16
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/serialiser.py +27 -12
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/PKG-INFO +1 -1
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_build_bonsai_addon.py +16 -2
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_cache.py +11 -8
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/LICENSE.md +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/README.md +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/setup.cfg +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/__init__.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/classes.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/config.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/construction.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/__init__.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/__main__.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/discovery.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/listener.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/server.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/app-constructions.js +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/app.js +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/constructions.html +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/index.html +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/picker-core.js +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/__init__.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/material_builder.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/material_psets.json +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/project_library.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/query.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/MaterialsDBIndex100.xsd +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/materialsdb102.xsd +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/materialsdb103.xsd +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/store.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/summary.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/utils.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/SOURCES.txt +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/dependency_links.txt +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/entry_points.txt +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/requires.txt +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/top_level.txt +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_bonsai_discovery.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_bonsai_insert.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_construction.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_construction_frontend.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_construction_ifc.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_gui_server.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_listener_payload.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_material_builder.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_picker_frontend.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_project_library.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_query.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_serialiser.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_store.py +0 -0
- {python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/tests/test_summary.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-materialsdb"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "A library to work with materialsdb.org open standard for building materials."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "GPL-3.0-or-later"
|
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
import pathlib
|
|
3
3
|
import urllib.request
|
|
4
4
|
from collections import namedtuple
|
|
5
|
+
from concurrent.futures import FIRST_COMPLETED, ThreadPoolExecutor, wait
|
|
5
6
|
|
|
6
7
|
from lxml import etree
|
|
7
8
|
|
|
@@ -85,25 +86,77 @@ def _plan_index(index):
|
|
|
85
86
|
return _IndexPlan(index, new_index, unchanged, todos)
|
|
86
87
|
|
|
87
88
|
|
|
88
|
-
def update_producers_data(url_list=MATERIALSDBINDEXURLLIST, on_progress=None):
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
def update_producers_data(url_list=MATERIALSDBINDEXURLLIST, on_progress=None, max_workers: int = 8):
|
|
90
|
+
"""Update the cached producer files from the index URLs.
|
|
91
|
+
|
|
92
|
+
Downloads run on a bounded thread pool (max_workers). on_progress(done,
|
|
93
|
+
total, name) is called once per completed download from the calling
|
|
94
|
+
thread with a monotonic running total; returning a truthy value stops
|
|
95
|
+
NEW submissions (queued jobs are abandoned, in-flight ones finish but
|
|
96
|
+
no longer count toward the partial Report). A download error stops the
|
|
97
|
+
run and the first exception is re-raised after the pool drains.
|
|
98
|
+
"""
|
|
92
99
|
plans = [_plan_index(index) for index in url_list]
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
jobs = [
|
|
101
|
+
(plan, company, cached_producer, producer_path)
|
|
102
|
+
for plan in plans
|
|
103
|
+
for (company, cached_producer, producer_path) in plan.todos
|
|
104
|
+
]
|
|
105
|
+
total = len(jobs)
|
|
106
|
+
workers = max(1, min(int(max_workers), total or 1))
|
|
107
|
+
|
|
108
|
+
existing: list = []
|
|
109
|
+
updated: list = []
|
|
110
|
+
deleted: list = []
|
|
95
111
|
done = 0
|
|
112
|
+
cancel_requested = False
|
|
113
|
+
failure = None
|
|
114
|
+
|
|
115
|
+
def _download(job):
|
|
116
|
+
_, company, cached_producer, producer_path = job
|
|
117
|
+
deleted_path = None
|
|
118
|
+
if cached_producer is not None:
|
|
119
|
+
deleted_path = get_producers_dir() / pathlib.Path(cached_producer.get("href")).name
|
|
120
|
+
deleted_path.unlink(True)
|
|
121
|
+
urllib.request.urlretrieve(company.get("href"), producer_path)
|
|
122
|
+
return deleted_path
|
|
123
|
+
|
|
124
|
+
pool = ThreadPoolExecutor(max_workers=workers)
|
|
125
|
+
pending = list(jobs) # pops from the FRONT, submission order preserved
|
|
126
|
+
futures: dict = {}
|
|
127
|
+
try:
|
|
128
|
+
while futures or pending:
|
|
129
|
+
while pending and len(futures) < workers:
|
|
130
|
+
job = pending.pop(0)
|
|
131
|
+
futures[pool.submit(_download, job)] = job
|
|
132
|
+
if not futures:
|
|
133
|
+
break
|
|
134
|
+
ready, _ = wait(set(futures), return_when=FIRST_COMPLETED)
|
|
135
|
+
for future in ready:
|
|
136
|
+
job = futures.pop(future)
|
|
137
|
+
try:
|
|
138
|
+
deleted_path = future.result()
|
|
139
|
+
except Exception as err: # noqa: BLE001 - re-raised below, caller decides
|
|
140
|
+
if failure is None:
|
|
141
|
+
failure = err
|
|
142
|
+
break
|
|
143
|
+
if deleted_path is not None:
|
|
144
|
+
deleted.append(deleted_path)
|
|
145
|
+
updated.append(job[3])
|
|
146
|
+
done += 1
|
|
147
|
+
if on_progress is not None and on_progress(done, total, pathlib.Path(job[3]).name):
|
|
148
|
+
cancel_requested = True
|
|
149
|
+
break
|
|
150
|
+
if cancel_requested or failure is not None:
|
|
151
|
+
break
|
|
152
|
+
finally:
|
|
153
|
+
pool.shutdown(wait=True, cancel_futures=True)
|
|
154
|
+
|
|
155
|
+
if failure is not None:
|
|
156
|
+
raise failure
|
|
157
|
+
if cancel_requested:
|
|
158
|
+
return Report(existing, updated, deleted)
|
|
96
159
|
for plan in plans:
|
|
97
|
-
for company, cached_producer, producer_path in plan.todos:
|
|
98
|
-
if cached_producer is not None:
|
|
99
|
-
cached_path = get_producers_dir() / pathlib.Path(cached_producer.get("href")).name
|
|
100
|
-
deleted.append(cached_path)
|
|
101
|
-
cached_path.unlink(True)
|
|
102
|
-
urllib.request.urlretrieve(company.get("href"), producer_path)
|
|
103
|
-
updated.append(producer_path)
|
|
104
|
-
done += 1
|
|
105
|
-
if on_progress is not None and on_progress(done, total, pathlib.Path(company.get("href")).name):
|
|
106
|
-
return Report(existing, updated, deleted)
|
|
107
160
|
if plan.todos:
|
|
108
161
|
plan.new_index.write(str(get_cached_index_path(plan.index)))
|
|
109
162
|
existing.extend(plan.unchanged)
|
|
@@ -25,9 +25,31 @@ def get_xml_schema() -> str:
|
|
|
25
25
|
return str(Path(__file__).parent / "schema/materialsdb103.xsd")
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
@cache
|
|
29
|
+
def cached_type_hints(cls) -> dict:
|
|
30
|
+
return typing.get_type_hints(cls)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@cache
|
|
34
|
+
def _tag_local_name(tag: str) -> str:
|
|
35
|
+
m = re.search("{.*}(.*)", tag)
|
|
36
|
+
return m.group(1) if m else tag
|
|
37
|
+
|
|
38
|
+
|
|
28
39
|
def get_element_name(element: objectify.ObjectifiedElement) -> str:
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
return _tag_local_name(element.tag)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@cache
|
|
44
|
+
def _is_optional(type_hint):
|
|
45
|
+
return typing.get_origin(type_hint) is typing.Union and typing.get_args(type_hint)[1] is type(None)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@cache
|
|
49
|
+
def _strip_optional(type_hint):
|
|
50
|
+
if _is_optional(type_hint):
|
|
51
|
+
return typing.get_args(type_hint)[0]
|
|
52
|
+
return type_hint
|
|
31
53
|
|
|
32
54
|
|
|
33
55
|
def create_element_maker():
|
|
@@ -49,11 +71,6 @@ def get_valid_root(tree: objectify.ObjectifiedElement) -> objectify.ObjectifiedE
|
|
|
49
71
|
return root
|
|
50
72
|
|
|
51
73
|
|
|
52
|
-
@cache
|
|
53
|
-
def cached_type_hints(cls) -> dict:
|
|
54
|
-
return typing.get_type_hints(cls)
|
|
55
|
-
|
|
56
|
-
|
|
57
74
|
class XmlDeserialiser:
|
|
58
75
|
def __init__(self):
|
|
59
76
|
self.schema = etree.XMLSchema(file=get_xml_schema())
|
|
@@ -93,7 +110,7 @@ class XmlDeserialiser:
|
|
|
93
110
|
value = element.get(attrib)
|
|
94
111
|
if value is None:
|
|
95
112
|
continue
|
|
96
|
-
base_class =
|
|
113
|
+
base_class = _strip_optional(type_hints[attrib])
|
|
97
114
|
|
|
98
115
|
kwargs[attrib] = base_class(value)
|
|
99
116
|
for child_name in getattr(element_class, "xml_elements", ()):
|
|
@@ -127,12 +144,10 @@ class XmlDeserialiser:
|
|
|
127
144
|
return instance
|
|
128
145
|
|
|
129
146
|
def strip_optional(self, type_hint):
|
|
130
|
-
|
|
131
|
-
return typing.get_args(type_hint)[0]
|
|
132
|
-
return type_hint
|
|
147
|
+
return _strip_optional(type_hint)
|
|
133
148
|
|
|
134
149
|
def is_optional(self, type_hint):
|
|
135
|
-
return
|
|
150
|
+
return _is_optional(type_hint)
|
|
136
151
|
|
|
137
152
|
def cls_name(self, name: str) -> str:
|
|
138
153
|
return name if name[0].isupper() else name.title()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import re
|
|
1
2
|
import sys
|
|
2
3
|
import zipfile
|
|
3
4
|
from pathlib import Path
|
|
@@ -8,13 +9,22 @@ sys.path.insert(0, str(ROOT / "dev_utils"))
|
|
|
8
9
|
import build_bonsai_addon # ty: ignore[unresolved-import] - dev_util on a side path
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
def _manifest_version():
|
|
13
|
+
text = (ROOT / "bonsai_addon" / "blender_manifest.toml").read_text(encoding="utf-8")
|
|
14
|
+
match = re.search(r'(?m)^version = "([^"]+)"$', text)
|
|
15
|
+
assert match is not None
|
|
16
|
+
return match.group(1)
|
|
17
|
+
|
|
18
|
+
|
|
11
19
|
def test_default_build_unchanged(tmp_path):
|
|
20
|
+
manifest_version = _manifest_version()
|
|
21
|
+
|
|
12
22
|
out = build_bonsai_addon.build(out_dir=tmp_path)
|
|
13
23
|
|
|
14
24
|
assert out.name == "materialsdb_listener.zip"
|
|
15
25
|
with zipfile.ZipFile(out) as zf:
|
|
16
26
|
assert "blender_manifest.toml" in zf.namelist()
|
|
17
|
-
assert 'version = "
|
|
27
|
+
assert f'version = "{manifest_version}"' in zf.read("blender_manifest.toml").decode("utf-8")
|
|
18
28
|
assert "blender_manifest.toml".replace(".", "/") not in zf.namelist() # manifest at zip ROOT
|
|
19
29
|
|
|
20
30
|
|
|
@@ -30,8 +40,12 @@ def test_version_injected_into_manifest_and_name(tmp_path):
|
|
|
30
40
|
def test_version_injection_is_literal_independent(tmp_path):
|
|
31
41
|
"""The injection must not depend on the manifest's current version
|
|
32
42
|
literal (it changes on every release bump)."""
|
|
43
|
+
|
|
44
|
+
current = _manifest_version()
|
|
45
|
+
stale = "0.0.1" if current != "0.0.1" else "0.0.2"
|
|
46
|
+
|
|
33
47
|
out = build_bonsai_addon.build(version="3.2.1", out_dir=tmp_path)
|
|
34
48
|
|
|
35
49
|
with zipfile.ZipFile(out) as zf:
|
|
36
50
|
assert 'version = "3.2.1"' in zf.read("blender_manifest.toml").decode("utf-8")
|
|
37
|
-
assert 'version = "
|
|
51
|
+
assert f'version = "{stale}"' not in zf.read("blender_manifest.toml").decode("utf-8")
|
|
@@ -33,7 +33,7 @@ def cache_env(tmp_path, monkeypatch):
|
|
|
33
33
|
# defaults are bound at def time, so patch __defaults__ too
|
|
34
34
|
single = [cache.MATERIALSDBINDEXURLLIST[0]]
|
|
35
35
|
monkeypatch.setattr(cache, "MATERIALSDBINDEXURLLIST", single)
|
|
36
|
-
monkeypatch.setattr(cache.update_producers_data, "__defaults__", (single, None))
|
|
36
|
+
monkeypatch.setattr(cache.update_producers_data, "__defaults__", (single, None, 8))
|
|
37
37
|
monkeypatch.setattr(cache.updates_available, "__defaults__", (single,))
|
|
38
38
|
recorded: _Recorded = {"urls": [], "dests": [], "index": INDEX_XML}
|
|
39
39
|
|
|
@@ -57,9 +57,11 @@ def test_first_refresh_downloads_all_with_global_total(cache_env):
|
|
|
57
57
|
on_progress=lambda done, total, name: progress.append((done, total, name)) or False
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
-
assert recorded["urls"] ==
|
|
61
|
-
assert progress == [
|
|
62
|
-
assert [
|
|
60
|
+
assert set(recorded["urls"]) == {"https://x.org/a.xml", "https://x.org/b.xml"}
|
|
61
|
+
assert [p[0] for p in progress] == [1, 2] # monotonic done
|
|
62
|
+
assert {p[1] for p in progress} == {2} # global total reached before any download finished
|
|
63
|
+
assert {p[2] for p in progress} == {"a.xml", "b.xml"}
|
|
64
|
+
assert {p.name for p in report.updated} == {"a.xml", "b.xml"}
|
|
63
65
|
assert report.existing == []
|
|
64
66
|
assert (cache_dir / "Producers" / "a.xml").exists() # downloads land in Producers dir
|
|
65
67
|
assert (cache_dir / "ProducerIndex.xml").exists() # new index persisted
|
|
@@ -68,7 +70,7 @@ def test_first_refresh_downloads_all_with_global_total(cache_env):
|
|
|
68
70
|
def test_second_refresh_uses_existing_files(cache_env):
|
|
69
71
|
cache, _, recorded = cache_env
|
|
70
72
|
report = cache.update_producers_data()
|
|
71
|
-
assert
|
|
73
|
+
assert {p.name for p in report.updated} == {"a.xml", "b.xml"}
|
|
72
74
|
recorded["urls"].clear()
|
|
73
75
|
|
|
74
76
|
progress = []
|
|
@@ -100,9 +102,9 @@ def test_outdated_single_producer_updates_with_total_one(cache_env):
|
|
|
100
102
|
on_progress=lambda done, total, name: progress.append((done, total, name)) or False
|
|
101
103
|
)
|
|
102
104
|
|
|
103
|
-
assert recorded["urls"] == ["https://x.org/a.xml"]
|
|
105
|
+
assert recorded["urls"] == ["https://x.org/a.xml"] # single job — deterministic
|
|
104
106
|
assert progress == [(1, 1, "a.xml")]
|
|
105
|
-
assert
|
|
107
|
+
assert {p.name for p in record.updated} == {"a.xml"}
|
|
106
108
|
assert [p.name for p in record.deleted] == ["a.xml"] # stale file removed before re-download
|
|
107
109
|
assert [p.name for p in record.existing] == ["b.xml"]
|
|
108
110
|
|
|
@@ -128,7 +130,8 @@ def test_cancel_stops_between_downloads(cache_env):
|
|
|
128
130
|
def cancel_after_first(done, total, name):
|
|
129
131
|
return done >= 1 # truthy → abort
|
|
130
132
|
|
|
131
|
-
|
|
133
|
+
# single worker: b.html cannot start before the callback runs
|
|
134
|
+
report = cache.update_producers_data(on_progress=cancel_after_first, max_workers=1)
|
|
132
135
|
|
|
133
136
|
assert recorded["urls"] == ["https://x.org/a.xml"] # second download never starts
|
|
134
137
|
assert [p.name for p in report.updated] == ["a.xml"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/constructions.html
RENAMED
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/gui/static/picker-core.js
RENAMED
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/material_builder.py
RENAMED
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/material_psets.json
RENAMED
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/ifc/project_library.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/MaterialsDBIndex100.xsd
RENAMED
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/materialsdb102.xsd
RENAMED
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/materialsdb/schema/materialsdb103.xsd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_materialsdb-0.3.0 → python_materialsdb-0.3.1}/src/python_materialsdb.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|