def _get_channel_lines_for_channel( # noqa: C901 snap_channel_map: ChannelMap, channel_name: str, architecture: str, current_tick: str, ) -> Tuple[str, List[List[str]]]: channel_lines: List[List[str]] = list() channel_info = snap_channel_map.get_channel_info(channel_name) try: progressive_mapped_channel: Optional[ MappedChannel] = snap_channel_map.get_mapped_channel( channel_name=channel_name, architecture=architecture, progressive=True) except ValueError: progressive_mapped_channel = None if progressive_mapped_channel is not None: progressive_revision = snap_channel_map.get_revision( progressive_mapped_channel.revision) if progressive_mapped_channel.progressive.percentage is None: raise RuntimeError("Unexpected null progressive percentage") else: percentage = progressive_mapped_channel.progressive.percentage if progressive_mapped_channel.progressive.current_percentage is None: current_percentage_fmt = _HINTS.UNKNOWN remaining_percentage_fmt = _HINTS.UNKNOWN else: current_percentage = ( progressive_mapped_channel.progressive.current_percentage) current_percentage_fmt = f"{current_percentage:.0f}" remaining_percentage_fmt = f"{100 - current_percentage:.0f}" progressive_mapped_channel_line = _get_channel_line( mapped_channel=progressive_mapped_channel, revision=progressive_revision, channel_info=channel_info, hint=current_tick, progress_string= f"{current_percentage_fmt}{_HINTS.PROGRESSING_TO}{percentage:.0f}%", ) # Setup progress for the actually released revision, this needs to be # calculated. But only show it if the channel is open. progress_string = ( f"{remaining_percentage_fmt}{_HINTS.PROGRESSING_TO}{100 - percentage:.0f}%" ) else: progress_string = _HINTS.NO_PROGRESS try: mapped_channel: Optional[ MappedChannel] = snap_channel_map.get_mapped_channel( channel_name=channel_name, architecture=architecture, progressive=False) except ValueError: mapped_channel = None next_tick = current_tick if mapped_channel is not None: revision = snap_channel_map.get_revision(mapped_channel.revision) channel_lines.append( _get_channel_line( mapped_channel=mapped_channel, revision=revision, channel_info=channel_info, hint=current_tick, progress_string=progress_string, )) if channel_info.branch is None: next_tick = _HINTS.FOLLOWING # Show an empty entry if there is no specific channel information, but # only for <track>/<risks> (ignoring /<branch>). elif channel_info.branch is None: channel_lines.append( _get_channel_line( mapped_channel=None, revision=None, channel_info=channel_info, hint=current_tick, progress_string=_HINTS.NO_PROGRESS if current_tick == _HINTS.CLOSED else progress_string, )) if (os.getenv("SNAPCRAFT_EXPERIMENTAL_PROGRESSIVE_RELEASES") and progressive_mapped_channel is not None): channel_lines.append(progressive_mapped_channel_line) if channel_info.branch is None: next_tick = _HINTS.FOLLOWING return next_tick, channel_lines
def setUp(self): super().setUp() # Our experimental environment variable is sticky self.useFixture( fixtures.EnvironmentVariable( "SNAPCRAFT_EXPERIMENTAL_PROGRESSIVE_RELEASES", None ) ) self.fake_store_login = fixtures.MockPatchObject(storeapi.StoreClient, "login") self.useFixture(self.fake_store_login) self.fake_store_register = fixtures.MockPatchObject( storeapi._sca_client.SCAClient, "register" ) self.useFixture(self.fake_store_register) self.fake_store_account_info = fixtures.MockPatchObject( storeapi._sca_client.SCAClient, "get_account_information", return_value={ "account_id": "abcd", "account_keys": list(), "snaps": { "16": { "snap-test": { "snap-id": "snap-test-snap-id", "status": "Approved", "private": False, "since": "2016-12-12T01:01Z", "price": "0", }, "basic": { "snap-id": "basic-snap-id", "status": "Approved", "private": False, "since": "2016-12-12T01:01Z", "price": "0", }, } }, }, ) self.useFixture(self.fake_store_account_info) self.fake_store_status = fixtures.MockPatchObject( storeapi._sca_client.SCAClient, "snap_status", return_value=dict() ) self.useFixture(self.fake_store_status) self.fake_store_revisions = fixtures.MockPatchObject( storeapi._sca_client.SCAClient, "snap_revisions", return_value=dict() ) self.useFixture(self.fake_store_revisions) self.fake_store_release = fixtures.MockPatchObject( storeapi.StoreClient, "release" ) self.useFixture(self.fake_store_release) self.fake_store_register_key = fixtures.MockPatchObject( storeapi._sca_client.SCAClient, "register_key" ) self.useFixture(self.fake_store_register_key) # channel-map endpoint self.channel_map = ChannelMap.unmarshal( { "channel-map": [ { "architecture": "amd64", "channel": "2.1/beta", "expiration-date": None, "revision": 19, "progressive": {"paused": None, "percentage": None}, } ], "revisions": [ {"architectures": ["amd64"], "revision": 19, "version": "10"} ], "snap": { "name": "snap-test", "channels": [ { "branch": None, "fallback": None, "name": "2.1/stable", "risk": "stable", "track": "2.1", }, { "branch": None, "fallback": "2.1/stable", "name": "2.1/candidate", "risk": "candidate", "track": "2.1", }, { "branch": None, "fallback": "2.1/candidate", "name": "2.1/beta", "risk": "beta", "track": "2.1", }, { "branch": None, "fallback": "2.1/beta", "name": "2.1/edge", "risk": "edge", "track": "2.1", }, ], "default-track": "2.1", }, } ) self.fake_store_get_snap_channel_map = fixtures.MockPatchObject( storeapi.StoreClient, "get_snap_channel_map", return_value=self.channel_map ) self.useFixture(self.fake_store_get_snap_channel_map) # Uploading self.mock_tracker = mock.Mock(storeapi._status_tracker.StatusTracker) self.mock_tracker.track.return_value = { "code": "ready_to_release", "processed": True, "can_release": True, "url": "/fake/url", "revision": 19, } self.fake_store_upload_precheck = fixtures.MockPatchObject( storeapi.StoreClient, "upload_precheck" ) self.useFixture(self.fake_store_upload_precheck) self.fake_store_upload = fixtures.MockPatchObject( storeapi.StoreClient, "upload", return_value=self.mock_tracker ) self.useFixture(self.fake_store_upload) # Mock the snap command, pass through a select few. self.fake_check_output = fixtures.MockPatch( "subprocess.check_output", side_effect=mock_check_output ) self.useFixture(self.fake_check_output) # Pretend that the snap command is available self.fake_package_installed = fixtures.MockPatch( "snapcraft.internal.repo.Repo.is_package_installed", return_value=True ) self.useFixture(self.fake_package_installed)
def setUp(self): super().setUp() # Our experimental environment variable is sticky self.useFixture( fixtures.EnvironmentVariable( "SNAPCRAFT_EXPERIMENTAL_PROGRESSIVE_RELEASES", None ) ) self.fake_store_login = fixtures.MockPatchObject(storeapi.StoreClient, "login") self.useFixture(self.fake_store_login) self.fake_store_register = fixtures.MockPatchObject( storeapi._dashboard_api.DashboardAPI, "register" ) self.useFixture(self.fake_store_register) self.fake_store_account_info = fixtures.MockPatchObject( storeapi._dashboard_api.DashboardAPI, "get_account_information", return_value={ "account_id": "abcd", "account_keys": list(), "snaps": { "16": { "snap-test": { "snap-id": "snap-test-snap-id", "status": "Approved", "private": False, "since": "2016-12-12T01:01Z", "price": "0", }, "basic": { "snap-id": "basic-snap-id", "status": "Approved", "private": False, "since": "2016-12-12T01:01Z", "price": "0", }, } }, }, ) self.useFixture(self.fake_store_account_info) self.fake_store_status = fixtures.MockPatchObject( storeapi._dashboard_api.DashboardAPI, "snap_status", return_value=dict() ) self.useFixture(self.fake_store_status) self.fake_store_release = fixtures.MockPatchObject( storeapi.StoreClient, "release" ) self.useFixture(self.fake_store_release) self.fake_store_register_key = fixtures.MockPatchObject( storeapi._dashboard_api.DashboardAPI, "register_key" ) self.useFixture(self.fake_store_register_key) # channel-map endpoint self.channel_map = ChannelMap.unmarshal( { "channel-map": [ { "architecture": "amd64", "channel": "2.1/beta", "expiration-date": None, "revision": 19, "progressive": { "paused": None, "percentage": None, "current-percentage": None, }, }, { "architecture": "amd64", "channel": "2.0/beta", "expiration-date": None, "revision": 18, "progressive": { "paused": None, "percentage": None, "current-percentage": None, }, }, ], "revisions": [ {"architectures": ["amd64"], "revision": 19, "version": "10"}, {"architectures": ["amd64"], "revision": 18, "version": "10"}, ], "snap": { "name": "snap-test", "channels": [ { "branch": None, "fallback": None, "name": "2.1/stable", "risk": "stable", "track": "2.1", }, { "branch": None, "fallback": "2.1/stable", "name": "2.1/candidate", "risk": "candidate", "track": "2.1", }, { "branch": None, "fallback": "2.1/candidate", "name": "2.1/beta", "risk": "beta", "track": "2.1", }, { "branch": None, "fallback": "2.1/beta", "name": "2.1/edge", "risk": "edge", "track": "2.1", }, { "branch": None, "fallback": None, "name": "2.0/stable", "risk": "stable", "track": "2.0", }, { "branch": None, "fallback": "2.0/stable", "name": "2.0/candidate", "risk": "candidate", "track": "2.0", }, { "branch": None, "fallback": "2.0/candidate", "name": "2.0/beta", "risk": "beta", "track": "2.0", }, { "branch": None, "fallback": "2.0/beta", "name": "2.0/edge", "risk": "edge", "track": "2.0", }, ], "default-track": "2.1", "tracks": [ { "name": "2.0", "status": "default", "creation-date": "2019-10-17T14:11:59Z", "version-pattern": "2\\.*", }, { "name": "latest", "status": "active", "creation-date": None, "version-pattern": None, }, ], }, } ) self.fake_store_get_snap_channel_map = fixtures.MockPatchObject( storeapi.StoreClient, "get_snap_channel_map", return_value=self.channel_map ) self.useFixture(self.fake_store_get_snap_channel_map) self.releases = Releases.unmarshal( { "revisions": [ { "architectures": ["i386"], "base": "core20", "build_url": None, "confinement": "strict", "created_at": " 2016-09-27T19:23:40Z", "grade": "stable", "revision": 2, "sha3-384": "a9060ef4872ccacbfa440617a76fcd84967896b28d0d1eb7571f00a1098d766e7e93353b084ba6ad841d7b14b95ede48", "size": 20, "status": "Published", "version": "2.0.1", }, { "architectures": ["amd64"], "base": "core20", "build_url": None, "confinement": "strict", "created_at": "2016-09-27T18:38:43Z", "grade": "stable", "revision": 1, "sha3-384": "a9060ef4872ccacbfa440617a76fcd84967896b28d0d1eb7571f00a1098d766e7e93353b084ba6ad841d7b14b95ede48", "size": 20, "status": "Published", "version": "2.0.2", }, ], "releases": [ { "architecture": "amd64", "branch": None, "channel": "latest/stable", "expiration-date": None, "revision": 1, "risk": "stable", "track": "latest", "when": "2020-02-12T17:51:40.891996Z", }, { "architecture": "i386", "branch": None, "channel": "latest/stable", "expiration-date": None, "revision": None, "risk": "stable", "track": "latest", "when": "2020-02-11T17:51:40.891996Z", }, { "architecture": "amd64", "branch": None, "channel": "latest/edge", "expiration-date": None, "revision": 1, "risk": "stable", "track": "latest", "when": "2020-01-12T17:51:40.891996Z", }, ], } ) self.fake_store_get_releases = fixtures.MockPatchObject( storeapi.StoreClient, "get_snap_releases", return_value=self.releases ) self.useFixture(self.fake_store_get_releases) # Uploading self.mock_tracker = mock.Mock(storeapi._status_tracker.StatusTracker) self.mock_tracker.track.return_value = { "code": "ready_to_release", "processed": True, "can_release": True, "url": "/fake/url", "revision": 19, } self.fake_store_upload_precheck = fixtures.MockPatchObject( storeapi.StoreClient, "upload_precheck" ) self.useFixture(self.fake_store_upload_precheck) self.fake_store_upload = fixtures.MockPatchObject( storeapi.StoreClient, "upload", return_value=self.mock_tracker ) self.useFixture(self.fake_store_upload) # Mock the snap command, pass through a select few. self.fake_check_output = fixtures.MockPatch( "subprocess.check_output", side_effect=mock_check_output ) self.useFixture(self.fake_check_output) # Pretend that the snap command is available self.fake_package_installed = fixtures.MockPatch( "snapcraft.internal.repo.Repo.is_package_installed", return_value=True ) self.useFixture(self.fake_package_installed)
def _get_channel_lines_for_channel(snap_channel_map: ChannelMap, channel_name: str, architecture: str) -> List[List[str]]: channel_lines: List[List[str]] = list() channel_info = snap_channel_map.get_channel_info(channel_name) hint = _get_channel_hint( channel_map=snap_channel_map.channel_map, fallback=channel_info.fallback, architecture=architecture, ) try: progressive_mapped_channel: Optional[ MappedChannel] = snap_channel_map.get_mapped_channel( channel_name=channel_name, architecture=architecture, progressive=True) except ValueError: progressive_mapped_channel = None if progressive_mapped_channel is not None: progressive_revision = snap_channel_map.get_revision( progressive_mapped_channel.revision) progressive_mapped_channel_line = _get_channel_line( mapped_channel=progressive_mapped_channel, revision=progressive_revision, channel_info=channel_info, hint=hint, progress_string= f"{_HINTS.PROGRESSING_TO} {progressive_mapped_channel.progressive.percentage:.0f}%", ) if progressive_mapped_channel.progressive.percentage is None: percentage = 0.0 else: percentage = progressive_mapped_channel.progressive.percentage # Setup progress for the actually released revision, this needs to be # calculated. But only show it if the channel is open. progress_string = "{} {:.0f}%".format(_HINTS.PROGRESSING_TO, 100 - percentage) else: progress_string = _HINTS.NO_PROGRESS try: mapped_channel: Optional[ MappedChannel] = snap_channel_map.get_mapped_channel( channel_name=channel_name, architecture=architecture, progressive=False) except ValueError: mapped_channel = None if mapped_channel is not None: revision = snap_channel_map.get_revision(mapped_channel.revision) channel_lines.append( _get_channel_line( mapped_channel=mapped_channel, revision=revision, channel_info=channel_info, hint=hint, progress_string=progress_string, )) # Don't show empty branches elif channel_info.branch is None: channel_lines.append( _get_channel_line( mapped_channel=None, revision=None, channel_info=channel_info, hint=hint, progress_string=_HINTS.NO_PROGRESS if hint == _HINTS.CLOSED else progress_string, )) if (os.getenv("SNAPCRAFT_EXPERIMENTAL_PROGRESSIVE_RELEASES") and progressive_mapped_channel is not None): channel_lines.append(progressive_mapped_channel_line) return channel_lines