materials-commons-cli 2.3.0b3__tar.gz → 2.3.0b4__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.
Files changed (104) hide show
  1. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/PKG-INFO +1 -1
  2. materials_commons_cli-2.3.0b4/materials_commons/cli/__init__.py +1 -0
  3. materials_commons_cli-2.3.0b4/materials_commons/cli/old/cloned_project.py +223 -0
  4. materials_commons_cli-2.3.0b4/materials_commons/cli/old/exceptions.py +12 -0
  5. materials_commons_cli-2.3.0b4/materials_commons/cli/old/file_functions.py +137 -0
  6. materials_commons_cli-2.3.0b4/materials_commons/cli/old/functions.py +775 -0
  7. materials_commons_cli-2.3.0b4/materials_commons/cli/old/globus.py +418 -0
  8. materials_commons_cli-2.3.0b4/materials_commons/cli/old/list_objects.py +404 -0
  9. materials_commons_cli-2.3.0b4/materials_commons/cli/old/print_formatter.py +105 -0
  10. materials_commons_cli-2.3.0b4/materials_commons/cli/old/sqltable.py +213 -0
  11. materials_commons_cli-2.3.0b4/materials_commons/cli/old/tmp_functions.py +39 -0
  12. materials_commons_cli-2.3.0b4/materials_commons/cli/old/tree_functions.py +1736 -0
  13. materials_commons_cli-2.3.0b4/materials_commons/cli/old/treedb.py +644 -0
  14. materials_commons_cli-2.3.0b4/materials_commons/cli/old/user_config.py +216 -0
  15. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/admin_handler_lookup.py +26 -0
  16. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/download_handler_lookup.py +124 -0
  17. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/list_handler_lookup.py +158 -0
  18. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/multi_handler_lookup.py +16 -0
  19. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/protocol.py +7 -0
  20. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/search_find_handler_lookup.py +77 -0
  21. materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers/upload_handler_lookup.py +221 -0
  22. materials_commons_cli-2.3.0b4/materials_commons/cli/server/db/db_manager.py +54 -0
  23. materials_commons_cli-2.3.0b4/materials_commons/cli/server/indexer/__init__.py +0 -0
  24. materials_commons_cli-2.3.0b4/materials_commons/cli/server/uploader/__init__.py +0 -0
  25. materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/__init__.py +0 -0
  26. materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/__init__.py +0 -0
  27. materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/download_globus_runner.py +86 -0
  28. materials_commons_cli-2.3.0b4/materials_commons/cli/subcommands/runners/download_v1_runner.py +176 -0
  29. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/PKG-INFO +1 -1
  30. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/SOURCES.txt +26 -0
  31. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/setup.py +11 -1
  32. materials_commons_cli-2.3.0b3/materials_commons/cli/__init__.py +0 -1
  33. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/LICENSE +0 -0
  34. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/README.md +0 -0
  35. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/LICENSE.txt +0 -0
  36. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/async_reconciler.py +0 -0
  37. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/config.py +0 -0
  38. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/downloader.py +0 -0
  39. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/filedb.py +0 -0
  40. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/local_project.py +0 -0
  41. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/models.py +0 -0
  42. {materials_commons_cli-2.3.0b3/materials_commons/cli/server/downloader → materials_commons_cli-2.3.0b4/materials_commons/cli/old}/__init__.py +0 -0
  43. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/parser.py +0 -0
  44. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/reconcile2.py +0 -0
  45. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/reconcile3.py +0 -0
  46. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/requests.py +0 -0
  47. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/run.py +0 -0
  48. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/__init__.py +0 -0
  49. {materials_commons_cli-2.3.0b3/materials_commons/cli/server/indexer → materials_commons_cli-2.3.0b4/materials_commons/cli/server/command_handlers}/__init__.py +0 -0
  50. {materials_commons_cli-2.3.0b3/materials_commons/cli/server/uploader → materials_commons_cli-2.3.0b4/materials_commons/cli/server/db}/__init__.py +0 -0
  51. {materials_commons_cli-2.3.0b3/materials_commons/cli/subcommands → materials_commons_cli-2.3.0b4/materials_commons/cli/server/downloader}/__init__.py +0 -0
  52. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/downloader/file_download_manager.py +0 -0
  53. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/downloader/file_downloader.py +0 -0
  54. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/indexer/file_index_manager.py +0 -0
  55. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/local_rest_server.py +0 -0
  56. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/ocommand_handlers.py +0 -0
  57. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/project_filedbs.py +0 -0
  58. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/projects.py +0 -0
  59. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/service_container.py +0 -0
  60. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/service_runtime.py +0 -0
  61. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/client_api.py +0 -0
  62. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/file_upload_manager.py +0 -0
  63. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/uploader/file_uploader.py +0 -0
  64. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/server/websocket_server.py +0 -0
  65. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/clone.py +0 -0
  66. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/config.py +0 -0
  67. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/dataset.py +0 -0
  68. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/down.py +0 -0
  69. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/down2.py +0 -0
  70. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/expt.py +0 -0
  71. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/fetch.py +0 -0
  72. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/globus.py +0 -0
  73. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/init.py +0 -0
  74. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/ls.py +0 -0
  75. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/ls2.py +0 -0
  76. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/mkdir.py +0 -0
  77. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/mv.py +0 -0
  78. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/proj.py +0 -0
  79. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/remote.py +0 -0
  80. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/rm.py +0 -0
  81. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/scan.py +0 -0
  82. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/server.py +0 -0
  83. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/up.py +0 -0
  84. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/subcommands/versions.py +0 -0
  85. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons/cli/walk.py +0 -0
  86. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/dependency_links.txt +0 -0
  87. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/entry_points.txt +0 -0
  88. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/not-zip-safe +0 -0
  89. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/requires.txt +0 -0
  90. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/materials_commons_cli.egg-info/top_level.txt +0 -0
  91. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/setup.cfg +0 -0
  92. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_api.py +0 -0
  93. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_functions.py +0 -0
  94. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_dataset.py +0 -0
  95. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_down.py +0 -0
  96. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_mkdir.py +0 -0
  97. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_mv.py +0 -0
  98. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_proj.py +0 -0
  99. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_rm.py +0 -0
  100. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_mc_up.py +0 -0
  101. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treecompare_no_cache.py +0 -0
  102. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treecompare_with_cache.py +0 -0
  103. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_treedb.py +0 -0
  104. {materials_commons_cli-2.3.0b3 → materials_commons_cli-2.3.0b4}/test/test_user_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: materials_commons_cli
3
- Version: 2.3.0b3
3
+ Version: 2.3.0b4
4
4
  Summary: Materials Commons CLI
5
5
  Home-page: https://materials-commons.github.io/materials-commons-cli/html/index.html
6
6
  Author: Materials Commons development team
@@ -0,0 +1 @@
1
+ __version__ = '2.3.0b4'
@@ -0,0 +1,223 @@
1
+ import os
2
+ import pathlib
3
+ import tempfile
4
+
5
+ import materials_commons.cli.old.exceptions as cliexcept
6
+ import materials_commons.cli.old.functions as clifuncs
7
+ from materials_commons.cli.old.user_config import Config, \
8
+ get_remote_config_and_login_if_necessary
9
+ from materials_commons.cli.subcommands.down import down_subcommand
10
+ from materials_commons.cli.subcommands.up import up_subcommand
11
+
12
+ # TODO: only call os.getcwd() from parser::main
13
+
14
+ class ClonedProject(object):
15
+ """A cloned Materials Commons project instance
16
+
17
+ Attributes:
18
+ local_path (pathlib.Path): Location of the cloned Materials Commons
19
+ project
20
+ proj (materials_commons.api.models.Project): Materials Commons project
21
+ object
22
+ tmpdir (tempfile.TemporaryDirectory or None): Temporary directory
23
+ instance. If not None, the temporary directory is the parent of the
24
+ cloned Materials Commons project directory.
25
+
26
+ """
27
+
28
+ def __init__(self, email=None, mcurl=None, proj_id=None, path=None,
29
+ parent_path=None, name=None):
30
+ """Construct a cloned Materials Commons project instance
31
+
32
+ Examples:
33
+
34
+ Open a project that has already been cloned:
35
+
36
+ .. code-block:: python
37
+
38
+ path = "/path/to/materials_commons_projects/ProjectName"
39
+ mc_proj = ClonedProject(path=path)
40
+
41
+ Clone project to a particular directory or open if already cloned:
42
+
43
+ .. code-block:: python
44
+
45
+ email = "username@domain.com"
46
+ mcurl = "https://materialscommons.org/api"
47
+ proj_id = 25
48
+ parent_path = "/path/to/materials_commons_projects"
49
+ name = None # default uses remote project name
50
+ mc_proj = ClonedProject(email=email,
51
+ mcurl=mcurl,
52
+ proj_id=proj_id,
53
+ parent_path=parent_path,
54
+ name=name)
55
+
56
+ Clone project to a temporary directory:
57
+
58
+ .. code-block:: python
59
+
60
+ email = "username@domain.com"
61
+ mcurl = "https://materialscommons.org/api"
62
+ proj_id = 25
63
+ mc_proj = ClonedProject(email=email, mcurl=mcurl, proj_id=proj_id)
64
+
65
+ Args:
66
+ email (str): User account email
67
+ mcurl (str): URL for Materials Commons remote instance containing
68
+ the project. Example: "https://materialscommons.org/api".
69
+ proj_id (int): ID of project to clone.
70
+ path (str): Path where the project exists, if already cloned.
71
+ parent_path (str): Path to parent directory where the project should
72
+ be cloned if path is None. If neither path nor parent_path are
73
+ given, uses a tempfile.TemporaryDirectory for parent_path.
74
+ name (str): Name of created project directory. Default is remote
75
+ project name.
76
+ """
77
+ self.local_path = None
78
+ self.proj = None
79
+ self.tmpdir = None
80
+
81
+ if path is not None:
82
+ if clifuncs.project_exists(path):
83
+ self.proj = clifuncs.make_local_project(path)
84
+ else:
85
+ raise cliexcept.MCCLIException("No project found at " + path)
86
+ else:
87
+ if proj_id is None:
88
+ raise cliexcept.MCCLIException("`proj_id` is required if `path` is not provided")
89
+
90
+ if email is None or mcurl is None:
91
+ config = Config()
92
+ if not config.default_remote.mcurl or not config.default_remote.mcapikey:
93
+ raise cliexcept.NoDefaultRemoteException("Default remote not set")
94
+ remote_config = config.default_remote
95
+ else:
96
+ remote_config = get_remote_config_and_login_if_necessary(
97
+ mcurl=mcurl, email=email)
98
+
99
+ if parent_path is None:
100
+ self.tmpdir = tempfile.TemporaryDirectory()
101
+ self.proj = clifuncs.clone_project(remote_config, proj_id, self.tmpdir.name)
102
+
103
+ else:
104
+ self.tmpdir = None
105
+ parent_path = str(parent_path)
106
+
107
+ # check if project already exists, then construct or clone
108
+ client = remote_config.make_client()
109
+ proj = client.get_project(proj_id)
110
+ path = os.path.join(parent_path, proj.name)
111
+ if clifuncs.project_exists(path):
112
+ self.proj = clifuncs.make_local_project(path, proj._data)
113
+ else:
114
+ self.proj = clifuncs.clone_project(remote_config, proj_id, parent_path)
115
+
116
+ self.local_path = pathlib.Path(self.proj.local_path)
117
+
118
+ def glob(self, pattern):
119
+ """Helper to construct paths for upload or download
120
+
121
+ Args:
122
+ pattern (str): Pattern, relative to local project directory root,
123
+ passed as argument to `self.local_path.glob(pattern)`.
124
+
125
+ Returns:
126
+ List of str, File paths found from use of `glob`, made relative to
127
+ self.local_path and converted to str.
128
+
129
+ """
130
+ return [str(file.relative_to(self.local_path)) for file in self.local_path.glob(pattern)]
131
+
132
+ def download(self, *paths, recursive=False, only_print=False, force=False,
133
+ output=None, globus=False, label=None, no_compare=False):
134
+ """Download requested files from the Materials Commons project
135
+
136
+ Args:
137
+ recursive (bool): Download directory contents recursively
138
+ force (bool): Force overwrite of existing files
139
+ only_print (bool): Print file, do not write
140
+ output (str): Download file name. Only allowed if `len(paths) == 1`.
141
+ globus (bool): Use globus to download files
142
+ label (str): Globus transfer label to make finding tasks simpler
143
+ no_compare (bool): Download remote without checking if local is
144
+ equivalent
145
+ *paths (str): Files or directories to download, specified either
146
+ using absolute paths or paths relative to the project root
147
+ directory (`self.local_path`).
148
+ """
149
+ # TODO: convert to direct function calls rather than arg parsing
150
+
151
+ working_dir = self.local_path
152
+
153
+ argv = []
154
+ if recursive is True:
155
+ argv.append("-r")
156
+ if only_print is True:
157
+ argv.append("-p")
158
+ if force is True:
159
+ argv.append("-f")
160
+ if output is not None:
161
+ argv.append("-o")
162
+ argv.append(str(output))
163
+ if globus is True:
164
+ argv.append("-g")
165
+ if label is not None:
166
+ argv.append("--label")
167
+ argv.append(str(label))
168
+ if no_compare is True:
169
+ argv.append("--no-compare")
170
+ if len(paths):
171
+ # using relpaths is more robust within the working_dir context
172
+ # argv += [str(os.path.relpath(os.path.abspath(path), self.local_path)) for path in paths]
173
+ argv += [os.path.normpath(os.path.join(working_dir, path)) for path in paths]
174
+ try:
175
+ down_subcommand(argv, working_dir)
176
+ except SystemExit as e:
177
+ print("Invalid download request")
178
+
179
+ def upload(self, *paths, recursive=False, limit=None, globus=False,
180
+ label=None, no_compare=False, upload_as=None):
181
+ """Upload requested files to Materials Commons
182
+
183
+ Args:
184
+ recursive (bool): Download directory contents recursively
185
+ limit (str): File size upload limit (MB). Default="750" (750MB). Does
186
+ not apply to Globus uploads.
187
+ globus (bool): Use globus to download files
188
+ label (str): Globus transfer label to make finding tasks simpler
189
+ no_compare (bool): Download remote without checking if local is
190
+ equivalent
191
+ upload_as (str): Upload a file or directory to a particular location in the project. Raises if `len(paths) != 1`.
192
+ *paths (str): Files or directories to upload, specified either
193
+ using absolute paths or paths relative to the project root
194
+ directory (`self.local_path`).
195
+ """
196
+ # TODO: convert to direct function calls rather than arg parsing
197
+
198
+ working_dir = self.local_path
199
+
200
+ argv = []
201
+ if recursive is True:
202
+ argv.append("-r")
203
+ if limit is not None:
204
+ argv.append("--limit")
205
+ argv.append(str(limit))
206
+ if globus is True:
207
+ argv.append("-g")
208
+ if label is not None:
209
+ argv.append("--label")
210
+ argv.append(str(label))
211
+ if no_compare is True:
212
+ argv.append("--no-compare")
213
+ if upload_as is not None:
214
+ argv.append("--upload-as")
215
+ argv.append(str(upload_as))
216
+ if len(paths):
217
+ # using relpaths is more robust within the working_dir context
218
+ # argv += [str(os.path.relpath(os.path.abspath(path), self.local_path)) for path in paths]
219
+ argv += [os.path.normpath(os.path.join(working_dir, path)) for path in paths]
220
+ try:
221
+ up_subcommand(argv, working_dir)
222
+ except SystemExit as e:
223
+ print("Invalid upload request")
@@ -0,0 +1,12 @@
1
+
2
+ class MCCLIException(BaseException):
3
+ pass
4
+
5
+ class MissingRemoteException(BaseException):
6
+ pass
7
+
8
+ class MultipleRemoteException(BaseException):
9
+ pass
10
+
11
+ class NoDefaultRemoteException(BaseException):
12
+ pass
@@ -0,0 +1,137 @@
1
+ import io
2
+ import os.path
3
+ import requests
4
+ import materials_commons.api as mcapi
5
+ from materials_commons.cli.old.exceptions import MCCLIException
6
+
7
+ def isfile(file_or_dir):
8
+ return isinstance(file_or_dir, mcapi.File) and file_or_dir.mime_type != "directory"
9
+
10
+ def isdir(file_or_dir):
11
+ return isinstance(file_or_dir, mcapi.File) and file_or_dir.mime_type == "directory"
12
+
13
+ def get_parent_id(file_or_dir):
14
+ """Get file_or_dir.directory_id, else raise"""
15
+ if hasattr(file_or_dir, 'directory_id'):
16
+ if file_or_dir.directory_id == file_or_dir.id:
17
+ raise MCCLIException("directory_id == id")
18
+ return file_or_dir.directory_id
19
+ else:
20
+ raise MCCLIException("file_or_dir is missing attribute directory_id")
21
+
22
+ def make_local_abspath(proj_local_path, mcpath):
23
+ return os.path.normpath(os.path.join(proj_local_path, os.path.relpath(mcpath, "/")))
24
+
25
+ def path_in_project(proj_local_path, local_abspath):
26
+ """Check if local path is within the local project directory
27
+
28
+ Args:
29
+ proj_local_path (str): Path to project, i.e. "/path/to/project"
30
+ local_abspath (str): Path to file in project, i.e. "/path/to/project/
31
+ path/to/file"
32
+
33
+ Returns: True, if local_abspath is within the local project directory.
34
+ """
35
+ return os.path.commonpath([proj_local_path, local_abspath]) == os.path.normpath(proj_local_path)
36
+
37
+ def make_mcpath(proj_local_path, local_abspath):
38
+ """
39
+
40
+ Args:
41
+ proj_local_path (str): Path to project, i.e. "/path/to/project"
42
+ local_abspath (str): Path to file in project, i.e. "/path/to/project/
43
+ path/to/file"
44
+
45
+ Returns:
46
+ mcpath (str): Returns a Materials Commons style path, i.e. "/path/to/
47
+ file"
48
+
49
+ Raises:
50
+ MCCLIException, if any path in clipaths is not within the local project
51
+ directory.
52
+ """
53
+ if not path_in_project(proj_local_path, local_abspath):
54
+ raise MCCLIException("make_mcpath error: path not in project")
55
+ relpath = os.path.relpath(local_abspath, proj_local_path)
56
+ if relpath == ".":
57
+ mcpath = "/"
58
+ else:
59
+ mcpath = os.path.join("/", relpath)
60
+ return mcpath
61
+
62
+ def get_by_path_if_exists(client, project_id, file_path):
63
+ """
64
+ Get file (or directory) by path in project, if it exists.
65
+ :param int project_id: The id of the project containing the file or directory
66
+ :param file_path: The Materials Commons path to the file or directory
67
+ :return: The file or None
68
+ :rtype File or None
69
+ """
70
+ try:
71
+ return client.get_file_by_path(project_id, file_path)
72
+ except mcapi.MCAPIError as e:
73
+ if e.response.status_code == 404:
74
+ return None
75
+ raise e
76
+
77
+ def _check_file_selection_dirs(path, file_selection, orig_path=None):
78
+ """Recursively checks if a path is included in a dataset file selection, and why"""
79
+ if path == orig_path:
80
+ selected_by = "(self)"
81
+ else:
82
+ selected_by = path
83
+ if path in file_selection['include_dirs']:
84
+ return (True, selected_by)
85
+ elif path in file_selection['exclude_dirs']:
86
+ return (False, selected_by)
87
+ else:
88
+ parent = os.path.dirname(path)
89
+ if parent == "/":
90
+ return (False, None)
91
+ else:
92
+ return _check_file_selection_dirs(parent, file_selection, orig_path=orig_path)
93
+
94
+ def check_file_selection(path, file_selection):
95
+ """Check if a file or directory is selected in a dataset file selection, and why.
96
+
97
+ Notes:
98
+ A file is selected in a dataset's file selection if it is listed explicitly in "include_files". It is not selected if it is listed in "exclude_files". If it is neither explicitly included or excluded, its parent directories are searched up to the project root directory to see if they are included or excluded. If the first parent directory listed is in "include_dirs", then the file is also selected. If the first parent directory listed is in "exclude_dirs", or if no parent directory is listed at all, the file is not selected.
99
+
100
+ Args:
101
+ path (str): Materials Commons path of file or directory to check
102
+ file_selection (dict): A file selection dict. Expected format: ::
103
+
104
+ {
105
+ "include_files": [... list of file paths ...],
106
+ "exclude_files": [... list of file paths ...],
107
+ "include_dirs": [... list of directory paths ...],
108
+ "exclude_dirs": [... list of directory paths ...]
109
+ }
110
+
111
+ Returns:
112
+ (selected, selected_by):
113
+
114
+ selected (bool): True if selected, False if not selected
115
+
116
+ selected_by (str or None): One of "(self)" if included/excluded explicitly; Else, "<path>", the path of the first parent directory that is included or excluded; Otherwise, None, to indicate that it is not selected, but neither included nor excluded.
117
+ """
118
+ result = None
119
+ if path in file_selection['include_files']:
120
+ result = (True, "(self)")
121
+ elif path in file_selection['exclude_files']:
122
+ result = (False, "(self)")
123
+ else:
124
+ result = _check_file_selection_dirs(path, file_selection, orig_path=path)
125
+ return result
126
+
127
+ def download_file_as_string(client, project_id, file_id):
128
+ f = io.BytesIO()
129
+ client._throttle()
130
+ urlpart = "/projects/" + str(project_id) + "/files/" + str(file_id) + "/download"
131
+ url = client.base_url + urlpart
132
+ with requests.get(url, stream=True, verify=False, headers=client.headers) as r:
133
+ client._handle(r)
134
+ for chunk in r.iter_content(chunk_size=8192):
135
+ if chunk:
136
+ f.write(chunk)
137
+ return f.getvalue().decode('utf-8')