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.
Files changed (208) hide show
  1. pyreprism-1.0.0/.dockerignore +18 -0
  2. pyreprism-1.0.0/.github/pyreprism-action.sh +58 -0
  3. {pyreprism-0.1.0 → pyreprism-1.0.0}/.gitignore +1 -0
  4. pyreprism-1.0.0/CHANGELOG.md +210 -0
  5. pyreprism-1.0.0/Dockerfile +36 -0
  6. pyreprism-1.0.0/PKG-INFO +190 -0
  7. pyreprism-1.0.0/README.md +474 -0
  8. pyreprism-1.0.0/action.yml +79 -0
  9. pyreprism-1.0.0/docs/intro.rst +126 -0
  10. {pyreprism-0.1.0 → pyreprism-1.0.0}/pyproject.toml +9 -1
  11. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/__init__.py +45 -3
  12. pyreprism-1.0.0/src/PyReprism/_parallel.py +47 -0
  13. pyreprism-1.0.0/src/PyReprism/_tokenops.py +177 -0
  14. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/batch.py +66 -25
  15. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/cli.py +216 -6
  16. pyreprism-1.0.0/src/PyReprism/clones.py +308 -0
  17. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/pygments_engine.py +24 -8
  18. pyreprism-1.0.0/src/PyReprism/fingerprints.py +145 -0
  19. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/__init__.py +64 -19
  20. pyreprism-1.0.0/src/PyReprism/languages/_scanners.py +137 -0
  21. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/actionscript.py +5 -10
  22. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ada.py +3 -11
  23. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/apacheconf.py +5 -9
  24. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/applescript.py +5 -3
  25. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/arduino.py +0 -23
  26. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/arff.py +0 -18
  27. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/asm6502.py +5 -6
  28. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/aspnet.py +3 -31
  29. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/autohotkey.py +5 -12
  30. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/autoit.py +5 -12
  31. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/base.py +232 -29
  32. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bash.py +2 -1
  33. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bro.py +5 -2
  34. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/c.py +1 -1
  35. pyreprism-1.0.0/src/PyReprism/languages/cobol.py +69 -0
  36. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/coffeescript.py +5 -2
  37. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/cpp.py +1 -1
  38. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/crystal.py +4 -12
  39. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/css.py +2 -1
  40. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/docker.py +5 -11
  41. pyreprism-1.0.0/src/PyReprism/languages/dynamic.py +153 -0
  42. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/eiffel.py +3 -2
  43. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/elixir.py +4 -15
  44. pyreprism-1.0.0/src/PyReprism/languages/erb.py +29 -0
  45. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/erlang.py +0 -11
  46. pyreprism-1.0.0/src/PyReprism/languages/flow.py +23 -0
  47. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/fortran.py +0 -11
  48. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/fsharp.py +0 -11
  49. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/gedcom.py +1 -1
  50. pyreprism-1.0.0/src/PyReprism/languages/generated.py +158 -0
  51. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/gherkin.py +1 -1
  52. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/glsl.py +5 -3
  53. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/go.py +7 -1
  54. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/graphql.py +4 -12
  55. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/groovy.py +0 -11
  56. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/hpkp.py +4 -2
  57. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/hsts.py +4 -2
  58. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ichigojam.py +4 -9
  59. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/icon.py +4 -9
  60. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/io.py +1 -1
  61. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/java.py +1 -1
  62. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/javascript.py +6 -1
  63. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/jsx.py +6 -21
  64. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/less.py +1 -1
  65. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/livescript.py +5 -2
  66. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/lua.py +5 -2
  67. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nginx.py +5 -2
  68. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nix.py +1 -1
  69. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nsis.py +1 -1
  70. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/objectivec.py +0 -12
  71. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/plsql.py +3 -5
  72. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/properties.py +3 -4
  73. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pug.py +3 -4
  74. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/python.py +22 -1
  75. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/qore.py +4 -1
  76. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/roboconf.py +3 -4
  77. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scheme.py +4 -13
  78. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scss.py +3 -4
  79. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/smalltalk.py +7 -13
  80. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sql.py +1 -1
  81. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/stylus.py +0 -11
  82. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/tcl.py +4 -2
  83. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/tsx.py +6 -12
  84. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/typescript.py +6 -1
  85. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/yaml.py +3 -4
  86. pyreprism-1.0.0/src/PyReprism/metrics.py +101 -0
  87. pyreprism-1.0.0/src/PyReprism/ngrams.py +169 -0
  88. pyreprism-1.0.0/src/PyReprism/reporters.py +449 -0
  89. pyreprism-1.0.0/src/PyReprism/semantic.py +147 -0
  90. pyreprism-1.0.0/src/PyReprism/syntactic.py +163 -0
  91. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/tokens.py +6 -3
  92. pyreprism-0.1.0/CHANGELOG.md +0 -78
  93. pyreprism-0.1.0/PKG-INFO +0 -111
  94. pyreprism-0.1.0/README.md +0 -246
  95. pyreprism-0.1.0/docs/intro.rst +0 -53
  96. pyreprism-0.1.0/src/PyReprism/_tokenops.py +0 -78
  97. pyreprism-0.1.0/src/PyReprism/languages/erb.py +0 -46
  98. pyreprism-0.1.0/src/PyReprism/languages/flow.py +0 -30
  99. pyreprism-0.1.0/src/PyReprism/metrics.py +0 -41
  100. {pyreprism-0.1.0 → pyreprism-1.0.0}/.flake8 +0 -0
  101. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/FUNDING.yaml +0 -0
  102. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  103. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  104. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  105. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/scripts/changelog_notes.py +0 -0
  106. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/scripts/package_version.py +0 -0
  107. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/workflows/ci.yml +0 -0
  108. {pyreprism-0.1.0 → pyreprism-1.0.0}/.github/workflows/publish.yml +0 -0
  109. {pyreprism-0.1.0 → pyreprism-1.0.0}/.pre-commit-hooks.yaml +0 -0
  110. {pyreprism-0.1.0 → pyreprism-1.0.0}/.readthedocs.yaml +0 -0
  111. {pyreprism-0.1.0 → pyreprism-1.0.0}/CONTRIBUTING.md +0 -0
  112. {pyreprism-0.1.0 → pyreprism-1.0.0}/LICENSE +0 -0
  113. {pyreprism-0.1.0 → pyreprism-1.0.0}/RELEASING.md +0 -0
  114. {pyreprism-0.1.0 → pyreprism-1.0.0}/codecov.yml +0 -0
  115. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/__main__.py +0 -0
  116. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/diffs.py +0 -0
  117. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/__init__.py +0 -0
  118. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/base.py +0 -0
  119. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/engines/regex_engine.py +0 -0
  120. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/abap.py +0 -0
  121. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/apl.py +0 -0
  122. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/asciidoc.py +0 -0
  123. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/basic.py +0 -0
  124. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/batch.py +0 -0
  125. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/bison.py +0 -0
  126. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/brainfuck.py +0 -0
  127. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/clike.py +0 -0
  128. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/clojure.py +0 -0
  129. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/csharp.py +0 -0
  130. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/csp.py +0 -0
  131. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/css_extras.py +0 -0
  132. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/d.py +0 -0
  133. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/dart.py +0 -0
  134. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/diff.py +0 -0
  135. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/django.py +0 -0
  136. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/git.py +0 -0
  137. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haml.py +0 -0
  138. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/handlebars.py +0 -0
  139. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haskell.py +0 -0
  140. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/haxe.py +0 -0
  141. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/html.py +0 -0
  142. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/inform7.py +0 -0
  143. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ini.py +0 -0
  144. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/j.py +0 -0
  145. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/jolie.py +0 -0
  146. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/json.py +0 -0
  147. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/julia.py +0 -0
  148. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/keyman.py +0 -0
  149. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/kotlin.py +0 -0
  150. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/latex.py +0 -0
  151. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/liquid.py +0 -0
  152. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/lolcode.py +0 -0
  153. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/makefile.py +0 -0
  154. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markdown.py +0 -0
  155. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markup.py +0 -0
  156. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/markup_templating.py +0 -0
  157. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/matlab.py +0 -0
  158. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/mel.py +0 -0
  159. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/mizar.py +0 -0
  160. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/monkey.py +0 -0
  161. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/n4js.py +0 -0
  162. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nasm.py +0 -0
  163. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/nim.py +0 -0
  164. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ocaml.py +0 -0
  165. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/opencl.py +0 -0
  166. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/oz.py +0 -0
  167. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/parigp.py +0 -0
  168. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/parser.py +0 -0
  169. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pascal.py +0 -0
  170. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/perl.py +0 -0
  171. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/php.py +0 -0
  172. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/php_extras.py +0 -0
  173. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/powershell.py +0 -0
  174. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/processing.py +0 -0
  175. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/prolog.py +0 -0
  176. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/protobuf.py +0 -0
  177. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/puppet.py +0 -0
  178. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/pure.py +0 -0
  179. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/q.py +0 -0
  180. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/r.py +0 -0
  181. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/reason.py +0 -0
  182. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/registry.py +0 -0
  183. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/renpy.py +0 -0
  184. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rest.py +0 -0
  185. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rip.py +0 -0
  186. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/ruby.py +0 -0
  187. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/rust.py +0 -0
  188. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sas.py +0 -0
  189. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/sass.py +0 -0
  190. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/scala.py +0 -0
  191. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/smarty.py +0 -0
  192. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/soy.py +0 -0
  193. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/swift.py +0 -0
  194. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/textile.py +0 -0
  195. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/twig.py +0 -0
  196. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vbnet.py +0 -0
  197. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/velocity.py +0 -0
  198. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/verilog.py +0 -0
  199. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vhdl.py +0 -0
  200. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/vim.py +0 -0
  201. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/visual_basic.py +0 -0
  202. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/wasam.py +0 -0
  203. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/xeora.py +0 -0
  204. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/languages/xojo.py +0 -0
  205. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/py.typed +0 -0
  206. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/utils/__init__.py +0 -0
  207. {pyreprism-0.1.0 → pyreprism-1.0.0}/src/PyReprism/utils/extension.py +0 -0
  208. {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"
@@ -169,3 +169,4 @@ __test__.py
169
169
  .DS_Store
170
170
  # Claude Code agent workspace
171
171
  .claude/
172
+ manuscript/replication/
@@ -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"]
@@ -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