Skip to content

Commit

Permalink
removing openw class
Browse files Browse the repository at this point in the history
  • Loading branch information
ye11owSub committed Sep 13, 2024
1 parent 401a386 commit f807d34
Showing 1 changed file with 73 additions and 119 deletions.
192 changes: 73 additions & 119 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@

import argparse
import glob
import io as cStringIO
import os
import pathlib
import re
import shutil
import sys
import sysconfig
import time
from collections import defaultdict
from itertools import chain
from pathlib import Path
from subprocess import PIPE, Popen

import numpy
Expand All @@ -26,97 +26,63 @@
from setuptools.command.install import install

# non-empty DEBUG variable turns off optimization and adds -g flag
DEBUG = bool(os.getenv("DEBUG", ""))
DEBUG = os.getenv("DEBUG", False)
WIN = sys.platform.startswith("win")
MAC = sys.platform.startswith("darwin")


# Have to copy from "create_shadertext.py" script due to the use of pyproject.toml
# Full explanation:
# https://github.com/pypa/setuptools/issues/3939
def create_all(generated_dir, pymoldir="."):
def create_all(generated_dir: str, pymol_dir: str = "."):
"""
Generate various stuff
"""
create_shadertext(
os.path.join(pymoldir, "data", "shaders"),
generated_dir,
os.path.join(generated_dir, "ShaderText.h"),
os.path.join(generated_dir, "ShaderText.cpp"),
)
create_buildinfo(generated_dir, pymoldir)


class openw(object):
"""
File-like object for writing files. File is actually only
written if the content changed.
"""

def __init__(self, filename):
if os.path.exists(filename):
self.out = cStringIO.StringIO()
self.filename = filename
else:
os.makedirs(os.path.dirname(filename), exist_ok=True)
self.out = open(filename, "w")
self.filename = None
generated_dir_path = Path(generated_dir)
pymol_dir_path = Path(pymol_dir)

def close(self):
if self.out.closed:
return
if self.filename:
with open(self.filename) as handle:
oldcontents = handle.read()
newcontents = self.out.getvalue()
if oldcontents != newcontents:
self.out = open(self.filename, "w")
self.out.write(newcontents)
self.out.close()

def __getattr__(self, name):
return getattr(self.out, name)

def __enter__(self):
return self

def __exit__(self, *a, **k):
self.close()

def __del__(self):
self.close()
generated_dir_path.mkdir(parents=True, exist_ok=True)
pymol_dir_path.mkdir(parents=True, exist_ok=True)

create_shadertext(
shader_dir=pymol_dir_path / "data" / "shaders",
shader_dir2=pymol_dir_path,
output_header_file=pymol_dir_path / "ShaderText.h",
output_source_file=generated_dir_path / "ShaderText.cpp",
)
create_buildinfo(generated_dir, pymol_dir)

def create_shadertext(shaderdir, shaderdir2, outputheader, outputfile):
outputheader = openw(outputheader)
outputfile = openw(outputfile)

def create_shadertext(
shader_dir: Path,
shader_dir2: Path,
output_header_file: Path,
output_source_file: Path,
):
varname = "_shader_cache_raw"
include_deps = defaultdict(set)
ifdef_deps = defaultdict(set)
extension_regexp = "*.[gs][vs][fs][shared][tsc][tse]"

# get all *.gs *.vs *.fs *.shared from the two input directories
shaderfiles = set()
for sdir in [shaderdir, shaderdir2]:
for ext in ["gs", "vs", "fs", "shared", "tsc", "tse"]:
shaderfiles.update(
map(os.path.basename, sorted(glob.glob(os.path.join(sdir, "*." + ext))))
)

varname = "_shader_cache_raw"
outputheader.write("extern const char * %s[];\n" % varname)
outputfile.write("const char * %s[] = {\n" % varname)

for filename in sorted(shaderfiles):
shaderfile = os.path.join(shaderdir, filename)
if not os.path.exists(shaderfile):
shaderfile = os.path.join(shaderdir2, filename)
shaderfiles = set(
chain(
shader_dir.glob(extension_regexp),
shader_dir2.glob(extension_regexp),
)
)

with open(shaderfile, "r") as handle:
contents = handle.read()
with (
open(output_header_file, "w") as output_header_descriptor,
open(output_source_file, "w") as output_source_descriptor,
):
output_header_descriptor.write(f"extern const char * {varname}[];\n")
output_source_descriptor.write(f"const char * {varname}[] = {{\n")

if True:
outputfile.write('"%s", ""\n' % (filename))
for filename in shaderfiles:
output_source_descriptor.write(f'"{filename.name}", ""\n')

contents = filename.read_text()
for line in contents.splitlines():
line = line.strip()

Expand All @@ -125,52 +91,43 @@ def create_shadertext(shaderdir, shaderdir2, outputheader, outputfile):
continue

# write line, quoted, escaped and with a line feed
outputfile.write(
'"%s\\n"\n' % line.replace("\\", "\\\\").replace('"', r"\"")
)
escaped_line = line.replace("\\", "\\\\").replace('"', r"\"")
output_source_descriptor.write(f'"{escaped_line}\\n"\n')

# include and ifdef dependencies
if line.startswith("#include"):
include_deps[line.split()[1]].add(filename)
elif line.startswith("#ifdef") or line.startswith("#ifndef"):
ifdef_deps[line.split()[1]].add(filename)

outputfile.write(",\n")

outputfile.write("0};\n")

# include and ifdef dependencies
for varname, deps in [("_include_deps", include_deps), ("_ifdef_deps", ifdef_deps)]:
outputheader.write("extern const char * %s[];\n" % varname)
outputfile.write("const char * %s[] = {\n" % varname)
for name, itemdeps in deps.items():
outputfile.write('"%s", "%s", 0,\n' % (name, '", "'.join(sorted(itemdeps))))
outputfile.write("0};\n")
output_source_descriptor.write(",\n")
output_source_descriptor.write("0};\n")

outputheader.close()
outputfile.close()


def create_buildinfo(outputdir, pymoldir="."):
try:
sha = (
Popen(["git", "rev-parse", "HEAD"], cwd=pymoldir, stdout=PIPE)
.stdout.read()
.strip()
.decode()
)
except OSError:
sha = ""

with openw(os.path.join(outputdir, "PyMOLBuildInfo.h")) as out:
print(
"""
#define _PyMOL_BUILD_DATE %d
#define _PYMOL_BUILD_GIT_SHA "%s"
"""
% (time.time(), sha),
file=out,
)
# include and ifdef dependencies
for varname, deps in [
("_include_deps", include_deps),
("_ifdef_deps", ifdef_deps),
]:
output_header_descriptor.write(f"extern const char * {varname}[];\n")
output_source_descriptor.write(f"const char * {varname}[] = {{\n")
for name, item_deps in deps.items():
item_deps = '", "'.join(sorted(item_deps))
output_source_descriptor.write(f'"{name}", "{item_deps}", 0,\n')
output_source_descriptor.write("0};\n")


def create_buildinfo(output_dir_path: str, pymoldir: str = "."):
output_dir = Path(output_dir_path)
sha_raw = Popen(["git", "rev-parse", "HEAD"], cwd=pymoldir, stdout=PIPE).stdout
sha = sha_raw.read().strip().decode() if sha_raw is not None else ""

info_file = output_dir / "PyMOLBuildInfo.h"
info_file.write_text(
f"""
#define _PyMOL_BUILD_DATE {time.time()}
#define _PYMOL_BUILD_GIT_SHA "{sha}"
"""
)


# handle extra arguments
Expand Down Expand Up @@ -302,7 +259,6 @@ def guess_msgpackc():


class CMakeExtension(Extension):

def __init__(
self,
name,
Expand Down Expand Up @@ -336,15 +292,15 @@ def run(self):
self.build_cmake(ext)

def build_cmake(self, ext):
cwd = pathlib.Path().absolute()
cwd = Path().absolute()

# these dirs will be created in build_py, so if you don't have
# any python sources to bundle, the dirs will be missing
name_split = ext.name.split(".")
target_name = name_split[-1]
build_temp = pathlib.Path(self.build_temp) / target_name
build_temp = Path(self.build_temp) / target_name
build_temp.mkdir(parents=True, exist_ok=True)
extdir = pathlib.Path(self.get_ext_fullpath(ext.name))
extdir = Path(self.get_ext_fullpath(ext.name))
extdirabs = extdir.absolute()

extdir.parent.mkdir(parents=True, exist_ok=True)
Expand Down Expand Up @@ -394,7 +350,7 @@ def concat_paths(paths):

if WIN:
# Move up from VS release folder
cmake_lib_loc = pathlib.Path(
cmake_lib_loc = Path(
lib_output_dir, "Release", f"{target_name}{shared_suffix}"
)
if cmake_lib_loc.exists():
Expand Down Expand Up @@ -487,7 +443,7 @@ def make_launch_script(self):
launch_script = os.path.join(self.install_scripts, launch_script)

python_exe = os.path.abspath(sys.executable)
site_packages_dir = sysconfig.get_path('purelib')
site_packages_dir = sysconfig.get_path("purelib")
pymol_file = self.unchroot(
os.path.join(site_packages_dir, "pymol", "__init__.py")
)
Expand Down Expand Up @@ -701,8 +657,6 @@ def make_launch_script(self):
libs += [
"opengl32",
]
# TODO: Remove when we move to setup-CMake
ext_comp_args += ["/std:c++17"]

if not (MAC or WIN):
libs += [
Expand Down Expand Up @@ -816,7 +770,7 @@ def get_packages(base, parent="", r=None):

if WIN:
# pyconfig.py forces linking against pythonXY.lib on MSVC
py_lib = pathlib.Path(sysconfig.get_paths()["stdlib"]).parent / "libs"
py_lib = Path(sysconfig.get_paths()["stdlib"]).parent / "libs"
lib_dirs.append(str(py_lib))

ext_modules += [
Expand Down

0 comments on commit f807d34

Please sign in to comment.