diff --git a/.gitignore b/.gitignore index 45ecce48..0bf4874c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ apidocs/ .tox/ .coverage.* .vscode +.idea .python-version \ No newline at end of file diff --git a/README.rst b/README.rst index 9cf5013e..a424a8e6 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ Install from PyPI:: .. note:: ``towncrier``, as a command line tool, works on Python 3.5+ only. - It is usable by projects written in other languages, provided you give it the version of the project when invoking it. + It is usable by projects written in other languages, provided you specify the project version either in the configuration file or on the command line. For Python 2/3 compatible projects, the version can be discovered automatically. In your project root, add a ``pyproject.toml`` file. @@ -64,13 +64,21 @@ Using the above example, your news fragments would be ``src/myproject/newsfragme This will keep the folder around, but otherwise "empty". -``towncrier`` needs to know what version your project is, and there are two ways you can give it: +``towncrier`` needs to know what version your project is, and there are three ways you can give it: - For Python 2/3 compatible projects, a ``__version__`` in the top level package. This can be either a string literal, a tuple, or an `Incremental `_ version. - Manually passing ``--version=`` when interacting with ``towncrier``. +- Definining a ``version`` option in a configuration file: + +.. code-block:: ini + + [tool.towncrier] + # ... + version = "1.2.3" # project version if maintained separately + To create a new news fragment, use the ``towncrier create`` command. For example:: @@ -123,6 +131,8 @@ Towncrier has the following global options, which can be specified in the toml f single_file = true # if false, filename is formatted like `title_format`. filename = "NEWS.rst" directory = "directory/of/news/fragments" + version = "1.2.3" # project version if maintained separately + name = "arbitrary project name" template = "path/to/template.rst" start_line = "start of generated content" title_format = "{name} {version} ({project_date})" # or false if template includes title diff --git a/src/towncrier/_settings.py b/src/towncrier/_settings.py index 57ab2d39..f84dcb99 100644 --- a/src/towncrier/_settings.py +++ b/src/towncrier/_settings.py @@ -144,6 +144,8 @@ def parse_toml(base_path, config): "single_file": single_file, "filename": config.get("filename", "NEWS.rst"), "directory": config.get("directory"), + "version": config.get("version"), + "name": config.get("name"), "sections": sections, "types": types, "template": template, diff --git a/src/towncrier/build.py b/src/towncrier/build.py index d1f87b8a..2824598a 100644 --- a/src/towncrier/build.py +++ b/src/towncrier/build.py @@ -119,20 +119,24 @@ def __main( ) if project_version is None: - project_version = get_version( - os.path.join(base_directory, config["package_dir"]), config["package"] - ).strip() + project_version = config.get('version') + if project_version is None: + project_version = get_version( + os.path.join(base_directory, config["package_dir"]), config["package"] + ).strip() if project_name is None: - package = config.get("package") - if package: - project_name = get_project_name( - os.path.abspath(os.path.join(base_directory, config["package_dir"])), - package, - ) - else: - # Can't determine a project_name, but maybe it is not needed. - project_name = "" + project_name = config.get('name') + if not project_name: + package = config.get("package") + if package: + project_name = get_project_name( + os.path.abspath(os.path.join(base_directory, config["package_dir"])), + package, + ) + else: + # Can't determine a project_name, but maybe it is not needed. + project_name = "" if project_date is None: project_date = _get_date().strip() diff --git a/src/towncrier/newsfragments/165.feature.rst b/src/towncrier/newsfragments/165.feature.rst new file mode 100644 index 00000000..3a8deb68 --- /dev/null +++ b/src/towncrier/newsfragments/165.feature.rst @@ -0,0 +1,2 @@ +Allow definition of the project ``version`` and ``name`` in the configuration file. +This allows use of towncrier seamlessly with non-Python projects. diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index bee1ca1e..3e59445f 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -343,6 +343,90 @@ def test_projectless_changelog(self): ).lstrip(), ) + def test_version_in_config(self): + """The calling towncrier with version defined in configfile. + + Specifying a version in toml file will be helpful if version + is maintained by i.e. bumpversion and it's not a python project. + """ + runner = CliRunner() + + with runner.isolated_filesystem(): + with open("pyproject.toml", "w") as f: + f.write("[tool.towncrier]\n" 'version = "7.8.9"\n') + os.mkdir("newsfragments") + with open("newsfragments/123.feature", "w") as f: + f.write("Adds levitation") + + result = runner.invoke( + _main, ["--date", "01-01-2001", "--draft"] + ) + + self.assertEqual(0, result.exit_code, result.output) + self.assertEqual( + result.output, + dedent( + """ + Loading template... + Finding news fragments... + Rendering news fragments... + Draft only -- nothing has been written. + What is seen below is what would be written. + + 7.8.9 (01-01-2001) + ================== + + Features + -------- + + - Adds levitation (#123) + + """ + ).lstrip(), + ) + + def test_project_name_in_config(self): + """The calling towncrier with project name defined in configfile. + + Specifying a project name in toml file will be helpful to keep the + project name consistent as part of the towncrier configuration, not call. + """ + runner = CliRunner() + + with runner.isolated_filesystem(): + with open("pyproject.toml", "w") as f: + f.write("[tool.towncrier]\n" 'name = "ImGoProject"\n') + os.mkdir("newsfragments") + with open("newsfragments/123.feature", "w") as f: + f.write("Adds levitation") + + result = runner.invoke( + _main, ["--version", "7.8.9", "--date", "01-01-2001", "--draft"] + ) + + self.assertEqual(0, result.exit_code, result.output) + self.assertEqual( + result.output, + dedent( + """ + Loading template... + Finding news fragments... + Rendering news fragments... + Draft only -- nothing has been written. + What is seen below is what would be written. + + ImGoProject 7.8.9 (01-01-2001) + ============================== + + Features + -------- + + - Adds levitation (#123) + + """ + ).lstrip(), + ) + def test_no_package_changelog(self): """The calling towncrier with any package argument.