Package: hyperstyle
HyperstyleA tool for running a set of pre-configured linters and evaluating code quality.
It is used on theHyperskillplatform
to check the quality of learners' code.Read more detail about the project at Hyperskill Help CenterThe dockerized versionWhat it does:Runs linters for several programming languages and parses their output;Prints the result using a unified JSON-based format;Evaluates the code quality value (EXCELLENT,GOOD,MODERATE, orBAD)
based on the linters' output and some heuristics.License and 3rd party softwareThe source code ofhyperstyleis distributed under the Apache 2.0 License.The 3rd party software we use in this project has its own licenses.Python language (all versions can be found in therequirements.txtfile):flake8 [MIT]Site and docsRepositoryPylint [GNU LGPL v2]Site and docsRepositoryRadon [MIT]Site and docsRepositoryJava language:PMD [BSD] (Version: 6.37.0)Site and docsRepositoryCheckstyle [GNU LGPL v2.1] (Version: 8.44)Site and docsRepositoryKotlin language:Detekt [Apache 2.0] (Version: 1.14.2)Site and docsRepositoryJavaScript language:ESlint [MIT] (Version: 7.5.0)Site and docsRepositoryGo language:golangci-lint [GNU GPL v3.0] (Version: 1.49.0)Site and docsRepositoryInstallationYou have to create set of environment variables:CHECKSTYLE_VERSION(the value of the variable must be the same with its value inDockerfile)CHECKSTYLE_DIRECTORY(the directory withCHECKSTYLElinter sources)DETEKT_VERSION(the value of the variable must be the same with its value inDockerfile)DETEKT_DIRECTORY(the directory withDETEKTlinter sources)PMD_VERSION(the value of the variable must be the same with its value inDockerfile)PMD_DIRECTORY(the directory withPMDlinter sources)GOLANG_LINT_VERSION(the value of the variable must be the same with its value inDockerfile)GOLANG_LINT_DIRECTORY(the directory withGOLANG_LINTlinter sources)Using scriptJust run the following command:./setup_environment.shand install everything the script suggests.Note: You can also use this script to update linters. To do this, just update the corresponding
linter version variables, run the script, and reinstall only the necessary linters.ManuallyIf you don't want to use the script, you can install the environment manually.Simply clone the repository and run the following commands:pip install -r requirements.txtpip install -r requirements-test.txtfor testsnpm install eslint@7.5.0 -g && eslint --initYou can download all linters sources manually or by the following commands:CHECKSTYLE:curl-Lhttps://github.com/checkstyle/checkstyle/releases/download/checkstyle-${CHECKSTYLE_VERSION}/checkstyle-${CHECKSTYLE_VERSION}-all.jar>${CHECKSTYLE_DIRECTORY}/checkstyle-${CHECKSTYLE_VERSION}-all.jarDETEKT:curl-sSLOhttps://github.com/detekt/detekt/releases/download/v${DETEKT_VERSION}/detekt-cli-${DETEKT_VERSION}.zip\&&unzipdetekt-cli-${DETEKT_VERSION}.zip-d${DETEKT_DIRECTORY}\&&curl-H"Accept: application/zip"https://repo.maven.apache.org/maven2/io/gitlab/arturbosch/detekt/detekt-formatting/${DETEKT_VERSION}/detekt-formatting-${DETEKT_VERSION}.jar-o${DETEKT_DIRECTORY}/detekt-formatting-${DETEKT_VERSION}.jarPMD:curl-sSLOhttps://github.com/pmd/pmd/releases/download/pmd_releases/${PMD_VERSION}/pmd-bin-${PMD_VERSION}.zip\&&unzippmd-bin-${PMD_VERSION}.zip-d${PMD_DIRECTORY}GOLANG_LINT:curl-sSfLhttps://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh|sh-s---b${GOLANG_LINT_DIRECTORY}v${GOLANG_LINT_VERSION}Using dockerAlternatively, you can build a docker image byDockerfileand run the tool inside this image.
Or use the public docker image, that we use in thebuild.ymlfile.UsageRun therun_tool.pywith the arguments.A simple configuration:python run_tool.py <path>.Required arguments:path— path to file or directory to inspect.Optional arguments:ArgumentDescription‑h,‑‑helpshow the help message and exit.‑v,‑‑verbositychoose logging level accordingthislist:1-ERROR;2-INFO;3-DEBUG;0- disable logging (CRITICALvalue); default value is0(CRITICAL).‑d,‑‑disabledisable inspectors. Available values: forPythonlanguage:pylintforPylint,flake8forflake8,radonforRadon,python_astto check different measures providing by AST; forJavalanguage:checkstylefor theCheckstyle,pmdforPMD; forKotlinlanguage: detekt forDetekt; forJavaScriptlanguage:eslintforESlint; forGolanguage:golang_lintforgolangci-lint. Example:-d pylint,flake8.‑‑allow-duplicatesallow duplicate issues found by different linters. By default, duplicates are skipped.‑‑language-version,‑‑language_versionspecify the language version for JAVA inspectors. Available values:java7,java8,java9,java11,java15,java17.Note:‑‑language_versionis deprecated and will be deleted in the future.‑‑n-cpu,‑‑n_cpuspecify number ofcputhat can be used to run inspectors.Note:‑‑n_cpuis deprecated. Will be deleted in the future.‑f,‑‑formatthe output format. Available values:json,text. Default value isjson.‑s,‑‑start-linethe first line to be analyzed. By default it starts from1.‑e,‑‑end-linethe end line to be analyzed. The default value isNone, which meant to handle file by the end.‑‑new-formatthe argument determines whether the tool should use thenew format.New formatmeans separating the result by the files to allow getting quality and observed issues for each file separately. The default value isFalse.‑‑historyJSON string with a list of issues for each language. For each issue its class and quantity are specified. Example:--history "{\"python\": [{\"origin_class\": \"SC200\", \"number\": 20}, {\"origin_class\": \"WPS314\", \"number\": 3}]}"‑‑with‑all‑categoriesWithout this flag, all issues will be categorized into 5 main categories:CODE_STYLE,BEST_PRACTICES,ERROR_PRONE,COMPLEXITY,INFO.‑‑group‑by‑difficultyWith this flag, the final grade and influence on penalty will be grouped by the issue difficulty.‑‑languageSpecify the language to inspect. The tool will check all languages by default. The default value isNone.The output examples:(New formatmeans separating the result by the files to allow getting quality and observed issues for each file separately)Jsonold format(without‑‑new-formatargument):{"quality":{"code":"BAD","text":"Code quality (beta): BAD"},"issues":[{"code":"C002","text":"Too long function. Try to split it into smaller functions / methods.It will make your code easy to understand and less error prone.","line":"<the code line>","line_number":54,"column_number":0,"category":"FUNC_LEN","difficulty":"EASY","influence_on_penalty":0},...]}Jsonnew format(with‑‑new-formatargument):{"quality":{"code":"BAD","text":"Code quality (beta): BAD"},"file_review_results":[{"file_name":"<your file>","quality":{"code":"BAD","text":"Code quality (beta): BAD"},"issues":[{"code":"W0703","text":"Catching too general exception Exception","line":"<the code line>","line_number":174,"column_number":12,"category":"BEST_PRACTICES","difficulty":"MEDIUM","influence_on_penalty":0},...]}]}Jsonold format(with‑‑group‑by‑difficultyargument):{"quality":{"EASY":{"code":"BAD","text":"Code quality (beta): BAD"},"MEDIUM":{"code":"BAD","text":"Code quality (beta): BAD"},"HARD":{"code":"BAD","text":"Code quality (beta): BAD"}},"issues":[{"code":"C002","text":"Too long function. Try to split it into smaller functions / methods.It will make your code easy to understand and less error prone.","line":"<the code line>","line_number":54,"column_number":0,"category":"FUNC_LEN","difficulty":"EASY","influence_on_penalty":{"EASY":0,"MEDIUM":0,"HARD":0}},...]}Jsonnew format(with‑‑group‑by‑difficultyargument){"quality":{"EASY":{"code":"BAD","text":"Code quality (beta): BAD"},"MEDIUM":{"code":"BAD","text":"Code quality (beta): BAD"},"HARD":{"code":"BAD","text":"Code quality (beta): BAD"}},"file_review_results":[{"file_name":"<your file>","quality":{"EASY":{"code":"BAD","text":"Code quality (beta): BAD"},"MEDIUM":{"code":"BAD","text":"Code quality (beta): BAD"},"HARD":{"code":"BAD","text":"Code quality (beta): BAD"}},"issues":[{"code":"W0703","text":"Catching too general exception Exception","line":"<the code line>","line_number":174,"column_number":12,"category":"BEST_PRACTICES","difficulty":"MEDIUM","influence_on_penalty":{"EASY":0,"MEDIUM":0,"HARD":0}},...]}]}Text format:Review of <path to your file or project> (N violations)
***********************************************************************************************************
File <file_name>
-----------------------------------------------------------------------------------------------------------
Line № : Column № : Type     : Inspector  : Origin : Description   : Line         : Path
54     : 0        : FUNC_LEN : PYTHON_AST : C002   : <Description> : <code line > : <path to the file>
...
-----------------------------------------------------------------------------------------------------------
Code quality (beta): BAD
Next level: EXCELLENT
Next level requirements:
FUNC_LEN: 12

***********************************************************************************************************
General quality:
Code quality (beta): BAD
Next level: EXCELLENT
Next level requirements:
FUNC_LEN: 12Tests runningWe usepytestlibrary for tests.Note: If you haveModuleNotFoundErrorwhile you try to run tests, please callpip install -e .before using the test system.Note: We useeslintandopen-jdk 11in the tests. Please, set up the environment before running the tests.
You can see en example of the environment configuration in
theDockerfilefile.Usepytestfrom the root directory to runALLtests.