|
37 | 37 | ERROR_README_MISSING_DISCORD_BADGE = "README missing Discord badge"
|
38 | 38 | ERROR_README_MISSING_RTD_BADGE = "README missing ReadTheDocs badge"
|
39 | 39 | ERROR_README_MISSING_TRAVIS_BADGE = "README missing Travis badge"
|
| 40 | +ERROR_PYFILE_DOWNLOAD_FAILED = "Failed to download .py code file" |
| 41 | +ERROR_PYFILE_MISSING_STRUCT = ".py file contains reference to import ustruct" \ |
| 42 | +" without reference to import struct. See issue " \ |
| 43 | +"https://github.com/adafruit/circuitpython/issues/782" |
40 | 44 | ERROR_MISMATCHED_READTHEDOCS = "Mismatched readthedocs.yml"
|
41 | 45 | ERROR_MISSING_EXAMPLE_FILES = "Missing .py files in examples folder"
|
42 | 46 | ERROR_MISSING_EXAMPLE_FOLDER = "Missing examples folder"
|
|
71 | 75 | ERROR_RTD_MISSING_LATEST_RELEASE = "ReadTheDocs missing the latest release. (Ignore me! RTD doesn't update when a new version is released. Only on pushes.)"
|
72 | 76 | ERROR_DRIVERS_PAGE_DOWNLOAD_FAILED = "Failed to download drivers page from CircuitPython docs"
|
73 | 77 | ERROR_DRIVERS_PAGE_DOWNLOAD_MISSING_DRIVER = "CircuitPython drivers page missing driver"
|
| 78 | +ERROR_UNABLE_PULL_REPO_DIR = "Unable to pull repository directory" |
| 79 | +ERROR_UNABLE_PULL_REPO_EXAMPLES = "Unable to pull repository examples files" |
74 | 80 |
|
75 | 81 | # These are warnings or errors that sphinx generate that we're ok ignoring.
|
76 | 82 | RTD_IGNORE_NOTICES = ("WARNING: html_static_path entry", "WARNING: nonlocal image URI found:")
|
@@ -306,6 +312,27 @@ def validate_readme(repo, download_url):
|
306 | 312 |
|
307 | 313 | return errors
|
308 | 314 |
|
| 315 | +def validate_py_for_ustruct(repo, download_url): |
| 316 | + """ For a .py file, look for usage of "import ustruct" and |
| 317 | + look for "import struct". If the "import ustruct" is |
| 318 | + used with NO "import struct" generate an error. |
| 319 | + """ |
| 320 | + # We use requests because file contents are hosted by githubusercontent.com, not the API domain. |
| 321 | + contents = requests.get(download_url) |
| 322 | + if not contents.ok: |
| 323 | + return [ERROR_PYFILE_DOWNLOAD_FAILED] |
| 324 | + |
| 325 | + errors = [] |
| 326 | + |
| 327 | + lines = contents.text.split("\n") |
| 328 | + ustruct_lines = [l for l in lines if re.match(r"[\s]*import[\s][\s]*ustruct", l)] |
| 329 | + struct_lines = [l for l in lines if re.match(r"[\s]*import[\s][\s]*struct", l)] |
| 330 | + if ustruct_lines and not struct_lines: |
| 331 | + errors.append(ERROR_PYFILE_MISSING_STRUCT) |
| 332 | + |
| 333 | + return errors |
| 334 | + |
| 335 | + |
309 | 336 | def validate_contents(repo):
|
310 | 337 | """Validate the contents of a repository meets current CircuitPython
|
311 | 338 | criteria (within reason, functionality checks are not possible). Expects
|
@@ -373,6 +400,28 @@ def validate_contents(repo):
|
373 | 400 | else:
|
374 | 401 | errors.append(ERROR_MISSING_EXAMPLE_FOLDER)
|
375 | 402 |
|
| 403 | + # first location .py files whose names begin with "adafruit_" |
| 404 | + re_str = re.compile('adafruit\_[\w]*\.py') |
| 405 | + pyfiles = [x["download_url"] for x in content_list if re_str.fullmatch(x["name"])] |
| 406 | + for pyfile in pyfiles: |
| 407 | + # adafruit_xxx.py file; check if for proper usage of ustruct |
| 408 | + errors.extend(validate_py_for_ustruct(repo, pyfile)) |
| 409 | + |
| 410 | + # now location any directories whose names begin with "adafruit_" |
| 411 | + re_str = re.compile('adafruit\_[\w]*') |
| 412 | + for adir in dirs: |
| 413 | + if re_str.fullmatch(adir): |
| 414 | + # retrieve the files in that directory |
| 415 | + dir_file_list = github.get("/repos/" + repo["full_name"] + "/contents/" + adir) |
| 416 | + if not dir_file_list.ok: |
| 417 | + errors.append(ERROR_UNABLE_PULL_REPO_DIR) |
| 418 | + dir_file_list = dir_file_list.json() |
| 419 | + # search for .py files in that directory |
| 420 | + dir_files = [x["download_url"] for x in dir_file_list if x["type"] == "file" and x["name"].endswith(".py")] |
| 421 | + for dir_file in dir_files: |
| 422 | + # .py files in subdirectory adafruit_xxx; check if for proper usage of ustruct |
| 423 | + errors.extend(validate_py_for_ustruct(repo, dir_file)) |
| 424 | + |
376 | 425 | return errors
|
377 | 426 |
|
378 | 427 | def validate_travis(repo):
|
@@ -710,7 +759,7 @@ def print_circuitpython_download_stats():
|
710 | 759 | list_repos_for_errors = [ERROR_NOT_IN_BUNDLE]
|
711 | 760 |
|
712 | 761 | for error in repos_by_error:
|
713 |
| - if len(repos_by_error[error]) == 0: |
| 762 | + if not repos_by_error[error]: |
714 | 763 | continue
|
715 | 764 | print()
|
716 | 765 | error_count = len(repos_by_error[error])
|
|
0 commit comments