python-obfuscation-framework 1.10.0__tar.gz → 1.11.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 (186) hide show
  1. {python_obfuscation_framework-1.10.0/python_obfuscation_framework.egg-info → python_obfuscation_framework-1.11.0}/PKG-INFO +33 -4
  2. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/README.md +32 -3
  3. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/esoteric/doc.py +6 -6
  4. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/esoteric/globals.py +2 -2
  5. python_obfuscation_framework-1.11.0/pof/obfuscator/esoteric/imports.py +257 -0
  6. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/names.py +16 -0
  7. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/stegano/ipv6encoding.py +9 -5
  8. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/stegano/macencoding.py +9 -5
  9. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/stegano/uuidencoding.py +15 -5
  10. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pyproject.toml +1 -1
  11. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0/python_obfuscation_framework.egg-info}/PKG-INFO +33 -4
  12. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/python_obfuscation_framework.egg-info/SOURCES.txt +6 -1
  13. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/conftest.py +32 -68
  14. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/fixtures/complex.py +0 -52
  15. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/decorators.py +54 -0
  16. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/getattr.py +27 -0
  17. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/import.py +21 -0
  18. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/lambda.py +4 -0
  19. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/fixtures/moderate.py +0 -27
  20. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/numbers.py +12 -0
  21. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/fixtures/simple.py +0 -4
  22. python_obfuscation_framework-1.10.0/tests/obfuscator/fixtures/multiline_strings.py → python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/strings.py +6 -1
  23. python_obfuscation_framework-1.11.0/tests/obfuscator/fixtures/try.py +6 -0
  24. python_obfuscation_framework-1.10.0/pof/obfuscator/esoteric/imports.py +0 -71
  25. python_obfuscation_framework-1.10.0/tests/obfuscator/fixtures/getattr.py +0 -10
  26. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/LICENSE +0 -0
  27. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/MANIFEST.in +0 -0
  28. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/__init__.py +0 -0
  29. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/__main__.py +0 -0
  30. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/cli.py +0 -0
  31. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/cli_v2.py +0 -0
  32. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/errors.py +0 -0
  33. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/__init__.py +0 -0
  34. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/argv.py +0 -0
  35. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/base.py +0 -0
  36. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/cpu/__init__.py +0 -0
  37. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/cpu/cpu_count.py +0 -0
  38. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/__init__.py +0 -0
  39. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/directory_exist.py +0 -0
  40. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/directory_list_exist.py +0 -0
  41. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/directory_list_missing.py +0 -0
  42. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/directory_missing.py +0 -0
  43. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/exec_method.py +0 -0
  44. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/executable_path.py +0 -0
  45. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/file_exist.py +0 -0
  46. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/file_list_exist.py +0 -0
  47. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/file_list_missing.py +0 -0
  48. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/file_missing.py +0 -0
  49. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/fs/tmp.py +0 -0
  50. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/hardware/__init__.py +0 -0
  51. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/hardware/ram_count.py +0 -0
  52. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/hooks/__init__.py +0 -0
  53. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/hooks/debugger.py +0 -0
  54. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/hooks/tracemalloc.py +0 -0
  55. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/human/__init__.py +0 -0
  56. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/human/p.py +0 -0
  57. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/human/prompt.py +0 -0
  58. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/integrity.py +0 -0
  59. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/multi.py +0 -0
  60. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/os/__init__.py +0 -0
  61. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/os/domain.py +0 -0
  62. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/os/hostname.py +0 -0
  63. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/os/uid.py +0 -0
  64. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/os/username.py +0 -0
  65. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/processes/__init__.py +0 -0
  66. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/processes/proc_count.py +0 -0
  67. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/time/__init__.py +0 -0
  68. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/time/expire.py +0 -0
  69. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/time/uptime.py +0 -0
  70. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/time/utc.py +0 -0
  71. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/evasion/utils.py +0 -0
  72. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/logger.py +0 -0
  73. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/main.py +0 -0
  74. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/__init__.py +0 -0
  75. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/boolean.py +0 -0
  76. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/builtins.py +0 -0
  77. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/cipher/__init__.py +0 -0
  78. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/cipher/deep_encryption.py +0 -0
  79. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/cipher/rc4.py +0 -0
  80. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/cipher/shift.py +0 -0
  81. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/cipher/xor.py +0 -0
  82. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/compression/__init__.py +0 -0
  83. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/compression/bz2.py +0 -0
  84. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/compression/gzip.py +0 -0
  85. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/compression/lzma.py +0 -0
  86. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/compression/zlib.py +0 -0
  87. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/constants.py +0 -0
  88. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/controlflow/__init__.py +0 -0
  89. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/controlflow/control_flow_flatten.py +0 -0
  90. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/__init__.py +0 -0
  91. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/a85.py +0 -0
  92. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/b16.py +0 -0
  93. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/b32.py +0 -0
  94. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/b32hex.py +0 -0
  95. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/b64.py +0 -0
  96. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/b85.py +0 -0
  97. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/binascii.py +0 -0
  98. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/snt.py +0 -0
  99. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/encoding/whitespace.py +0 -0
  100. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/esoteric/__init__.py +0 -0
  101. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/esoteric/call.py +0 -0
  102. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/extract_variables.py +0 -0
  103. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/junk/__init__.py +0 -0
  104. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/junk/add_comments.py +0 -0
  105. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/junk/add_newlines.py +0 -0
  106. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/junk/dead_code.py +0 -0
  107. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/numbers.py +0 -0
  108. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/other/__init__.py +0 -0
  109. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/other/tokens.py +0 -0
  110. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/__init__.py +0 -0
  111. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/comments.py +0 -0
  112. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/exceptions.py +0 -0
  113. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/indents.py +0 -0
  114. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/loggings.py +0 -0
  115. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/loggings_old.py +0 -0
  116. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/newline.py +0 -0
  117. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/remove/print.py +0 -0
  118. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/restructure.py +0 -0
  119. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/stegano/__init__.py +0 -0
  120. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/stegano/docstrings.py +0 -0
  121. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/stegano/ipv6encoding.py +0 -0
  122. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/stegano/macencoding.py +0 -0
  123. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/stegano/uuidencoding.py +0 -0
  124. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/obfuscator/strings.py +0 -0
  125. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/__init__.py +0 -0
  126. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/cipher/__init__.py +0 -0
  127. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/cipher/rc4.py +0 -0
  128. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/download.py +0 -0
  129. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/image.py +0 -0
  130. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/lots/__init__.py +0 -0
  131. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/lots/cl1pnet.py +0 -0
  132. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/lots/pastebin.py +0 -0
  133. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/lots/pasters.py +0 -0
  134. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/stager/quine.py +0 -0
  135. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/__init__.py +0 -0
  136. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/cipher/__init__.py +0 -0
  137. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/cipher/rc4.py +0 -0
  138. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/cipher/shift.py +0 -0
  139. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/compression/__init__.py +0 -0
  140. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/compression/bz2.py +0 -0
  141. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/compression/gzip.py +0 -0
  142. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/compression/lzma.py +0 -0
  143. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/compression/zlib.py +0 -0
  144. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/__init__.py +0 -0
  145. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/a85.py +0 -0
  146. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b16.py +0 -0
  147. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b3.py +0 -0
  148. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b32.py +0 -0
  149. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b32hex.py +0 -0
  150. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b64.py +0 -0
  151. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/b85.py +0 -0
  152. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/binascii.py +0 -0
  153. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/snt.py +0 -0
  154. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/encoding/whitespace.py +0 -0
  155. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/entropy.py +0 -0
  156. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/extract_names.py +0 -0
  157. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/format.py +0 -0
  158. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/__init__.py +0 -0
  159. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/advanced.py +0 -0
  160. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/base.py +0 -0
  161. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/basic.py +0 -0
  162. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/comments.py +0 -0
  163. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/comments.txt +0 -0
  164. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/names.txt +0 -0
  165. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/generator/unicode.py +0 -0
  166. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/se/__init__.py +0 -0
  167. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/se/homoglyphs.py +0 -0
  168. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/se/homoglyphs.txt +0 -0
  169. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/stegano/__init__.py +0 -0
  170. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/pof/utils/tokens.py +0 -0
  171. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/python_obfuscation_framework.egg-info/dependency_links.txt +0 -0
  172. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/python_obfuscation_framework.egg-info/entry_points.txt +0 -0
  173. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/python_obfuscation_framework.egg-info/requires.txt +0 -0
  174. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/python_obfuscation_framework.egg-info/top_level.txt +0 -0
  175. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/setup.cfg +0 -0
  176. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/__init__.py +0 -0
  177. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/__init__.py +0 -0
  178. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/fixtures/__init__.py +0 -0
  179. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/test_edge_cases.py +0 -0
  180. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/test_integration.py +0 -0
  181. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/obfuscator/utils.py +0 -0
  182. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/pyproject.toml +0 -0
  183. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/utils/__init__.py +0 -0
  184. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/utils/se/__init__.py +0 -0
  185. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/utils/se/test_homoglyphs.py +0 -0
  186. {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.0}/tests/utils/test_generator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-obfuscation-framework
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary: Python Obfuscation Framework
5
5
  Author-email: deoktr <35725720+deoktr@users.noreply.github.com>
6
6
  Maintainer-email: deoktr <35725720+deoktr@users.noreply.github.com>
@@ -795,20 +795,50 @@ exec(binascii.a2b_hex("".join(['7072696e-7428-2748-656c-6c6f2c20776f','726c6427-
795
795
 
796
796
  #### ImportsObfuscator
797
797
 
798
- Source: `import pathlib`
798
+ Remove keyword `import`.
799
799
 
800
800
  ```python
801
- pathlib=__import__('pathlib')
801
+ # import X
802
+ X = __import__("X")
803
+
804
+ # import X as Y
805
+ Y = __import__("X")
806
+
807
+ # import X, Y
808
+ X = __import__("X")
809
+ Y = __import__("Y")
810
+
811
+ # import X.Y
812
+ X = __import__("X.Y")
813
+
814
+ # from X import Y
815
+ Y = __import__("X", fromlist=["Y"]).Y
816
+
817
+ # from X import Y as Z
818
+ Z = __import__("X", fromlist=["Y"]).Y
819
+
820
+ # from X import Y, Z
821
+ Y = __import__("X", fromlist=["Y"]).Y
822
+ Z = __import__("X", fromlist=["Z"]).Z
802
823
  ```
803
824
 
825
+ > [!NOTE]
826
+ > Does not support wildcard imports `*`, or local imports `from . import`.
827
+
804
828
  #### CharFromDocObfuscator
805
829
 
830
+ Get a single character from a documentation.
831
+
806
832
  Source: `print('h')`
807
833
 
808
834
  ```python
809
835
  print(oct.__doc__[8])
810
836
  ```
811
837
 
838
+ > [!WARNING]
839
+ > This is highly prone to error, if the documentation change between Python
840
+ > versions, then this may break.
841
+
812
842
  #### AddCommentsObfuscator
813
843
 
814
844
  ```python
@@ -1372,7 +1402,6 @@ Other Python obfuscation projects:
1372
1402
 
1373
1403
  ## TODO
1374
1404
 
1375
- - Fix `NamesObfuscator`.
1376
1405
  - Add option to prepend a shebang, and add ability to customize it.
1377
1406
 
1378
1407
  ## License
@@ -750,20 +750,50 @@ exec(binascii.a2b_hex("".join(['7072696e-7428-2748-656c-6c6f2c20776f','726c6427-
750
750
 
751
751
  #### ImportsObfuscator
752
752
 
753
- Source: `import pathlib`
753
+ Remove keyword `import`.
754
754
 
755
755
  ```python
756
- pathlib=__import__('pathlib')
756
+ # import X
757
+ X = __import__("X")
758
+
759
+ # import X as Y
760
+ Y = __import__("X")
761
+
762
+ # import X, Y
763
+ X = __import__("X")
764
+ Y = __import__("Y")
765
+
766
+ # import X.Y
767
+ X = __import__("X.Y")
768
+
769
+ # from X import Y
770
+ Y = __import__("X", fromlist=["Y"]).Y
771
+
772
+ # from X import Y as Z
773
+ Z = __import__("X", fromlist=["Y"]).Y
774
+
775
+ # from X import Y, Z
776
+ Y = __import__("X", fromlist=["Y"]).Y
777
+ Z = __import__("X", fromlist=["Z"]).Z
757
778
  ```
758
779
 
780
+ > [!NOTE]
781
+ > Does not support wildcard imports `*`, or local imports `from . import`.
782
+
759
783
  #### CharFromDocObfuscator
760
784
 
785
+ Get a single character from a documentation.
786
+
761
787
  Source: `print('h')`
762
788
 
763
789
  ```python
764
790
  print(oct.__doc__[8])
765
791
  ```
766
792
 
793
+ > [!WARNING]
794
+ > This is highly prone to error, if the documentation change between Python
795
+ > versions, then this may break.
796
+
767
797
  #### AddCommentsObfuscator
768
798
 
769
799
  ```python
@@ -1327,7 +1357,6 @@ Other Python obfuscation projects:
1327
1357
 
1328
1358
  ## TODO
1329
1359
 
1330
- - Fix `NamesObfuscator`.
1331
1360
  - Add option to prepend a shebang, and add ability to customize it.
1332
1361
 
1333
1362
  ## License
@@ -183,31 +183,31 @@ class CharFromDocObfuscator:
183
183
  )
184
184
 
185
185
  @staticmethod
186
- def get_char_indexes(string, char):
186
+ def _get_char_indexes(string, char):
187
187
  return [pos for pos, c in enumerate(string) if c == char]
188
188
 
189
189
  @classmethod
190
- def try_find_doc_index(cls, char):
190
+ def _try_find_doc_index(cls, char):
191
191
  # take a random builtin doc and search for index in it
192
192
  builtin = random.choice(cls.BUILTINS)
193
193
  doc = __builtins__[builtin].__doc__
194
194
  if not doc:
195
195
  msg = f"doc for {builtin} is not a string"
196
196
  raise PofError(msg)
197
- indexes = cls.get_char_indexes(doc, char)
197
+ indexes = cls._get_char_indexes(doc, char)
198
198
  if len(indexes) == 0:
199
199
  msg = "char not present"
200
200
  raise PofError(msg)
201
201
  index = random.choice(indexes)
202
202
  return builtin, index
203
203
 
204
- def obfuscate_char(self, char):
204
+ def _obfuscate_char(self, char):
205
205
  builtin = None
206
206
  index = None
207
207
  retry = 3
208
208
  for _ in range(retry):
209
209
  try:
210
- builtin, index = self.try_find_doc_index(char)
210
+ builtin, index = self._try_find_doc_index(char)
211
211
  except PofError:
212
212
  pass
213
213
  else:
@@ -239,7 +239,7 @@ class CharFromDocObfuscator:
239
239
  string = ast.literal_eval(tokval)
240
240
  if len(string) == 1:
241
241
  try:
242
- new_tokens = self.obfuscate_char(string)
242
+ new_tokens = self._obfuscate_char(string)
243
243
  except PofError as e:
244
244
  logger.debug(str(e))
245
245
  except Exception: # noqa: BLE001
@@ -47,7 +47,7 @@ class GlobalsObfuscator:
47
47
  local_functions.append(tokval)
48
48
  prev_tokval = tokval
49
49
 
50
- result = [] # obfuscated tokens
50
+ result = []
51
51
  prev_tokval = None
52
52
  for index, (toknum, tokval, *_) in enumerate(tokens):
53
53
  new_tokens = [(toknum, tokval)]
@@ -60,7 +60,7 @@ class GlobalsObfuscator:
60
60
  # ensure it's not a definition
61
61
  and prev_tokval not in ["def", "class", "."]
62
62
  # ensure it's not an argument of a call
63
- and next_tokval not in ["="]
63
+ and next_tokval != "="
64
64
  and tokval not in cls.RESERVED
65
65
  ):
66
66
  new_tokens = [
@@ -0,0 +1,257 @@
1
+ # POF, a free and open source Python obfuscation framework.
2
+ # Copyright (C) 2022 - 2026 Deoktr
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ from tokenize import ENDMARKER, NAME, NEWLINE, NL, OP, STRING
18
+
19
+
20
+ class ImportsObfuscator:
21
+ """Obfuscate import statements using __import__().
22
+
23
+ Supported forms:
24
+
25
+ ```
26
+ # import X
27
+ X = __import__("X")
28
+
29
+ # import X as Y
30
+ Y = __import__("X")
31
+
32
+ # import X, Y
33
+ X = __import__("X")
34
+ Y = __import__("Y")
35
+
36
+ # import X.Y
37
+ X = __import__("X.Y")
38
+
39
+ # from X import Y
40
+ Y = __import__("X", fromlist=["Y"]).Y
41
+
42
+ # from X import Y as Z
43
+ Z = __import__("X", fromlist=["Y"]).Y
44
+
45
+ # from X import Y, Z
46
+ Y = __import__("X", fromlist=["Y"]).Y
47
+ Z = __import__("X", fromlist=["Z"]).Z
48
+ ```
49
+
50
+ Left unchanged:
51
+
52
+ ```
53
+ from X import *
54
+ from . import X
55
+ ```
56
+ """
57
+
58
+ @staticmethod
59
+ def _is_statement_start(preceding_tokens: list) -> bool:
60
+ """Check if the current position is a valid statement start."""
61
+ if not preceding_tokens:
62
+ return True
63
+ for toknum, _ in reversed(preceding_tokens):
64
+ if toknum in (NEWLINE, NL, ENDMARKER):
65
+ return True
66
+ if toknum in (NAME, OP, STRING):
67
+ return False
68
+ return True
69
+
70
+ @classmethod
71
+ def _transform_import(cls, stmt_tokens: list) -> list | None:
72
+ """Transform collected import statement tokens into __import__() calls.
73
+
74
+ Returns None if the import should be left unchanged.
75
+ """
76
+ body = [
77
+ (t, v)
78
+ for t, v in stmt_tokens
79
+ if t not in (NEWLINE, NL, ENDMARKER) and v not in ("(", ")")
80
+ ]
81
+ trailing = [(t, v) for t, v in stmt_tokens if t in (NEWLINE, NL, ENDMARKER)]
82
+
83
+ if not body:
84
+ return None
85
+
86
+ first_val = body[0][1]
87
+
88
+ if first_val == "import":
89
+ return cls._transform_simple_import(body[1:]) + trailing
90
+ if first_val == "from":
91
+ t = cls._transform_from_import(body[1:])
92
+ if t is None:
93
+ return None
94
+ return t + trailing
95
+ return None
96
+
97
+ @classmethod
98
+ def _transform_simple_import(cls, tokens: list) -> list:
99
+ """Transform: import X / import X as Y / import X, Y / import X.Y."""
100
+ groups = cls._split_by_comma(tokens)
101
+ result: list = []
102
+
103
+ for group in groups:
104
+ if not group:
105
+ continue
106
+ if result:
107
+ result.append((NEWLINE, "\n"))
108
+
109
+ names, alias = cls._extract_alias(group)
110
+ module_name = cls._join_dotted_name(names)
111
+ bind_name = alias or names[0][1]
112
+
113
+ result.extend(
114
+ [
115
+ (NAME, bind_name),
116
+ (OP, "="),
117
+ (NAME, "__import__"),
118
+ (OP, "("),
119
+ (STRING, repr(module_name)),
120
+ (OP, ")"),
121
+ ],
122
+ )
123
+
124
+ return result
125
+
126
+ @classmethod
127
+ def _transform_from_import(cls, tokens: list) -> list | None:
128
+ """Transform: from X import Y / from X import Y as Z / from X import Y, Z.
129
+
130
+ Returns None for relative imports or wildcard imports.
131
+ """
132
+ import_idx = None
133
+ for idx, (_, v) in enumerate(tokens):
134
+ if v == "import":
135
+ import_idx = idx
136
+ break
137
+
138
+ if import_idx is None:
139
+ return None
140
+
141
+ module_tokens = tokens[:import_idx]
142
+ name_tokens = tokens[import_idx + 1 :]
143
+
144
+ if any(v == "." for _, v in module_tokens):
145
+ return None
146
+
147
+ if any(v == "*" for _, v in name_tokens):
148
+ return None
149
+
150
+ module_name = cls._join_dotted_name(module_tokens)
151
+
152
+ groups = cls._split_by_comma(name_tokens)
153
+ result: list = []
154
+
155
+ for group in groups:
156
+ if not group:
157
+ continue
158
+ if result:
159
+ result.append((NEWLINE, "\n"))
160
+
161
+ names, alias = cls._extract_alias(group)
162
+ imported_name = names[0][1]
163
+ bind_name = alias or imported_name
164
+
165
+ result.extend(
166
+ [
167
+ (NAME, bind_name),
168
+ (OP, "="),
169
+ (NAME, "__import__"),
170
+ (OP, "("),
171
+ (STRING, repr(module_name)),
172
+ (OP, ","),
173
+ (NAME, "fromlist"),
174
+ (OP, "="),
175
+ (OP, "["),
176
+ (STRING, repr(imported_name)),
177
+ (OP, "]"),
178
+ (OP, ")"),
179
+ (OP, "."),
180
+ (NAME, imported_name),
181
+ ],
182
+ )
183
+
184
+ return result
185
+
186
+ @staticmethod
187
+ def _split_by_comma(tokens: list) -> list[list]:
188
+ """Split a token list by comma operators."""
189
+ groups: list[list] = [[]]
190
+ for toknum, tokval in tokens:
191
+ if toknum == OP and tokval == ",":
192
+ groups.append([])
193
+ else:
194
+ groups[-1].append((toknum, tokval))
195
+ return groups
196
+
197
+ @staticmethod
198
+ def _extract_alias(tokens: list) -> tuple[list, str | None]:
199
+ """Extract name tokens and alias from a token group.
200
+
201
+ Returns (name_tokens, alias_string_or_None).
202
+ """
203
+ alias = None
204
+ name_tokens = []
205
+ saw_as = False
206
+ for toknum, tokval in tokens:
207
+ if tokval == "as":
208
+ saw_as = True
209
+ elif saw_as:
210
+ alias = tokval
211
+ saw_as = False
212
+ else:
213
+ name_tokens.append((toknum, tokval))
214
+ return name_tokens, alias
215
+
216
+ @staticmethod
217
+ def _join_dotted_name(tokens: list) -> str:
218
+ """Join NAME and OP('.') tokens into a dotted module name string."""
219
+ return "".join(v for _, v in tokens)
220
+
221
+ @classmethod
222
+ def obfuscate_tokens(cls, tokens: list) -> list:
223
+ result: list = []
224
+ i = 0
225
+ while i < len(tokens):
226
+ toknum, tokval, *_ = tokens[i]
227
+
228
+ if (
229
+ toknum == NAME
230
+ and tokval in ("import", "from")
231
+ and cls._is_statement_start(result)
232
+ ):
233
+ stmt_tokens = []
234
+ j = i
235
+ paren_depth = 0
236
+ while j < len(tokens):
237
+ st, sv, *_ = tokens[j]
238
+ stmt_tokens.append((st, sv))
239
+ if sv == "(":
240
+ paren_depth += 1
241
+ elif sv == ")":
242
+ paren_depth -= 1
243
+ if st in (NEWLINE, NL, ENDMARKER) and paren_depth <= 0:
244
+ break
245
+ j += 1
246
+
247
+ replacement = cls._transform_import(stmt_tokens)
248
+ if replacement is not None:
249
+ result.extend(replacement)
250
+ else:
251
+ result.extend(stmt_tokens)
252
+ i = j + 1
253
+ continue
254
+
255
+ result.append((toknum, tokval))
256
+ i += 1
257
+ return result
@@ -50,6 +50,22 @@ class _ScopeAnalyzer(ast.NodeVisitor):
50
50
  self.imported_names.add(alias.asname or alias.name)
51
51
  self.generic_visit(node)
52
52
 
53
+ def visit_Assign(self, node: ast.Assign) -> None:
54
+ """Detect `x = __import__(...)` and treat x as an imported name."""
55
+ if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
56
+ value = node.value
57
+ # unwrap attribute chains: x = __import__("m", fromlist=["y"]).y
58
+ # as they could be generated from the ImportObfuscator
59
+ while isinstance(value, ast.Attribute):
60
+ value = value.value
61
+ if (
62
+ isinstance(value, ast.Call)
63
+ and isinstance(value.func, ast.Name)
64
+ and value.func.id == "__import__"
65
+ ):
66
+ self.imported_names.add(node.targets[0].id)
67
+ self.generic_visit(node)
68
+
53
69
  def visit_ClassDef(self, node: ast.ClassDef) -> None:
54
70
  self.class_names.add(node.name)
55
71
  prev = self._in_class
@@ -38,9 +38,8 @@ class IPv6Encoding:
38
38
 
39
39
  for sc in string_chunks:
40
40
  string_chunk = sc
41
- if len(string_chunk) < cls.IPV6_LEN:
42
- padding = cls.IPV6_LEN - len(string_chunk)
43
- # TODO (deoktr): choose this randomly (anything BUT the padding_byte)
41
+ padding = cls.IPV6_LEN - len(string_chunk)
42
+ if padding > 0:
44
43
  string_chunk += b"1"
45
44
  string_chunk += cls.padding_byte * (padding - 1)
46
45
 
@@ -53,6 +52,11 @@ class IPv6Encoding:
53
52
 
54
53
  ipv6_list.append(ipv6)
55
54
 
55
+ if len(hex_string) % cls.IPV6_LEN == 0 and len(hex_string) > 0:
56
+ pad_chunk = (b"1" + cls.padding_byte * (cls.IPV6_LEN - 1)).decode()
57
+ ipv6_chunks = [pad_chunk[i : i + 4] for i in range(0, len(pad_chunk), 4)]
58
+ ipv6_list.append(":".join(ipv6_chunks))
59
+
56
60
  return ipv6_list
57
61
 
58
62
  @classmethod
@@ -78,7 +82,7 @@ class IPv6Encoding:
78
82
  """IPv6 decode tokens.
79
83
 
80
84
  ```
81
- binascii.a2b_hex("".join(["...",]).replace(":", "").strip("0")[:-1])
85
+ binascii.a2b_hex("".join(["...",]).replace(":", "").rstrip("0")[:-1])
82
86
  ```.
83
87
  """
84
88
  return [
@@ -100,7 +104,7 @@ class IPv6Encoding:
100
104
  (STRING, repr("")),
101
105
  (OP, ")"),
102
106
  (OP, "."),
103
- (NAME, "strip"),
107
+ (NAME, "rstrip"),
104
108
  (OP, "("),
105
109
  (STRING, repr(cls.padding_byte.decode())),
106
110
  (OP, ")"),
@@ -37,9 +37,8 @@ class MACEncoding:
37
37
 
38
38
  for sc in string_chunks:
39
39
  string_chunk = sc
40
- if len(string_chunk) < cls.MAC_LEN:
41
- padding = cls.MAC_LEN - len(string_chunk)
42
- # TODO (deoktr): choose this randomly (anything BUT the padding_byte)
40
+ padding = cls.MAC_LEN - len(string_chunk)
41
+ if padding > 0:
43
42
  string_chunk += b"1"
44
43
  string_chunk += cls.padding_byte * (padding - 1)
45
44
 
@@ -52,6 +51,11 @@ class MACEncoding:
52
51
 
53
52
  mac_list.append(mac)
54
53
 
54
+ if len(hex_string) % cls.MAC_LEN == 0 and len(hex_string) > 0:
55
+ pad_chunk = (b"1" + cls.padding_byte * (cls.MAC_LEN - 1)).decode()
56
+ mac_chunks = [pad_chunk[i : i + 2] for i in range(0, len(pad_chunk), 2)]
57
+ mac_list.append("-".join(mac_chunks))
58
+
55
59
  return mac_list
56
60
 
57
61
  @classmethod
@@ -77,7 +81,7 @@ class MACEncoding:
77
81
  """MAC encoding decode tokens.
78
82
 
79
83
  ```
80
- binascii.a2b_hex("".join(["...",]).replace("-", "").strip("0")[:-1])
84
+ binascii.a2b_hex("".join(["...",]).replace("-", "").rstrip("0")[:-1])
81
85
  ```.
82
86
  """
83
87
  return [
@@ -99,7 +103,7 @@ class MACEncoding:
99
103
  (STRING, repr("")),
100
104
  (OP, ")"),
101
105
  (OP, "."),
102
- (NAME, "strip"),
106
+ (NAME, "rstrip"),
103
107
  (OP, "("),
104
108
  (STRING, repr(cls.padding_byte.decode())),
105
109
  (OP, ")"),
@@ -40,9 +40,8 @@ class UUIDEncoding:
40
40
 
41
41
  for string_chunk in string_chunks:
42
42
  sc = string_chunk
43
- if len(sc) < cls.UUID_LEN:
44
- padding = cls.UUID_LEN - len(sc)
45
- # TODO (deoktr): choose this randomly (anything BUT the padding_byte)
43
+ padding = cls.UUID_LEN - len(sc)
44
+ if padding > 0:
46
45
  sc += b"1"
47
46
  sc += cls.padding_byte * (padding - 1)
48
47
 
@@ -58,6 +57,17 @@ class UUIDEncoding:
58
57
 
59
58
  uuid_list.append(uuid)
60
59
 
60
+ if len(hex_string) % cls.UUID_LEN == 0 and len(hex_string) > 0:
61
+ pc = (b"1" + cls.padding_byte * (cls.UUID_LEN - 1)).decode()
62
+ uuid_chunks = [
63
+ pc[0:8],
64
+ pc[8:12],
65
+ pc[12:16],
66
+ pc[16:20],
67
+ pc[20:],
68
+ ]
69
+ uuid_list.append("-".join(uuid_chunks))
70
+
61
71
  return uuid_list
62
72
 
63
73
  @classmethod
@@ -83,7 +93,7 @@ class UUIDEncoding:
83
93
  """UUID decode tokens.
84
94
 
85
95
  ```
86
- binascii.a2b_hex("".join(["...",]).replace("-", "").strip("0")[:-1])
96
+ binascii.a2b_hex("".join(["...",]).replace("-", "").rstrip("0")[:-1])
87
97
  ```
88
98
  """
89
99
  return [
@@ -105,7 +115,7 @@ class UUIDEncoding:
105
115
  (STRING, '""'),
106
116
  (OP, ")"),
107
117
  (OP, "."),
108
- (NAME, "strip"),
118
+ (NAME, "rstrip"),
109
119
  (OP, "("),
110
120
  (STRING, repr(cls.padding_byte.decode())),
111
121
  (OP, ")"),
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-obfuscation-framework"
7
- version = "1.10.0"
7
+ version = "1.11.0"
8
8
  description = "Python Obfuscation Framework"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-obfuscation-framework
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary: Python Obfuscation Framework
5
5
  Author-email: deoktr <35725720+deoktr@users.noreply.github.com>
6
6
  Maintainer-email: deoktr <35725720+deoktr@users.noreply.github.com>
@@ -795,20 +795,50 @@ exec(binascii.a2b_hex("".join(['7072696e-7428-2748-656c-6c6f2c20776f','726c6427-
795
795
 
796
796
  #### ImportsObfuscator
797
797
 
798
- Source: `import pathlib`
798
+ Remove keyword `import`.
799
799
 
800
800
  ```python
801
- pathlib=__import__('pathlib')
801
+ # import X
802
+ X = __import__("X")
803
+
804
+ # import X as Y
805
+ Y = __import__("X")
806
+
807
+ # import X, Y
808
+ X = __import__("X")
809
+ Y = __import__("Y")
810
+
811
+ # import X.Y
812
+ X = __import__("X.Y")
813
+
814
+ # from X import Y
815
+ Y = __import__("X", fromlist=["Y"]).Y
816
+
817
+ # from X import Y as Z
818
+ Z = __import__("X", fromlist=["Y"]).Y
819
+
820
+ # from X import Y, Z
821
+ Y = __import__("X", fromlist=["Y"]).Y
822
+ Z = __import__("X", fromlist=["Z"]).Z
802
823
  ```
803
824
 
825
+ > [!NOTE]
826
+ > Does not support wildcard imports `*`, or local imports `from . import`.
827
+
804
828
  #### CharFromDocObfuscator
805
829
 
830
+ Get a single character from a documentation.
831
+
806
832
  Source: `print('h')`
807
833
 
808
834
  ```python
809
835
  print(oct.__doc__[8])
810
836
  ```
811
837
 
838
+ > [!WARNING]
839
+ > This is highly prone to error, if the documentation change between Python
840
+ > versions, then this may break.
841
+
812
842
  #### AddCommentsObfuscator
813
843
 
814
844
  ```python
@@ -1372,7 +1402,6 @@ Other Python obfuscation projects:
1372
1402
 
1373
1403
  ## TODO
1374
1404
 
1375
- - Fix `NamesObfuscator`.
1376
1405
  - Add option to prepend a shebang, and add ability to customize it.
1377
1406
 
1378
1407
  ## License