ã¯ãŒã«ãªã³ãŒããèšè¿°ããããŸããŸãªã¢ã·ã¹ã¿ã³ãããç§ãã¡ããªã³ã¿ãŒãã¿ã€ããŒãè匱æ§ãæ€çŽ¢ããããã®ãŠãŒãã£ãªãã£ããã¹ãŠç§ãã¡ãšå
±ã«åãå²ãã§ããŸãã ç§ãã¡ã¯ããã«æ
£ããŠãããããã©ãã¯ããã¯ã¹ãã®ãããªè©³çŽ°ã«å
¥ããã«äœ¿çšããŠããŸãã ããšãã°ãPythonã³ãŒãã®æé©åãšæ¹åã«äžå¯æ¬ ãªããŒã«ã®1ã€ã§ããPylintã®åçãç解ããŠãã人ã¯ã»ãšãã©ããŸããã
ãããã
ããã·ã ãã¶ãšãã¯èªåã®ããŒã«ãç解ããããšãããã«éèŠããç¥ã£ãŠããã
ã¢ã¹ã¯ã¯Python Conf ++ã§ç§ãã¡ã«èªã£ãã å®éã®äŸã䜿çšããŠã圌ã¯Pylintã®å
éšããã€ã¹ãšãã®ãã©ã°ã€ã³ã®ç¥èãã³ãŒãã¬ãã¥ãŒæéã®ççž®ãã³ãŒãå質ã®åäžããããŠäžè¬çã«éçºå¹çã®åäžã«ã©ã®ããã«åœ¹ç«ã€ãã瀺ããŸããã 以äžã¯åŸ©å·ååœä»€ã§ãã
ãªãPylintãå¿
èŠãªã®ã§ããïŒ
æ¢ã«ããã䜿çšããŠããå ŽåããPylintã®å
éšã«äœãããã®ãââããªããã®ç¥èã圹ç«ã€ã®ãããšããçåãçãããããããŸããã
éåžžãéçºè
ã¯ã³ãŒããèšè¿°ãããªã³ã¿ãŒãèµ·åããæ¹åãã¹ãç¹ãã³ãŒããããçŸããããæ¹æ³ã«ã€ããŠã®ã¡ãã»ãŒãžãåãåããææ¡ãããå€æŽãè¡ããŸãã ããã§ãã³ãŒããèªã¿ããããªããååã«èŠããããšãæ¥ããããšããªããªããŸããã
é·ãéãããã¯åœŒããCIANã®Pylintã§æ£ç¢ºã«æ©èœããæ¹æ³ã§ãããããã€ããŒãªè¿œå ããããŸããïŒæ§æãå€æŽããäžèŠãªã«ãŒã«ãåé€ããæ倧æååé·ãå¢ãããŸããã
ããããããæç¹ã§åœŒãã¯åé¡ã«çŽé¢ããŸããããã®è§£æ±ºã®ããã«ãç§ã¯Pylintã®å¥¥æ·±ããæãäžããŠããããã©ã®ããã«æ©èœããããç解ããªããã°ãªããŸããã§ããã ãã®åé¡ãšããã解決ããæ¹æ³ã¯äœã§ãããèªãã§ãã ããã
ã¹ããŒã«ãŒã«ã€ããŠïŒéçºäžã®5幎éãMaxim MazaevïŒ
ããã¯ã¹ã©ãã·ã¥ ïŒã¯CIANã§åããŠããŸãã Pythonãéåæãããã³é¢æ°åããã°ã©ãã³ã°ãæ·±ãåŠã³ãŸãã
ã·ã¢ã³ã«ã€ããŠ
CIANã¯äžåç£æ¥è
ã®ããäžåç£äŒç€Ÿã§ãããäžåç£æ¥è
ã®ä»£ããã«ããã°ã©ããŒãããããšã«æ°ã¥ãããšããã»ãšãã©ã®äººãä¿¡ããŠããŸãã
ç§ãã¡ã¯å
šç±³ãªã¢ã«ã¿ãŒåäŒå å
¥è
ãããªãæè¡äŒç€Ÿã§ãããå€ãã®ããã°ã©ããŒãããŸãã
- 1æ¥ããã100äžã®ãŠããŒã¯ãŠãŒã¶ãŒã
- ã¢ã¹ã¯ã¯ãšãµã³ã¯ãããã«ãã«ã¯ã§ã®äžåç£ã®è²©å£²ãšã¬ã³ã¿ã«ã®ããã®æ倧ã®æ²ç€ºæ¿ã 2018幎ã圌ãã¯é£éŠã¬ãã«ã«å
¥ãããã·ã¢å
šåã§åããŸããã
- éçºããŒã ã®ã»ãŒ100人ãããã®ãã¡30人ãæ¯æ¥Pythonã³ãŒããèšè¿°ããŠããŸãã
æ¯æ¥ãæ°çŸãæ°åè¡ã®æ°ããã³ãŒããçç£ãããŠããŸãã ã³ãŒãã®èŠä»¶ã¯éåžžã«ç°¡åã§ãã
- ãŸãšããªå質ã®ã³ãŒãã
- æäœçãªåäžæ§ã ãã¹ãŠã®éçºè
ã¯ããªããžããªã«ãvinaigretteããªãã§ãã»ãŒåæ§ã®ã³ãŒããèšè¿°ããå¿
èŠããããŸãã
ãã¡ããããããå®çŸããã«ã¯ãã³ãŒãã¬ãã¥ãŒãå¿
èŠã§ãã
ã³ãŒãã¬ãã¥ãŒ
CIANã®ã³ãŒãã¬ãã¥ãŒã¯2段éã§è¡ãããŸãã
- æåã®æ®µéã¯èªååãããŠããŸãã Jenkinsããããã¯ãã¹ããå®è¡ããPylintãå®è¡ãããã€ã¯ããµãŒãã¹ã䜿çšããŠããããããã€ã¯ããµãŒãã¹éã®APIã®äžè²«æ§ããã§ãã¯ããŸãã ãã®æ®µéã§ãã¹ãã倱æãããããªã³ã¿ãŒã«å¥åŠãªäœãã衚瀺ãããå Žåãããã¯ãã«èŠæ±ãæåŠããä¿®æ£ã®ããã«ã³ãŒããéä¿¡ããæ©äŒã§ãã
- æåã®æ®µéãæåããå Žåã2çªç®ã®æ®µé-2 人㮠éçºè
ããã®æ¿èªã 圌ãã¯ãããžãã¹ããžãã¯ã®èŠ³ç¹ããã³ãŒããã©ãã ãåªããŠããããè©äŸ¡ãããããã«ãªã¯ãšã¹ããæ¿èªããããä¿®æ£ã®ããã«ã³ãŒããè¿ãããããããšãã§ããŸãã
ã³ãŒãã¬ãã¥ãŒã®åé¡
次ã®çç±ã«ããããã«ãªã¯ãšã¹ãã¯ã³ãŒãã¬ãã¥ãŒã«åæ Œããªãå ŽåããããŸãã
- éçºè
ãåé¡ãå¹æçãŸãã¯èª€ã£ãŠè§£æ±ºããå Žåã®ããžãã¹ããžãã¯ã®ãšã©ãŒã
- ã³ãŒãã¹ã¿ã€ã«ã®åé¡ã
ãªã³ã¿ãŒãã³ãŒãããã§ãã¯ããå Žåãã¹ã¿ã€ã«ã®åé¡ã¯äœã§ããïŒ
Pythonã§æžã人ã¯èª°ã§ãã
PEP-8ã³ãŒããæžãããã®ã¬ã€ããããããšãç¥ã£ãŠããŸãã ä»ã®æšæºãšåæ§ã«ãPEP-8ã¯éåžžã«äžè¬çã§ãããéçºè
ãšããŠã®ç§ãã¡ã«ãšã£ãŠããã¯ååã§ã¯ãããŸããã äžéšã®å Žæã§æšæºãæå®ããä»ã®å Žæã§æ¡åŒµãããã
ãã®ãããã³ãŒãã®å€èŠ³ãšåäœãå
éšã§èª¿æŽãã
ãDecline Cian ProposalsããšåŒã³ãŸããã
ãDecline Cian Proposalsã-äžé£ã®ã«ãŒã«ãçŸåšã¯çŽ15ãããŸãããããã®åã«ãŒã«ã¯ããã«ãªã¯ãšã¹ããæåŠãããä¿®æ£ã®ããã«éä¿¡ãããããã®åºç€ã§ãã
çç£çãªã³ãŒãã¬ãã¥ãŒã劚ãããã®ã¯äœã§ããïŒ
ç§ãã¡ã®å
éšã«ãŒã«ã«ã¯1ã€ã®åé¡ããããŸã-ãªã³ã¿ãŒã¯ãããã«ã€ããŠç¥ããŸããããããŠåœŒãç¥ã£ãŠãããå¥åŠã§ã-ãããã¯å
éšã§ãã
ã¿ã¹ã¯ãå®è¡ããéçºè
ã¯ãåžžã«ã«ãŒã«ãèŠããŠããå¿
èŠããããŸãã ã«ãŒã«ã®1ã€ãå¿ãããšãã³ãŒãã¬ãã¥ãŒã®ããã»ã¹ã§ã¬ãã¥ã¢ãŒãåé¡ãææããã¿ã¹ã¯ã¯æ¹èšã«é²ã¿ãã¿ã¹ã¯ã®ãªãªãŒã¹æéãé·ããªããŸãã ãšã©ãŒã®ä¿®æ£ãšä¿®æ£ã®åŸããã¹ã¿ãŒã¯ã¿ã¹ã¯ã®å
容ãèŠããŠãã³ã³ããã¹ããåãæ¿ããå¿
èŠããããŸãã
ããã«ãããéçºè
ãšã¬ãã¥ãŒã¢ã®äž¡æ¹ã«åé¡ãçºçããŸãã ãã®çµæãã³ãŒãã¬ãã¥ãŒã®é床ã倧å¹
ã«äœäžããŸãã ã³ãŒãã®ããžãã¯ãåæãã代ããã«ããã¹ã¿ãŒã¯èŠèŠã¹ã¿ã€ã«ã®åæãéå§ããŸããã€ãŸãããªã³ã¿ãŒã®äœæ¥ãå®è¡ããŸããã€ãŸããã³ãŒãã1è¡ãã€ã¹ãã£ã³ããã€ã³ããŒã圢åŒã®ã€ã³ãã³ãã®äžäžèŽãæ¢ããŸãã
ãã®åé¡ãåãé€ãããã§ãã
ããããç§ãã¡ã«ããªãã®ãªã³ã¿ãŒãæžããŠã¯ãããŸãããïŒ
ãã®åé¡ã¯ããã¹ãŠã®å
éšåæã«ã€ããŠç¥ã£ãŠããããŒã«ã«ãã£ãŠè§£æ±ºãããå®è£
ã®ã³ãŒãããã§ãã¯ã§ããããã«ãªããŸãã ç¬èªã®ãªã³ã¿ãŒãå¿
èŠã§ããïŒ
ããã§ããªãã ãã§ã«Pylintã䜿çšããŠããããããã®ã¢ã€ãã¢ã¯éŠ¬é¹¿ããŠããŸãã ããã¯äŸ¿å©ãªãªã³ã¿ãŒã§ãããéçºè
ã«å¥œãŸãããã¹ãŠã®ããã»ã¹ã«çµã¿èŸŒãŸããŠããŸãããžã§ã³ãã³ã¹ã§å®è¡ãããå®å
šã«æºè¶³ã®ããçŸããã¬ããŒããçæããã³ã¡ã³ãã®åœ¢ã§ãªã¯ãšã¹ãããã«ããŸãã ãã¹ãŠãæ£åžžã§ã
2çªç®ã®ãªã³ã¿ãŒã¯å¿
èŠãããŸãã ã
ããã§ã¯ãèªåã®ãªã³ã¿ãŒãæžããããªãå Žåãã©ã®ããã«åé¡ã解決ããã®ã§ããããïŒ
Pylintãã©ã°ã€ã³ãæžã
Pylintçšã®ãã©ã°ã€ã³ãäœæã§ããŸãããããã¯ãã§ãã«ãŒãšåŒã°ããŸãã åå
éšã«ãŒã«ã®äžã§ãããããã§ãã¯ããç¬èªã®ãã§ãã«ãŒãäœæã§ããŸãã
ãã®ãããªãã§ãã«ãŒã®2ã€ã®äŸãèããŠã¿ãŸãããã
äŸ1
ããæç¹ã§ãã³ãŒãã«ã¯ãTODOããšãã圢åŒã®å€ãã®ã³ã¡ã³ããå«ãŸããŠããããšãå€æããŸããããªãã¡ã¯ã¿ãªã³ã°ãäžèŠãªã³ãŒãã®åé€ããŸãã¯çŸããæžãçŽãããšãçŽæããŸãã ãã®ãããªã³ã¡ã³ãã«ã¯åé¡ããããŸã-圌ãã¯ããªãã«äœã矩åä»ããŸããã
åé¡
éçºè
ã¯çŽæãæžããåãåºããå®å¿ããŠæ¬¡ã®ã¿ã¹ã¯ãå®è¡ããŸããã
èŠçŽãããšïŒ
- çŽæã®ããã³ã¡ã³ãã¯é·å¹Žã«ããã£ãŠç¶ããåŸããªãã
- ã³ãŒããæ£ãã°ã£ãŠããŸãã
- æè¡çãªè² åµã¯äœå¹Žãç©ã¿äžããããŠããŸããã
ããšãã°ã3幎åã®éçºè
ã¯ããªãªãŒã¹ãæåããåŸã«äœããåé€ããããšãçŽæããŸãããããªãªãŒã¹ã¯3幎ã§è¡ãããŸãããïŒ ãã¶ãã¯ãã ãã®å Žåãã³ãŒããåé€ããå¿
èŠããããŸããïŒ ããã¯å€§ããªè³ªåã§ãããããããããã§ã¯ãããŸããã
解決çïŒPylintã®ãã§ãã«ãŒãäœæãã
éçºè
ããã®ãããªã³ã¡ã³ããæžãããšãçŠæ¢ããããšã¯ã§ããŸããããè¿œå ã®äœæ¥ããããããšãã§ããŸãããã©ãã«ãŒã§ã¿ã¹ã¯ãäœæããŠçŽæã確å®ããŸãã ãã®åŸãç§ãã¡ã¯åœŒå¥³ã®ããšãééããªãå¿ããŸããã
TODOãã©ãŒã ã®ãã¹ãŠã®ã³ã¡ã³ããèŠã€ããåã³ã¡ã³ãã«Jiraã®ã¿ã¹ã¯ãžã®ãªã³ã¯ãããããšã確èªããå¿
èŠããããŸãã æžããŸãããã
Pylintã«é¢ãããã§ãã«ãŒãšã¯äœã§ããïŒ ããã¯ããã§ãã«ãŒã®åºæ¬ã¯ã©ã¹ããç¶æ¿ããç¹å®ã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¯ã©ã¹ã§ãã
class TodoIssueChecker(BaseChecker): _ _implements_ _ = IRawChecker
ç§ãã¡ã®å Žåãããã¯
IRawChecker-ãããããçããã§ãã«ãŒã§ãã
çã®ãã§ãã«ãŒã¯ãã¡ã€ã«ã®è¡ãå埩åŠçããè¡ã«å¯ŸããŠç¹å®ã®ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã ãã®å Žåãåè¡ã§ãã§ãã«ãŒã¯ã³ã¡ã³ããšã¿ã¹ã¯ãžã®ãªã³ã¯ã«äŒŒããã®ãæ¢ããŸãã
ãã§ãã«ãŒã®å Žåãçºè¡ããã¡ãã»ãŒãžã®ãªã¹ãã決å®ããå¿
èŠããããŸãã
msgs = { '9999': (' TODO ', issue-code-in-todo', ' ')}
ã¡ãã»ãŒãžã«ã¯æ¬¡ã®ãã®ããããŸãã
- 説æã¯çããŠé·ãã§ãã
- ãã§ãã«ãŒã³ãŒããšããããã©ã®ãããªã¡ãã»ãŒãžã§ãããã決å®ããçãããŒã¢ããã¯åã
ã¡ãã»ãŒãžã³ãŒãã®åœ¢åŒã¯ãC1234ãã§ãã
- æåã®æåã¯ãããŸããŸãªã¿ã€ãã®ã¡ãã»ãŒãžã«å¯ŸããŠæ確ã«æšæºåãããŠããŸãã [W]èŠåã [E]ãšãŒã°; [F] atal; [R] efactoringã æçŽã®ãããã§ãå ±åæžã¯äœãèµ·ãã£ãŠããã®ããå³åº§ã«ç€ºããŠããŸããç·æ¥ã«å¯ŸåŠããå¿
èŠãããåæãèŽåœçãªåé¡ãæãåºããããã®ã§ãã
- Pylintã«åºæã®4ã€ã®ä¹±æ°ã
ãã§ãã¯ãäžèŠã«ãªã£ãå Žåããã§ãã¯ãç¡å¹ã«ããããã«ã³ãŒããå¿
èŠã§ãã PylintïŒdisableãšçãè±æ°åã³ãŒããŸãã¯ããŒã¢ããã¯åãæžãããšãã§ããŸãïŒ
Pylintã®èè
ã¯ãè±æ°åã³ãŒããæŸæ£ããããŒã¢ããã¯ã䜿çšããããšãæšå¥šããŠããŸããããã¯ããèŠèŠçã§ãã
次ã®ã¹ãããã¯ã
process_moduleãšããã¡ãœãããå®çŸ©ããããšã§ãã
ååã¯éåžžã«éèŠã§ãã Pylintãã¡ãœãããåŒã³åºããããã¡ãœããã¯ãã®ããã«åŒã³åºãå¿
èŠããããŸãã
nodeãã©ã¡ãŒã¿ãŒã¯ã¢ãžã¥ãŒã«ã«æž¡ãããŸãã ãã®å Žåããããäœã§ãããããŸãã¯ã©ã®ã¿ã€ãã§ãããã¯é¢ä¿ãããŸãããããŒãã«ã¯ãè¡ããšã«ãã¡ã€ã«ãè¿ã
ã¹ããªãŒã ã¡ãœãããããããšãèŠããŠããããšãéèŠã§ãã
ãã¡ã€ã«ã調ã¹ãŠãåè¡ã§ã³ã¡ã³ããšã¿ã¹ã¯ãžã®ãªã³ã¯ã確èªã§ããŸãã ã³ã¡ã³ãã¯ããããªã³ã¯ããªãå Žåã¯ããã§ãã«ãŒã³ãŒããšè¡çªå·ãå«ã
ãissue-code-in-todoããã©ãŒã
ã®èŠåãã¹ããŒããŸãã ã¢ã«ãŽãªãºã ã¯éåžžã«ç°¡åã§ãã
ãã§ãã«ãŒãç»é²ããŠãPylintãèªèã§ããããã«ããŸãã ããã¯ã
ç»é²æ©èœã«ãã£ãŠè¡ãããŸãã
def register(linter: Pylinter) -> None: linter. register_checker ( TodoIssueChecker(linter) )
- Pylintã®ã€ã³ã¹ã¿ã³ã¹ãé¢æ°ã«å
¥ããŸãã
- register_checkerã¡ãœãããåŒã³åºããŸãã
- ã¡ãœããã«ãã§ãã«ãŒãæž¡ããŸãã
éèŠãªãã€ã³ãïŒãã§ãã«ãŒã¢ãžã¥ãŒã«ã¯Pylthonpathã«ååšããŠããå¿
èŠããããŸããããã«ãããPylintã¯åŸã§ãããã€ã³ããŒãã§ããŸãã
ç»é²ããããã§ãã«ãŒã¯ãã¿ã¹ã¯ãžã®ãªã³ã¯ã®ãªãã³ã¡ã³ãä»ãã®ãã¹ããã¡ã€ã«ã«ãã£ãŠãã§ãã¯ãããŸãã
$ cat work.
ãã¹ãã®ããã«ãPylintãå®è¡ããã¢ãžã¥ãŒã«ãæž¡ãã
load-pluginsãã©ã¡ãŒã¿ãŒã䜿çšããŠãã§ãã«ãŒã転éãããªã³ã¿ãŒå
ã§2ã€ã®ãã§ãŒãºãå®è¡ããŸãã
ãã§ãŒãº1.ãã©ã°ã€ã³ã®åæå
- ãã©ã°ã€ã³ãå«ããã¹ãŠã®ã¢ãžã¥ãŒã«ãã€ã³ããŒããããŸãã Pylintã«ã¯ãå
éšãã§ãã«ãŒãšå€éšãã§ãã«ãŒããããŸãã ãããã¯ãã¹ãŠäžç·ã«ãªã£ãŠã€ã³ããŒããããŸãã
- ç»é²-module.registerïŒselfïŒ ã åãã§ãã«ãŒã«å¯ŸããŠãPylintã€ã³ã¹ã¿ã³ã¹ãæž¡ãããregisteré¢æ°ãåŒã³åºãããŸãã
- ãã§ãã¯ãå®è¡ãããŸãïŒãã©ã¡ãŒã¿ãŒã®æå¹æ§ãã¡ãã»ãŒãžããªãã·ã§ã³ãããã³æ£ãã圢åŒã®ã¬ããŒãã®ååšã
ãã§ãŒãº2.ãã§ãã«ãŒã®ããŒã«ã解æãã
ãã§ãŒãº1ã®åŸãããŸããŸãªçš®é¡ã®ãã§ãã«ãŒã®å®å
šãªãªã¹ããæ®ããŸãã
- ASTãã§ãã«ãŒ
- çãã§ãã«ãŒã
- ããŒã¯ã³ãã§ãã«ãŒã
ãªã¹ããããæªå å·¥ã®ãã§ãã«ãŒã€ã³ã¿ãŒãã§ã€ã¹ã«é¢é£ãããã®ãéžæããŸããã©ã®ãã§ãã«ãŒãIRawCheckerã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŠãããã確èªããããããèªåçšã«åããŸãã
éžæãããã§ãã«ãŒããšã«ã
checker.process_moduleïŒã¢ãžã¥ãŒã«ïŒã¡ãœãããåŒã³åºããŠããã§ãã¯ãå®è¡ããŸãã
çµæ
ãã¹ããã¡ã€ã«ã§ãã§ãã«ãŒãå床å®è¡ããŸãã
$ cat work.
TODOãå«ãã³ã¡ã³ãããããã¿ã¹ã¯ãžã®ãªã³ã¯ããªãããšã瀺ãã¡ãã»ãŒãžã衚瀺ãããŸãã
ãã®åé¡ã¯è§£æ±ºãããã³ãŒãã¬ãã¥ãŒã®éçšã§ãéçºè
ã¯ç®ã§ã³ãŒããã¹ãã£ã³ããããã³ã¡ã³ããèŠã€ããããã³ãŒãäœæè
ã«åæãããããªã³ã¯ãæ®ãããšããå§ãããããšãæãåºãããå¿
èŠã¯ãããŸããã ãã¹ãŠãèªåçã«è¡ãããã³ãŒãã®ã¬ãã¥ãŒãå°ãéããªããŸãã
äŸ2ãããŒã¯ãŒãåŒæ°
äœçœ®åŒæ°ãåãé¢æ°ããããŸãã å€æ°ã®åŒæ°ãããå Žåãé¢æ°ãåŒã³åºããšãã«ãåŒæ°ãã©ãã«ããã®ãããªãå¿
èŠãªã®ãã¯æ確ã§ã¯ãããŸããã
åé¡
ããšãã°ã次ã®é¢æ°ããããŸãã
get_offer_by_cian_id( "sale", rue, 859483, )
ã³ãŒãã«ã¯
ã»ãŒã«ãš
Trueãããããããã®æå³ãæ確ã§ã¯ãããŸããã å€ãã®åŒæ°ãããé¢æ°ãååä»ãåŒæ°ã§ã®ã¿åŒã³åºãããå Žåã¯ãã¯ããã«äŸ¿å©ã§ãã
get_offer_by_cian_id( deal_type="sale", truncate=True, cian_id=859483, )
ããã¯åªããã³ãŒãã§ããããã©ã¡ãŒã¿ãã©ãã«ããããããã«ããããã·ãŒã±ã³ã¹ãæ··åããŸããã ãã®ãããªå Žåããã§ãã¯ãããã§ãã«ãŒãäœæããŠã¿ãŸãããã
åã®äŸã§äœ¿çšãããçã®ããã§ãã«ãŒã¯ããã®ãããªå Žåã«æžãã®ã¯éåžžã«å°é£ã§ãã è¶
è€éãªæ£èŠè¡šçŸãè¿œå ã§ããŸããããã®ãããªã³ãŒãã¯èªã¿ã«ããã§ãã Pylintãæœè±¡
ASTæ§æããªãŒã«åºã¥ããŠå¥ã®ã¿ã€ãã®ãã§ãã«ãŒãèšè¿°ã§ããããã«ããŠãããã®ã¯è¯ãããšã§ãããããã䜿çšããŸãã
ASTã«é¢ããæè©ã®äœè«
ASTãŸãã¯æœè±¡æ§æããªãŒã¯ã³ãŒãã®ããªãŒè¡šçŸã§ãããé ç¹ã¯ãªãã©ã³ãã§ããããªãŒãã¯æŒç®åã§ãã
ããšãã°ã1ã€ã®äœçœ®åŒæ°ãš2ã€ã®ååä»ãåŒæ°ãããé¢æ°åŒã³åºãã¯ãæœè±¡ããªãŒã«å€æãããŸãã
Callåã®é ç¹ãããã次ã®èŠçŽ ããããŸãã
- funcãšåŒã°ããé¢æ°å±æ§ã
- ã¿ã€ããConstã§å€ã112ã®ããŒããååšããäœçœ®åŒæ°argsã®ãªã¹ãã
- ååä»ãåŒæ°ã®ãªã¹ãããŒã¯ãŒãã
ãã®å Žåã®ã¿ã¹ã¯ïŒ
- ã¢ãžã¥ãŒã«ã§ãã¿ã€ãCallïŒé¢æ°åŒã³åºãïŒãæã€ãã¹ãŠã®ããŒããèŠã€ããŸãã
- é¢æ°ãåãåŒæ°ã®ç·æ°ãèšç®ããŸãã
- 3ã€ä»¥äžã®åŒæ°ãããå Žåã¯ãããŒãã«äœçœ®åŒæ°ããªãããšã確èªããŠãã ããã
- äœçœ®åŒæ°ãããå Žåã¯ãèŠåã衚瀺ããŸãã
ll( func=Name(name='get_offer'), args=[Const(value=1298880)], keywords=[ ⊠]))]
Pylintã®èŠ³ç¹ããèŠããšãASTããŒã¹ã®ãã§ãã«ãŒã¯ããŒã¹ãã§ãã«ãŒã¯ã©ã¹ãç¶æ¿ãã
IAstroidCheckerã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¯ã©ã¹ã§ãã
class NonKeywordArgsChecker(BaseChecker): -_ _implements_ _ = IAstroidChecker
æåã®äŸã®ããã«ããã§ãã«ãŒã®èª¬æãã¡ãã»ãŒãžã³ãŒããçãããŒã¢ããã¯åãã¡ãã»ãŒãžãªã¹ãã«è¡šç€ºãããŸãã
msgs = { '9191': (' ', keyword-only-args', ' ')}
次ã®ã¹ãããã¯
visit_callã¡ãœããã®
å®çŸ©ã§ãïŒ
def visit_call(self, node: Call) âŠ
ãã®ã¡ãœãããåŒã³åºãå¿
èŠã¯ãããŸããã ãã®äžã§æãéèŠãªã®ã¯visit_æ¥é èŸã§ãããããããç§ãã¡ã®èå³ãåŒãé ç¹ã®ååã«å°ããªæåãä»ããŸãã
- ASTããŒãµãŒã¯ããªãŒããŠã©ãŒã¯ã¹ã«ãŒããåé ç¹ã«ã€ããŠããã§ãã«ãŒã«visit_ <Name>ã€ã³ã¿ãŒãã§ã€ã¹ãå®çŸ©ãããŠãããã©ããã確èªããŸãã
- ãããããªãããããåŒã³åºããŸãã
- ãã¹ãŠã®åäŸãååž°çã«ééããŸãã
- ããŒããé¢ãããšããleave_ <Name>ã¡ãœãããåŒã³åºããŸãã
ãã®äŸã§ã¯ãvisit_callã¡ãœããã¯å
¥åãšããŠCallã¿ã€ãããŒããåãåãã3ã€ä»¥äžã®åŒæ°ããããã©ãããããã³èŠåãã¹ããŒããŠã³ãŒããããŒãèªäœã«æž¡ãããã®äœçœ®åŒæ°ããããã©ããã確èªããŸãã
def visit_call(self, n): if node.args and len(node.args + node.keywords) > 2: self.add_message( 'keyword-only-args', node=node )
åã®äŸã®ããã«ãã§ãã«ãŒãç»é²ããŸããPylintã€ã³ã¹ã¿ã³ã¹ã転éããregister_checkerãåŒã³åºãããã§ãã«ãŒèªäœãæž¡ããŠèµ·åããŸãã
def register(linter: Pylinter) -> None: linter.register_checker( TodoIssueChecker(linter) )
ããã¯ã3ã€ã®åŒæ°ãããããã®ãã¡ã®1ã€ã ãã«ååãä»ããããŠãããã¹ãé¢æ°åŒã³åºãã®äŸã§ãã
$ cat work. get_offers(1, True, deal_type="sale") $ Pylint work.py --load-plugins non_kwargs_checker âŠ
ããã¯ãç§ãã¡ã®èŠ³ç¹ãã誀ã£ãŠåŒã³åºãããå¯èœæ§ã®ããé¢æ°ã§ãã Pylintãèµ·åããŸãã
åã®äŸã®ããã«ããã©ã°ã€ã³ã®åæåãã§ãŒãº1ã¯å®å
šã«ç¹°ãè¿ãããŸãã
ãã§ãŒãº2. ASTã§ã®ã¢ãžã¥ãŒã«ã®åæ
ã³ãŒãã¯è§£æãããŠASTããªãŒã«ãªããŸãã åæã¯
Astroidã©ã€ãã©ãªã«ãã£ãŠå®è¡ãã
ãŸã ã
ASTã§ã¯ãªãAstroidã䜿çšããçç±ïŒstdlibïŒ
Astroidã¯å
éšçã«ã¯æšæºã®Python ASTã¢ãžã¥ãŒã«ã䜿çšããŸãããã
typed_aståä»ãASTããŒãµãŒã¯ãPEP 484
åãã³ãããµããŒããããšããç¹ã§ç°ãªããŸãã èå³æ·±ãããšã«ãASTã«ã¯åããã°ãããã䞊è¡ããŠä¿®åŸ©ãããŸãã
from module import Entity def foo(bar):
以åã¯ãAstroidã¯æšæºã®ASTã¢ãžã¥ãŒã«ã䜿çšããŠããŸããããã®ã¢ãžã¥ãŒã«ã§ã¯ã2çªç®ã®Pythonã§äœ¿çšãããŠããã³ã¡ã³ãã§å®çŸ©ãããŠããã¿ã€ãã£ã³ãã䜿çšããåé¡ã«ééããå¯èœæ§ããããŸãã Pylintã䜿çšããŠãã®ãããªã³ãŒãããã§ãã¯ãããšãã€ã³ããŒããããEntityã¯ã©ã¹ã¯ã³ã¡ã³ãå
ã«ã®ã¿ååšãããããç¹å®ã®æç¹ãŸã§ã¯æªäœ¿çšã®ã€ã³ããŒããèªããŸãã
ããæç¹ã§ãGuido Van Rossumã¯GitHubã§Astroidã«æ¥ãŠæ¬¡ã®ããã«èšããŸããã åéã«ãªããïŒã
ä»äºãå§ãŸã£ãïŒ 2幎ãçµã¡ããã®æ¥ã®Pylintã¯æ¢ã«åä»ãASTããŒãµãŒã«åãæ¿ãããã®ãããªããšãèªãããšããããŸããã taiphintsã®ã€ã³ããŒãã¯ãæªäœ¿çšãšããŠããŒã¯ãããªããªããŸããã
Astroidã¯ASTããŒãµãŒã䜿çšããŠã³ãŒããããªãŒã«è§£æããæ§ç¯æã«èå³æ·±ãããšãè¡ããŸãã ããšãã°ã
import *ã䜿çšããå Žåããã¹ãŠãã¢ã¹ã¿ãªã¹ã¯ã§ã€ã³ããŒãããããŒã«ã«ã«è¿œå ããŠãæªäœ¿çšã®ã€ã³ããŒãã§ã®ãšã©ãŒãé²ããŸãã
å€æãã©ã°ã€ã³ã¯ããã¹ãŠã®å±æ§ãåçã«çæãããã¡ã¿ã¯ã©ã¹ã«åºã¥ããããã€ãã®è€éãªã¢ãã«ãããå Žåã«äœ¿çšãããŸãã ãã®å ŽåãAstroidã®æå³ãç解ããã®ã¯éåžžã«å°é£ã§ãã ãã§ãã¯ãããšãPylintã¯ãã¢ãã«ã«ã¢ã¯ã»ã¹ãããšãã«ãã®ãããªå±æ§ããªãããšãèªããTransformãã©ã°ã€ã³ã䜿çšããŠåé¡ã解決ã§ããŸãã
- Astroidãæœè±¡ããªãŒãå€æŽããPythonã®åçãªæ§è³ªãç解ããã®ã«åœ¹ç«ã¡ãŸãã
- ASTã«åœ¹ç«ã€æ
å ±ãè¿œå ããŸãã
å
žåçãªäŸã¯ã
pylint-djangoã§ãã è€éãªdjangoã¢ãã«ã§äœæ¥ãããšãããªã³ã¿ãŒã¯ãã°ãã°æªç¥ã®å±æ§ãèªããŸãã Pylint-djangoã¯ãã®åé¡ã解決ããã ãã§ãã
ãã§ãŒãº3.ãã§ãã«ãŒã®ããŒã«ã解æãã
ãã§ãã«ãŒã«æ»ããŸãã å床ãã§ãã«ãŒã®ãªã¹ãããããããããASTãã§ãã«ãŒã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãããã§ãã«ãŒãèŠã€ãããŸãã
ãã§ãŒãº4.ããŒãã®ã¿ã€ãå¥ã«ãã§ãã«ãŒã解æãã
次ã«ãåãã§ãã«ãŒã®ã¡ãœãããèŠã€ããŸãã2ã€ã®ã¿ã€ãããããŸãã
- visit_ <ããŒãå>
- lev_<ããŒãå>ã
ããªãŒå
ãæ©ããŠãããšãã«ããŒããåŒã³åºãå¿
èŠãããããŒããç¥ã£ãŠãããšäŸ¿å©ã§ãã ãããã£ãŠãããŒã¯ããŒãã®ååã§ãããå€ã¯ãã®ããŒããžã®ã¢ã¯ã»ã¹ã®äºå®ã«é¢å¿ããããã§ãã«ãŒã®ãªã¹ãã§ããèŸæžãç解ããŸãã
_visit_methods = dict( < > : [checker1, checker2 ... checkerN] )
leave-methodsã§ãåãã§ããããŒãåã®åœ¢åŒã®ããŒããã®ããŒãããã®éåºã®äºå®ã«é¢å¿ã®ãããã§ãã«ãŒã®ãªã¹ãã
_leave_methods = dict( < >: [checker1, checker2 ... checkerN] )
Pylintãèµ·åããŸãã 3ã€ä»¥äžã®åŒæ°ãããããã®äžã«äœçœ®åŒæ°ãããé¢æ°ããããšããèŠåã瀺ããŠããŸãã
$ cat work. get_offers(1, True, deal_type="sale") $ Pylint work.py --load-plugins non_kwargs_checker C: 0, 0: c >2 (keyword-only-args)
åé¡ã¯è§£æ±ºããŸããã ããã§ãã³ãŒãã¬ãã¥ãŒããã°ã©ããŒã¯é¢æ°ã®åŒæ°ãèªã¿åãå¿
èŠããªããªãããªã³ã¿ãŒããããè¡ããŸãã æ¬çªç°å¢ã§ã®æéãã³ãŒãã®ã¬ãã¥ãŒãã¿ã¹ã¯ã®æé
ãç¯çŽããŸããã
ãããŠããã¹ããæžãããã«ïŒ
Pylintã䜿çšãããšããã§ãã«ãŒã®åäœãã¹ããå®è¡ã§ããéåžžã«ç°¡åã§ãã ãªã³ã¿ãŒã®èŠ³ç¹ããèŠããšããã¹ããã§ãã«ãŒã¯æœè±¡
CheckerTestCaseãç¶æ¿ããã¯ã©ã¹ã®ããã«èŠããŸãã ãã§ãã¯ã€ã³ãããŠãããã§ãã«ãŒã瀺ãå¿
èŠããããŸãã
class TestNonKwArgsChecker(CheckerTestCase): CHECKER_CLASS = NonKeywordArgsChecker
ã¹ããã1.ãã§ãã¯ããã³ãŒãã®äžéšãããã¹ãASTããŒããäœæããŸãã
node = astroid.extract_node( "get_offers(3, 'magic', 'args')" )
æé 2.ããŒãã«å
¥ããã§ãã«ãŒãã察å¿ããã¡ãã»ãŒãžãã¹ããŒãããããªããã確èªããŸãã
with self.assertAddsMessages(message): self.checker.visit_call(node)
ããŒã¯ã³ãã§ãã«ãŒ
TokenCheckerãšåŒã°ããå¥ã®ã¿ã€ãã®ãã§ãã«ãŒããããŸãã åå¥è§£æã®åçã§åäœããŸãã Pythonã«ã¯ãåå¥ã¹ãã£ããŒã®æ©èœãå®è¡ããã³ãŒããããŒã¯ã³ã®ãªã¹ãã«åå²ãã
tokenizeã¢ãžã¥ãŒã«ããããŸãã 次ã®ããã«ãªããŸãã
å€æ°åãé¢æ°åãããã³ããŒã¯ãŒãã¯ã¿ã€ãNAMEã®ããŒã¯ã³ã«ãªããåºåãæåãæ¬åŒ§ãã³ãã³ã¯ã¿ã€ãOPã®ããŒã¯ã³ã«ãªããŸãã ããã«ãã€ã³ãã³ããæ¹è¡ãéå€æçšã®åå¥ã®ããŒã¯ã³ããããŸãã
PylintãTokenCheckerãšé£æºããæ¹æ³ïŒ
- ãã¹ãäžã®ã¢ãžã¥ãŒã«ã¯ããŒã¯ã³åãããŸãã
- ããŒã¯ã³ã®èšå€§ãªãªã¹ããITokenCheckerãå®è£
ãããã¹ãŠã®ãã§ãã«ãŒã«æž¡ããã process_tokens ïŒããŒã¯ã³ïŒã¡ãœãããåŒã³åºãããŸãã
TokenCheckerã®äœ¿çšã¯èŠã€ãããŸããã§ããããPylintã䜿çšãããã®ãããªäŸããããŸãã
- ã¹ãã«ãã§ã㯠ã ããšãã°ãããã¹ãã¿ã€ãã®ãã¹ãŠã®ããŒã¯ã³ãååŸããåå¥ãªãã©ã·ãŒã確èªããããã¹ãããã¯ãŒããªã¹ãã®åèªã確èªãããã§ããŸãã
- ã€ã³ãã³ã ãã¹ããŒã¹ã確èªããŠãã ãã ã
- æååãæäœããŸã ã ããšãã°ãPython 3ãUnicodeãªãã©ã«ã䜿çšããŠããªãããšã確èªãããããã€ãæååã«ASCIæåã®ã¿ãååšããããšã確èªãããã§ããŸãã
çµè«
ã³ãŒãã¬ãã¥ãŒã«åé¡ããããŸããã éçºè
ã¯ãªã³ã¿ãŒã®ä»äºãããç¡æå³ãªã³ãŒãã¹ãã£ã³ã«æéãè²»ãããäœè
ã«ãšã©ãŒãéç¥ããŸããã Pylintã®å ŽåïŒ
- å®æç¹æ€ããªã³ã¿ãŒã«ç§»ããå
éšå¥çŽãå®æœããŸããã
- ã³ãŒãã¬ãã¥ãŒã®é床ãšå質ã®åäžã
- æåŠããããã«ãªã¯ãšã¹ãã®æ°ãæžãããæ¬çªç°å¢ã§ã¿ã¹ã¯ãæž¡ãæéãççž®ããŸããã
ç°¡åãªãã§ãã«ãŒã¯30åã§æžãããè€éãªãã§ãã«ãŒã¯æ°æéã§æžãããŸãã ãã§ãã«ãŒã¯ãæžã蟌ã¿ã«ãããæéãããã¯ããã«å€ãã®æéãç¯çŽããæåŠãããŠããªãããã€ãã®ãã«ãªã¯ãšã¹ãã«å¯ŸåŠããŸãã
Pylintã®è©³çŽ°ãšãã§ãã«ãŒã®äœææ¹æ³ã«ã€ããŠã¯
å
¬åŒããã¥ã¡ã³ãã§åŠã¶ããšãã§ããŸããããã§ãã«ãŒã®äœæãšããç¹ã§ã¯ããªã貧匱ã§ãã ããšãã°ãTokenCheckerã«ã€ããŠã¯èšåãããŠããã ãã§ããããã§ãã«ãŒèªäœã®èšè¿°æ¹æ³ã«ã€ããŠã¯èšåãããŠããŸããã 詳现ã«ã€ããŠã¯
ãGitHubã®PylintãœãŒã¹ãåç
§ããŠãã ãã ã æšæºããã±ãŒãžã«å«ãŸããŠãããã§ãã«ãŒã確èªããç¬èªã®ãã§ãã«ãŒãäœæããããã®ã€ã³ã¹ãã¬ãŒã·ã§ã³ãåŸãããšãã§ããŸãã
Pylintã®å
éšèšèšã«é¢ããç¥èã«ãããå·¥æ°ãåæžãããç°¡çŽ åãããŸã
ããã©ãŒãã³ã¹ãšã³ãŒãã®æ¹åã æéãç¯çŽããè¯ãã³ãŒããæžãã
ãªã³ã¿ãŒã䜿çšããŸãã次ã®ã¢ã¹ã¯ã¯Python Conf ++ã«ã³ãã¡ã¬ã³ã¹ã¯2019幎4æ5æ¥ã«éå¬ãã ãä»ã§ã¯æ©æbirfãã±ãããäºçŽã§ããŸãã æèŠãéããŠã¬ããŒãã«ç³ã蟌ããš ã蚪åãç¡æã«ãªããã¬ããŒãã®æºåã«é¢ããã³ãŒãã³ã°ãå«ãçŽ æµãªãã³ãããŒãã¹ãšããŠéãããŸãã
ç§ãã¡ã®äŒè°ã¯ãå¿ãåãããã人ã
ãç£æ¥ãšã³ãžã³ãšã®åºäŒãã®ããã®ãã©ãããã©ãŒã ã§ãããPythonéçºè
ãæãããã®ïŒããã¯ãšã³ããšãŠã§ããããŒã¿åéãšåŠçãAI / MLããã¹ããIoTãªã©ã«ã€ããŠè©±ãåããè°è«ããããã®ãã©ãããã©ãŒã ã§ãã ç§ã®æ§åã¯ã Pythonãã£ã³ãã«ã® ãããªã¬ããŒããã芧ã«ãªãããã£ã³ãã«ã«ç»é²ããŠãã ãããè¿æ¥äžã«ã«ã³ãã¡ã¬ã³ã¹ããã®æé«ã®ã¬ããŒããç¡æã§ã¢ã¯ã»ã¹ã§ããããã«æçš¿ããŸãã