Skip to content

Commit

Permalink
base → core (#353)
Browse files Browse the repository at this point in the history
* Change -base to -core.

* Rename --ansible-base-source to --ansible-core-source; deprecate the old name.

* Rename ansible_base module to ansible_core.

* Rename ansible_base to ansible_core in code.

* AnsibleBase -> AnsibleCore.

* Allow to use _ansible_core_version instead of _ansible_base_version; switch to _ansible_core_version for Ansible 6.

* Fix bug, adjust tests.

* Some more fixes.

* Apply suggestions from code review

Co-authored-by: Alicia Cozine <[email protected]>

* Update src/antsibull/ansible_core.py

Co-authored-by: Alicia Cozine <[email protected]>

Co-authored-by: Alicia Cozine <[email protected]>
  • Loading branch information
felixfontein and acozine authored Dec 11, 2021
1 parent 3a79287 commit 5dc66f3
Show file tree
Hide file tree
Showing 22 changed files with 304 additions and 216 deletions.
6 changes: 3 additions & 3 deletions docs/changelog.yaml-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You can use the `antsibull-lint changelog-yaml` tool to validate these files:

antsibull-lint changelog-yaml /path/to/changelog.yaml

(This only works for `changelog.yaml` files in collections, not for the corresponding files in ansible-base, since ansible-base currently does not conform to semantic versioning.)
(This only works for `changelog.yaml` files in collections, not for the corresponding files in ansible-core, since ansible-core currently does not conform to semantic versioning.)

The tool does not output anything and exits with exit code 0 in case the file is OK, and outputs errors and exits with exit code 3 in case an error was found. Other exit codes indicate problems with the command line or during the execution of the linter.

Expand All @@ -25,7 +25,7 @@ At the top level, there are two entries:
1. A string `ancestor`, which can also be `null` or omitted if the changelog has no ancestor.
2. A dictionary `releases`, which maps version numbers to release information.

If `ancestor` is a string, it must be an existing version of the collection which precedes all versions mentioned in this changelog. This is used when the changelog is truncated, for example when using release branches like for ansible-base. There, the `stable-2.10` branch's changelog contains only changelog entries for 2.10.x releases. Since the first 2.10.0b1 release contains all changes made to `devel` after `stable-2.9` was branched, the ancestor for the 2.10 changelog is `2.9.0b1`, the first release made after branching `stable-2.9`.
If `ancestor` is a string, it must be an existing version of the collection which precedes all versions mentioned in this changelog. This is used when the changelog is truncated, for example when using release branches like for ansible-core. There, the `stable-2.10` branch's changelog contains only changelog entries for 2.10.x releases. Since the first 2.10.0b1 release contains all changes made to `devel` after `stable-2.9` was branched, the ancestor for the 2.10 changelog is `2.9.0b1`, the first release made after branching `stable-2.9`.

The following shows the outline of a `changelog.yaml` file with four versions:

Expand All @@ -47,7 +47,7 @@ releases:
For a release `x.y.z`, the `releases` dictionary contains an entry `x.y.z` mapping to another dictionary. That dictionary can have the following entries:

1. `release_date`: a string in ISO format (`YYYY-MM-DD`) specifying on which date the release was made.
1. `codename`: a string for the version's codename. Optional; mainly required for ansible-base.
1. `codename`: a string for the version's codename. Optional; mainly required for ansible-core.
1. `fragments`: a list of strings mentioning changelog fragment files used for this release. This is not used for compiling a changelog.
1. `changes`: a dictionary containing all changes. See below.
1. `modules`: a list of plugin dictionaries. See below.
Expand Down
2 changes: 1 addition & 1 deletion docs/schemas.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.. automodule:: antsibull.schemas.base
.. automodule:: antsibull.schemas.docs.base

There is a dictionary named ANSIBLE_DOC_SCHEMAS to allow you easier access to these
programmatically. It is a mapping of plugin types to the ansible_doc schema which handle it.
Expand Down
138 changes: 69 additions & 69 deletions src/antsibull/ansible_base.py → src/antsibull/ansible_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Author: Toshio Kuratomi <[email protected]>
# License: GPLv3+
# Copyright: Ansible Project, 2020
"""Functions for working with the ansible-base package."""
"""Functions for working with the ansible-core package."""
import ast
import asyncio
import os
Expand All @@ -27,8 +27,8 @@

mlog = log.fields(mod=__name__)

#: URL to checkout ansible-base from.
_ANSIBLE_BASE_URL = str(app_context.AppContext().ansible_base_url)
#: URL to checkout ansible-core from.
_ANSIBLE_CORE_URL = str(app_context.AppContext().ansible_base_url)
#: URL to pypi.
_PYPI_SERVER_URL = str(app_context.AppContext().pypi_url)

Expand All @@ -41,13 +41,13 @@ class CannotBuild(Exception):
"""Raised when we can't figure out how to build a package."""


class AnsibleBasePyPiClient:
"""Class to retrieve information about AnsibleBase from Pypi."""
class AnsibleCorePyPiClient:
"""Class to retrieve information about ansible-core from Pypi."""

def __init__(self, aio_session: 'aiohttp.client.ClientSession',
pypi_server_url: str = _PYPI_SERVER_URL) -> None:
"""
Initialize the AnsibleBasePypi class.
Initialize the AnsibleCorePypiClient class.
:arg aio_session: :obj:`aiohttp.client.ClientSession` to make requests to pypi from.
:kwarg pypi_server_url: URL to the pypi server to use.
Expand All @@ -66,7 +66,7 @@ async def _get_json(self, query_url: str) -> t.Dict[str, t.Any]:
@lru_cache(None)
async def get_release_info(self) -> t.Dict[str, t.Any]:
"""
Retrieve information about releases of the ansible-base/ansible-core package from pypi.
Retrieve information about releases of the ansible-core/ansible-base package from pypi.
:returns: The dict which represents the release info keyed by version number.
To examine the data structure, use::
Expand All @@ -90,12 +90,12 @@ async def get_release_info(self) -> t.Dict[str, t.Any]:

async def get_versions(self) -> t.List[PypiVer]:
"""
Get the versions of the ansible-base package on pypi.
Get the versions of the ansible-core package on pypi.
:returns: A list of :pypkg:obj:`packaging.versioning.Version`s
for all the versions on pypi, including prereleases.
"""
flog = mlog.fields(func='AnsibleBasePyPiClient.get_versions')
flog = mlog.fields(func='AnsibleCorePyPiClient.get_versions')
flog.debug('Enter')

release_info = await self.get_release_info()
Expand All @@ -108,33 +108,33 @@ async def get_versions(self) -> t.List[PypiVer]:

async def get_latest_version(self) -> PypiVer:
"""
Get the latest version of ansible-base uploaded to pypi.
Get the latest version of ansible-core uploaded to pypi.
:return: A :pypkg:obj:`packaging.versioning.Version` object representing the latest version
of the package on pypi. This may be a pre-release.
"""
versions = await self.get_versions()
return versions[0]

async def retrieve(self, ansible_base_version: str, download_dir: str) -> str:
async def retrieve(self, ansible_core_version: str, download_dir: str) -> str:
"""
Get the release from pypi.
:arg ansible_base_version: Version of ansible-base to download.
:arg ansible_core_version: Version of ansible-core to download.
:arg download_dir: Directory to download the tarball to.
:returns: The name of the downloaded tarball.
"""
package_name = get_ansible_core_package_name(ansible_base_version)
package_name = get_ansible_core_package_name(ansible_core_version)
release_info = await self.get_release_info()

pypi_url = tar_filename = ''
for release in release_info[ansible_base_version]:
if release['filename'].startswith(f'{package_name}-{ansible_base_version}.tar.'):
for release in release_info[ansible_core_version]:
if release['filename'].startswith(f'{package_name}-{ansible_core_version}.tar.'):
tar_filename = release['filename']
pypi_url = release['url']
break
else: # for-else: http://bit.ly/1ElPkyg
raise UnknownVersion(f'{package_name} {ansible_base_version} does not'
raise UnknownVersion(f'{package_name} {ansible_core_version} does not'
' exist on {self.pypi_server_url}')

tar_filename = os.path.join(download_dir, tar_filename)
Expand All @@ -150,25 +150,25 @@ async def retrieve(self, ansible_base_version: str, download_dir: str) -> str:
return tar_filename


def get_ansible_core_package_name(ansible_base_version: t.Union[str, PypiVer]) -> str:
def get_ansible_core_package_name(ansible_core_version: t.Union[str, PypiVer]) -> str:
"""
Returns the name of the minimal ansible package.
:arg ansible_base_version: The version of the minimal ansible package to retrieve the
:arg ansible_core_version: The version of the minimal ansible package to retrieve the
name for.
:returns: 'ansible-core' when the version is 2.11 or higher. Otherwise 'ansible-base'.
"""
if not isinstance(ansible_base_version, PypiVer):
ansible_base_version = PypiVer(ansible_base_version)
if not isinstance(ansible_core_version, PypiVer):
ansible_core_version = PypiVer(ansible_core_version)

if ansible_base_version.major <= 2 and ansible_base_version.minor <= 10:
if ansible_core_version.major <= 2 and ansible_core_version.minor <= 10:
return 'ansible-base'

return 'ansible-core'


def _get_source_version(ansible_base_source: str) -> PypiVer:
with open(os.path.join(ansible_base_source, 'lib', 'ansible', 'release.py')) as f:
def _get_source_version(ansible_core_source: str) -> PypiVer:
with open(os.path.join(ansible_core_source, 'lib', 'ansible', 'release.py')) as f:
root = ast.parse(f.read())

# Find the version of the source
Expand All @@ -191,18 +191,18 @@ def _get_source_version(ansible_base_source: str) -> PypiVer:
return PypiVer(source_version)


def source_is_devel(ansible_base_source: t.Optional[str]) -> bool:
def source_is_devel(ansible_core_source: t.Optional[str]) -> bool:
"""
:arg ansible_base_source: A path to an Ansible-base checkout or expanded sdist or None.
This will be used instead of downloading an ansible-base package if the version matches
with ``ansible_base_version``.
:arg ansible_core_source: A path to an Ansible-core checkout or expanded sdist or None.
This will be used instead of downloading an ansible-core package if the version matches
with ``ansible_core_version``.
:returns: True if the source looks like it is for the devel branch.
"""
if ansible_base_source is None:
if ansible_core_source is None:
return False

try:
source_version = _get_source_version(ansible_base_source)
source_version = _get_source_version(ansible_core_source)
except Exception:
return False

Expand All @@ -213,47 +213,47 @@ def source_is_devel(ansible_base_source: t.Optional[str]) -> bool:
return False


def source_is_correct_version(ansible_base_source: t.Optional[str],
ansible_base_version: PypiVer) -> bool:
def source_is_correct_version(ansible_core_source: t.Optional[str],
ansible_core_version: PypiVer) -> bool:
"""
:arg ansible_base_source: A path to an Ansible-base checkout or expanded sdist or None.
This will be used instead of downloading an ansible-base package if the version matches
with ``ansible_base_version``.
:arg ansible_base_version: Version of ansible-base to retrieve.
:arg ansible_core_source: A path to an Ansible-core checkout or expanded sdist or None.
This will be used instead of downloading an ansible-core package if the version matches
with ``ansible_core_version``.
:arg ansible_core_version: Version of ansible-core to retrieve.
:returns: True if the source is for a compatible version at or newer than the requested version
"""
if ansible_base_source is None:
if ansible_core_source is None:
return False

try:
source_version = _get_source_version(ansible_base_source)
source_version = _get_source_version(ansible_core_source)
except Exception:
return False

# If the source is a compatible version of ansible-base and it is the same or more recent than
# If the source is a compatible version of ansible-core and it is the same or more recent than
# the requested version then allow this.
if (source_version.major == ansible_base_version.major
and source_version.minor == ansible_base_version.minor
and source_version.micro >= ansible_base_version.micro):
if (source_version.major == ansible_core_version.major
and source_version.minor == ansible_core_version.minor
and source_version.micro >= ansible_core_version.micro):
return True

return False


@lru_cache(None)
async def checkout_from_git(download_dir: str, repo_url: str = _ANSIBLE_BASE_URL) -> str:
async def checkout_from_git(download_dir: str, repo_url: str = _ANSIBLE_CORE_URL) -> str:
"""
Checkout the ansible-base git repo.
Checkout the ansible-core git repo.
:arg download_dir: Directory to checkout into.
:kwarg: repo_url: The url to the git repo.
:return: The directory that ansible-base has been checked out to.
:return: The directory that ansible-core has been checked out to.
"""
loop = best_get_loop()
ansible_base_dir = os.path.join(download_dir, 'ansible-base')
await loop.run_in_executor(None, sh.git, 'clone', repo_url, ansible_base_dir)
ansible_core_dir = os.path.join(download_dir, 'ansible-core')
await loop.run_in_executor(None, sh.git, 'clone', repo_url, ansible_core_dir)

return ansible_base_dir
return ansible_core_dir


@lru_cache(None)
Expand Down Expand Up @@ -300,48 +300,48 @@ async def create_sdist(source_dir: str, dest_dir: str) -> str:
return os.path.join(dist_dir, dist_files[0])


async def get_ansible_base(aio_session: 'aiohttp.client.ClientSession',
ansible_base_version: str,
async def get_ansible_core(aio_session: 'aiohttp.client.ClientSession',
ansible_core_version: str,
tmpdir: str,
ansible_base_source: t.Optional[str] = None) -> str:
ansible_core_source: t.Optional[str] = None) -> str:
"""
Create an ansible-base directory of the requested version.
Create an ansible-core directory of the requested version.
:arg aio_session: :obj:`aiohttp.client.ClientSession` to make http requests with.
:arg ansible_base_version: Version of ansible-base to retrieve. If it is the special string
``@devel``, then we will retrieve ansible-base from its git repository. If it is the
:arg ansible_core_version: Version of ansible-core to retrieve. If it is the special string
``@devel``, then we will retrieve ansible-core from its git repository. If it is the
special string ``@latest``, then we will retrieve the latest version from pypi.
:arg tmpdir: Temporary directory use as a scratch area for downloading to and the place that the
ansible-base directory should be placed in.
:kwarg ansible_base_source: If given, a path to an ansible-base checkout or expanded sdist.
This will be used instead of downloading an ansible-base package if the version matches
with ``ansible_base_version``.
ansible-core directory should be placed in.
:kwarg ansible_core_source: If given, a path to an ansible-core checkout or expanded sdist.
This will be used instead of downloading an ansible-core package if the version matches
with ``ansible_core_version``.
"""
if ansible_base_version == '@devel':
if ansible_core_version == '@devel':
# is the source usable?
if source_is_devel(ansible_base_source):
if source_is_devel(ansible_core_source):
# source_is_devel() protects against this. This assert is to inform the type checker
assert ansible_base_source is not None
source_location: str = ansible_base_source
assert ansible_core_source is not None
source_location: str = ansible_core_source

else:
source_location = await checkout_from_git(tmpdir)

# Create an sdist from the source that can be installed
install_file = await create_sdist(source_location, tmpdir)
else:
pypi_client = AnsibleBasePyPiClient(aio_session)
if ansible_base_version == '@latest':
ansible_base_version: PypiVer = await pypi_client.get_latest_version()
pypi_client = AnsibleCorePyPiClient(aio_session)
if ansible_core_version == '@latest':
ansible_core_version: PypiVer = await pypi_client.get_latest_version()
else:
ansible_base_version: PypiVer = PypiVer(ansible_base_version)
ansible_core_version: PypiVer = PypiVer(ansible_core_version)

# is the source the asked for version?
if source_is_correct_version(ansible_base_source, ansible_base_version):
assert ansible_base_source is not None
if source_is_correct_version(ansible_core_source, ansible_core_version):
assert ansible_core_source is not None
# Create an sdist from the source that can be installed
install_file = await create_sdist(ansible_base_source, tmpdir)
install_file = await create_sdist(ansible_core_source, tmpdir)
else:
install_file = await pypi_client.retrieve(ansible_base_version.public, tmpdir)
install_file = await pypi_client.retrieve(ansible_core_version.public, tmpdir)

return install_file
2 changes: 1 addition & 1 deletion src/antsibull/app_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
def do_something():
app_ctx = app_context.app_ctx.get()
base_filename = download_python_package('ansible-base', server_url=app_ctx.pypi_url)
base_filename = download_python_package('ansible-core', server_url=app_ctx.pypi_url)
return base_filename
def run(args):
Expand Down
Loading

0 comments on commit 5dc66f3

Please sign in to comment.