diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/README.rst b/README.rst index 6a451c0..ef07553 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,23 @@ rockstar-py =========== -Python transpiler for the esoteric language `Rockstar`_ +.. raw:: html + +

Python transpiler for the esoteric language Rockstar

+ +

+ Travis (.org) + PyPI - Version + PyPI - Status + PyPI - Status + PyPI - Python Version + PyPI - Wheel + Code Style - Black + GitHub contributors + GitHub stars + GitHub code size in bytes + License - MIT +

Getting Started --------------- @@ -12,43 +28,274 @@ your local machine for development and testing purposes. Installing ~~~~~~~~~~ -The easiest way is installing using pip: +First, make sure you have installed a supported Python version. We use ``python_requires=">= 3.4"``, +but our tests only cover Python >= 3.6, since 3.5 is already reaching its EOF on september/2020. + +Now, the easiest way of installing **rockstar-py** is using pip: :: - sudo pip install rockstar-py + pip install rockstar-py -You can also clone this project using git: +(This may require ``sudo`` if you're installing globally on a \*nix system. + +You can also clone this project using git and install the package with setuptools: :: - git clone https://github.com/yanorestes/rockstar-py.git + git clone https://github.com/yyyyyyyan/rockstar-py.git + cd rockstar-py + python3 setup.py install Usage ----- -If you installed the package using pip, you can simply run rockstar-py in the command line: +If you installed the package using pip or setuptools, you can simply run rockstar-py in the command line: + +:: + + rockstar-py [-h] (-i INPUT | --stdin) [-o OUTPUT | --stdout | --exec] [-v] + +Otherwise, you can run the transpiler from inside the ``rockstar-py`` folder by calling python with the ``-m`` flag: + +:: + + python3 -W ignore -m rockstarpy [-h] (-i INPUT | --stdin) [-o OUTPUT | --stdout | --exec] [-v] + +Call ``rockstar-py`` with the flag ``-h``/``--help`` to see a description of all options: + +:: + + usage: rockstar-py [-h] (-i INPUT | --stdin) [-o OUTPUT | --stdout | --exec] [-v] + + Python transpiler for the esoteric language Rockstar + + optional arguments: + -h, --help show this help message and exit + -i INPUT, --input INPUT + Input file (.rock) + --stdin Stream in stdin + -o OUTPUT, --output OUTPUT + Output file (.py) + --stdout Stream to stdout + --exec Execute (without saving) the transpiled code + -v, --version Version + +Examples +-------- + +Just to make it more clear, some examples with the `fizz.rock`_ code. + +Basic usage +~~~~~~~~~~~ :: - rockstar-py [--output OUTPUT.py] input.rock + > rockstar-py -i fizz.rock -o fizz.py + > ls + fizz.py fizz.rock + > cat fizz.py + def Midnight(your_heart, your_soul): + while your_heart >= your_soul: # this is a comment + your_heart = your_heart - your_soul + return your_heart + Desire = 100 + my_world = False + Fire = 3 # i love comments + Hate = 5 + while not my_world == Desire: + my_world += 1 + if Midnight(my_world, Fire) == False and Midnight(my_world, Hate) == False: + print("FizzBuzz!") + continue + if Midnight(my_world, Fire) == False: + print("Fizz!") + continue + if Midnight(my_world, Hate) == False: + print("Buzz!") + continue + print(my_world) + +Using ``--stdout`` +~~~~~~~~~~~~~~~~~~ + +:: + + > rockstar-py -i fizz.rock --stdout + def Midnight(your_heart, your_soul): + while your_heart >= your_soul: # this is a comment + your_heart = your_heart - your_soul + return your_heart + Desire = 100 + my_world = False + Fire = 3 # i love comments + Hate = 5 + while not my_world == Desire: + my_world += 1 + if Midnight(my_world, Fire) == False and Midnight(my_world, Hate) == False: + print("FizzBuzz!") + continue + if Midnight(my_world, Fire) == False: + print("Fizz!") + continue + if Midnight(my_world, Hate) == False: + print("Buzz!") + continue + print(my_world) + +Using ``--stdin`` +~~~~~~~~~~~~~~~~~ + +:: + + > rockstar-py --stdin -o fizz.py + Midnight takes your heart and your soul + While your heart is as high as your soul (this is a comment) + Put your heart without your soul into your heart + + Give back your heart + + + Desire's a lovestruck ladykiller + My world is empty + Fire's ice (i love comments) + Hate is water + Until my world is Desire, + Build my world up + If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing + Shout "FizzBuzz!" + Take it to the top + + If Midnight taking my world, Fire is nothing + Shout "Fizz!" + Take it to the top + + If Midnight taking my world, Hate is nothing + Say "Buzz!" + Take it to the top + + Whisper my world + [Ctrl+D] + > ls + fizz.py fizz.rock -You can also run the transpiler directly by ``rockstar.py``: +Using ``--exec`` +~~~~~~~~~~~~~~~~ :: - python3 -W ignore -m rockstarpy [--output OUTPUT.py] input.rock + > rockstar-py -i fizz.rock --exec + 1 + 2 + Fizz! + 4 + Buzz! + Fizz! + 7 + 8 + Fizz! + Buzz! + 11 + Fizz! + 13 + 14 + FizzBuzz! + 16 + 17 + Fizz! + 19 + Buzz! + Fizz! + 22 + 23 + Fizz! + Buzz! + 26 + Fizz! + 28 + 29 + FizzBuzz! + 31 + 32 + Fizz! + 34 + Buzz! + Fizz! + 37 + 38 + Fizz! + Buzz! + 41 + Fizz! + 43 + 44 + FizzBuzz! + 46 + 47 + Fizz! + 49 + Buzz! + Fizz! + 52 + 53 + Fizz! + Buzz! + 56 + Fizz! + 58 + 59 + FizzBuzz! + 61 + 62 + Fizz! + 64 + Buzz! + Fizz! + 67 + 68 + Fizz! + Buzz! + 71 + Fizz! + 73 + 74 + FizzBuzz! + 76 + 77 + Fizz! + 79 + Buzz! + Fizz! + 82 + 83 + Fizz! + Buzz! + 86 + Fizz! + 88 + 89 + FizzBuzz! + 91 + 92 + Fizz! + 94 + Buzz! + Fizz! + 97 + 98 + Fizz! + Buzz! Contributing ------------ -I’m accepting pull requests that improve speed and legibility of the +The project has basically reached its end, but I'm still accepting pull requests that improve speed and legibility of the code. Authors ------- -- **Yan Orestes** - *Initial work* - `yanorestes`_ +- **yyyyyyyan** - *Initial work* - `yyyyyyyan`_ Contributors ------------ @@ -71,7 +318,8 @@ Acknowledgments suggestions on how/where to do that. .. _Rockstar: https://github.com/dylanbeattie/rockstar -.. _yanorestes: https://github.com/yanorestes -.. _Contributors: https://github.com/yanorestes/rockstar-py/graphs/contributors -.. _LICENSE: https://github.com/yanorestes/rockstar-py/blob/master/LICENSE.txt +.. _fizz.rock: https://github.com/yyyyyyyan/rockstar-py/blob/master/tests/fizz.rock +.. _yyyyyyyan: https://github.com/yyyyyyyan +.. _Contributors: https://github.com/yyyyyyyan/rockstar-py/graphs/contributors +.. _LICENSE: https://github.com/yyyyyyyan/rockstar-py/blob/master/LICENSE .. _dylanbeattie: https://github.com/dylanbeattie/ \ No newline at end of file diff --git a/rockstarpy/__init__.py b/rockstarpy/__init__.py index 207c6db..275653c 100644 --- a/rockstarpy/__init__.py +++ b/rockstarpy/__init__.py @@ -1,3 +1,4 @@ -if __name__ == '__main__': +if __name__ == "__main__": from .command_line import command_line + command_line() diff --git a/rockstarpy/__main__.py b/rockstarpy/__main__.py index a67bb83..5091c57 100644 --- a/rockstarpy/__main__.py +++ b/rockstarpy/__main__.py @@ -1,4 +1,4 @@ from .command_line import command_line -if __name__ == '__main__': +if __name__ == "__main__": command_line() diff --git a/rockstarpy/command_line.py b/rockstarpy/command_line.py index dd75e56..db4ca63 100644 --- a/rockstarpy/command_line.py +++ b/rockstarpy/command_line.py @@ -1,55 +1,51 @@ +from rockstarpy.transpile import Transpiler +from io import BytesIO import sys import argparse -from rockstarpy.transpile import Transpiler - - -parser = argparse.ArgumentParser(description="Python transpiler for the esoteric language Rockstar") +parser = argparse.ArgumentParser( + description="Python transpiler for the esoteric language Rockstar" +) input_group = parser.add_mutually_exclusive_group(required=True) -input_group.add_argument('--input', action='store', help='Input file (.rock)') -input_group.add_argument('--stdin', action='store_true', help='Stream in stdin') - -output_group = parser.add_mutually_exclusive_group(required=True) -output_group.add_argument('--output', action='store', help='Output file (.py)', default='output.py') -output_group.add_argument('--stdout', action='store_true', help='Stream to stdout') - -parser.add_argument('-v', action='version', help='Version', version='1.3.6') +input_group.add_argument("-i", "--input", action="store", help="Input file (.rock)") +input_group.add_argument( + "--stdin", + action="store_const", + const=sys.stdin.buffer, + help="Stream in stdin. Send EOF (Ctrl+D in *nix, Ctrl+Z in Windows) to stop", +) + +output_group = parser.add_mutually_exclusive_group() +output_group.add_argument( + "-o", "--output", action="store", help="Output file (.py)", default="output.py" +) +output_group.add_argument( + "--stdout", action="store_const", const=sys.stdout.buffer, help="Stream to stdout" +) +output_group.add_argument( + "--exec", action="store_true", help="Execute (without saving) the transpiled code " +) + +parser.add_argument( + "-v", "--version", action="version", help="Version", version="2.0.0" +) args = parser.parse_args() def command_line(): + lyrics = args.stdin or open(args.input, "rb") + output = BytesIO() if args.exec else args.stdout or open(args.output, "wb") - # connnect input - if args.stdin: - lyrics = sys.stdin - else: - lyrics = open(args.input, 'r') - - # connect output - if args.stdout: - enc = False - output = sys.stdout - else: - enc = True - output = open(args.output, 'wb', 0) - - # Read, Convert, Write, loop transpiler = Transpiler() for line in lyrics: - output.write( encode( transpiler.transpile_line(line), enc ) ) + line = line.decode("utf8") + output.write(transpiler.transpile_line(line).encode("utf8")) - # close input - if not args.stdin: + if args.exec: + exec(output.getvalue()) + if args.stdin is None: lyrics.close() - - # close output - if not args.stdout: + if args.stdout is None: output.close() - - -def encode(line, enc): - if enc: - return line.encode() - return line diff --git a/rockstarpy/transpile.py b/rockstarpy/transpile.py index c2fd223..f0ddf66 100644 --- a/rockstarpy/transpile.py +++ b/rockstarpy/transpile.py @@ -2,196 +2,245 @@ class Transpiler(object): - def __init__(self): self.ident = 0 - self.regex_variables = r'\b(?:(?:[Aa]n?|[Tt]he|[Mm]y|[Yy]our) [a-z]+|[A-Z][A-Za-z]+(?: [A-Z][A-Za-z]+)*)\b' - self.most_recently_named = '' + self.regex_variables = r"\b(?:(?:[Aa]n?|[Tt]he|[Mm]y|[Yy]our) [a-z]+|[A-Z][A-Za-z]+(?: [A-Z][A-Za-z]+)*)\b" + self.most_recently_named = "" self.simple_subs = { - '(':'#', - ')':'', - 'Give back':'return', - 'Take it to the top':'continue', - 'Break it down':'break', - ' false ':' False ', - ' wrong ':' False ', - ' no ':' False ', - ' lies ':' False ', - ' null ':' False ', - ' nothing ':' False ', - ' nowhere ':' False ', - ' nobody ':' False ', - ' empty ':' False ', - ' gone ':' False ', - ' mysterious ':' False ', - ' true ':' True ', - ' right ':' True ', - ' yes ':' True ', - ' ok ':' True ', - ' plus ':' + ', - ' with ':' + ', - ' minus ':' - ', - ' without ':' - ', - ' times ':' * ', - ' of ':' * ', - ' over ':' / ', - ' is higher than ':' > ', - ' is greater than ':' > ', - ' is bigger than ':' > ', - ' is stronger than ':' > ', - ' is lower than ':' < ', - ' is less than ':' < ', - ' is smaller than ':' < ', - ' is weaker than ':' < ', - ' is as high as ':' >= ', - ' is as great as ':' >= ', - ' is as big as ':' >= ', - ' is as strong as ':' >= ', - ' is as low as ':' <= ', - ' is as little as ':' <= ', - ' is as small as ':' <= ', - ' is as weak as ':' <= ', - ' is not ':' != ', - ' aint ':' != ', - 'Until ':'while not ', - 'While ':'while ' + "(": "#", + ")": "", + "Give back": "return", + "Take it to the top": "continue", + "Break it down": "break", + " false ": " False ", + " wrong ": " False ", + " no ": " False ", + " lies ": " False ", + " null ": " False ", + " nothing ": " False ", + " nowhere ": " False ", + " nobody ": " False ", + " empty ": " False ", + " gone ": " False ", + " mysterious ": " False ", + " true ": " True ", + " right ": " True ", + " yes ": " True ", + " ok ": " True ", + " plus ": " + ", + " with ": " + ", + " minus ": " - ", + " without ": " - ", + " times ": " * ", + " of ": " * ", + " over ": " / ", + " is higher than ": " > ", + " is greater than ": " > ", + " is bigger than ": " > ", + " is stronger than ": " > ", + " is lower than ": " < ", + " is less than ": " < ", + " is smaller than ": " < ", + " is weaker than ": " < ", + " is as high as ": " >= ", + " is as great as ": " >= ", + " is as big as ": " >= ", + " is as strong as ": " >= ", + " is as low as ": " <= ", + " is as little as ": " <= ", + " is as small as ": " <= ", + " is as weak as ": " <= ", + " is not ": " != ", + " aint ": " != ", + "Until ": "while not ", + "While ": "while ", } def get_comments(self, line): - if '(' in line: - line, comment = line.split('(') - comment = ' # ' + comment.strip(')\n ') + if "(" in line: + line, comment = line.split("(") + comment = " # " + comment.strip(")\n ") else: - comment = '' + comment = "" return line, comment def create_function(self, line): - match = re.match(r'\b({0}) takes ({0}(?: and {0})*)\b'.format(self.regex_variables), line) + match = re.match( + r"\b({0}) takes ({0}(?: and {0})*)\b".format(self.regex_variables), line + ) if match: self.ident += 1 - line = 'def {}({}):'.format(match.group(1), match.group(2).replace(' and', ',')) + line = "def {}({}):".format( + match.group(1), match.group(2).replace(" and", ",") + ) return line def create_while(self, line): - if line.startswith('while '): - line = line.replace(' is ', ' == ') - line += ':' + if line.startswith("while "): + line = line.replace(" is ", " == ") + line += ":" self.ident += 1 return line def create_if(self, line): - match = re.match(r'If .*', line) + match = re.match(r"If .*", line) if match: self.ident += 1 - line = line.replace(' is ', ' == ') - line = line.replace('If', 'if') - line += ':' + line = line.replace(" is ", " == ") + line = line.replace("If", "if") + line += ":" return line def replace_let_be_with_is(self, line): - match = re.match(r'Let ({0}) be (.+)'.format(self.regex_variables), line) + match = re.match(r"Let ({0}) be (.+)".format(self.regex_variables), line) if match: return match.group(1) + " is " + match.group(2) return line def find_poetic_number_literal(self, line): - poetic_type_literals_keywords = ['True', 'False'] - match = re.match(r'\b({0})(?: is|\'s| was| were) ([\d\w\.,\:\!\;\'\-\s]+)'.format(self.regex_variables), line) + poetic_type_literals_keywords = ["True", "False"] + match = re.match( + r"\b({0})(?: is|\'s| was| were) ([\d\w\.,\:\!\;\'\-\s]+)".format( + self.regex_variables + ), + line, + ) if match and match.group(2).split()[0] not in poetic_type_literals_keywords: - line = '{} = '.format(match.group(1)) + line = "{} = ".format(match.group(1)) for word_number in match.group(2).split(): - if re.match(r'\d+', word_number): + if re.match(r"\d+", word_number): line += str(word_number) else: - period = '.' if word_number.endswith('.') else '' - alpha_word = re.sub(r'[^A-Za-z\-]', '', word_number) + period = "." if word_number.endswith(".") else "" + alpha_word = re.sub(r"[^A-Za-z\-]", "", word_number) line += str(len(alpha_word) % 10) + period return line def find_proper_variables(self, line): - match_list = re.findall(r'\b[A-Z][A-Za-z]+(?: [A-Z][A-Za-z]+)*\b', line) + match_list = re.findall(r"\b[A-Z][A-Za-z]+(?: [A-Z][A-Za-z]+)*\b", line) if match_list: for match in match_list: - line = line.replace(match, match.replace(' ', '_')) + line = line.replace(match, match.replace(" ", "_")) return line def find_common_variables(self, line): - match_list = re.findall(r'\b([Aa]n?|[Tt]he|[Mm]y|[Yy]our) ([a-z]+)\b', line) + match_list = re.findall(r"\b([Aa]n?|[Tt]he|[Mm]y|[Yy]our) ([a-z]+)\b", line) if match_list: for match in match_list: - line = line.replace(' '.join(match), '{}_{}'.format(*match).lower()) + line = line.replace(" ".join(match), "{}_{}".format(*match).lower()) return line def find_named(self, line): - match = re.match(r'([A-Za-z]+(?:_[A-Za-z]+)*) [+-]?= .+', line) + match = re.match(r"([A-Za-z]+(?:_[A-Za-z]+)*) [+-]?= .+", line) if match: return match.group(1) def get_strings(self, line): - says_match = re.match(r'({}) says (.*)'.format(self.regex_variables), line) + says_match = re.match(r"({}) says (.*)".format(self.regex_variables), line) if says_match: line = says_match.group(1) + ' = "{}"' return line, says_match.group(2) - quotes_match = re.match(r'([^\"]* )(\".*\"(?:, ?\".*\")*)([^\"]*)', line) + quotes_match = re.match(r"([^\"]* )(\".*\"(?:, ?\".*\")*)([^\"]*)", line) if quotes_match: - line = quotes_match.group(1) + '{}' + quotes_match.group(3) + line = quotes_match.group(1) + "{}" + quotes_match.group(3) return line, quotes_match.group(2) return line, None def transpile_line(self, line): - if line == '\n': + if line == "\n": self.ident = self.ident - 1 if self.ident > 0 else 0 - return '' + return "" else: - line_ident = ' ' * self.ident + line_ident = " " * self.ident line, comments = self.get_comments(line) py_line, line_strings = self.get_strings(line) for key in self.simple_subs: py_line = py_line.strip() - py_line += ' ' + py_line += " " py_line = py_line.replace(key, self.simple_subs[key]) - py_line = py_line.strip('\n ,.;') + py_line = py_line.strip("\n ,.;") py_line = self.replace_let_be_with_is(py_line) py_line = self.find_poetic_number_literal(py_line) - py_line = py_line.replace('\'', '') + py_line = py_line.replace("'", "") for key in self.simple_subs: py_line = py_line.strip() - py_line += ' ' + py_line += " " py_line = py_line.replace(key, self.simple_subs[key]) - py_line = py_line.strip('\n ,.;') - - most_recently_named_keywords = [' it ', ' he ', ' she ', ' him ', ' her ', ' them ', ' they ', - ' ze ', ' hir ', ' zie ', ' zir ', ' xe ', ' xem ', ' ve ', ' ver '] + py_line = py_line.strip("\n ,.;") + + most_recently_named_keywords = [ + " it ", + " he ", + " she ", + " him ", + " her ", + " them ", + " they ", + " ze ", + " hir ", + " zie ", + " zir ", + " xe ", + " xem ", + " ve ", + " ver ", + ] for keyword in most_recently_named_keywords: - py_line = py_line.replace(keyword, ' {} '.format(self.most_recently_named)) + py_line = py_line.replace( + keyword, " {} ".format(self.most_recently_named) + ) py_line = self.create_function(py_line) py_line = self.create_while(py_line) py_line = self.create_if(py_line) - line_ident = ' ' * (self.ident - 1) if py_line == 'Else' else line_ident - py_line = 'else:' if py_line == 'Else' else py_line - - py_line = re.sub(r'Put (.*) into ({})'.format(self.regex_variables), r'\g<2> = \g<1>', py_line) - py_line = re.sub(r'Build ({}) up'.format(self.regex_variables), r'\g<1> += 1', py_line) - py_line = re.sub(r'Knock ({}) down(\, down)*'.format(self.regex_variables), r'\g<1> -= ' + str(1 + py_line.count(", down")), py_line) - py_line = re.sub(r'Listen to ({})'.format(self.regex_variables), r'\g<1> = input()', py_line) - py_line = re.sub(r'(?:Say|Shout|Whisper|Scream) (.*)', r'print(\g<1>)', py_line) - - py_line = py_line.replace(' is ', ' = ', 1) - - py_line = re.sub(r'({0}) taking ((?:{0}|\"[^\"]*\"|[0-9]+)(?:, ?(?:{0}|\"[^\"]*\"|[0-9]+))*)'.format(self.regex_variables), r'\g<1>(\g<2>)', py_line) + line_ident = " " * (self.ident - 1) if py_line == "Else" else line_ident + py_line = "else:" if py_line == "Else" else py_line + + py_line = re.sub( + r"Put (.*) into ({})".format(self.regex_variables), + r"\g<2> = \g<1>", + py_line, + ) + py_line = re.sub( + r"Build ({}) up".format(self.regex_variables), r"\g<1> += 1", py_line + ) + py_line = re.sub( + r"Knock ({}) down(\, down)*".format(self.regex_variables), + r"\g<1> -= " + str(1 + py_line.count(", down")), + py_line, + ) + py_line = re.sub( + r"Listen to ({})".format(self.regex_variables), + r"\g<1> = input()", + py_line, + ) + py_line = re.sub( + r"(?:Say|Shout|Whisper|Scream) (.*)", r"print(\g<1>)", py_line + ) + + py_line = py_line.replace(" is ", " = ", 1) + + py_line = re.sub( + r"({0}) taking ((?:{0}|\"[^\"]*\"|[0-9]+)(?:, ?(?:{0}|\"[^\"]*\"|[0-9]+))*)".format( + self.regex_variables + ), + r"\g<1>(\g<2>)", + py_line, + ) py_line = self.find_proper_variables(py_line) py_line = self.find_common_variables(py_line) line_named = self.find_named(py_line) - self.most_recently_named = line_named if line_named else self.most_recently_named + self.most_recently_named = ( + line_named if line_named else self.most_recently_named + ) py_line = py_line.format(line_strings) if line_strings else py_line - return line_ident + py_line + comments + '\n' + return line_ident + py_line + comments + "\n" diff --git a/setup.py b/setup.py index 1754a7d..0af3de9 100644 --- a/setup.py +++ b/setup.py @@ -1,37 +1,36 @@ from setuptools import setup -with open('README.rst') as file: - long_description = file.read() +with open("README.rst") as file: + long_description = file.read() setup( - name='rockstar-py', - version='1.3.6', - author='Yan Orestes', - author_email='yan.orestes@alura.com.br', - packages=['rockstarpy'], - description='Python transpiler for the esoteric language Rockstar', - long_description=long_description, - url='https://github.com/yanorestes/rockstar-py', - -download_url='https://github.com/yanorestes/rockstar-py/archive/1.3.6.zip', - license='MIT', - keywords='esoteric rockstar', - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Topic :: Software Development :: Compilers' - ], - python_requires='>= 3.4', - entry_points={ - 'console_scripts':['rockstar-py=rockstarpy.command_line:command_line'] - } + name="rockstar-py", + version="2.0.0", + author="yyyyyyyan", + author_email="contact@yyyyyyyan.tech", + packages=["rockstarpy"], + description="Python transpiler for the esoteric language Rockstar", + long_description=long_description, + url="https://github.com/yyyyyyyan/rockstar-py", + download_url="https://github.com/yyyyyyyan/rockstar-py/archive/2.0.0.zip", + license="MIT", + keywords="esoteric rockstar transpiler", + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Software Development :: Compilers", + "Topic :: Software Development :: Interpreters", + ], + python_requires=">= 3.4", + entry_points={ + "console_scripts": ["rockstar-py=rockstarpy.command_line:command_line"] + }, )