maco 1.2.18__py3-none-any.whl → 1.2.20__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.
@@ -27,6 +27,7 @@ def process_file(
27
27
  pretty: bool,
28
28
  force: bool,
29
29
  include_base64: bool,
30
+ extracted_dir: str = "",
30
31
  ):
31
32
  """Process a filestream with the extractors and rules.
32
33
 
@@ -37,6 +38,7 @@ def process_file(
37
38
  pretty (bool): Pretty print the JSON output
38
39
  force (bool): Run all extractors regardless of YARA rule match
39
40
  include_base64 (bool): include base64'd data in output
41
+ extracted_dir (str): directory to write CaRTed binary data to
40
42
 
41
43
  Returns:
42
44
  (dict): The output from the extractors analyzing the sample
@@ -87,6 +89,34 @@ def process_file(
87
89
  if include_base64:
88
90
  # this can be large
89
91
  row["base64"] = base64.b64encode(row["data"]).decode("utf8")
92
+
93
+ # write binary data to disk if enabled
94
+ if extracted_dir:
95
+ # only allow writes to already existing directories with permissions
96
+ if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
97
+ filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
98
+ # don't overwrite existing files
99
+ if os.path.exists(filepath):
100
+ logger.debug(f"{filepath} already exists.")
101
+ else:
102
+ # CaRT data before writing to disk
103
+ in_stream = io.BytesIO(row["data"])
104
+ output_stream = io.BytesIO()
105
+ try:
106
+ cart.pack_stream(in_stream, output_stream)
107
+ except Exception:
108
+ logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
109
+ else:
110
+ output_stream.seek(0)
111
+ try:
112
+ with open(filepath, "wb") as f:
113
+ f.write(output_stream.getbuffer())
114
+ logger.debug(f"Wrote binary output to {filepath}.")
115
+ except (FileNotFoundError, PermissionError, OSError):
116
+ logger.error(f"Error trying to write binary output to {filepath}")
117
+ else:
118
+ logger.error(f"Cannot write files to {extracted_dir}")
119
+
90
120
  # do not print raw bytes to console
91
121
  row.pop("data")
92
122
  ret[extractor_name] = resp
@@ -107,6 +137,7 @@ def process_filesystem(
107
137
  include_base64: bool,
108
138
  create_venv: bool = False,
109
139
  skip_install: bool = False,
140
+ extracted_dir: str = "",
110
141
  ) -> Tuple[int, int, int]:
111
142
  """Process filesystem with extractors and print results of extraction.
112
143
 
@@ -159,6 +190,7 @@ def process_filesystem(
159
190
  pretty=pretty,
160
191
  force=force,
161
192
  include_base64=include_base64,
193
+ extracted_dir=extracted_dir,
162
194
  )
163
195
  if resp:
164
196
  num_hits += 1
@@ -194,6 +226,7 @@ def main():
194
226
  help="Include base64 encoded binary data in output "
195
227
  "(can be large, consider printing to file rather than console)",
196
228
  )
229
+ parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
197
230
  parser.add_argument("--logfile", type=str, help="file to log output")
198
231
  parser.add_argument("--include", type=str, help="comma separated extractors to run")
199
232
  parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
@@ -268,6 +301,7 @@ def main():
268
301
  include_base64=args.base64,
269
302
  create_venv=args.create_venv,
270
303
  skip_install=not args.force_install,
304
+ extracted_dir=args.binarydir,
271
305
  )
272
306
 
273
307
 
@@ -122,6 +122,7 @@ class Collector:
122
122
  "author": member.author,
123
123
  "last_modified": member.last_modified,
124
124
  "sharing": member.sharing,
125
+ "result_sharing": member.result_sharing,
125
126
  "description": member.__doc__,
126
127
  },
127
128
  )
@@ -25,7 +25,8 @@ class Extractor:
25
25
  family: Union[str, List[str]] = None # family or families of malware that is detected by the extractor
26
26
  author: str = None # author of the extractor (name@organisation)
27
27
  last_modified: str = None # last modified date (YYYY-MM-DD)
28
- sharing: str = "TLP:WHITE" # who can this be shared with?
28
+ sharing: str = "TLP:CLEAR" # who can this be shared with?
29
+ result_sharing: str = sharing # who can the results be shared with? (defaults to sharing)
29
30
  yara_rule: str = None # yara rule that we filter inputs with
30
31
  reference: str = None # link to malware report or other reference information
31
32
  logger: logging.Logger = None # logger for use when debugging
maco/cli.py CHANGED
@@ -27,6 +27,7 @@ def process_file(
27
27
  pretty: bool,
28
28
  force: bool,
29
29
  include_base64: bool,
30
+ extracted_dir: str = "",
30
31
  ):
31
32
  """Process a filestream with the extractors and rules.
32
33
 
@@ -37,6 +38,7 @@ def process_file(
37
38
  pretty (bool): Pretty print the JSON output
38
39
  force (bool): Run all extractors regardless of YARA rule match
39
40
  include_base64 (bool): include base64'd data in output
41
+ extracted_dir (str): directory to write CaRTed binary data to
40
42
 
41
43
  Returns:
42
44
  (dict): The output from the extractors analyzing the sample
@@ -87,6 +89,34 @@ def process_file(
87
89
  if include_base64:
88
90
  # this can be large
89
91
  row["base64"] = base64.b64encode(row["data"]).decode("utf8")
92
+
93
+ # write binary data to disk if enabled
94
+ if extracted_dir:
95
+ # only allow writes to already existing directories with permissions
96
+ if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
97
+ filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
98
+ # don't overwrite existing files
99
+ if os.path.exists(filepath):
100
+ logger.debug(f"{filepath} already exists.")
101
+ else:
102
+ # CaRT data before writing to disk
103
+ in_stream = io.BytesIO(row["data"])
104
+ output_stream = io.BytesIO()
105
+ try:
106
+ cart.pack_stream(in_stream, output_stream)
107
+ except Exception:
108
+ logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
109
+ else:
110
+ output_stream.seek(0)
111
+ try:
112
+ with open(filepath, "wb") as f:
113
+ f.write(output_stream.getbuffer())
114
+ logger.debug(f"Wrote binary output to {filepath}.")
115
+ except (FileNotFoundError, PermissionError, OSError):
116
+ logger.error(f"Error trying to write binary output to {filepath}")
117
+ else:
118
+ logger.error(f"Cannot write files to {extracted_dir}")
119
+
90
120
  # do not print raw bytes to console
91
121
  row.pop("data")
92
122
  ret[extractor_name] = resp
@@ -107,6 +137,7 @@ def process_filesystem(
107
137
  include_base64: bool,
108
138
  create_venv: bool = False,
109
139
  skip_install: bool = False,
140
+ extracted_dir: str = "",
110
141
  ) -> Tuple[int, int, int]:
111
142
  """Process filesystem with extractors and print results of extraction.
112
143
 
@@ -159,6 +190,7 @@ def process_filesystem(
159
190
  pretty=pretty,
160
191
  force=force,
161
192
  include_base64=include_base64,
193
+ extracted_dir=extracted_dir,
162
194
  )
163
195
  if resp:
164
196
  num_hits += 1
@@ -194,6 +226,7 @@ def main():
194
226
  help="Include base64 encoded binary data in output "
195
227
  "(can be large, consider printing to file rather than console)",
196
228
  )
229
+ parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
197
230
  parser.add_argument("--logfile", type=str, help="file to log output")
198
231
  parser.add_argument("--include", type=str, help="comma separated extractors to run")
199
232
  parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
@@ -268,6 +301,7 @@ def main():
268
301
  include_base64=args.base64,
269
302
  create_venv=args.create_venv,
270
303
  skip_install=not args.force_install,
304
+ extracted_dir=args.binarydir,
271
305
  )
272
306
 
273
307
 
maco/collector.py CHANGED
@@ -122,6 +122,7 @@ class Collector:
122
122
  "author": member.author,
123
123
  "last_modified": member.last_modified,
124
124
  "sharing": member.sharing,
125
+ "result_sharing": member.result_sharing,
125
126
  "description": member.__doc__,
126
127
  },
127
128
  )
maco/extractor.py CHANGED
@@ -25,7 +25,8 @@ class Extractor:
25
25
  family: Union[str, List[str]] = None # family or families of malware that is detected by the extractor
26
26
  author: str = None # author of the extractor (name@organisation)
27
27
  last_modified: str = None # last modified date (YYYY-MM-DD)
28
- sharing: str = "TLP:WHITE" # who can this be shared with?
28
+ sharing: str = "TLP:CLEAR" # who can this be shared with?
29
+ result_sharing: str = sharing # who can the results be shared with? (defaults to sharing)
29
30
  yara_rule: str = None # yara rule that we filter inputs with
30
31
  reference: str = None # link to malware report or other reference information
31
32
  logger: logging.Logger = None # logger for use when debugging
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maco
3
- Version: 1.2.18
3
+ Version: 1.2.20
4
4
  Summary: Maco is a framework for creating and using malware configuration extractors.
5
5
  Author: sl-govau
6
6
  Maintainer: cccs-rs
@@ -10,36 +10,36 @@ demo_extractors/complex/complex.py,sha256=GYKmPOD8-fyVHxwjZb-3t1IghKVMuLtdUvCs5C
10
10
  demo_extractors/complex/complex_utils.py,sha256=5kdMl-niSH9d-d3ChuItpmlPT4U-S9g-iyBZlR4tfmQ,296
11
11
  extractor_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  extractor_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
13
- extractor_setup/maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
14
- extractor_setup/maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
13
+ extractor_setup/maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
14
+ extractor_setup/maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
15
15
  extractor_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
16
- extractor_setup/maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
16
+ extractor_setup/maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
17
17
  extractor_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
18
18
  extractor_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
19
19
  extractor_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
20
20
  extractor_setup/maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
21
21
  maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
23
- maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
24
- maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
23
+ maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
24
+ maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
25
25
  maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
26
- maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
26
+ maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
27
27
  maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
28
28
  maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
29
29
  maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
30
30
  maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
31
- maco-1.2.18.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
31
+ maco-1.2.20.dist-info/licenses/LICENSE.md,sha256=gMSjshPhXvV_F1qxmeNkKdBqGWkd__fEJf4glS504bM,1478
32
32
  model_setup/maco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  model_setup/maco/base_test.py,sha256=DrVE7vOazeLQpOQeIDwBYK1WtlmdJrRe50JOqP5t4Y0,3198
34
- model_setup/maco/cli.py,sha256=nrSukAJAthbstZT3-lQNPz4zOOMcBhvfYQqLh_B5Jdk,9457
35
- model_setup/maco/collector.py,sha256=R3zw-fUJBlwmcSqvkQ-PnoJdHfRm2V0JAOl7N8MTAbY,8240
34
+ model_setup/maco/cli.py,sha256=jFtYWuKNlqcnSl0W4vgITctpgfd3J9kgN37IwoW3pDY,11477
35
+ model_setup/maco/collector.py,sha256=I0Nidf4-xcvoe6X0bbCsAXjr66iPf00JDO6ocKkaZLc,8309
36
36
  model_setup/maco/exceptions.py,sha256=XBHUrs1kr1ZayPI9B_W-WejKgVmC8sWL_o4RL0b4DQE,745
37
- model_setup/maco/extractor.py,sha256=s36aGcsXSc-9iCik6iihVt5G1a1DZUA7TquvWYQNwdE,2912
37
+ model_setup/maco/extractor.py,sha256=nqIfUcrc_l57FicKZc6HLtN223-_zkYWL1AYMy1WAmA,3007
38
38
  model_setup/maco/utils.py,sha256=yNm5CiHc9033ONX_gFwg9Lng5IYFujLDtw6FfiJkAao,23425
39
39
  model_setup/maco/yara.py,sha256=y141t8NqDDXHY23uE1d6BDPeNmSuUuohR6Yr_LKa7GI,4067
40
40
  model_setup/maco/model/__init__.py,sha256=ULdyHx8R5D2ICHZo3VoCk1YTlewTok36TYIpwx__pNY,45
41
41
  model_setup/maco/model/model.py,sha256=DBHTmZXMzjpVq0s2mzZv3VCzPhwPnv7sH6u_QZCTcA4,24484
42
- pipelines/publish.yaml,sha256=yjc3eqrI-LHLSfZ0DPtxwdfPDT0NI6LUA_zy61UxN_8,1654
42
+ pipelines/publish.yaml,sha256=BfsbDsg2ijtXF8lhRUjzkenw3zi2mL7ESNv3KuC1cVE,1626
43
43
  pipelines/test.yaml,sha256=btJVI-R39UBeYosGu7TOpU6V9ogFW3FT3ROtWygQGQ0,1472
44
44
  tests/data/example.txt.cart,sha256=j4ZdDnFNVq7lb-Qi4pY4evOXKQPKG-GSg-n-uEqPhV0,289
45
45
  tests/data/trigger_complex.txt,sha256=uqnLSrnyDGCmXwuPmZ2s8vdhH0hJs8DxvyaW_tuYY24,64
@@ -52,8 +52,8 @@ tests/extractors/bob/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
52
52
  tests/extractors/bob/bob.py,sha256=4fpqy_O6NDinJImghyW5OwYgnaB05aY4kgoIS_C3c_U,253
53
53
  tests/extractors/import_rewriting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  tests/extractors/import_rewriting/importer.py,sha256=wqF1AG2zXXuj9EMt9qlDorab-UD0GYuFggtrCuz4sf0,289735
55
- maco-1.2.18.dist-info/METADATA,sha256=citbYasnfKhc-PAxK7tLQt_Dc2LZRbhKn26ChD0PC3g,15310
56
- maco-1.2.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
- maco-1.2.18.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
58
- maco-1.2.18.dist-info/top_level.txt,sha256=xiVS11ZoyN8ChHJQGpOzTH4ZyQ3YJe1qT3Yt4gcKGUk,65
59
- maco-1.2.18.dist-info/RECORD,,
55
+ maco-1.2.20.dist-info/METADATA,sha256=8ZvRVvxy741jFWHAP1g-B_57zuamXaiglsEglweURUI,15310
56
+ maco-1.2.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ maco-1.2.20.dist-info/entry_points.txt,sha256=TpcwG1gedIg8Y7a9ZOv8aQpuwEUftCefDrAjzeP-o6U,39
58
+ maco-1.2.20.dist-info/top_level.txt,sha256=xiVS11ZoyN8ChHJQGpOzTH4ZyQ3YJe1qT3Yt4gcKGUk,65
59
+ maco-1.2.20.dist-info/RECORD,,
model_setup/maco/cli.py CHANGED
@@ -27,6 +27,7 @@ def process_file(
27
27
  pretty: bool,
28
28
  force: bool,
29
29
  include_base64: bool,
30
+ extracted_dir: str = "",
30
31
  ):
31
32
  """Process a filestream with the extractors and rules.
32
33
 
@@ -37,6 +38,7 @@ def process_file(
37
38
  pretty (bool): Pretty print the JSON output
38
39
  force (bool): Run all extractors regardless of YARA rule match
39
40
  include_base64 (bool): include base64'd data in output
41
+ extracted_dir (str): directory to write CaRTed binary data to
40
42
 
41
43
  Returns:
42
44
  (dict): The output from the extractors analyzing the sample
@@ -87,6 +89,34 @@ def process_file(
87
89
  if include_base64:
88
90
  # this can be large
89
91
  row["base64"] = base64.b64encode(row["data"]).decode("utf8")
92
+
93
+ # write binary data to disk if enabled
94
+ if extracted_dir:
95
+ # only allow writes to already existing directories with permissions
96
+ if os.path.isdir(extracted_dir) and os.access(extracted_dir, os.W_OK):
97
+ filepath = os.path.abspath(os.path.join(extracted_dir, f"{row['sha256']}.cart"))
98
+ # don't overwrite existing files
99
+ if os.path.exists(filepath):
100
+ logger.debug(f"{filepath} already exists.")
101
+ else:
102
+ # CaRT data before writing to disk
103
+ in_stream = io.BytesIO(row["data"])
104
+ output_stream = io.BytesIO()
105
+ try:
106
+ cart.pack_stream(in_stream, output_stream)
107
+ except Exception:
108
+ logger.error(f"Error trying to CaRT binary output ({row['sha256']}) from {path_file}.")
109
+ else:
110
+ output_stream.seek(0)
111
+ try:
112
+ with open(filepath, "wb") as f:
113
+ f.write(output_stream.getbuffer())
114
+ logger.debug(f"Wrote binary output to {filepath}.")
115
+ except (FileNotFoundError, PermissionError, OSError):
116
+ logger.error(f"Error trying to write binary output to {filepath}")
117
+ else:
118
+ logger.error(f"Cannot write files to {extracted_dir}")
119
+
90
120
  # do not print raw bytes to console
91
121
  row.pop("data")
92
122
  ret[extractor_name] = resp
@@ -107,6 +137,7 @@ def process_filesystem(
107
137
  include_base64: bool,
108
138
  create_venv: bool = False,
109
139
  skip_install: bool = False,
140
+ extracted_dir: str = "",
110
141
  ) -> Tuple[int, int, int]:
111
142
  """Process filesystem with extractors and print results of extraction.
112
143
 
@@ -159,6 +190,7 @@ def process_filesystem(
159
190
  pretty=pretty,
160
191
  force=force,
161
192
  include_base64=include_base64,
193
+ extracted_dir=extracted_dir,
162
194
  )
163
195
  if resp:
164
196
  num_hits += 1
@@ -194,6 +226,7 @@ def main():
194
226
  help="Include base64 encoded binary data in output "
195
227
  "(can be large, consider printing to file rather than console)",
196
228
  )
229
+ parser.add_argument("--binarydir", type=str, help="directory to write extracted binary data to")
197
230
  parser.add_argument("--logfile", type=str, help="file to log output")
198
231
  parser.add_argument("--include", type=str, help="comma separated extractors to run")
199
232
  parser.add_argument("--exclude", type=str, help="comma separated extractors to not run")
@@ -268,6 +301,7 @@ def main():
268
301
  include_base64=args.base64,
269
302
  create_venv=args.create_venv,
270
303
  skip_install=not args.force_install,
304
+ extracted_dir=args.binarydir,
271
305
  )
272
306
 
273
307
 
@@ -122,6 +122,7 @@ class Collector:
122
122
  "author": member.author,
123
123
  "last_modified": member.last_modified,
124
124
  "sharing": member.sharing,
125
+ "result_sharing": member.result_sharing,
125
126
  "description": member.__doc__,
126
127
  },
127
128
  )
@@ -25,7 +25,8 @@ class Extractor:
25
25
  family: Union[str, List[str]] = None # family or families of malware that is detected by the extractor
26
26
  author: str = None # author of the extractor (name@organisation)
27
27
  last_modified: str = None # last modified date (YYYY-MM-DD)
28
- sharing: str = "TLP:WHITE" # who can this be shared with?
28
+ sharing: str = "TLP:CLEAR" # who can this be shared with?
29
+ result_sharing: str = sharing # who can the results be shared with? (defaults to sharing)
29
30
  yara_rule: str = None # yara rule that we filter inputs with
30
31
  reference: str = None # link to malware report or other reference information
31
32
  logger: logging.Logger = None # logger for use when debugging
pipelines/publish.yaml CHANGED
@@ -12,33 +12,34 @@ pool:
12
12
  vmImage: "ubuntu-22.04"
13
13
 
14
14
  jobs:
15
- # - job: test
16
- # displayName: Test
17
- # strategy:
18
- # matrix:
19
- # Python38:
20
- # python.version: '3.8'
21
- # Python39:
22
- # python.version: '3.9'
23
- # Python310:
24
- # python.version: '3.10'
25
- # Python311:
26
- # python.version: '3.11'
27
- # Python312:
28
- # python.version: '3.12'
29
- # steps:
30
- # - task: UsePythonVersion@0
31
- # displayName: 'Use Python $(python.version)'
32
- # inputs:
33
- # versionSpec: '$(python.version)'
15
+ - job: test
16
+ displayName: Test
17
+ strategy:
18
+ matrix:
19
+ Python38:
20
+ python.version: '3.8'
21
+ Python39:
22
+ python.version: '3.9'
23
+ Python310:
24
+ python.version: '3.10'
25
+ Python311:
26
+ python.version: '3.11'
27
+ Python312:
28
+ python.version: '3.12'
29
+ steps:
30
+ - task: UsePythonVersion@0
31
+ displayName: 'Use Python $(python.version)'
32
+ inputs:
33
+ versionSpec: '$(python.version)'
34
34
 
35
- # - script: |
36
- # set -x
35
+ - script: |
36
+ set -x
37
37
 
38
- # python -m pip install -U tox
39
- # python -m tox -e py
38
+ python -m pip install -U tox
39
+ python -m tox -e py
40
40
 
41
41
  - job: build_and_deploy
42
+ dependsOn: test
42
43
  displayName: Build and Deploy
43
44
  variables:
44
45
  - group: deployment-information
File without changes