forked from coala/coala-bears
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
763aa4e
commit f7836d1
Showing
6 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,4 @@ Gemfile.lock | |
.Rprofile | ||
*.swp | ||
venv | ||
bears/upload/ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import argparse | ||
import glob | ||
import os | ||
import shutil | ||
from string import Template | ||
import subprocess | ||
import sys | ||
|
||
from bears import VERSION | ||
from coalib.collecting.Importers import iimport_objects | ||
from coalib.parsing.Globbing import glob | ||
|
||
|
||
def touch(file_name): | ||
""" | ||
Creates an empty file. An existing file remains untouched. | ||
:param file_name: Name of the file. | ||
""" | ||
open(file_name, 'a').close() | ||
|
||
|
||
def create_file_from_template(template_file, output_file, substitution_dict): | ||
""" | ||
Creates a file from a template file, using a substitution dict. | ||
:param template_file: The template file. | ||
:param output_file: The file to be written. | ||
:param substitution_dict: The dict from which the substitutions are taken. | ||
""" | ||
with open(template_file) as fl: | ||
template = fl.read() | ||
template = Template(template).safe_substitute(**substitution_dict) | ||
|
||
with open(output_file, 'w') as output_handle: | ||
output_handle.write(template) | ||
|
||
|
||
def create_file_structure_for_packages(root_folder, file_to_copy, object_name): | ||
""" | ||
Creates a file structure for the packages to be uploaded. The structure | ||
will be ``root_folder/object_name/object_name/file_to_copy``. | ||
The file structure has two object_name folders because ``setup.py`` file | ||
needs files to be one level deeper than itself so that they can be uploaded. | ||
:param root_folder: The folder in which the packages are going to be | ||
generated. | ||
:param file_to_copy: The file that is going to be generated the package for. | ||
:param object_name: The name of the object that is inside the file_to_copy. | ||
""" | ||
upload_package_folder = os.path.join(root_folder, object_name, object_name) | ||
os.makedirs(upload_package_folder, exist_ok=True) | ||
touch(os.path.join(upload_package_folder, '__init__.py')) | ||
shutil.copyfile(file_to_copy, os.path.join(upload_package_folder, | ||
object_name + '.py')) | ||
|
||
|
||
def perform_register(path, file_name): | ||
""" | ||
Register the directory to PyPi, after creating a ``sdist`` and | ||
a ``bdist_wheel``. | ||
:param path: The file on which the register should be done. | ||
""" | ||
subprocess.call( | ||
[sys.executable, 'setup.py', 'sdist', 'bdist_wheel'], cwd=path) | ||
subprocess.call(['twine', 'register', '-r', 'pypitest', os.path.join( | ||
path, 'dist', file_name + '.tar.gz')]) | ||
subprocess.call(['twine', 'register', '-r', 'pypitest', os.path.join( | ||
path, 'dist', file_name + '-py3-none-any.whl')]) | ||
|
||
|
||
def perform_upload(path): | ||
""" | ||
Uploads the directory to PyPi. | ||
:param path: The folder in which the upload should be done. | ||
""" | ||
subprocess.call( | ||
['twine', 'upload', '-r', 'pypitest', path + '/dist/*']) | ||
|
||
|
||
def create_upload_parser(): | ||
""" | ||
Creates a parser for command line arguments. | ||
:return: Parser arguments. | ||
""" | ||
parser = argparse.ArgumentParser( | ||
description='Generates PyPi packages from bears.') | ||
parser.add_argument('-r', '--register', | ||
help='Register the packages on PyPi', | ||
action='store_true') | ||
parser.add_argument('-u', '--upload', help='Upload the packages on PyPi', | ||
action='store_true') | ||
return parser | ||
|
||
|
||
def main(): | ||
args = create_upload_parser().parse_args() | ||
|
||
os.makedirs(os.path.join('bears', 'upload'), exist_ok=True) | ||
|
||
bear_file_name_list = glob('bears/**/*Bear.py') | ||
|
||
for bear_file_name in bear_file_name_list: | ||
bear_object = next(iimport_objects( | ||
bear_file_name, attributes='kind', local=True), | ||
None) | ||
if bear_object: | ||
bear_name, _ = os.path.splitext(os.path.basename(bear_file_name)) | ||
create_file_structure_for_packages( | ||
os.path.join('bears', 'upload'), bear_file_name, bear_name) | ||
|
||
substitution_dict = {'NAME': repr(bear_name), | ||
'VERSION': repr(VERSION), | ||
'AUTHORS': str(bear_object.AUTHORS), | ||
'AUTHORS_EMAILS': | ||
str(bear_object.AUTHORS_EMAILS), | ||
'MAINTAINERS': str(bear_object.maintainers), | ||
'MAINTAINERS_EMAILS': | ||
str(bear_object.maintainers_emails), | ||
'PLATFORMS': str(bear_object.PLATFORMS), | ||
'LICENSE': str(bear_object.LICENSE), | ||
'LONG_DESCRIPTION': str(bear_object.__doc__)} | ||
|
||
create_file_from_template(os.path.join('bears', 'setup.py.in'), | ||
os.path.join('bears', 'upload', | ||
bear_name, 'setup.py'), | ||
substitution_dict) | ||
|
||
bear_dist_name = bear_name + '-' + VERSION | ||
if args.register: | ||
perform_register(os.path.join('bears', 'upload', bear_name), | ||
bear_dist_name) | ||
if args.upload: | ||
perform_upload(os.path.join('bears', 'upload', bear_name)) | ||
|
||
|
||
if __name__ == '__main__': # pragma: no cover | ||
sys.exit(main()) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
twine~=1.7.4 | ||
wheel~=8.1.2 |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#!/usr/bin/env python3 | ||
import locale | ||
|
||
from setuptools import setup | ||
|
||
|
||
try: | ||
locale.getlocale() | ||
except (ValueError, UnicodeError): | ||
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
setup(name=$NAME, | ||
version=$VERSION, | ||
description="$NAME bear for coala (http://coala.rtfd.org/)", | ||
authors=$AUTHORS, | ||
authors_emails=$AUTHORS_EMAILS, | ||
maintainers=$MAINTAINERS, | ||
maintainers_emails=$MAINTAINERS_EMAILS, | ||
platforms=$PLATFORMS, | ||
license='$LICENSE', | ||
long_description="""$LONG_DESCRIPTION""", | ||
classifiers=[ | ||
"Development Status :: 4 - Beta", | ||
"Environment :: Console", | ||
"Environment :: Win32 (MS Windows)", | ||
"Intended Audience :: Science/Research", | ||
"Intended Audience :: Developers", | ||
"Programming Language :: " | ||
"Python :: Implementation :: CPython", | ||
"Programming Language :: Python :: 3.3", | ||
"Programming Language :: Python :: 3.4", | ||
"Programming Language :: Python :: 3.5", | ||
"Programming Language :: Python :: 3 :: Only", | ||
"Topic :: Scientific/Engineering :: Information Analysis", | ||
"Topic :: Software Development :: Quality Assurance", | ||
"Topic :: Text Processing :: Linguistic"]) | ||
|
||
finally: | ||
print('[WARN] If you do not install the bears using the coala' | ||
'installation tool, there may be problems with the dependencies' | ||
'and they may not work.') |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import os | ||
import shutil | ||
import sys | ||
import unittest | ||
from unittest.mock import patch | ||
from bears.generate_package import (touch, create_file_from_template, | ||
create_file_structure_for_packages, | ||
perform_register, perform_upload, main, | ||
create_upload_parser) | ||
|
||
|
||
class touchTest(unittest.TestCase): | ||
|
||
def setUp(self): | ||
if os.path.exists('TestFile.py'): | ||
os.remove('TestFile.py') | ||
|
||
def test_file_doesnt_exist(self): | ||
self.assertFalse(os.path.exists('TestFile.py')) | ||
touch('TestFile.py') | ||
self.assertTrue(os.path.exists('TestFile.py')) | ||
|
||
def tearDown(self): | ||
os.remove('TestFile.py') | ||
|
||
|
||
class create_file_from_templateTest(unittest.TestCase): | ||
|
||
SUBST_FILE = os.path.join( | ||
'tests', 'generate_package_input_files', 'substituted_file.py') | ||
TEMPL_FILE = os.path.join( | ||
'tests', 'generate_package_input_files', 'template_file.py.in') | ||
|
||
def test_output_file(self): | ||
data = {'who': 'George', 'sport': 'swimming'} | ||
create_file_from_template(self.TEMPL_FILE, self.SUBST_FILE, data) | ||
with open(self.SUBST_FILE) as fl: | ||
substituted_file = fl.read() | ||
self.assertEqual(substituted_file, 'George has gone swimming again.\n') | ||
|
||
def tearDown(self): | ||
os.remove(self.SUBST_FILE) | ||
|
||
|
||
class create_file_structure_for_packagesTest(unittest.TestCase): | ||
|
||
TEST_FILE_PATH = os.path.join('folder', 'Test', 'Test', 'Test.py') | ||
INIT_FILE_PATH = os.path.join('folder', 'Test', 'Test', '__init__.py') | ||
|
||
def test_structure(self): | ||
touch('TestFile.py') | ||
create_file_structure_for_packages('folder', 'TestFile.py', 'Test') | ||
self.assertTrue(os.path.exists(self.TEST_FILE_PATH)) | ||
self.assertTrue(os.path.exists(self.INIT_FILE_PATH)) | ||
|
||
def tearDown(self): | ||
shutil.rmtree('folder') | ||
|
||
|
||
class create_upload_parserTest(unittest.TestCase): | ||
|
||
def test_parser(self): | ||
self.assertTrue(create_upload_parser().parse_args(['--upload']).upload) | ||
|
||
|
||
class perform_registerTest(unittest.TestCase): | ||
|
||
@patch('subprocess.call') | ||
def test_command(self, call_mock): | ||
perform_register('.', 'MarkdownBear-0.8.0.dev20160623094115') | ||
call_mock.assert_called_with( | ||
['twine', 'register', '-r', 'pypitest', os.path.join( | ||
'.', 'dist', | ||
'MarkdownBear-0.8.0.dev20160623094115-py3-none-any.whl')]) | ||
|
||
|
||
class perform_uploadTest(unittest.TestCase): | ||
|
||
@patch('subprocess.call') | ||
def test_command(self, call_mock): | ||
perform_upload('.') | ||
call_mock.assert_called_with(['twine', 'upload', '-r', 'pypitest', | ||
'./dist/*']) | ||
|
||
|
||
class mainTest(unittest.TestCase): | ||
|
||
CSS_BEAR_SETUP_PATH = os.path.join( | ||
'bears', 'upload', 'CSSLintBear', 'setup.py') | ||
NO_BEAR_PATH = os.path.join('bears', 'BadBear', 'NoBearHere.py') | ||
|
||
def setUp(self): | ||
self.old_argv = sys.argv | ||
|
||
def test_main(self): | ||
sys.argv = ["generate_package.py"] | ||
main() | ||
self.assertTrue(os.path.exists(os.path.join('bears', 'upload'))) | ||
with open(self.CSS_BEAR_SETUP_PATH) as fl: | ||
setup_py = fl.read() | ||
self.assertIn("Check code for syntactical or semantical", setup_py) | ||
|
||
@patch('bears.generate_package.perform_upload') | ||
def test_upload(self, call_mock): | ||
sys.argv = ["generate_package.py", "--upload"] | ||
main() | ||
for call_object in call_mock.call_args_list: | ||
self.assertRegex(call_object[0][0], r".+Bear") | ||
|
||
@patch('bears.generate_package.perform_register') | ||
def test_register(self, call_mock): | ||
sys.argv = ["generate_package.py", "--register"] | ||
main() | ||
for call_object in call_mock.call_args_list: | ||
self.assertRegex(call_object[0][0], r".+Bear") | ||
|
||
def test_no_bear_object(self): | ||
if not os.path.exists(self.NO_BEAR_PATH): | ||
os.makedirs(os.path.join('bears', 'BadBear')) | ||
touch(self.NO_BEAR_PATH) | ||
sys.argv = ["generate_package.py"] | ||
main() | ||
self.assertFalse(os.path.exists(os.path.join( | ||
'bears', 'upload', 'BadBear'))) | ||
shutil.rmtree(os.path.join('bears', 'BadBear')) | ||
|
||
def tearDown(self): | ||
shutil.rmtree(os.path.join('bears', 'upload')) | ||
sys.argv = self.old_argv |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
$who has gone $sport again. |