|
43 | 43 | from tensorflow_docs.tools.nblint.decorator import Options |
44 | 44 |
|
45 | 45 |
|
| 46 | +def search_wordlist(wordlist, src_str): |
| 47 | + """Search for wordlist entries in text and return set of found items. |
| 48 | +
|
| 49 | + Args: |
| 50 | + wordlist: Dict of word entries and recommendations to search in string. |
| 51 | + src_str: String to search for word entries. |
| 52 | +
|
| 53 | + Returns: |
| 54 | + A dict that is a subset of entries from `wordlist` found in `src_str`. |
| 55 | + """ |
| 56 | + found_words = {} |
| 57 | + for word in wordlist: |
| 58 | + # Word-boundary and ignore between path separator '/'. |
| 59 | + if re.search(rf"[^/]\b{word}\b[^/]", src_str, re.IGNORECASE): |
| 60 | + alt_word = wordlist[word] |
| 61 | + if not alt_word: |
| 62 | + alt_word = "n/a" |
| 63 | + found_words[word] = alt_word |
| 64 | + return found_words |
| 65 | + |
| 66 | + |
46 | 67 | # Acceptable copyright heading for notebooks following this style. |
47 | 68 | copyrights_re = [ |
48 | 69 | r"Copyright 20[1-9][0-9] The TensorFlow\s.*?\s?Authors", |
@@ -339,3 +360,48 @@ def button_r1_extra(args): |
339 | 360 | ) |
340 | 361 | else: |
341 | 362 | return True |
| 363 | + |
| 364 | + |
| 365 | +# Non-exhaustive list: {word: alt-word} (Use False if alt not provided.) |
| 366 | +_SECOND_PERSON_WORDLIST = {"we": "you", "we're": "you are"} |
| 367 | + |
| 368 | + |
| 369 | +@lint( |
| 370 | + message="Prefer second person instead of first person: https://developers.google.com/style/person", |
| 371 | + cond=Options.Cond.ALL) |
| 372 | +def second_person(args): |
| 373 | + """Test for first person usage in doc and recommend second person.""" |
| 374 | + found_words = search_wordlist(_SECOND_PERSON_WORDLIST, args["cell_source"]) |
| 375 | + if found_words: |
| 376 | + words = ", ".join([f"{word} => {alt}" for word, alt in found_words.items()]) |
| 377 | + fail( |
| 378 | + f"Prefer second person instead of first person. Found: {words} in" |
| 379 | + f" {args['cell_source']}" |
| 380 | + ) |
| 381 | + else: |
| 382 | + return True |
| 383 | + |
| 384 | + |
| 385 | +# Non-exhaustive list: {word: alt-word} (Use False if alt not provided.) |
| 386 | +_INCLUSIVE_WORDLIST = { |
| 387 | + "blacklist": "blocked", |
| 388 | + "whitelist": "allowed", |
| 389 | + "master": "primary", |
| 390 | + "slave": "replica", |
| 391 | +} |
| 392 | + |
| 393 | + |
| 394 | +@lint( |
| 395 | + message="Use inclusive language: https://developers.google.com/style/inclusive-documentation", |
| 396 | + cond=Options.Cond.ALL) |
| 397 | +def inclusive_language(args): |
| 398 | + """Test for words found in inclusive wordlist and recommend alternatives.""" |
| 399 | + found_words = search_wordlist(_INCLUSIVE_WORDLIST, args["cell_source"]) |
| 400 | + if found_words: |
| 401 | + words = ", ".join([f"{word} => {alt}" for word, alt in found_words.items()]) |
| 402 | + fail( |
| 403 | + f"Use inclusive language where possible and accurate. Found: {words} in" |
| 404 | + f" {args['cell_source']}" |
| 405 | + ) |
| 406 | + else: |
| 407 | + return True |
0 commit comments