Created
June 18, 2019 17:59
-
-
Save LeMeteore/cac019562822388a5d11c0ead629848c to your computer and use it in GitHub Desktop.
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
import re | |
import io | |
import os | |
import fnmatch | |
import argparse | |
import mimetypes | |
import subprocess | |
import urllib.request | |
from contextlib import contextmanager | |
@contextmanager | |
def cd(newdir): | |
""" Custom change directory command. """ | |
prevdir = os.getcwd() | |
os.chdir(os.path.expanduser(newdir)) | |
try: | |
yield | |
finally: | |
os.chdir(prevdir) | |
def get_python_files(path): | |
""" Retrive all Python files inside cube. """ | |
python_files = [] | |
with cd(path): | |
hg_files = subprocess.check_output( | |
"hg status -A", shell=True).decode().split("\n") | |
tracked_files = [x.split(" ", 1)[1] for x in hg_files if x.startswith("C ")] | |
tracked_files = filter(None, tracked_files) | |
for f in tracked_files: | |
typ = mimetypes.MimeTypes().guess_type(f)[0] | |
if typ == 'text/x-python': | |
python_files.append(f) | |
return python_files | |
def print_warning(msg): | |
""" Custom print coloring printed message. """ | |
print(f'\x1b[1;33;40m {msg} \x1b[0m') | |
def _dtnm(path): | |
""" Returns a list of folders to not move. """ | |
folders_not_to_move = [] | |
for root, dirs, files in os.walk(path): | |
for d in ['bin', 'debian', 'test', '.hg', '.tox', 'cubicweb_*']: | |
for folder in fnmatch.filter(dirs, d): | |
folders_not_to_move.append(folder) | |
break | |
return folders_not_to_move | |
def _ftnm(path): | |
""" Returns a list of files to not move. """ | |
files_not_to_move = [] | |
for root, dirs, files in os.walk(path): | |
for f in ['setup.py', 'README', '*.ini', 'MANIFEST.in', | |
'*.txt', '*.spec', '.hgtags', '.hgrc', 'test*']: | |
for filename in fnmatch.filter(files, f): | |
files_not_to_move.append(filename) | |
break | |
return files_not_to_move | |
def create_cube_folder(cube_root, cube_folder): | |
""" Creates the cube folder. """ | |
with cd(cube_root): | |
try: | |
if not os.path.exists(cube_folder): | |
os.makedirs(cube_folder) | |
print_warning(f'Info: {cube_folder} successfully created') | |
return cube_folder | |
else: | |
print_warning(f'Error: {cube_folder} already exists.') | |
except OSError: | |
print_warning(f'Error: Creating directory {cube_folder}.') | |
def update_pkginfo(pkginfo): | |
""" Update __pkginfo__.py content. """ | |
# retrieve numversion, depends, recommends | |
__pkginfo__ = {} | |
with open(pkginfo, "r") as f: | |
exec(f.read(), __pkginfo__) | |
context = { | |
'numversion': __pkginfo__['numversion'], | |
'cubename': os.path.split(pkginfo)[0], | |
'distname': 'cubicweb-' + os.path.split(pkginfo)[0], | |
'license': __pkginfo__['license'], | |
'author': __pkginfo__['author'], | |
'author-email': __pkginfo__['author_email'], | |
'shortdesc': __pkginfo__['description'], | |
'dependencies': __pkginfo__['__depends__'], | |
} | |
if '__recommends__' in __pkginfo__: | |
context['__recommends__'] = __pkginfo__['__recommends__'] | |
command = f"hg rm {pkginfo}" | |
subprocess.Popen(command, shell=True).wait() | |
url = "https://hg.logilab.org/master/cubicweb/raw-file/tip/cubicweb/skeleton/cubicweb_CUBENAME/__pkginfo__.py.tmpl" | |
with urllib.request.urlopen(url) as response, open(pkginfo, 'w') as out: | |
template = response.read().decode() | |
new_pkginfo = template % context | |
new_pkginfo = new_pkginfo.split('\n') | |
for l in new_pkginfo: | |
if "numversion" in l: | |
l = re.sub(r"^numversion ?= ?.*$", f"numversion = {context['numversion']}", l) | |
# if '>= ' in l: # not sure how to update cubicweb version to 3.24 | |
# l = re.sub(r"'^.*cubicweb' ?: ?'>?= ?'\d{1}\.\d{1}\.\d{1}',?.*", "'cubicweb': '>= 3.24.0'", l) | |
out.write(l+'\n') | |
command = f"hg add {pkginfo}" | |
subprocess.Popen(command, shell=True).wait() | |
print_warning(f'Info: Successfully updated __pkginfo__.py.') | |
def move_cube_files(cube_root, cube_folder): | |
""" Move cube files from root to cube folder. """ | |
ftnm = _ftnm(cube_root) | |
dtnm = _dtnm(cube_root) | |
cf = [] | |
for root, dirs, files in os.walk(cube_root): | |
for filename in files: | |
if fnmatch.fnmatch(filename, '__pkginfo__.py'): | |
update_pkginfo(os.path.join(cube_root,filename)) | |
if filename not in ftnm: | |
cf.append(filename) | |
for dirname in dirs: | |
if dirname not in dtnm: | |
cf.append(dirname) | |
break # we just need level 1 walk | |
with cd(cube_root): | |
for i in cf: | |
command = f"hg mv {i} {cube_folder}" | |
subprocess.Popen(command, shell=True).wait() | |
print_warning(f'Info: cube files successfully moved into {cube_folder}') | |
def replace_cube_file(cube_root, filename): | |
""" Delete & replace files that needs to be rewritten using the skeleton. """ | |
with cd(cube_root): | |
command = f"hg rm {filename}" | |
subprocess.Popen(command, shell=True).wait() | |
url = f"https://hg.logilab.org/master/cubicweb/raw-file/tip/cubicweb/skeleton/{filename}.tmpl" | |
context = {'cubename': cube_root, 'distname': 'cubicweb-'+cube_root} | |
with urllib.request.urlopen(url) as response, open(filename, 'w') as out: | |
template = response.read().decode() | |
out.write(template % context) | |
command = f"hg add {filename}" | |
subprocess.Popen(command, shell=True).wait() | |
print_warning(f'Info: {filename} successfully updated') | |
def remove_useless_files(cube_root): | |
""" Remove all the files that are no more used. """ | |
with cd(cube_root): | |
for filename in ['apycot.ini', 'pytestconf.py']: | |
command = f"hg rm {filename}" | |
subprocess.Popen(command, shell=True).wait() | |
print_warning(f'Info: {filename} successfully removed') | |
def fix_unittest_import(cube_root, filename): | |
""" Make sure we use unittest from standard lib.""" | |
with cd(cube_root): | |
content = [] | |
with open(filename, 'r') as f: | |
content = f.readlines() | |
with open(filename, 'w') as f: | |
for l in content: | |
if "unittest_main" in l: | |
l = re.sub(r"^from logilab\.common\.testlib import unittest_main$", r"import unittest", l) | |
l = re.sub(r"^ from logilab\.common\.testlib import unittest_main$", r" import unittest", l) | |
l = re.sub(r"^ unittest_main\(\)$", " unittest.main()", l) | |
f.write(l) | |
def fix_cube_import(cube_root, filename): | |
""" Make sure we import cube using new layout.""" | |
with cd(cube_root): | |
content = [] | |
with open(filename, 'r') as f: | |
content = f.readlines() | |
with open(filename, 'w') as f: | |
for l in content: | |
if "cubes." in l: | |
l = re.sub(r"", r"", l) | |
f.write(l) | |
def main(): | |
parser = argparse.ArgumentParser(description='Cube mgt system.') | |
parser.add_argument('-p', '--path', default=".", help='cube path to migrate') | |
args = parser.parse_args() | |
path = os.path.realpath(os.path.expanduser(args.path)) | |
cube_root = os.path.basename(path) | |
cube_folder = f'cubicweb_{cube_root}' | |
# setup.py and MANIFEST.in can just be replaced | |
for i in ['setup.py', 'MANIFEST.in', 'tox.ini']: | |
replace_cube_file(cube_root, i) | |
create_cube_folder(cube_root, cube_folder) | |
move_cube_files(cube_root, cube_folder) | |
py_files = get_python_files(cube_root) | |
# remove_useless_files | |
for f in py_files: | |
fix_unittest_import(cube_root, f) | |
# fix_cubes_import | |
# automatically call autopep8? | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment