pyedb 0.2.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.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (128) hide show
  1. pyedb/__init__.py +17 -0
  2. pyedb/dotnet/__init__.py +0 -0
  3. pyedb/dotnet/application/Variables.py +2261 -0
  4. pyedb/dotnet/application/__init__.py +0 -0
  5. pyedb/dotnet/clr_module.py +103 -0
  6. pyedb/dotnet/edb.py +4237 -0
  7. pyedb/dotnet/edb_core/__init__.py +1 -0
  8. pyedb/dotnet/edb_core/cell/__init__.py +0 -0
  9. pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
  10. pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
  11. pyedb/dotnet/edb_core/components.py +2669 -0
  12. pyedb/dotnet/edb_core/configuration.py +423 -0
  13. pyedb/dotnet/edb_core/definition/__init__.py +0 -0
  14. pyedb/dotnet/edb_core/definition/component_def.py +166 -0
  15. pyedb/dotnet/edb_core/definition/component_model.py +30 -0
  16. pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
  17. pyedb/dotnet/edb_core/definition/definitions.py +12 -0
  18. pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
  19. pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
  20. pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
  21. pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
  22. pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
  23. pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
  24. pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
  25. pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
  26. pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
  27. pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
  28. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
  29. pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
  30. pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
  31. pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
  32. pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
  33. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
  34. pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
  35. pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
  36. pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
  37. pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
  38. pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
  39. pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
  40. pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
  41. pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
  42. pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
  43. pyedb/dotnet/edb_core/general.py +181 -0
  44. pyedb/dotnet/edb_core/hfss.py +1646 -0
  45. pyedb/dotnet/edb_core/layout.py +1244 -0
  46. pyedb/dotnet/edb_core/layout_validation.py +272 -0
  47. pyedb/dotnet/edb_core/materials.py +939 -0
  48. pyedb/dotnet/edb_core/net_class.py +335 -0
  49. pyedb/dotnet/edb_core/nets.py +1215 -0
  50. pyedb/dotnet/edb_core/padstack.py +1389 -0
  51. pyedb/dotnet/edb_core/siwave.py +1427 -0
  52. pyedb/dotnet/edb_core/stackup.py +2703 -0
  53. pyedb/edb_logger.py +396 -0
  54. pyedb/generic/__init__.py +0 -0
  55. pyedb/generic/constants.py +1063 -0
  56. pyedb/generic/data_handlers.py +320 -0
  57. pyedb/generic/design_types.py +104 -0
  58. pyedb/generic/filesystem.py +150 -0
  59. pyedb/generic/general_methods.py +1535 -0
  60. pyedb/generic/plot.py +1840 -0
  61. pyedb/generic/process.py +285 -0
  62. pyedb/generic/settings.py +224 -0
  63. pyedb/ipc2581/__init__.py +0 -0
  64. pyedb/ipc2581/bom/__init__.py +0 -0
  65. pyedb/ipc2581/bom/bom.py +21 -0
  66. pyedb/ipc2581/bom/bom_item.py +32 -0
  67. pyedb/ipc2581/bom/characteristics.py +37 -0
  68. pyedb/ipc2581/bom/refdes.py +16 -0
  69. pyedb/ipc2581/content/__init__.py +0 -0
  70. pyedb/ipc2581/content/color.py +38 -0
  71. pyedb/ipc2581/content/content.py +55 -0
  72. pyedb/ipc2581/content/dictionary_color.py +29 -0
  73. pyedb/ipc2581/content/dictionary_fill.py +28 -0
  74. pyedb/ipc2581/content/dictionary_line.py +30 -0
  75. pyedb/ipc2581/content/entry_color.py +13 -0
  76. pyedb/ipc2581/content/entry_line.py +14 -0
  77. pyedb/ipc2581/content/fill.py +15 -0
  78. pyedb/ipc2581/content/layer_ref.py +10 -0
  79. pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
  80. pyedb/ipc2581/ecad/__init__.py +0 -0
  81. pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
  82. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
  83. pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
  84. pyedb/ipc2581/ecad/cad_data/component.py +41 -0
  85. pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
  86. pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
  87. pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
  88. pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
  89. pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
  90. pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
  91. pyedb/ipc2581/ecad/cad_data/package.py +104 -0
  92. pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
  93. pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
  94. pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
  95. pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
  96. pyedb/ipc2581/ecad/cad_data/path.py +89 -0
  97. pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
  98. pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
  99. pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
  100. pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
  101. pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
  102. pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
  103. pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
  104. pyedb/ipc2581/ecad/cad_data/step.py +275 -0
  105. pyedb/ipc2581/ecad/cad_header.py +33 -0
  106. pyedb/ipc2581/ecad/ecad.py +19 -0
  107. pyedb/ipc2581/ecad/spec.py +46 -0
  108. pyedb/ipc2581/history_record.py +37 -0
  109. pyedb/ipc2581/ipc2581.py +387 -0
  110. pyedb/ipc2581/logistic_header.py +25 -0
  111. pyedb/misc/__init__.py +0 -0
  112. pyedb/misc/aedtlib_personalib_install.py +14 -0
  113. pyedb/misc/downloads.py +322 -0
  114. pyedb/misc/misc.py +67 -0
  115. pyedb/misc/pyedb.runtimeconfig.json +13 -0
  116. pyedb/misc/siw_feature_config/__init__.py +0 -0
  117. pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
  118. pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
  119. pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
  120. pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
  121. pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
  122. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
  123. pyedb/misc/utilities.py +27 -0
  124. pyedb/modeler/geometry_operators.py +2082 -0
  125. pyedb-0.2.0.dist-info/LICENSE +21 -0
  126. pyedb-0.2.0.dist-info/METADATA +208 -0
  127. pyedb-0.2.0.dist-info/RECORD +128 -0
  128. pyedb-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,320 @@
1
+ # -*- coding: utf-8 -*-
2
+ from collections import OrderedDict
3
+ from decimal import Decimal
4
+ import json
5
+ import math
6
+ import random
7
+ import re
8
+ import string
9
+
10
+ from pyedb.generic.general_methods import pyedb_function_handler, settings
11
+
12
+
13
+ @pyedb_function_handler()
14
+ def format_decimals(el): # pragma: no cover
15
+ """
16
+
17
+ Parameters
18
+ ----------
19
+ el :
20
+
21
+
22
+ Returns
23
+ -------
24
+
25
+ """
26
+ if float(el) > 1000:
27
+ num = "{:,.0f}".format(Decimal(el))
28
+ elif float(el) > 1:
29
+ num = "{:,.3f}".format(Decimal(el))
30
+ else:
31
+ num = "{:.3E}".format(Decimal(el))
32
+ return num
33
+
34
+
35
+ @pyedb_function_handler()
36
+ def random_string(length=6, only_digits=False, char_set=None): # pragma: no cover
37
+ """Generate a random string
38
+
39
+ Parameters
40
+ ----------
41
+ length :
42
+ length of the random string (Default value = 6)
43
+ only_digits : bool, optional
44
+ ``True`` if only digits are to be included.
45
+ char_set : str, optional
46
+ Custom character set to pick the characters from. By default chooses from
47
+ ASCII and digit characters or just digits if ``only_digits`` is ``True``.
48
+
49
+ Returns
50
+ -------
51
+ type
52
+ random string
53
+
54
+ """
55
+ if not char_set:
56
+ if only_digits:
57
+ char_set = string.digits
58
+ else:
59
+ char_set = string.ascii_uppercase + string.digits
60
+ random_str = "".join(random.choice(char_set) for _ in range(int(length)))
61
+ return random_str
62
+
63
+
64
+ @pyedb_function_handler()
65
+ def unique_string_list(element_list, only_string=True): # pragma: no cover
66
+ """Return a unique list of strings from an element list.
67
+
68
+ Parameters
69
+ ----------
70
+ element_list :
71
+
72
+ only_string :
73
+ (Default value = True)
74
+
75
+ Returns
76
+ -------
77
+
78
+ """
79
+ if element_list:
80
+ if isinstance(element_list, list):
81
+ element_list = set(element_list)
82
+ elif isinstance(element_list, str):
83
+ element_list = [element_list]
84
+ else:
85
+ error_message = "Invalid list data"
86
+ try:
87
+ error_message += " {}".format(element_list)
88
+ except:
89
+ pass
90
+ raise Exception(error_message)
91
+
92
+ if only_string:
93
+ non_string_entries = [x for x in element_list if type(x) is not str]
94
+ assert not non_string_entries, "Invalid list entries {} are not a string!".format(non_string_entries)
95
+
96
+ return element_list
97
+
98
+
99
+ @pyedb_function_handler()
100
+ def string_list(element_list): # pragma: no cover
101
+ """
102
+
103
+ Parameters
104
+ ----------
105
+ element_list :
106
+
107
+
108
+ Returns
109
+ -------
110
+
111
+ """
112
+ if isinstance(element_list, str):
113
+ element_list = [element_list]
114
+ else:
115
+ assert isinstance(element_list, str), "Input must be a list or a string"
116
+ return element_list
117
+
118
+
119
+ @pyedb_function_handler()
120
+ def ensure_list(element_list): # pragma: no cover
121
+ """
122
+
123
+ Parameters
124
+ ----------
125
+ element_list :
126
+
127
+
128
+ Returns
129
+ -------
130
+
131
+ """
132
+ if not isinstance(element_list, list):
133
+ element_list = [element_list]
134
+ return element_list
135
+
136
+
137
+ @pyedb_function_handler()
138
+ def from_rkm(code): # pragma: no cover
139
+ """Convert an RKM code string to a string with a decimal point.
140
+
141
+ Parameters
142
+ ----------
143
+ code : str
144
+ RKM code string.
145
+
146
+ Returns
147
+ -------
148
+ str
149
+ String with a decimal point and an R value.
150
+
151
+ Examples
152
+ --------
153
+ >>> from_rkm('R47')
154
+ '0.47'
155
+
156
+ >>> from_rkm('4R7')
157
+ '4.7'
158
+
159
+ >>> from_rkm('470R')
160
+ '470'
161
+
162
+ >>> from_rkm('4K7')
163
+ '4.7k'
164
+
165
+ >>> from_rkm('47K')
166
+ '47k'
167
+
168
+ >>> from_rkm('47K3')
169
+ '47.3k'
170
+
171
+ >>> from_rkm('470K')
172
+ '470k'
173
+
174
+ >>> from_rkm('4M7')
175
+ '4.7M'
176
+
177
+ """
178
+
179
+ # Matches RKM codes that start with a digit.
180
+ # fd_pattern = r'([0-9]+)([LREkKMGTFmuµUnNpP]+)([0-9]*)'
181
+ fd_pattern = r"([0-9]+)([{}]+)([0-9]*)".format(
182
+ "".join(RKM_MAPS.keys()),
183
+ )
184
+ # matches rkm codes that end with a digit
185
+ # ld_pattern = r'([0-9]*)([LREkKMGTFmuµUnNpP]+)([0-9]+)'
186
+ ld_pattern = r"([0-9]*)([{}]+)([0-9]+)".format("".join(RKM_MAPS.keys()))
187
+
188
+ fd_regex = re.compile(fd_pattern, re.I)
189
+ ld_regex = re.compile(ld_pattern, re.I)
190
+
191
+ for regex in [fd_regex, ld_regex]:
192
+ m = regex.match(code)
193
+ if m:
194
+ fd, base, ld = m.groups()
195
+ ps = RKM_MAPS[base]
196
+
197
+ if ld:
198
+ return_str = "".join([fd, ".", ld, ps])
199
+ else:
200
+ return_str = "".join([fd, ps])
201
+ return return_str
202
+ return code
203
+
204
+
205
+ def str_to_bool(s): # pragma: no cover
206
+ """Convert a ``"True"`` or ``"False"`` string to its corresponding Boolean value.
207
+
208
+ If the passed arguments are not relevant in the context of conversion, the argument
209
+ itself is returned. This method can be called using the ``map()`` function to
210
+ ensure conversion of Boolean strings in a list.
211
+
212
+ Parameters
213
+ ----------
214
+ s: str
215
+
216
+ Returns
217
+ -------
218
+ bool or str
219
+ The method is not case-sensitive.
220
+ - ``True`` is returned if the input is ``"true"``, ``"1"``,
221
+ `"yes"``, or ``"y"``,
222
+ - ``False`` is returned if the input is ``"false"``, ``"no"``,
223
+ ``"n``, or ``"0"``.
224
+ - Otherwise, the input value is passed through the method unchanged.
225
+
226
+ """
227
+ if type(s) == str:
228
+ if s.lower() in ["true", "yes", "y", "1"]:
229
+ return True
230
+ elif s.lower() in ["false", "no", "n", "0"]:
231
+ return False
232
+ else:
233
+ return s
234
+ elif type(s) == int:
235
+ return False if s == 0 else True
236
+
237
+
238
+ unit_val = {
239
+ "": 1.0,
240
+ "uV": 1e-6,
241
+ "mV": 1e-3,
242
+ "V": 1.0,
243
+ "kV": 1e3,
244
+ "MegV": 1e6,
245
+ "ns": 1e-9,
246
+ "us": 1e-6,
247
+ "ms": 1e-3,
248
+ "s": 1.0,
249
+ "min": 60,
250
+ "hour": 3600,
251
+ "rad": 1.0,
252
+ "deg": math.pi / 180,
253
+ "Hz": 1.0,
254
+ "kHz": 1e3,
255
+ "MHz": 1e6,
256
+ "nm": 1e-9,
257
+ "um": 1e-6,
258
+ "mm": 1e-3,
259
+ "in": 0.0254,
260
+ "inches": 0.0254,
261
+ "mil": 2.54e-5,
262
+ "cm": 1e-2,
263
+ "dm": 1e-1,
264
+ "meter": 1.0,
265
+ "km": 1e3,
266
+ }
267
+
268
+
269
+ @pyedb_function_handler()
270
+ def float_units(val_str, units=""): # pragma: no cover
271
+ """Retrieve units for a value.
272
+
273
+ Parameters
274
+ ----------
275
+ val_str : str
276
+ Name of the float value.
277
+
278
+ units : str, optional
279
+ The default is ``""``.
280
+
281
+ Returns
282
+ -------
283
+
284
+ """
285
+ if not units in unit_val:
286
+ raise Exception("Specified unit string " + units + " not known!")
287
+
288
+ loc = re.search("[a-zA-Z]", val_str)
289
+ try:
290
+ b = loc.span()[0]
291
+ var = [float(val_str[0:b]), val_str[b:]]
292
+ val = var[0] * unit_val[var[1]]
293
+ except:
294
+ val = float(val_str)
295
+
296
+ val = val / unit_val[units]
297
+ return val
298
+
299
+
300
+ @pyedb_function_handler()
301
+ def json_to_dict(fn): # pragma: no cover
302
+ """Load Json File to a dictionary.
303
+
304
+ Parameters
305
+ ----------
306
+ fn : str
307
+ json file full path.
308
+
309
+ Returns
310
+ -------
311
+ dict
312
+ """
313
+ json_data = {}
314
+ with open(fn) as json_file:
315
+ try:
316
+ json_data = json.load(json_file)
317
+ except json.JSONDecodeError as e: # pragma: no cover
318
+ error = "Error reading json: {} at line {}".format(e.msg, e.lineno)
319
+ settings.logger.error(error)
320
+ return json_data
@@ -0,0 +1,104 @@
1
+ import os
2
+
3
+
4
+ # lazy imports
5
+ def Edb(
6
+ edbpath=None,
7
+ cellname=None,
8
+ isreadonly=False,
9
+ edbversion=None,
10
+ isaedtowned=False,
11
+ oproject=None,
12
+ student_version=False,
13
+ use_ppe=False,
14
+ technology_file=None,
15
+ ):
16
+ """Provides the EDB application interface.
17
+
18
+ This module inherits all objects that belong to EDB.
19
+
20
+ Parameters
21
+ ----------
22
+ edbpath : str, optional
23
+ Full path to the ``aedb`` folder. The variable can also contain
24
+ the path to a layout to import. Allowed formats are BRD,
25
+ XML (IPC2581), GDS, and DXF. The default is ``None``.
26
+ For GDS import, the Ansys control file (also XML) should have the same
27
+ name as the GDS file. Only the file extension differs.
28
+ cellname : str, optional
29
+ Name of the cell to select. The default is ``None``.
30
+ isreadonly : bool, optional
31
+ Whether to open EBD in read-only mode when it is
32
+ owned by HFSS 3D Layout. The default is ``False``.
33
+ edbversion : str, optional
34
+ Version of EDB to use. The default is ``"2021.2"``.
35
+ isaedtowned : bool, optional
36
+ Whether to launch EDB from HFSS 3D Layout. The
37
+ default is ``False``.
38
+ oproject : optional
39
+ Reference to the AEDT project object.
40
+ student_version : bool, optional
41
+ Whether to open the AEDT student version. The default is ``False.``
42
+ technology_file : str, optional
43
+ Full path to technology file to be converted to xml before importing or xml. Supported by GDS format only.
44
+
45
+ Returns
46
+ -------
47
+ :class:`pyedb.dotnet.edb.Edb`, :class:`pyedb.grpc.edb.Edb`
48
+
49
+ Examples
50
+ --------
51
+ Create an ``Edb`` object and a new EDB cell.
52
+
53
+ >>> from pyedb import Edb
54
+ >>> app = Edb()
55
+
56
+ Add a new variable named "s1" to the ``Edb`` instance.
57
+
58
+ >>> app['s1'] = "0.25 mm"
59
+ >>> app['s1'].tofloat
60
+ >>> 0.00025
61
+ >>> app['s1'].tostring
62
+ >>> "0.25mm"
63
+
64
+ or add a new parameter with description:
65
+
66
+ >>> app['s2'] = ["20um", "Spacing between traces"]
67
+ >>> app['s2'].value
68
+ >>> 1.9999999999999998e-05
69
+ >>> app['s2'].description
70
+ >>> 'Spacing between traces'
71
+
72
+
73
+ Create an ``Edb`` object and open the specified project.
74
+
75
+ >>> app = Edb("myfile.aedb")
76
+
77
+ Create an ``Edb`` object from GDS and control files.
78
+ The XML control file resides in the same directory as the GDS file: (myfile.xml).
79
+
80
+ >>> app = Edb("/path/to/file/myfile.gds")
81
+
82
+ """
83
+
84
+ # Use EDB legacy (default choice)
85
+ if bool(os.getenv("PYEDB_USE_DOTNET", "1")):
86
+ from pyedb.dotnet.edb import Edb as app
87
+
88
+ return app(
89
+ edbpath=edbpath,
90
+ cellname=cellname,
91
+ isreadonly=isreadonly,
92
+ edbversion=edbversion,
93
+ isaedtowned=isaedtowned,
94
+ oproject=oproject,
95
+ student_version=student_version,
96
+ use_ppe=use_ppe,
97
+ technology_file=technology_file,
98
+ )
99
+ # TODO: Use EDB gRPC
100
+ else:
101
+ raise Exception("not implemented yet.")
102
+
103
+
104
+ app_map = {"EDB": Edb}
@@ -0,0 +1,150 @@
1
+ import os
2
+ import random
3
+ import shutil
4
+ import string
5
+
6
+
7
+ def search_files(dirname, pattern="*"):
8
+ """Search for files inside a directory given a specific pattern.
9
+
10
+ Parameters
11
+ ----------
12
+ dirname : str
13
+ pattern :str, optional
14
+
15
+ Returns
16
+ -------
17
+ list
18
+ """
19
+ from pyedb.generic.general_methods import is_ironpython
20
+
21
+ if is_ironpython:
22
+ import glob
23
+
24
+ return list(glob.glob(os.path.join(dirname, pattern)))
25
+ else:
26
+ import pathlib
27
+
28
+ return [os.path.abspath(i) for i in pathlib.Path(dirname).glob(pattern)]
29
+
30
+
31
+ def my_location():
32
+ """ """
33
+ return os.path.normpath(os.path.dirname(__file__))
34
+
35
+
36
+ class Scratch:
37
+ """ """
38
+
39
+ @property
40
+ def path(self):
41
+ """ """
42
+ return self._scratch_path
43
+
44
+ @property
45
+ def is_empty(self):
46
+ """ """
47
+ return self._cleaned
48
+
49
+ def __init__(self, local_path, permission=0o777, volatile=False):
50
+ self._volatile = volatile
51
+ self._cleaned = True
52
+ char_set = string.ascii_uppercase + string.digits
53
+ self._scratch_path = os.path.normpath(os.path.join(local_path, "scratch" + "".join(random.sample(char_set, 6))))
54
+ if os.path.exists(self._scratch_path):
55
+ try:
56
+ self.remove()
57
+ except:
58
+ self._cleaned = False
59
+ if self._cleaned:
60
+ try:
61
+ os.mkdir(self.path)
62
+ os.chmod(self.path, permission)
63
+ except FileNotFoundError as fnf_error: # Raise error if folder doesn't exist.
64
+ print(fnf_error)
65
+
66
+ def remove(self):
67
+ """ """
68
+ try:
69
+ # TODO check why on Anaconda 3.7 get errors with os.path.exists
70
+ shutil.rmtree(self._scratch_path, ignore_errors=True)
71
+ except:
72
+ pass
73
+
74
+ def copyfile(self, src_file, dst_filename=None):
75
+ """
76
+ Copy a file to the scratch directory. The target filename is optional.
77
+ If omitted, the target file name is identical to the source file name.
78
+
79
+ Parameters
80
+ ----------
81
+ src_file : str
82
+ Source file with fullpath.
83
+ dst_filename : str, optional
84
+ Destination filename with the extension. The default is ``None``,
85
+ in which case the destination file is given the same name as the
86
+ source file.
87
+
88
+
89
+ Returns
90
+ -------
91
+ dst_file : str
92
+ Full path and file name of the copied file.
93
+
94
+ """
95
+ if dst_filename:
96
+ dst_file = os.path.join(self.path, dst_filename)
97
+ else:
98
+ dst_file = os.path.join(self.path, os.path.basename(src_file))
99
+ if os.path.exists(dst_file):
100
+ try:
101
+ os.unlink(dst_file)
102
+ except OSError: # pragma: no cover
103
+ pass
104
+ try:
105
+ shutil.copy2(src_file, dst_file)
106
+ except FileNotFoundError as fnf_error:
107
+ print(fnf_error)
108
+
109
+ return dst_file
110
+
111
+ def copyfolder(self, src_folder, destfolder):
112
+ """
113
+
114
+ Parameters
115
+ ----------
116
+ src_folder :
117
+
118
+ destfolder :
119
+
120
+
121
+ Returns
122
+ -------
123
+
124
+ """
125
+ from distutils.dir_util import copy_tree
126
+
127
+ copy_tree(src_folder, destfolder)
128
+ return True
129
+
130
+ def __enter__(self):
131
+ return self
132
+
133
+ def __exit__(self, ex_type, ex_value, ex_traceback):
134
+ if ex_type or self._volatile:
135
+ self.remove()
136
+
137
+
138
+ def get_json_files(start_folder):
139
+ """
140
+ Get the absolute path to all *.json files in start_folder.
141
+
142
+ Parameters
143
+ ----------
144
+ start_folder, str
145
+ Path to the folder where the json files are located.
146
+
147
+ Returns
148
+ -------
149
+ """
150
+ return [y for x in os.walk(start_folder) for y in search_files(x[0], "*.json")]