diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7a91a19 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +dist: xenial +language: python + +cache: pip + +python: + - "3.6" + - "3.7" + - "3.8" + +install: + - pip install -U -r requirements-dev.txt + +script: + - scripts/test + +after_script: + - pip install codecov + - codecov diff --git a/chachacha/__init__.py b/chachacha/__init__.py new file mode 100644 index 0000000..3dc1f76 --- /dev/null +++ b/chachacha/__init__.py @@ -0,0 +1 @@ +__version__ = "0.1.0" diff --git a/chachacha/drivers/__init__.py b/chachacha/drivers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/chachacha/drivers/kac.py b/chachacha/drivers/kac.py new file mode 100644 index 0000000..7bc7a53 --- /dev/null +++ b/chachacha/drivers/kac.py @@ -0,0 +1,128 @@ +""" +Created on 25 feb 2020 + +@author: Alessandro Ogier +""" + +import os.path +import typing +from datetime import datetime + +import keepachangelog +import semver +from jinja2 import Template + +DEFAULT_HEADER = """ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +""".strip() + +TEMPLATE = Template( + """ + +{{ header }} + +{%- for version, changes in current.items() %} + +## [{{ version }}]{% if changes.release_date %} - {{ changes.release_date }}{% endif %} +{%- for section in ['added', 'changed', 'deprecated', 'removed', 'fixed', 'security'] %} +{%- if changes[section] %} + +### {{ section | title }} +{% for entry in changes[section] %} +{{ entry }} +{%- endfor %} +{%- endif %} +{%- endfor %} +{%- endfor %} +""".strip() +) + + +class ChangelogFormat: + def __init__(self, filename): + self.filename = filename + + def init(self, overwrite: bool = False): + if os.path.exists(self.filename) and not overwrite: + print("file exists") + import sys + + sys.exit(1) + + with open(self.filename, "w") as outfile: + outfile.write(TEMPLATE.render(header=DEFAULT_HEADER, current={}) + "\n") + + print("changelog created") + + def _write(self, current: dict) -> None: + with open(self.filename, "w") as outfile: + + outfile.write( + TEMPLATE.render(header=DEFAULT_HEADER, current=current) + "\n" + ) + + def add_entry( + self, section_name: str, changelog_line: typing.Union[str, tuple] + ) -> None: + + _changelog_line = "- " + " ".join(changelog_line) + current = keepachangelog.to_dict(self.filename, show_unreleased=True) + + if "Unreleased" not in current: + unreleased = {"Unreleased": {"version": "Unreleased", "release_date": None}} + + new = {} + new.update(unreleased) + new.update(current) + + current = new + + else: + unreleased = current["Unreleased"] + + unreleased = current.setdefault( + "Unreleased", {"version": "Unreleased", "release_date": None} + ) + + section = unreleased.setdefault(section_name, []) + + section.append(_changelog_line) + + self._write(current) + + def release(self, mode: str) -> None: + + current = keepachangelog.to_dict(self.filename, show_unreleased=True) + + if "Unreleased" not in current: + print("nothing to bump!") + import sys + + sys.exit(1) + + try: + last = [version for version in current if version != "Unreleased"][0] + except IndexError: + last = "0.0.0" + + version = semver.parse_version_info(last) + + if mode == "major": + last = str(version.bump_major()) + elif mode == "minor": + last = str(version.bump_minor()) + else: + last = str(version.bump_patch()) + + entries = current.pop("Unreleased") + + changelog = {last: entries} + changelog[last]["release_date"] = datetime.now().isoformat().split("T")[0] + changelog.update(current) + + self._write(changelog) diff --git a/chachacha/main.py b/chachacha/main.py new file mode 100644 index 0000000..8375cad --- /dev/null +++ b/chachacha/main.py @@ -0,0 +1,94 @@ +""" +Created on 25 feb 2020 + +@author: Alessandro Ogier +""" + +import typing + +import click +from click.core import Context + +from chachacha import drivers +from chachacha.drivers.kac import ChangelogFormat + + +@click.group() +@click.option("--filename", default="CHANGELOG.md", help="changelog filename") +@click.option("--driver", default="kac", help="changelog format driver") +@click.pass_context +def main(ctx: Context, filename: str, driver: str) -> None: + + driver = drivers.kac.ChangelogFormat(filename) + + ctx.obj = driver + + +@main.command(help="initialize a new file") +@click.option("--overwrite", default=False, help="overwrite", is_flag=True) +@click.pass_obj +def init(driver: ChangelogFormat, overwrite: bool) -> None: + + driver.init(overwrite) + + +@main.command(help='add an "added" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def added(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("added", changes) + + +@main.command(help='add a "changed" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def changed(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("changed", changes) + + +@main.command(help='add a "deprecated" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def deprecated(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("deprecated", changes) + + +@main.command(help='add a "removed" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def removed(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("removed", changes) + + +@main.command(help='add a "fixed" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def fixed(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("fixed", changes) + + +@main.command(help='add a "security" entry') +@click.pass_obj +@click.argument("changes", nargs=-1) +def security(driver: ChangelogFormat, changes: typing.Union[str, tuple]) -> None: + + driver.add_entry("security", changes) + + +@main.command(help="release a version") +@click.option("--major", "mode", flag_value="major", help="overwrite") +@click.option("--minor", "mode", flag_value="minor", help="overwrite") +@click.option("--patch", "mode", flag_value="patch", help="overwrite", default=True) +@click.pass_obj +def release(driver: ChangelogFormat, mode: str) -> None: + + driver.release(mode) + + +if __name__ == "__main__": # pragma: no cover + main() # pylint: disable=no-value-for-parameter diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..8c5d533 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,252 @@ +appdirs==1.4.3 \ + --hash=sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e \ + --hash=sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92 +appnope==0.1.0; sys_platform == "darwin" \ + --hash=sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0 \ + --hash=sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71 +atomicwrites==1.3.0 \ + --hash=sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4 \ + --hash=sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6 +attrs==19.3.0 \ + --hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \ + --hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72 +autoflake==1.3.1 \ + --hash=sha256:680cb9dade101ed647488238ccb8b8bfb4369b53d58ba2c8cdf7d5d54e01f95b +backcall==0.1.0 \ + --hash=sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4 \ + --hash=sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2 +black==19.10b0 \ + --hash=sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b \ + --hash=sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539 +click==7.0 \ + --hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \ + --hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 +colorama==0.4.3; sys_platform == "win32" and python_version != "3.4" or sys_platform == "win32" \ + --hash=sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff \ + --hash=sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1 +coverage==5.0.3 \ + --hash=sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f \ + --hash=sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc \ + --hash=sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a \ + --hash=sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52 \ + --hash=sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c \ + --hash=sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73 \ + --hash=sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68 \ + --hash=sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691 \ + --hash=sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301 \ + --hash=sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf \ + --hash=sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3 \ + --hash=sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0 \ + --hash=sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0 \ + --hash=sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2 \ + --hash=sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894 \ + --hash=sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf \ + --hash=sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477 \ + --hash=sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc \ + --hash=sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8 \ + --hash=sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987 \ + --hash=sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea \ + --hash=sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc \ + --hash=sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e \ + --hash=sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb \ + --hash=sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37 \ + --hash=sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d \ + --hash=sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954 \ + --hash=sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e \ + --hash=sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40 \ + --hash=sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af \ + --hash=sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef +decorator==4.4.1 \ + --hash=sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d \ + --hash=sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce +importlib-metadata==1.5.0; python_version < "3.8" \ + --hash=sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b \ + --hash=sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302 +ipython==7.12.0 \ + --hash=sha256:f6689108b1734501d3b59c84427259fd5ac5141afe2e846cfa8598eb811886c9 \ + --hash=sha256:d9459e7237e2e5858738ff9c3e26504b79899b58a6d49e574d352493d80684c6 +ipython-genutils==0.2.0 \ + --hash=sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8 \ + --hash=sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8 +isort==4.3.21 \ + --hash=sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd \ + --hash=sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1 +jedi==0.16.0 \ + --hash=sha256:b4f4052551025c6b0b0b193b29a6ff7bdb74c52450631206c262aef9f7159ad2 \ + --hash=sha256:d5c871cb9360b414f981e7072c52c33258d598305280fef91c6cae34739d65d5 +jinja2==2.11.1 \ + --hash=sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49 \ + --hash=sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250 +keepachangelog==0.2.0 \ + --hash=sha256:0c04b04e1941896c0665c43cc7e1dece99ebeb851e9358ea33ce13d51ac927f9 \ + --hash=sha256:b5db765530ae00822df0bef93c9f604858e3e5e6cd6465434475191a990dc4d0 +markupsafe==1.1.1 \ + --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \ + --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \ + --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \ + --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \ + --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \ + --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \ + --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \ + --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \ + --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \ + --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \ + --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \ + --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \ + --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \ + --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \ + --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \ + --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \ + --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \ + --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \ + --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \ + --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \ + --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \ + --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \ + --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \ + --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \ + --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \ + --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \ + --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \ + --hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \ + --hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \ + --hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \ + --hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \ + --hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \ + --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b +more-itertools==8.2.0; python_version > "2.7" \ + --hash=sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507 \ + --hash=sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c +mypy==0.761 \ + --hash=sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6 \ + --hash=sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36 \ + --hash=sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72 \ + --hash=sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2 \ + --hash=sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0 \ + --hash=sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474 \ + --hash=sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a \ + --hash=sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749 \ + --hash=sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1 \ + --hash=sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7 \ + --hash=sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1 \ + --hash=sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b \ + --hash=sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217 \ + --hash=sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf +mypy-extensions==0.4.3 \ + --hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \ + --hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8 +packaging==20.1 \ + --hash=sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73 \ + --hash=sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334 +parso==0.6.1 \ + --hash=sha256:951af01f61e6dccd04159042a0706a31ad437864ec6e25d0d7a96a9fbb9b0095 \ + --hash=sha256:56b2105a80e9c4df49de85e125feb6be69f49920e121406f15e7acde6c9dfc57 +pathspec==0.7.0 \ + --hash=sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424 \ + --hash=sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96 +pexpect==4.8.0; sys_platform != "win32" \ + --hash=sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937 \ + --hash=sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c +pickleshare==0.7.5 \ + --hash=sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56 \ + --hash=sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca +pluggy==0.13.1 \ + --hash=sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d \ + --hash=sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0 +poetry-version==0.1.5 \ + --hash=sha256:f7d77b5c4f0761c5a5b9031f199c79c7f81d125676248053ea84e69ad79faa89 \ + --hash=sha256:ba259257640cd36c76375563a001b9e85c6f54d764cc56b3eed0f3b5cefb0317 +prompt-toolkit==3.0.3 \ + --hash=sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a \ + --hash=sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e +ptyprocess==0.6.0; sys_platform != "win32" \ + --hash=sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f \ + --hash=sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0 +py==1.8.1 \ + --hash=sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0 \ + --hash=sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa +pyflakes==2.1.1 \ + --hash=sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0 \ + --hash=sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2 +pygments==2.5.2 \ + --hash=sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b \ + --hash=sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe +pyparsing==2.4.6 \ + --hash=sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec \ + --hash=sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f +pytest==4.6.9 \ + --hash=sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324 \ + --hash=sha256:19e8f75eac01dd3f211edd465b39efbcbdc8fc5f7866d7dd49fedb30d8adf339 +pytest-cov==2.8.1 \ + --hash=sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b \ + --hash=sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626 +regex==2020.2.20 \ + --hash=sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb \ + --hash=sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74 \ + --hash=sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400 \ + --hash=sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0 \ + --hash=sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc \ + --hash=sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0 \ + --hash=sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69 \ + --hash=sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b \ + --hash=sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e \ + --hash=sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242 \ + --hash=sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce \ + --hash=sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab \ + --hash=sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431 \ + --hash=sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1 \ + --hash=sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045 \ + --hash=sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26 \ + --hash=sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2 \ + --hash=sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70 \ + --hash=sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d \ + --hash=sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa \ + --hash=sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5 +semver==2.9.1 \ + --hash=sha256:095c3cba6d5433f21451101463b22cf831fe6996fcc8a603407fd8bea54f116b \ + --hash=sha256:723be40c74b6468861e0e3dbb80a41fc3b171a2a45bf956c245304773dc06055 +six==1.14.0 \ + --hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \ + --hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a +toml==0.10.0 \ + --hash=sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3 \ + --hash=sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e \ + --hash=sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c +tomlkit==0.5.8 \ + --hash=sha256:96e6369288571799a3052c1ef93b9de440e1ab751aa045f435b55e9d3bcd0690 \ + --hash=sha256:32c10cc16ded7e4101c79f269910658cc2a0be5913f1252121c3cd603051c269 +traitlets==4.3.3 \ + --hash=sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44 \ + --hash=sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7 +typed-ast==1.4.1 \ + --hash=sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3 \ + --hash=sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb \ + --hash=sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919 \ + --hash=sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01 \ + --hash=sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75 \ + --hash=sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652 \ + --hash=sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7 \ + --hash=sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1 \ + --hash=sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa \ + --hash=sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614 \ + --hash=sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41 \ + --hash=sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b \ + --hash=sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe \ + --hash=sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355 \ + --hash=sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6 \ + --hash=sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907 \ + --hash=sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d \ + --hash=sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c \ + --hash=sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4 \ + --hash=sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34 \ + --hash=sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b +typing-extensions==3.7.4.1 \ + --hash=sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d \ + --hash=sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575 \ + --hash=sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2 +wcwidth==0.1.8 \ + --hash=sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603 \ + --hash=sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8 +zipp==3.0.0; python_version < "3.8" \ + --hash=sha256:12248a63bbdf7548f89cb4c7cda4681e537031eda29c02ea29674bc6854460c2 \ + --hash=sha256:7c0f8e91abc0dc07a5068f315c52cb30c66bfbc581e5b50704c8a2f6ebae794a diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 0000000..d940d94 --- /dev/null +++ b/scripts/lint @@ -0,0 +1,13 @@ +#!/bin/sh -e + +export PREFIX="" +if [ -d 'venv' ] ; then + export PREFIX="venv/bin/" +fi + +set -x + +${PREFIX}autoflake --in-place --recursive chachacha tests +${PREFIX}black chachacha tests +${PREFIX}isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --apply chachacha tests +#${PREFIX}mypy chachacha --ignore-missing-imports --disallow-untyped-defs diff --git a/scripts/test b/scripts/test new file mode 100755 index 0000000..e1c4506 --- /dev/null +++ b/scripts/test @@ -0,0 +1,16 @@ +#!/bin/sh -e + +export PREFIX="" +if [ -d 'venv' ] ; then + export PREFIX="venv/bin/" +fi + +export VERSION_SCRIPT="import sys; print('%s.%s' % sys.version_info[0:2])" +export PYTHON_VERSION=`python -c "$VERSION_SCRIPT"` + +set -x + +PYTHONPATH=. ${PREFIX}pytest --ignore venv -W ignore::DeprecationWarning --cov=chachacha --cov=tests --cov-fail-under=100 --cov-report=term-missing ${@} +#${PREFIX}mypy chachacha --ignore-missing-imports --disallow-untyped-defs +${PREFIX}autoflake --recursive chachacha tests +${PREFIX}black chachacha tests --check diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_changelog_cli.py b/tests/test_changelog_cli.py new file mode 100644 index 0000000..1d546ee --- /dev/null +++ b/tests/test_changelog_cli.py @@ -0,0 +1,292 @@ +import os +from datetime import datetime + +import keepachangelog +from click.testing import CliRunner + +from chachacha import __version__, main +from chachacha.drivers.kac import DEFAULT_HEADER + + +def test_version(): + assert __version__ == "0.1.0" + + +def test_release_major(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + result = runner.invoke(main.main, ["release", "--major"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + assert parsed == { + "1.0.0": { + "added": ["- a changelog entry string"], + "release_date": datetime.now().isoformat().split("T")[0], + "version": "1.0.0", + } + } + + +def test_release_minor(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + result = runner.invoke(main.main, ["release", "--minor"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + assert parsed == { + "0.1.0": { + "added": ["- a changelog entry string"], + "release_date": datetime.now().isoformat().split("T")[0], + "version": "0.1.0", + } + } + + +def test_release_patch(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + result = runner.invoke(main.main, ["release", "--patch"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + assert parsed == { + "0.0.1": { + "added": ["- a changelog entry string"], + "release_date": datetime.now().isoformat().split("T")[0], + "version": "0.0.1", + } + } + + +def test_release(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + result = runner.invoke(main.main, ["init"]) + assert result.exit_code == 0 + + result = runner.invoke(main.main, ["release"]) + assert result.exit_code == 1 + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + + result = runner.invoke(main.main, ["release"]) + assert result.exit_code == 0 + + # test changelog entries order creation + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert list(parsed.keys()) == ["Unreleased", "0.0.1"] + assert parsed == { + "Unreleased": { + "added": ["- a changelog entry string"], + "release_date": None, + "version": "Unreleased", + }, + "0.0.1": { + "added": ["- a changelog entry string"], + "release_date": datetime.now().isoformat().split("T")[0], + "version": "0.0.1", + }, + } + + +def test_file_creation(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + result = runner.invoke(main.main, ["init"]) + + assert result.exit_code == 0 + + with open("CHANGELOG.md") as changelog: + + assert changelog.read() == DEFAULT_HEADER + "\n" + + with open("FILENAME.md", "w") as changelog: + changelog.write("foo") + + result = runner.invoke(main.main, ["--filename", "FILENAME.md", "init"]) + assert result.exit_code == 1 + + result = runner.invoke( + main.main, ["--filename", "FILENAME.md", "init", "--overwrite"] + ) + assert result.exit_code == 0 + + with open("FILENAME.md") as changelog: + + assert changelog.read() == DEFAULT_HEADER + "\n" + + +def test_add_added(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "added": ["- a changelog entry string"], + } + } + + +def test_add_changed(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["changed", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "changed": ["- a changelog entry string"], + } + } + + +def test_add_deprecated(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["deprecated", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "deprecated": ["- a changelog entry string"], + } + } + + +def test_add_fixed(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["fixed", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "fixed": ["- a changelog entry string"], + } + } + + +def test_add_security(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["security", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "security": ["- a changelog entry string"], + } + } + + +def test_add_removed(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["removed", "a changelog entry string"]) + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "removed": ["- a changelog entry string"], + } + } + + +def test_add_entries(tmp_path): + os.chdir(tmp_path) + runner = CliRunner() + runner.invoke(main.main, ["init"]) + + result = runner.invoke(main.main, ["added", "a changelog entry string"]) + + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "added": ["- a changelog entry string"], + } + } + + result = runner.invoke( + main.main, ["added", "an", "unquoted", "changelog", "entry", "string"] + ) + + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "added": [ + "- a changelog entry string", + "- an unquoted changelog entry string", + ], + } + } + + result = runner.invoke( + main.main, ["changed", "an", "unquoted", "changelog", "entry", "string"] + ) + + parsed = keepachangelog.to_dict("CHANGELOG.md", show_unreleased=True) + + assert result.exit_code == 0 + + assert parsed == { + "Unreleased": { + "version": "Unreleased", + "release_date": None, + "changed": ["- an unquoted changelog entry string"], + "added": [ + "- a changelog entry string", + "- an unquoted changelog entry string", + ], + } + }