PyReprism 0.1.0__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyreprism-1.0.0/.dockerignore +18 -0
- pyreprism-1.0.0/.github/pyreprism-action.sh +58 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.gitignore +1 -0
- pyreprism-1.0.0/CHANGELOG.md +210 -0
- pyreprism-1.0.0/Dockerfile +36 -0
- pyreprism-1.0.0/PKG-INFO +190 -0
- pyreprism-1.0.0/README.md +474 -0
- pyreprism-1.0.0/action.yml +79 -0
- pyreprism-1.0.0/docs/intro.rst +126 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/pyproject.toml +9 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/__init__.py +45 -3
- pyreprism-1.0.0/src/PyReprism/_parallel.py +47 -0
- pyreprism-1.0.0/src/PyReprism/_tokenops.py +177 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/batch.py +66 -25
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/cli.py +216 -6
- pyreprism-1.0.0/src/PyReprism/clones.py +308 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/pygments_engine.py +24 -8
- pyreprism-1.0.0/src/PyReprism/fingerprints.py +145 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/__init__.py +64 -19
- pyreprism-1.0.0/src/PyReprism/languages/_scanners.py +137 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/actionscript.py +5 -10
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ada.py +3 -11
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/apacheconf.py +5 -9
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/applescript.py +5 -3
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/arduino.py +0 -23
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/arff.py +0 -18
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/asm6502.py +5 -6
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/aspnet.py +3 -31
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/autohotkey.py +5 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/autoit.py +5 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/base.py +232 -29
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bash.py +2 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bro.py +5 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/c.py +1 -1
- pyreprism-1.0.0/src/PyReprism/languages/cobol.py +69 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/coffeescript.py +5 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/cpp.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/crystal.py +4 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/css.py +2 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/docker.py +5 -11
- pyreprism-1.0.0/src/PyReprism/languages/dynamic.py +153 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/eiffel.py +3 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/elixir.py +4 -15
- pyreprism-1.0.0/src/PyReprism/languages/erb.py +29 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/erlang.py +0 -11
- pyreprism-1.0.0/src/PyReprism/languages/flow.py +23 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/fortran.py +0 -11
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/fsharp.py +0 -11
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/gedcom.py +1 -1
- pyreprism-1.0.0/src/PyReprism/languages/generated.py +158 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/gherkin.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/glsl.py +5 -3
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/go.py +7 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/graphql.py +4 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/groovy.py +0 -11
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/hpkp.py +4 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/hsts.py +4 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ichigojam.py +4 -9
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/icon.py +4 -9
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/io.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/java.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/javascript.py +6 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/jsx.py +6 -21
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/less.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/livescript.py +5 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/lua.py +5 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nginx.py +5 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nix.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nsis.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/objectivec.py +0 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/plsql.py +3 -5
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/properties.py +3 -4
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pug.py +3 -4
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/python.py +22 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/qore.py +4 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/roboconf.py +3 -4
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scheme.py +4 -13
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scss.py +3 -4
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/smalltalk.py +7 -13
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sql.py +1 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/stylus.py +0 -11
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/tcl.py +4 -2
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/tsx.py +6 -12
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/typescript.py +6 -1
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/yaml.py +3 -4
- pyreprism-1.0.0/src/PyReprism/metrics.py +101 -0
- pyreprism-1.0.0/src/PyReprism/ngrams.py +169 -0
- pyreprism-1.0.0/src/PyReprism/reporters.py +449 -0
- pyreprism-1.0.0/src/PyReprism/semantic.py +147 -0
- pyreprism-1.0.0/src/PyReprism/syntactic.py +163 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/tokens.py +6 -3
- pyreprism-0.1.0/CHANGELOG.md +0 -78
- pyreprism-0.1.0/PKG-INFO +0 -111
- pyreprism-0.1.0/README.md +0 -246
- pyreprism-0.1.0/docs/intro.rst +0 -53
- pyreprism-0.1.0/src/PyReprism/_tokenops.py +0 -78
- pyreprism-0.1.0/src/PyReprism/languages/erb.py +0 -46
- pyreprism-0.1.0/src/PyReprism/languages/flow.py +0 -30
- pyreprism-0.1.0/src/PyReprism/metrics.py +0 -41
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.flake8 +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/FUNDING.yaml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/scripts/changelog_notes.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/scripts/package_version.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/workflows/ci.yml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/workflows/publish.yml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.pre-commit-hooks.yaml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/.readthedocs.yaml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/CONTRIBUTING.md +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/LICENSE +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/RELEASING.md +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/codecov.yml +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/__main__.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/diffs.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/__init__.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/base.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/regex_engine.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/abap.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/apl.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/asciidoc.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/basic.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/batch.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bison.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/brainfuck.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/clike.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/clojure.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/csharp.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/csp.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/css_extras.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/d.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/dart.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/diff.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/django.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/git.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haml.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/handlebars.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haskell.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haxe.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/html.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/inform7.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ini.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/j.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/jolie.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/json.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/julia.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/keyman.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/kotlin.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/latex.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/liquid.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/lolcode.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/makefile.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markdown.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markup.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markup_templating.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/matlab.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/mel.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/mizar.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/monkey.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/n4js.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nasm.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nim.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ocaml.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/opencl.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/oz.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/parigp.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/parser.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pascal.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/perl.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/php.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/php_extras.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/powershell.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/processing.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/prolog.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/protobuf.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/puppet.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pure.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/q.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/r.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/reason.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/registry.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/renpy.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rest.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rip.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ruby.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rust.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sas.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sass.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scala.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/smarty.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/soy.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/swift.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/textile.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/twig.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vbnet.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/velocity.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/verilog.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vhdl.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vim.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/visual_basic.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/wasam.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/xeora.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/xojo.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/py.typed +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/utils/__init__.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/utils/extension.py +0 -0
- {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/utils/normalizer.py +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Keep the build context small: only pyproject.toml, LICENSE, docs/intro.rst,
|
|
2
|
+
# and src/ are needed to build the wheel (see Dockerfile).
|
|
3
|
+
.git
|
|
4
|
+
.github
|
|
5
|
+
manuscript
|
|
6
|
+
tests
|
|
7
|
+
venv
|
|
8
|
+
.venv
|
|
9
|
+
docs/*
|
|
10
|
+
!docs/intro.rst
|
|
11
|
+
*.egg-info
|
|
12
|
+
__pycache__
|
|
13
|
+
.pytest_cache
|
|
14
|
+
.mypy_cache
|
|
15
|
+
dist
|
|
16
|
+
build
|
|
17
|
+
*.pyc
|
|
18
|
+
.DS_Store
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Entry point for the "PyReprism Clone Gate" composite action (see action.yml).
|
|
3
|
+
# Installs PyReprism from the action's own checked-out source (so the CLI matches
|
|
4
|
+
# the pinned ref), runs `pyreprism clones` with the configured inputs, writes the
|
|
5
|
+
# report, and propagates the duplication-gate exit code.
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
action_path="${GITHUB_ACTION_PATH:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
9
|
+
|
|
10
|
+
extras="accurate"
|
|
11
|
+
if [ "${INPUT_SEMANTIC:-false}" = "true" ]; then
|
|
12
|
+
extras="accurate,ast,semantic"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
venv="${RUNNER_TEMP:-/tmp}/pyreprism-venv"
|
|
16
|
+
echo "::group::Install PyReprism [${extras}]"
|
|
17
|
+
python3 -m venv "$venv"
|
|
18
|
+
"$venv/bin/python" -m pip install --quiet --upgrade pip
|
|
19
|
+
"$venv/bin/python" -m pip install --quiet "${action_path}[${extras}]"
|
|
20
|
+
"$venv/bin/pyreprism" --version
|
|
21
|
+
echo "::endgroup::"
|
|
22
|
+
|
|
23
|
+
# Build the `pyreprism clones` argument list from the inputs.
|
|
24
|
+
args=(clones)
|
|
25
|
+
# Intentionally word-split PATHS and EXTRA_ARGS (space-separated inputs).
|
|
26
|
+
# shellcheck disable=SC2206
|
|
27
|
+
args+=(${INPUT_PATHS:-.})
|
|
28
|
+
args+=(--reporter "${INPUT_REPORTER:-sarif}")
|
|
29
|
+
args+=(--min-tokens "${INPUT_MIN_TOKENS:-50}" --min-lines "${INPUT_MIN_LINES:-5}")
|
|
30
|
+
[ -n "${INPUT_LANG:-}" ] && args+=(--lang "$INPUT_LANG")
|
|
31
|
+
[ "${INPUT_NEAR:-false}" = "true" ] && args+=(--near)
|
|
32
|
+
[ "${INPUT_SEMANTIC:-false}" = "true" ] && args+=(--semantic)
|
|
33
|
+
[ -n "${INPUT_MAX_DUPLICATION:-}" ] && args+=(--max-duplication "$INPUT_MAX_DUPLICATION")
|
|
34
|
+
# shellcheck disable=SC2206
|
|
35
|
+
[ -n "${INPUT_EXTRA_ARGS:-}" ] && args+=(${INPUT_EXTRA_ARGS})
|
|
36
|
+
|
|
37
|
+
out="${INPUT_OUTPUT:-}"
|
|
38
|
+
echo "::group::pyreprism ${args[*]}"
|
|
39
|
+
set +e
|
|
40
|
+
if [ -n "$out" ]; then
|
|
41
|
+
"$venv/bin/pyreprism" "${args[@]}" > "$out"
|
|
42
|
+
code=$?
|
|
43
|
+
cat "$out"
|
|
44
|
+
else
|
|
45
|
+
"$venv/bin/pyreprism" "${args[@]}"
|
|
46
|
+
code=$?
|
|
47
|
+
fi
|
|
48
|
+
set -e
|
|
49
|
+
echo "::endgroup::"
|
|
50
|
+
|
|
51
|
+
if [ -n "$out" ]; then
|
|
52
|
+
echo "report=$out" >> "${GITHUB_OUTPUT:-/dev/null}"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if [ "$code" -ne 0 ]; then
|
|
56
|
+
echo "::error::PyReprism duplication gate failed (exit ${code})."
|
|
57
|
+
fi
|
|
58
|
+
exit "$code"
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PyReprism are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.0.0] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
The first stable release. The public API (the top-level functions, the
|
|
13
|
+
language classes, `Token`/`TokenType`, `CodeStats`, and the `batch`, `diffs`,
|
|
14
|
+
`fingerprints`, `ngrams`, `clones`, `reporters`, `syntactic`, and `semantic`
|
|
15
|
+
modules) and the `pyreprism` command line now follow semantic versioning:
|
|
16
|
+
breaking changes only in a new major version. This release adds located clone
|
|
17
|
+
detection with CI reports, optional syntactic and semantic tiers, and parallel
|
|
18
|
+
processing; makes tokenization several times faster; and fixes the lexer
|
|
19
|
+
defects found by validating token classes against tree-sitter parses on a
|
|
20
|
+
project-stratified sample of open-source code.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- **Located clones and reports** (`PyReprism.clones`, `PyReprism.reporters`):
|
|
24
|
+
`clones.detect()` finds which line ranges are duplicated between files
|
|
25
|
+
(Rabin-Karp over the normalized token stream, with jscpd-style
|
|
26
|
+
`min_tokens`/`min_lines` floors), optionally adds Type-3 near-duplicate files
|
|
27
|
+
(`near=True`) and Type-4 semantic clones (`semantic=True`), and reports the
|
|
28
|
+
percentage of duplicated lines. Reporters render console, JSON, SARIF (one
|
|
29
|
+
rule id per clone kind), Markdown, and a self-contained HTML page. CLI:
|
|
30
|
+
`pyreprism clones --reporter ... --max-duplication PCT` (non-zero exit above
|
|
31
|
+
the threshold, for CI).
|
|
32
|
+
- **Syntactic tier** (`PyReprism.syntactic`, `pip install "PyReprism[ast]"`):
|
|
33
|
+
tree-sitter ASTs for exact cyclomatic complexity and per-function metrics
|
|
34
|
+
(`cyclomatic()`, `functions()`).
|
|
35
|
+
- **Semantic tier** (`PyReprism.semantic`, `pip install "PyReprism[semantic]"`):
|
|
36
|
+
code embeddings for Type-4 clone detection (`embed()`, `similarity()`, and an
|
|
37
|
+
`EmbeddingIndex` mirroring `FingerprintIndex`).
|
|
38
|
+
- **GitHub Action** (`action.yml`, "PyReprism Clone Gate") and a `Dockerfile`
|
|
39
|
+
for the CLI, to gate pull requests on duplication.
|
|
40
|
+
- Parallel processing: `jobs=` on `batch.analyze`, `batch.transform`, and
|
|
41
|
+
`clones.detect`, and a new `batch.map_files(paths, fn, jobs=...)` that runs any
|
|
42
|
+
per-file function on all cores. `pyreprism scan` and `pyreprism clones` take
|
|
43
|
+
`-j/--jobs` and use one process per CPU by default (`-j 1` for one process).
|
|
44
|
+
Reports are identical for any number of jobs.
|
|
45
|
+
- Secondary file extensions map to their language: `.h` (C); `.cc`, `.cxx`,
|
|
46
|
+
`.hpp`, `.hh`, `.hxx` (C++); `.mjs`, `.cjs`, `.mts`, `.cts`; `.pyi`; `.bash`,
|
|
47
|
+
`.zsh`, `.ksh`; `.yml`; and others. These files were skipped before.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
- Faster tokenization (about 2.7x on one core) with identical tokens: each
|
|
51
|
+
language's string, number, identifier, and operator patterns are joined into
|
|
52
|
+
one pattern and compiled once, instead of being tried one by one at every
|
|
53
|
+
position; line numbers are tracked incrementally. `stats` (and `scan`)
|
|
54
|
+
count tokens as they are classified instead of building the token list
|
|
55
|
+
(about 4x faster than before on one core; same results). `code_metrics` computes
|
|
56
|
+
Halstead measures and complexity once instead of twice. Extension lookup no
|
|
57
|
+
longer re-imports every language module (1.4 ms to under 1 µs per file).
|
|
58
|
+
- The Pygments engine is about 3x faster on large files with the same tokens:
|
|
59
|
+
it merged tokens by repeated string concatenation and counted each token's
|
|
60
|
+
line from the start of the file, both quadratic in file size.
|
|
61
|
+
- `Token` is now an immutable `NamedTuple` instead of a frozen dataclass, which
|
|
62
|
+
makes tokens cheaper to create. Fields, attribute access, and immutability
|
|
63
|
+
are unchanged; a `Token` now also compares equal to a plain tuple with the
|
|
64
|
+
same values.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
- `pyreprism --help` stated "160+ built-in languages"; it now says 187, matching
|
|
68
|
+
`pyreprism languages`. A test keeps the two in sync.
|
|
69
|
+
- `pyreprism clones --max-duplication`: when stdout and stderr go to the same log
|
|
70
|
+
(as in CI), the gate message could be written into the middle of the report's
|
|
71
|
+
summary line. stdout is now flushed before the gate message.
|
|
72
|
+
- Defects found by validating token classes against tree-sitter parses:
|
|
73
|
+
- `remove_comments` dropped text that a language's comment regex skips (e.g.
|
|
74
|
+
the `/` in `#include "api/z3.h"`, a `{` in Scala). The base implementation
|
|
75
|
+
now keeps it, and 20 modules that duplicated the old loop inherit it.
|
|
76
|
+
- C, C++, Java, and CSS strings containing `/` were split, so `//` or `/*`
|
|
77
|
+
inside them started a comment (Java text blocks are kept whole too).
|
|
78
|
+
- Python: only a triple-quoted string that starts a line is a docstring
|
|
79
|
+
(comment); `x = """..."""` and call arguments are strings.
|
|
80
|
+
- JavaScript, TypeScript, JSX, TSX: template literals are strings, and
|
|
81
|
+
regular-expression literals no longer start comments.
|
|
82
|
+
- Pygments engine: C preprocessor directives were typed as comments, and
|
|
83
|
+
Python docstrings as strings; both now follow the regex engine's policies.
|
|
84
|
+
- Strings containing comment delimiters (`"a//b"`, `"a#b"`, `'--'`) were split
|
|
85
|
+
in 36 more languages, starting a comment inside the string: ActionScript,
|
|
86
|
+
Ada, AppleScript, Asm6502, ASP.NET, AutoHotkey, AutoIt, Bro, CoffeeScript,
|
|
87
|
+
Crystal, Elixir, Flow, GLSL, GraphQL, HPKP, HSTS, IchigoJam, Icon, Less,
|
|
88
|
+
LiveScript, Lua (including `[[...]]` long strings), Nginx, NSIS, PL/SQL, Qore,
|
|
89
|
+
Roboconf, Scheme (including `#\;` characters), SCSS (including unquoted
|
|
90
|
+
`url(...)`), and SQL. Comments now follow each language's rules in Apache
|
|
91
|
+
config, Dockerfiles, `.properties`, and Pug (own line only), Tcl (where a
|
|
92
|
+
command starts), YAML (after whitespace), and ERB (`<%# %>` tags, not `#` in
|
|
93
|
+
markup). A test checks every language with such a string.
|
|
94
|
+
- Defects found on the project-stratified evaluation sample: Go raw strings
|
|
95
|
+
(`` `...` ``) containing `//` or `/*` became comments; in Bash, `#` inside a
|
|
96
|
+
word (`$#`, `${#a}`, `a#b`) started a comment; a UTF-8 byte-order mark at the
|
|
97
|
+
start of a file was counted as code, so the first line could not be a comment
|
|
98
|
+
line (both engines); and a Python triple-quoted string on the line after an
|
|
99
|
+
opening bracket, comma, or `=` was taken for a docstring.
|
|
100
|
+
|
|
101
|
+
## [0.2.0] - 2026-07-08
|
|
102
|
+
|
|
103
|
+
This release adds a static code-analysis toolkit on top of the tokenizer:
|
|
104
|
+
diff/PR analysis, complexity metrics, n-gram "naturalness", and clone/plagiarism
|
|
105
|
+
similarity — plus a comprehensive per-language test suite that hardened comment
|
|
106
|
+
handling across the board.
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
- **Fingerprinting & similarity** (`PyReprism.fingerprints`): winnowing k-gram
|
|
110
|
+
fingerprints over the normalized token stream for clone/plagiarism detection —
|
|
111
|
+
`fingerprint()`, `similarity()`/`containment()` (rename-invariant by default),
|
|
112
|
+
and a `FingerprintIndex` for many-to-many detection over a corpus. CLI:
|
|
113
|
+
`pyreprism similarity a b` and `pyreprism clones DIR --threshold`.
|
|
114
|
+
- **N-gram analysis & code naturalness** (`PyReprism.ngrams`): token/type n-gram
|
|
115
|
+
extraction and frequency counts, plus an `NgramModel` (add-k smoothing,
|
|
116
|
+
save/load) that measures cross-entropy / perplexity against a trained corpus
|
|
117
|
+
("naturalness of software"). CLI: `pyreprism ngrams` and
|
|
118
|
+
`pyreprism perplexity --train`.
|
|
119
|
+
- **Complexity metrics** computed from the token stream: `halstead()`
|
|
120
|
+
(volume/difficulty/effort/bugs), `cyclomatic_complexity()` (approximate McCabe),
|
|
121
|
+
`maintainability_index()` (0–100), `max_nesting_depth()`, and `code_metrics()`
|
|
122
|
+
which bundles them with the line/token stats. Exposed on the CLI via
|
|
123
|
+
`pyreprism stats --full`.
|
|
124
|
+
- **Diff processing** (`PyReprism.diffs`): parse unified/`git` diffs and analyze
|
|
125
|
+
the changed code per file in its own language. Includes churn metrics
|
|
126
|
+
(`diff_stats`: added/removed split into code, comment and blank), cosmetic
|
|
127
|
+
(comment/whitespace-only) change detection, reconstruction of the added/removed
|
|
128
|
+
code, and ML-oriented `tokenize`/`normalize`/`extract_comments` on changes.
|
|
129
|
+
Fragment mode works from the diff alone; setting a file's `new_source` /
|
|
130
|
+
`old_source` enables accurate full-file classification. New CLI command
|
|
131
|
+
`pyreprism diff` (`--json` / `--csv` / `--per-file` / `--cosmetic`).
|
|
132
|
+
|
|
133
|
+
### Changed
|
|
134
|
+
- Adopted the standard `src/` layout with tests at the top level, consolidated
|
|
135
|
+
all dependencies into `pyproject.toml` extras, and rewrote the landing page.
|
|
136
|
+
- Single-sourced the version from the package and automated releases: pushing a
|
|
137
|
+
`vX.Y.Z` tag now publishes to PyPI (Trusted Publishing) and creates a GitHub
|
|
138
|
+
Release. Added Python 3.13 to the CI matrix.
|
|
139
|
+
- Added a comprehensive, data-driven per-language comment test suite that
|
|
140
|
+
requires every registered language to be covered.
|
|
141
|
+
|
|
142
|
+
### Fixed
|
|
143
|
+
- Fixed comment stripping in 8 more languages surfaced by the new test suite:
|
|
144
|
+
`smalltalk` (kept the comment and deleted the code) and
|
|
145
|
+
`eiffel`/`bro`/`coffeescript`/`io`/`nix`/`gherkin`/`gedcom` (trailing comments
|
|
146
|
+
not removed and newlines dropped).
|
|
147
|
+
- Fixed a CLI argument-ordering incompatibility on Python ≤ 3.11 (options must
|
|
148
|
+
follow positionals).
|
|
149
|
+
|
|
150
|
+
## [0.1.0] - 2026-07-07
|
|
151
|
+
|
|
152
|
+
This release turns PyReprism from a comment-removal helper into a full
|
|
153
|
+
source-preprocessing toolkit with a high-level API, a CLI, code metrics,
|
|
154
|
+
ML-oriented normalization, an optional accurate backend, and batch processing.
|
|
155
|
+
|
|
156
|
+
### Added
|
|
157
|
+
- **High-level API** (`import PyReprism as pr`): `remove_*`, `extract_*`,
|
|
158
|
+
`count_*`, `match_*` for comments, keywords, numbers, operators, strings and
|
|
159
|
+
identifiers; plus `preprocess`, `remove_whitespaces`, `get_language` and
|
|
160
|
+
`detect_language`. `lang=` accepts a language name, file extension, or class.
|
|
161
|
+
- **Tokenizer**: `tokenize()` on every language returns a lossless, typed
|
|
162
|
+
`Token` stream (`Token`/`TokenType` in `PyReprism.tokens`).
|
|
163
|
+
- **Code metrics**: `stats()` returns a `CodeStats` (line/token counts,
|
|
164
|
+
comment-to-code ratio, comment density; `as_dict()` for JSON/dataframes).
|
|
165
|
+
- **ML normalization**: `normalize()` canonicalizes code (rename identifiers to
|
|
166
|
+
`VAR1…`, mask string/number literals, drop comments) for clone/plagiarism
|
|
167
|
+
detection and code-embedding pipelines; `blank_comments()` strips comments
|
|
168
|
+
while preserving line numbers.
|
|
169
|
+
- **Pluggable backends**: `engine="regex"` (default, zero-dependency) or
|
|
170
|
+
`engine="pygments"` (`pip install pyreprism[accurate]`) for higher accuracy,
|
|
171
|
+
plus `"auto"`. Available on every operation.
|
|
172
|
+
- **Batch processing** (`PyReprism.batch`): `analyze()` walks a directory tree
|
|
173
|
+
and returns an aggregate report (`to_json`/`to_csv`, per-language breakdown);
|
|
174
|
+
`transform()` bulk-applies a transformation into a mirrored output directory.
|
|
175
|
+
- **Command-line interface** (`pyreprism`, also `python -m PyReprism`):
|
|
176
|
+
`remove`, `extract`, `count`, `preprocess`, `tokenize`, `stats`, `normalize`,
|
|
177
|
+
`scan`, and `languages`; reads stdin/files/globs/directories; supports
|
|
178
|
+
`--lang`, `--engine`, `--in-place`, `--output`, and `--json`/`--csv`.
|
|
179
|
+
- **Source-based language detection**: `detect_language(source=...)` recognizes
|
|
180
|
+
`#!` shebangs and (when Pygments is installed) makes a best-effort content
|
|
181
|
+
guess; the CLI uses this to auto-detect the language of piped input.
|
|
182
|
+
- Pre-commit hooks (`.pre-commit-hooks.yaml`), a `py.typed` marker (PEP 561),
|
|
183
|
+
and a registry-wide test suite covering all supported languages.
|
|
184
|
+
|
|
185
|
+
### Changed
|
|
186
|
+
- Implemented real support for 25 previously-empty language stubs and migrated
|
|
187
|
+
22 legacy languages (HTML, JSON, YAML, CSS, Markdown, …) to the
|
|
188
|
+
`BaseLanguage` + registry pattern, making them importable via the public API.
|
|
189
|
+
- Ambiguous file extensions now resolve to a canonical language
|
|
190
|
+
(`.py` → Python, `.js` → JavaScript, …).
|
|
191
|
+
- Consolidated packaging into `pyproject.toml` (single version source, pytest
|
|
192
|
+
and coverage config), updated CI to a Python 3.8–3.12 matrix, and refreshed
|
|
193
|
+
the README.
|
|
194
|
+
|
|
195
|
+
### Fixed
|
|
196
|
+
- Corrected comment-stripping for ~30 languages whose regexes either failed to
|
|
197
|
+
remove line comments or consumed surrounding code, and fixed duplicate/broken
|
|
198
|
+
definitions (Perl, csp, glsl, django, apacheconf, php_extras, ruby, and the
|
|
199
|
+
Python triple-quoted-docstring bug).
|
|
200
|
+
|
|
201
|
+
## [0.0.4] - 2024
|
|
202
|
+
|
|
203
|
+
- Early beta releases: comment removal for an initial set of languages and the
|
|
204
|
+
`Normalizer` whitespace helper.
|
|
205
|
+
|
|
206
|
+
[Unreleased]: https://github.com/unlv-evol/PyReprism/compare/v1.0.0...HEAD
|
|
207
|
+
[1.0.0]: https://github.com/unlv-evol/PyReprism/compare/v0.2.0...v1.0.0
|
|
208
|
+
[0.2.0]: https://github.com/unlv-evol/PyReprism/compare/v0.1.0...v0.2.0
|
|
209
|
+
[0.1.0]: https://github.com/unlv-evol/PyReprism/releases/tag/v0.1.0
|
|
210
|
+
[0.0.4]: https://github.com/unlv-evol/PyReprism/releases/tag/v0.0.4
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# PyReprism CLI, containerized.
|
|
2
|
+
#
|
|
3
|
+
# docker build -t pyreprism .
|
|
4
|
+
# docker run --rm -v "$PWD:/work" pyreprism clones . --reporter sarif
|
|
5
|
+
# docker run --rm -v "$PWD:/work" pyreprism scan . --json
|
|
6
|
+
#
|
|
7
|
+
# The image ships the 187-language, zero-dependency lexical core plus the
|
|
8
|
+
# optional Pygments backend ([accurate], pure Python). The heavier [ast]
|
|
9
|
+
# (tree-sitter) and [semantic] (torch/transformers) tiers are intentionally
|
|
10
|
+
# left out to keep the image small; derive your own image if you need them.
|
|
11
|
+
|
|
12
|
+
# ---- build stage: produce a wheel from the source tree ----
|
|
13
|
+
FROM python:3.12-slim AS build
|
|
14
|
+
WORKDIR /src
|
|
15
|
+
# Only the files hatchling needs to build the wheel and read metadata.
|
|
16
|
+
COPY pyproject.toml LICENSE ./
|
|
17
|
+
COPY docs/intro.rst ./docs/intro.rst
|
|
18
|
+
COPY src ./src
|
|
19
|
+
RUN pip install --no-cache-dir build \
|
|
20
|
+
&& python -m build --wheel --outdir /dist
|
|
21
|
+
|
|
22
|
+
# ---- runtime stage: install the wheel, drop the build tooling ----
|
|
23
|
+
FROM python:3.12-slim
|
|
24
|
+
LABEL org.opencontainers.image.title="PyReprism" \
|
|
25
|
+
org.opencontainers.image.description="Lossless token substrate for polyglot code analysis (CLI)" \
|
|
26
|
+
org.opencontainers.image.source="https://github.com/unlv-evol/PyReprism" \
|
|
27
|
+
org.opencontainers.image.licenses="MIT"
|
|
28
|
+
COPY --from=build /dist/*.whl /tmp/
|
|
29
|
+
RUN pip install --no-cache-dir "$(ls /tmp/*.whl)[accurate]" \
|
|
30
|
+
&& rm -rf /tmp/*.whl /root/.cache/pip
|
|
31
|
+
# Run as an unprivileged user; /work is where the caller mounts their code.
|
|
32
|
+
RUN useradd --create-home --uid 1000 app
|
|
33
|
+
USER app
|
|
34
|
+
WORKDIR /work
|
|
35
|
+
ENTRYPOINT ["pyreprism"]
|
|
36
|
+
CMD ["--help"]
|
pyreprism-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: PyReprism
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Framework for Source Code Preprocessing
|
|
5
|
+
Project-URL: Homepage, https://github.com/unlv-evol/PyReprism
|
|
6
|
+
Project-URL: Documentation, https://pyreprism.readthedocs.io
|
|
7
|
+
Project-URL: Issues, https://github.com/unlv-evol/PyReprism/issues
|
|
8
|
+
Author-email: UNLV EVOL LAB <ogenrwot@unlv.nevada.edu>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2024 UNLV EVOL
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
32
|
+
Classifier: Environment :: Console
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
44
|
+
Requires-Python: >=3.8
|
|
45
|
+
Provides-Extra: accurate
|
|
46
|
+
Requires-Dist: pygments; extra == 'accurate'
|
|
47
|
+
Provides-Extra: ast
|
|
48
|
+
Requires-Dist: tree-sitter; extra == 'ast'
|
|
49
|
+
Requires-Dist: tree-sitter-language-pack; extra == 'ast'
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: build; extra == 'dev'
|
|
52
|
+
Requires-Dist: flake8; extra == 'dev'
|
|
53
|
+
Requires-Dist: pygments; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
56
|
+
Requires-Dist: twine; extra == 'dev'
|
|
57
|
+
Provides-Extra: docs
|
|
58
|
+
Requires-Dist: sphinx; extra == 'docs'
|
|
59
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
60
|
+
Provides-Extra: semantic
|
|
61
|
+
Requires-Dist: torch; extra == 'semantic'
|
|
62
|
+
Requires-Dist: transformers; extra == 'semantic'
|
|
63
|
+
Description-Content-Type: text/x-rst
|
|
64
|
+
|
|
65
|
+
.. _intro_toplevel:
|
|
66
|
+
|
|
67
|
+
========
|
|
68
|
+
Overview
|
|
69
|
+
========
|
|
70
|
+
|
|
71
|
+
**PyReprism** is a Python framework for source-code preprocessing. It lets you
|
|
72
|
+
**match, extract, count, and remove** comments, strings, numbers, operators,
|
|
73
|
+
keywords and other language-specific constructs across **187+ programming
|
|
74
|
+
languages and file formats** (500+ with the optional Pygments backend) — through a
|
|
75
|
+
small high-level API, a command-line tool, code metrics, ML-oriented
|
|
76
|
+
normalization, and diff/pull-request analysis.
|
|
77
|
+
|
|
78
|
+
Everything is derived from one lossless token stream, and the same substrate
|
|
79
|
+
anchors a **fidelity ladder** of optional-cost tiers: a zero-dependency
|
|
80
|
+
**lexical** tier (default), an optional **syntactic** tier (`tree-sitter ASTs
|
|
81
|
+
<https://pyreprism.readthedocs.io/en/latest/syntactic.html>`__ for precise per-function metrics),
|
|
82
|
+
and an optional **semantic** tier (`code embeddings
|
|
83
|
+
<https://pyreprism.readthedocs.io/en/latest/semantic.html>`__ for Type-4 clone detection).
|
|
84
|
+
|
|
85
|
+
Highlights
|
|
86
|
+
==========
|
|
87
|
+
|
|
88
|
+
* One consistent API for every language: ``remove_*`` / ``extract_*`` /
|
|
89
|
+
``count_*`` / ``match_*`` for each construct, plus a lossless ``tokenize()``.
|
|
90
|
+
* Code metrics (``stats``) and ML canonicalization (``normalize``) for
|
|
91
|
+
clone/plagiarism detection and code-embedding pipelines.
|
|
92
|
+
* Optional high-accuracy `Pygments`_ backend and an on-demand Pygments fallback
|
|
93
|
+
for 500+ languages — with **zero required dependencies** by default.
|
|
94
|
+
* Optional `syntactic (AST) <https://pyreprism.readthedocs.io/en/latest/syntactic.html>`__ and
|
|
95
|
+
`semantic (embedding) <https://pyreprism.readthedocs.io/en/latest/semantic.html>`__ tiers for
|
|
96
|
+
precise per-function metrics and Type-4 clone detection.
|
|
97
|
+
* Located clone detection with console, JSON, SARIF, Markdown, and HTML
|
|
98
|
+
reports and a duplication gate for CI (also as a GitHub Action).
|
|
99
|
+
* Batch/corpus analysis on every core, and unified/``git`` diff processing.
|
|
100
|
+
* A ``pyreprism`` command-line tool (also ``python -m PyReprism``).
|
|
101
|
+
|
|
102
|
+
Stability
|
|
103
|
+
=========
|
|
104
|
+
|
|
105
|
+
PyReprism 1.0 is the first stable release. From 1.0 on, releases follow
|
|
106
|
+
`semantic versioning`_: the public API and the ``pyreprism`` command line change
|
|
107
|
+
incompatibly only in a new major version. Modules whose names start with an
|
|
108
|
+
underscore are internal. Token classifications may still change in minor
|
|
109
|
+
releases when they fix a lexer defect; the changelog lists every such change.
|
|
110
|
+
|
|
111
|
+
Requirements
|
|
112
|
+
============
|
|
113
|
+
|
|
114
|
+
* `Python`_ 3.8 or newer
|
|
115
|
+
|
|
116
|
+
Install
|
|
117
|
+
=======
|
|
118
|
+
|
|
119
|
+
.. code-block:: shell
|
|
120
|
+
|
|
121
|
+
pip install PyReprism
|
|
122
|
+
|
|
123
|
+
The optional tiers are opt-in extras (install only what you need):
|
|
124
|
+
|
|
125
|
+
.. code-block:: shell
|
|
126
|
+
|
|
127
|
+
pip install "PyReprism[accurate]" # Pygments backend (higher lexical fidelity)
|
|
128
|
+
pip install "PyReprism[ast]" # syntactic tier (tree-sitter)
|
|
129
|
+
pip install "PyReprism[semantic]" # semantic tier (code embeddings)
|
|
130
|
+
|
|
131
|
+
Quick start
|
|
132
|
+
===========
|
|
133
|
+
|
|
134
|
+
.. code-block:: python
|
|
135
|
+
|
|
136
|
+
import PyReprism as pr
|
|
137
|
+
|
|
138
|
+
source = """
|
|
139
|
+
# a comment
|
|
140
|
+
x = 5 + 6
|
|
141
|
+
print(x) # inline
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
pr.remove_comments(source, lang="python") # code without comments
|
|
145
|
+
pr.extract_comments(source, lang="python") # ['# a comment', '# inline']
|
|
146
|
+
pr.count_comments(source, lang="python") # 2
|
|
147
|
+
|
|
148
|
+
``lang`` accepts a language name (``"python"``), a file extension (``".py"``),
|
|
149
|
+
or a language class. Canonicalize code for machine learning, or measure it:
|
|
150
|
+
|
|
151
|
+
.. code-block:: python
|
|
152
|
+
|
|
153
|
+
pr.normalize("total = price * 42", lang="python") # 'VAR1 = VAR2 * 0'
|
|
154
|
+
pr.stats(source, lang="python").comment_to_code_ratio
|
|
155
|
+
|
|
156
|
+
Command line
|
|
157
|
+
============
|
|
158
|
+
|
|
159
|
+
.. code-block:: shell
|
|
160
|
+
|
|
161
|
+
pyreprism remove comments file.py
|
|
162
|
+
pyreprism scan myproject/ --csv # aggregate code metrics over a tree
|
|
163
|
+
git diff | pyreprism diff --cosmetic # flag comment/whitespace-only changes
|
|
164
|
+
pyreprism clones src/ --max-duplication 5 # located clones; fail above 5%
|
|
165
|
+
|
|
166
|
+
Documentation
|
|
167
|
+
=============
|
|
168
|
+
|
|
169
|
+
Full documentation, including the API reference and the list of supported
|
|
170
|
+
languages, is available at https://pyreprism.readthedocs.io.
|
|
171
|
+
|
|
172
|
+
Source code
|
|
173
|
+
===========
|
|
174
|
+
|
|
175
|
+
PyReprism is developed on GitHub at
|
|
176
|
+
https://github.com/unlv-evol/PyReprism. To work on it locally:
|
|
177
|
+
|
|
178
|
+
.. code-block:: shell
|
|
179
|
+
|
|
180
|
+
git clone https://github.com/unlv-evol/PyReprism.git
|
|
181
|
+
cd PyReprism
|
|
182
|
+
python3 -m venv venv && source venv/bin/activate
|
|
183
|
+
pip install -e ".[dev]"
|
|
184
|
+
pytest
|
|
185
|
+
|
|
186
|
+
See ``CONTRIBUTING.md`` for contribution guidelines.
|
|
187
|
+
|
|
188
|
+
.. _Python: https://www.python.org
|
|
189
|
+
.. _Pygments: https://pygments.org
|
|
190
|
+
.. _semantic versioning: https://semver.org
|