from setuptools import setup, Distribution, find_packages
from setuptools.command.install import install
from distutils.command.build import build as _build
import os
import re
import shutil
import subprocess
import sys
from pathlib import Path
import wheel.bdist_wheel
sys.dont_write_bytecode = True
if sys.version_info < (3, 6):
print("cryptatools requires at least Python 3.6", file=sys.stderr)
sys.exit(1)
from pathlib import Path
PYTHON_ROOT = Path(__file__).parent.absolute()
FROM_TOP = PYTHON_ROOT.relative_to(Path.cwd())
SRC_ROOT = PYTHON_ROOT.parents[1]
requirements = [
"wheel",
"setuptools",
]
buildvariant = os.environ.get("GLEAN_BUILD_VARIANT", "debug")
class BinaryDistribution(Distribution):
def is_pure(self):
return False
def has_ext_modules(self):
return True
def macos_compat(target):
if target.startswith("aarch64-"):
return "11.0"
return "10.7"
class bdist_wheel(wheel.bdist_wheel.bdist_wheel):
def get_tag(self):
cpu, _, __ = target.partition("-")
impl, abi_tag = "cp36", "abi3"
if "-linux" in target:
plat_name = f"linux_{cpu}"
elif "-darwin" in target:
compat = macos_compat(target).replace(".", "_")
if cpu == "aarch64":
cpu = "arm64"
plat_name = f"macosx_{compat}_{cpu}"
elif "-windows" in target:
impl, abi_tag = "py3", "none"
if cpu == "i686":
plat_name = "win32"
elif cpu == "x86_64":
plat_name = "win_amd64"
else:
raise ValueError("Unsupported Windows platform")
else:
_, __, plat_name = super().get_tag()
return (impl, abi_tag, plat_name)
class InstallPlatlib(install):
def finalize_options(self):
install.finalize_options(self)
if self.distribution.has_ext_modules():
self.install_lib = self.install_platlib
def get_rustc_info():
regex = re.compile(r"(?P<key>[^:]+)(: *(?P<value>\S+))")
output = subprocess.check_output(["rustc", "--version", "--verbose"])
data = {}
for line in output.decode("utf-8").splitlines():
match = regex.match(line)
if match:
d = match.groupdict()
data[d["key"]] = d["value"]
return data
target = os.environ.get("GLEAN_BUILD_TARGET")
if not target:
target = get_rustc_info()["host"]
extension = ""
file_start = ""
if "-darwin" in target:
shared_object = "libcryptatools_core.dylib"
extension = ".dylib"
file_start = "lib"
elif "-windows" in target:
shared_object = "cryptatools_core.dll"
extension = ".dll"
file_start = ""
else:
shared_object = "libcryptatools_core.so"
extension = ".so"
file_start = "lib"
new_shared_object_name = file_start + "uniffi_cryptatools" + extension
class build(_build):
def run(self):
try:
subprocess.check_output(["cargo"])
except subprocess.CalledProcessError:
print("Install Rust and Cargo through Rustup: https://rustup.rs/.")
print(
"Need help installing the glean_sdk? https://github.com/mozilla/glean/#contact"
)
sys.exit(1)
env = os.environ.copy()
if "-musl" in target:
env["RUSTFLAGS"] = (
env.get("RUSTFLAGS", "") + " -C target-feature=-crt-static"
)
if target == "i686-pc-windows-gnu":
env["RUSTFLAGS"] = env.get("RUSTFLAGS", "") + " -C panic=abort"
command = [
"cargo",
"build",
"--package",
"cryptatools-core",
"--target",
target,
]
if buildvariant != "debug":
command.append(f"--{buildvariant}")
if "-darwin" in target:
env["MACOSX_DEPLOYMENT_TARGET"] = macos_compat(target)
subprocess.check_call(command, env=env)
shutil.copyfile(
SRC_ROOT / "cryptatools-rs" / "target" / target / buildvariant / "deps" / shared_object,
SRC_ROOT / "cryptatools-rs" / "cryptatools-core" / "bindings" / "python3" / "cryptatools-core" / new_shared_object_name,
)
command = [
"cargo",
"run",
"--features=uniffi/cli",
"--bin",
"uniffi-bindgen",
"generate",
"src/cryptatools.udl",
"--language",
"python",
"--out-dir",
SRC_ROOT / "cryptatools-rs" / "target",
]
subprocess.check_call(command, cwd=Path("cryptatools-core"), env=env)
shutil.copyfile(
SRC_ROOT / "cryptatools-rs" / "target" / "cryptatools.py", SRC_ROOT / "cryptatools-rs" / "cryptatools-core" / "bindings" / "python3" / "cryptatools-core" / "python3_bindings.py"
)
return _build.run(self)
long_description = (Path(__file__).parent.parent / "README.md").read_text()
setup(
author="gogo2464",
author_email="gogo246475@gmail.com",
classifiers=[
"Intended Audience :: Developers",
"Natural Language :: English",
"Programming Language :: Python :: 3"
],
description="Python Binding of the library and cryptanalysis tool 'cryptatools'.",
long_description=long_description,
install_requires=requirements,
long_description_content_type="text/markdown",
include_package_data=True,
keywords="cryptatools",
name="cryptatools-python3",
version="0.1.14",
packages=[
"cryptatools_core",
"cryptatools_core.cryptography",
"cryptatools_core.cryptography.encryption",
"cryptatools_core.cryptography.encryption.monoalphabetic_cipher",
"cryptatools_core.cryptography.encryption.transpositional_ciphers",
"cryptatools_core.utils",
"cryptatools_core.cryptanalysis",
"cryptatools_core.cryptanalysis.general_cryptanalysis_methods",
"cryptatools_core.cryptanalysis.general_cryptanalysis_methods.frequency_analysis",
],
package_dir={
"cryptatools_core": "cryptatools-core/bindings/python3/cryptatools-core",
"cryptography": "cryptatools-core/bindings/python3/cryptatools-core/cryptography",
"encryption": "cryptatools_core/cryptography/encryption",
"monoalphabetic_cipher": "cryptatools_core/cryptography/encryption/monoalphabetic_cipher",
"transpositional_ciphers": "cryptatools_core/cryptography/encryption/transpositional_ciphers",
"utils": "cryptatools_core/utils",
"cryptanalysis": "cryptatools_core/cryptanalysis",
"general_cryptanalysis_methods": "cryptatools_core/cryptanalysis/general_cryptanalysis_methods",
"frequency_analysis": "cryptatools_core/cryptanalysis/general_cryptanalysis_methods/frequency_analysis",
},
setup_requires=requirements,
url="https://github.com/gogo2464/cryptatools-rs",
zip_safe=False,
package_data={"cryptatools_core": [new_shared_object_name]},
distclass=BinaryDistribution,
cmdclass={"install": InstallPlatlib, "bdist_wheel": bdist_wheel, "build": build},
)