Created
January 20, 2020 03:40
-
-
Save walchko/40a09975de0d491cc27bc08755e6e8d3 to your computer and use it in GitHub Desktop.
My build tools
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
############################################################################## | |
# The MIT License (MIT) | |
# | |
# Copyright (c) 2017 Kevin J. Walchko | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in | |
# all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
# THE SOFTWARE. | |
############################################################################## | |
# WTF: | |
# I am breaking this out of my pip package as a script, because I think it might | |
# work better this way ... we will see. | |
#### | |
import os | |
import sys | |
from colorama import Fore, Back, Style | |
from shutil import rmtree | |
from os import path | |
import urllib | |
import urllib.request | |
def update_script(): | |
""" | |
This will pull the latest verison from my git repo and keep things current. | |
Oh God why are you doing this ... long story, but I hate to have to install | |
something before I can use the pip command on a brand new system. This is my | |
solution ... let's see how well it works. | |
""" | |
url = "" | |
try: | |
urllib.request.urlretrieve(url,"buildtools.py") | |
except urllib.error.HTTPError as e: | |
print(f">> {e}") | |
# from psutils | |
def get_pkg_version(relfile): | |
""" | |
Given a relative path to a file, this searches it and returns the version | |
string. The nice thing about this, it doesn't execute any python code when | |
it searches. This is an issues during setup when I have C extensions that | |
have not been compiled yet, but python code looks for the library (which | |
is not built yet). | |
import build_utils as bu | |
bu.get_pkg_version('build_utils/__init__.py') | |
"0.2.0" | |
""" | |
pkg = path.abspath(relfile) | |
with open(pkg, 'r') as f: | |
for line in f: | |
if line.startswith('__version__'): | |
ret = eval(line.strip().split(' = ')[1]) | |
assert ret.count('.') == 2, ret | |
for num in ret.split('.'): | |
assert num.isdigit(), ret | |
return ret | |
raise ValueError("couldn't find version string") | |
class BuildCommand: | |
"""Build binaries/packages""" | |
pkg = None | |
version = None | |
test = True # run tests | |
py2 = False # build python 2 package | |
py3 = True # build python 3 package | |
rm_egg = False # rm egg-info directory | |
rm_so = False # rm shared library, this is for c extensions | |
def __init__(self, name): | |
self.pkg = name | |
self.version = get_pkg_version(f"{self.pkg}/__init__.py") | |
def cprint(self, color, msg): | |
print(color + msg + Style.RESET_ALL) | |
def rmdir(self, folder): | |
try: | |
rmtree(folder) | |
self.cprint(Fore.RED, ">> Deleted Folder {}".format(folder)) | |
except OSError: | |
pass | |
def rm(self, file): | |
try: | |
os.system('rm -f {}'.format(file)) | |
self.cprint(Fore.RED, ">> Deleted File {}".format(file)) | |
except OSError: | |
pass | |
def build(self): | |
if not self.pkg or not self.version: | |
raise Exception('BuildCommand::pkg is not set') | |
print(Fore.BLUE + '+----------------------------------') | |
print(f'| Package: {self.pkg}') | |
print(f"| Version: {self.version}") | |
print('+----------------------------------') | |
print('| Python 2: tests & build: {}'.format(self.py2)) | |
print('| Python 3: tests & build: {}'.format(self.py3)) | |
print('+----------------------------------\n\n' + Style.RESET_ALL) | |
pkg = self.pkg | |
self.cprint(Fore.RED, 'Delete dist directory and clean up binary files') | |
self.cprint(Fore.RED, '-----------------------------------------------') | |
self.rmdir('dist') | |
self.rmdir('build') | |
self.rmdir('.eggs') | |
if self.rm_egg: | |
self.rmdir(f'{pkg}.egg-info') | |
if self.rm_so: | |
self.rm('*.so') | |
self.rm(f'{pkg}/*.so') | |
self.rm('{}/*.pyc'.format(pkg)) | |
self.rmdir('{}/__pycache__'.format(pkg)) | |
self.cprint(Fore.RED, '-----------------------------------------------\n\n') | |
if self.test: | |
print(Fore.YELLOW + 'Run Nose tests') | |
if self.py2: | |
ret = os.system("unset PYTHONPATH; python2 -m nose -w tests -v test.py") | |
if ret > 0: | |
self.cprint(Fore.WHITE + Back.RED, '<<< Python2 nose tests failed >>>') | |
return | |
if self.py3: | |
ret = os.system("unset PYTHONPATH; python3 -m nose -w tests -v test.py") | |
if ret > 0: | |
self.cprint(Fore.WHITE + Back.RED, '<<< Python3 nose tests failed >>>') | |
return | |
print(Style.RESET_ALL + '\nBuilding packages ...') | |
print(Fore.WHITE + Back.MAGENTA + '\n>> Python source ----------------------------------------------' + Fore.MAGENTA + Back.RESET) | |
os.system("unset PYTHONPATH; python setup.py sdist") | |
if self.py2: | |
print(Fore.WHITE + Back.CYAN +'\n>> Python 2 Wheel ---------------------------------------------------'+ Fore.CYAN + Back.RESET) | |
os.system("unset PYTHONPATH; python2 setup.py bdist_wheel") | |
else: | |
print(Fore.WHITE + Back.CYAN +'\n*** Skipping Python 2 ***'+Style.RESET_ALL) | |
if self.py3: | |
print(Fore.WHITE + Back.BLUE + '\n>> Python 3 Wheel ---------------------------------------------------' + Fore.BLUE + Back.RESET) | |
os.system("unset PYTHONPATH; python3 setup.py bdist_wheel") | |
else: | |
print(Fore.WHITE + Back.BLUE +'\n*** Skipping Python 3 ***'+Style.RESET_ALL) | |
print("---------------------------------------------------" + Style.RESET_ALL) | |
def set_git_tag(self): | |
"""Set version tag on github""" | |
if self.version is None: | |
raise Exception("set_git_tag needs version set to something") | |
print('Pushing git tags') | |
os.system(f'git tag v{self.version}') | |
os.system('git push --tags') | |
def publish(self): | |
"""Publish to Pypi""" | |
if not self.pkg or not self.version: | |
raise Exception('publish: pkg or version is not set') | |
print('Publishing to PyPi ...') | |
os.system(f"unset PYTHONPATH; twine upload dist/{self.pkg}-{self.version}*") | |
if __name__ == "__main__": | |
b = BuildCommand("mdh") | |
b.build() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment