Added additional checks for boards and images

This commit is contained in:
Melissa LeBlanc-Williams 2022-05-26 14:12:06 -07:00
parent 593ef15b98
commit a2fca8870c
82 changed files with 245 additions and 54 deletions

View file

@ -43,8 +43,11 @@ jobs:
gem install bundler:1.17.3
bundle install --full-index
pip install python-frontmatter
- name: Check feature names
run: python3 check-features.py
pip install pillow
- name: Check feature names and other data
run: python3 check-boards.py
- name: Check Image Dimensions
run: python3 check-images.py
- name: Build site with jekyll
run: |
bundle exec jekyll build -d build

View file

@ -7,6 +7,7 @@ manufacturer: "SEEED"
board_url: "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html"
board_image: "Seeed_XIAO_nRF52840_Sense.jpg"
date_added: 2021-12-29
family: nrf52840
downloads_display: true

View file

@ -8,6 +8,7 @@ board_url: "https://www.crowdsupply.com/diodes-delight/piunora"
board_image: "diodes_delight_piunora.jpg"
download_instructions:
date_added: 2021-2-14
family: raspberrypi
features:
- Wi-Fi
- Bluetooth/BTLE

View file

@ -6,7 +6,7 @@ name: "DynaLoRa-USB"
manufacturer: "BH Dynamics"
board_url: "https://github.com/BHDynamics/rfm_radio_dongle"
board_image: "dynalora_usb.jpg"
date_added:
date_added: 2021-02-11
family: atmel-samd
features:
- LoRa/Radio

View file

@ -6,7 +6,7 @@ name: "DynOSSAT-EDU EPS"
manufacturer: "BH Dynamics"
board_url: "https://bhdyn.com/newspace"
board_image: "dynossat_edu_eps.jpg"
date_added:
date_added: 2020-10-16
family: atmel-samd
downloads_display: true

View file

@ -6,7 +6,7 @@ name: "DynOSSAT-EDU OBC"
manufacturer: "BH Dynamics"
board_url: "https://bhdyn.com/newspace"
board_image: "dynossat_edu_obc.jpg"
date_added:
date_added: 2020-10-16
family: atmel-samd
downloads_display: true

View file

@ -7,6 +7,7 @@ manufacturer: "ELECFREAKS"
board_url: "https://www.elecfreaks.com/picoed.html"
board_image: "elecfreaks_picoed.jpg"
date_added: 2022-4-21
family: raspberrypi
features:
- Speaker
- Display

View file

@ -6,7 +6,7 @@ name: "TTGO T8 ESP32-S2"
manufacturer: "LILYGO"
board_url: "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=1321"
board_image: "lilygo_ttgo_t8_s2.jpg"
date_added:
date_added: 2022-03-09
family: esp32s2
bootloader_id: lilygo_ttgo_t8_s2
features:

View file

@ -6,7 +6,7 @@ name: "TTGO T8 ESP32-S2 ST7789"
manufacturer: "LILYGO"
board_url: "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=1321"
board_image: "lilygo_ttgo_t8_s2_st7789.jpg"
date_added:
date_added: 2021-02-14
family: esp32s2
bootloader_id: lilygo_ttgo_t8_s2_st7789
features:

View file

@ -7,6 +7,7 @@ manufacturer: "Mixly"
board_url: "https://mixly.org/"
board_image: "mixgo_ce_serial.jpg"
date_added: 2022-5-22
family: esp32s2
features:
- Display
- Wi-Fi

View file

@ -7,6 +7,7 @@ manufacturer: "Mixly"
board_url: "https://mixly.org/"
board_image: "mixgo_ce_udisk.jpg"
date_added: 2022-5-1
family: esp32s2
features:
- Display
- Wi-Fi

View file

@ -7,7 +7,9 @@ manufacturer: "PyCubed.org"
board_url: "https://pycubed.org/"
board_image: "pycubed_v05.jpg"
date_added: 2021-9-12
family: atmel-samd
features:
---
### ⭐ Double-check the your PyCubed board version before updating firmware.

View file

@ -7,7 +7,9 @@ manufacturer: "PyCubed.org"
board_url: "https://pycubed.org/"
board_image: "pycubed_v05.jpg"
date_added: 2021-9-12
family: atmel-samd
features:
---
### ⭐ Double-check the your PyCubed board version before updating firmware.

View file

@ -7,6 +7,7 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/compute-module-4/"
board_image: "raspberry_pi_cm4.jpg"
date_added: 2022-1-4
family: raspberrypi
---

View file

@ -7,6 +7,7 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/compute-module-4-io-board/"
board_image: "raspberrypi_cm4io.jpg"
date_added: 2021-11-29
family: raspberrypi
---

View file

@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/raspberry-pi-4-model-b/"
board_image: "raspberry_pi_4b.jpg"
date_added: 2021-11-29
family: raspberrypi
---
**NOTE**: Not all features are supported in CircuitPython.

View file

@ -7,7 +7,9 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero/"
board_image: "raspberry_pi_zero.jpg"
date_added: 2022-2-14
family: raspberrypi
features:
---
**NOTE**: Not all features are supported in CircuitPython.

View file

@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/"
board_image: "raspberry_pi_zero_2_w.jpg"
date_added: 2021-11-29
family: raspberrypi
---
**NOTE**: Not all features are supported in CircuitPython.

View file

@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero-w/"
board_image: "raspberry_pi_zero_w.jpg"
date_added: 2022-01-07
family: raspberrypi
---
**NOTE**: Not all features are supported in CircuitPython.

View file

@ -7,7 +7,7 @@ manufacturer: "SEEED"
board_url: "https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html"
board_image: "seeeduino_xiao_rp2040.jpg"
date_added: 2022-1-4
family: raspberrypi
features:
- Breadboard-Friendly
- Robotics

View file

@ -7,6 +7,7 @@ manufacturer: "Blues Wireless"
board_url: "https://blues.io/products/swan"
board_image: "swan_r5.jpg"
date_added: 2021-9-29
family: stm
features:
- Feather-Compatible
- Battery Charging

View file

@ -7,10 +7,10 @@ manufacturer: "Waveshare"
board_url: "https://www.waveshare.com/rp2040-zero.htm"
board_image: "waveshare_rp2040_zero.jpg"
date_added: "2022-1-12"
family: raspberrypi
features:
- USB-C
- Breadboard-Friendly
---
a Pico-like MCU board based on Raspberry Pi RP2040

View file

@ -7,6 +7,7 @@ manufacturer: "WIZnet"
board_url: "https://www.wiznet.io/product-item/w5100s-evb-pico/"
board_image: "w5100s-evb-pico.jpg"
date_added: 2022-4-26
family: raspberrypi
features:
- Breadboard-Friendly
---

View file

@ -1,7 +1,7 @@
{
"bootloaders": {
"nrf52840": {
"version": "0.6.3"
"version": "0.6.4"
},
"atmel-samd": {
"version": "v3.14.0"
@ -15,6 +15,8 @@
"esp32c3": {},
"stm": {},
"cxd56": {},
"mimxrt10xx": {}
"mimxrt10xx": {},
"raspberrypi": {},
"litex": {}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View file

Before

Width:  |  Height:  |  Size: 1,014 KiB

After

Width:  |  Height:  |  Size: 1,014 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 1,007 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

After

Width:  |  Height:  |  Size: 773 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 678 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 KiB

After

Width:  |  Height:  |  Size: 2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 6.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 KiB

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 21 KiB

127
check-boards.py Executable file
View file

@ -0,0 +1,127 @@
#!/usr/bin/python3
import json
import re
from pathlib import Path
import frontmatter
from dateutil.parser import parse
# Check CircuitPython Download Features
with open('template.md', "rt") as f:
metadata, content = frontmatter.parse(f.read())
acceptable_features = set(metadata['features'])
def valid_date(date):
date = str(date)
if date:
try:
parse(date)
return True
except:
return False
return False
def verify_features(folder, valid_features):
valid = True
for filename in Path(folder).glob("*.md"):
with open(filename, "rt") as f:
metadata, _ = frontmatter.parse(f.read())
downloads_display = metadata.get('downloads_display')
if downloads_display is None or downloads_display:
board_id = metadata.get('board_id')
if board_id == "unknown":
continue
features = metadata.get('features') or ()
for feature in sorted(set(features) - valid_features):
print(f"{filename}:0: Non-standard feature: {feature}")
valid = False
return valid
def verify_family(folder):
valid = True
bl_file = open('./_data/bootloaders.json')
bootloaders = json.load(bl_file)
valid_bootloaders = bootloaders["bootloaders"].keys()
for filename in Path(folder).glob("*.md"):
with open(filename, "rt") as f:
metadata, _ = frontmatter.parse(f.read())
downloads_display = metadata.get('downloads_display')
if downloads_display is None or downloads_display:
board_id = metadata.get('board_id') or ()
if board_id == "unknown":
continue
family = metadata.get('family')
if family is None:
print(f"Family field is missing for {board_id}")
valid = False
elif family not in valid_bootloaders:
print(f"Family field value of {family} for {board_id} is invalid.")
valid = False
bl_file.close()
return valid
def verify_date_added(folder):
valid = True
for filename in Path(folder).glob("*.md"):
with open(filename, "rt") as f:
metadata, _ = frontmatter.parse(f.read())
downloads_display = metadata.get('downloads_display')
if downloads_display is None or downloads_display:
board_id = metadata.get('board_id') or ()
if board_id == "unknown":
continue
date_added = metadata.get('date_added')
if date_added is None:
print(f"date_added field is missing for {board_id}")
valid = False
elif not valid_date(date_added):
print(f"{date_added} is an invalid date for {board_id}")
valid = False
return valid
def verify_contribute_not_present(folder):
valid = True
contribute = re.compile(r".*\n## Contribute", re.MULTILINE | re.DOTALL)
for filename in Path(folder).glob("*.md"):
with open(filename, "rt") as f:
metadata, content = frontmatter.parse(f.read())
board_id = metadata.get('board_id') or ()
result = contribute.match(content)
if result is not None:
print(f"Contribute Section found for {board_id} in {folder}")
return valid
if not verify_features("_board", acceptable_features):
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for acceptable features")
raise SystemExit(True)
# Check Blinka Download Features
blinka_features = {
"Ethernet",
"HDMI",
"Wi-Fi",
"40-pin GPIO",
"GPS",
"Feather-Compatible",
"Bluetooth/BLE",
"STEMMA QT/QWIIC",
"USB 3.0",
"Infrared Receiver",
}
if not verify_features("_blinka", blinka_features):
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-blinka for acceptable features")
raise SystemExit(True)
if not verify_family("_board"):
print("Family or not found or invalid value. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for details")
raise SystemExit(True)
if not verify_date_added("_board") or not verify_date_added("blinka"):
print("Date Added field not found or invalid value. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for details")
raise SystemExit(True)
if not verify_contribute_not_present("_board") or not verify_contribute_not_present("blinka"):
print("Contribute section found. This should not be there since it is automatically added.")
raise SystemExit(True)
raise SystemExit(False)

View file

@ -1,43 +0,0 @@
#!/usr/bin/python3
from pathlib import Path
import frontmatter
# Check CircuitPython Download Features
with open('template.md', "rt") as f:
metadata, content = frontmatter.parse(f.read())
acceptable_features = set(metadata['features'])
def verify_features(folder, valid_features):
success = True
for filename in Path(folder).glob("*.md"):
with open(filename, "rt") as f:
metadata, content = frontmatter.parse(f.read())
features = metadata.get('features') or ()
for feature in sorted(set(features) - valid_features):
print(f"{filename}:0: Non-standard feature: {feature}")
success = False
return success
if not verify_features("_board", acceptable_features):
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for acceptable features")
raise SystemExit(True)
# Check Blinka Download Features
blinka_features = {
"Ethernet",
"HDMI",
"Wi-Fi",
"40-pin GPIO",
"GPS",
"Feather-Compatible",
"Bluetooth/BLE",
"STEMMA QT/QWIIC",
"USB 3.0",
"Infrared Receiver",
}
failed = not verify_features("_blinka", blinka_features)
if failed:
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-blinka for acceptable features")
raise SystemExit(failed)

81
check-images.py Executable file
View file

@ -0,0 +1,81 @@
#!/usr/bin/python3
import os
from pathlib import Path
import frontmatter
from PIL import Image
MIN_ACCEPTABLE_RATIO = 0.75 # HEIGHT / WIDTH
MAX_ACCEPTABLE_RATIO = 0.8
SMALL_IMAGE_MIN_WIDTH = 292
SMALL_IMAGE_MAX_WIDTH = 800
LARGE_IMAGE_MIN_WIDTH = 590
REQUIRE_ORIGINAL_IMAGE = True
BOARD_IMAGE_PATH = "./assets/images/boards/"
SMALL_IMAGE_PATH = BOARD_IMAGE_PATH + "small/"
LARGE_IMAGE_PATH = BOARD_IMAGE_PATH + "large/"
ORIGINAL_IMAGE_PATH = BOARD_IMAGE_PATH + "original/"
def verify_images(folder):
valid = True
for filename in sorted(Path(folder).glob("*.md")):
with open(filename, "rt") as f:
metadata, _ = frontmatter.parse(f.read())
downloads_display = metadata.get('downloads_display')
if downloads_display is None or downloads_display:
board_image = metadata.get('board_image') or ()
board_id = metadata.get('board_id') or ()
if board_id == "unknown":
continue
# Small Image
small_image_found = os.path.exists(SMALL_IMAGE_PATH + board_image)
if small_image_found:
img = Image.open(SMALL_IMAGE_PATH + board_image)
if not verify_image_size(SMALL_IMAGE_PATH + board_image, SMALL_IMAGE_MIN_WIDTH, SMALL_IMAGE_MAX_WIDTH):
valid = False
large_image_found = os.path.exists(LARGE_IMAGE_PATH + board_image)
if large_image_found:
if not verify_image_size(LARGE_IMAGE_PATH + board_image, LARGE_IMAGE_MIN_WIDTH):
valid = False
img.close()
sized_images_missing = not small_image_found and not large_image_found
if REQUIRE_ORIGINAL_IMAGE or sized_images_missing:
if os.path.exists(ORIGINAL_IMAGE_PATH + board_image):
img = Image.open(ORIGINAL_IMAGE_PATH + board_image)
if not verify_image_size(ORIGINAL_IMAGE_PATH + board_image, LARGE_IMAGE_MIN_WIDTH, check_ratio=sized_images_missing):
valid = False
img.close()
else:
if sized_images_missing:
print(f"No images found for {board_id}")
else:
print(f"Original image {ORIGINAL_IMAGE_PATH + board_image} not found for {board_id}.")
valid = False
return valid
def verify_image_size(image_path, min_width, max_width=None, check_ratio=True):
valid = True
img = Image.open(image_path)
width, height = img.size
min_height = int(min_width * MIN_ACCEPTABLE_RATIO)
if width < min_width:
print(f"Image file {image_path} is too narrow ({width} x {height}). It should be at least {min_width} x {min_height} pixels.")
valid = False
elif (max_width and width > max_width):
max_height = int(max_width * MAX_ACCEPTABLE_RATIO)
print(f"Image file {image_path} is too wide ({width} x {height}). It should be no larger than {max_width} x {max_height} pixels.")
valid = False
elif check_ratio and height / width < MIN_ACCEPTABLE_RATIO:
print(f"Ratio for image file {image_path} is too wide ({width} x {height}). Try reducing width or increasing height.")
valid = False
elif check_ratio and height / width > MAX_ACCEPTABLE_RATIO:
print(f"Ratio for image file {image_path} is too tall ({width} x {height}). Try reducing height or increasing width.")
valid = False
img.close()
return valid
success = verify_images("_board") and verify_images("_blinka")
if not success:
print("Missing images or images that do not meet requirements found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/preparing-the-images for images acceptable sizes.")
raise SystemExit(not success)