Skip to content

Commit

Permalink
Add rc branch to python
Browse files Browse the repository at this point in the history
  • Loading branch information
DimaStebaev committed Jul 16, 2024
1 parent 9765bf8 commit 5106c9c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 9 deletions.
93 changes: 87 additions & 6 deletions python/src/skale_contracts/project.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
"""Contains Project class"""

# cspell:words maxsplit

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from itertools import count
from typing import TYPE_CHECKING, Generator

from eth_utils.address import to_canonical_address
import requests
from semver.version import Version as SemVersion

from .constants import REPOSITORY_URL, NETWORK_TIMEOUT
from .instance import Instance, InstanceData
Expand All @@ -13,6 +19,18 @@
from .network import Network


def alternative_versions_generator(version: str) -> Generator[str, None, None]:
"""Provides versions that have compatible ABI"""
sem_version = SemVersion.parse(version)
if sem_version.prerelease:
prerelease_title = sem_version.prerelease.split('.', maxsplit=1)[0]
if prerelease_title == 'stable':
for prerelease_version in count():
yield str(
sem_version.replace(prerelease=f'rc.{prerelease_version}')
)


class Project(ABC):
"""Represents set of smart contracts known as project"""

Expand Down Expand Up @@ -53,11 +71,23 @@ def get_instance(self, alias_or_address: str) -> Instance:

def download_abi_file(self, version: str) -> str:
"""Download file with ABI"""
url = self.get_abi_url(version)
response = requests.get(url, timeout=NETWORK_TIMEOUT)
if response.status_code != 200:
raise RuntimeError(f"Can't download abi file from {url}")
return response.text
exceptions: list[str] = []
abi_file = self._download_abi_file_by_version(
version,
exceptions
)
if abi_file:
return abi_file

# Stable version can be absent for some time after upgrade.
# Try release candidate branch
abi_file = self._download_alternative_abi_file(
version,
exceptions
)
if abi_file:
return abi_file
raise RuntimeError('\n'.join(exceptions))

def get_abi_url(self, version: str) -> str:
"""Calculate URL of ABI file"""
Expand All @@ -78,3 +108,54 @@ def get_instance_data_url(self, alias: str) -> str:
@abstractmethod
def create_instance(self, address: Address) -> Instance:
"""Create instance object based on known address"""

def get_abi_urls(self, version: str) -> list[str]:
"""Calculate URLs of ABI file"""
return [
self._get_github_release_abi_url(version),
self._get_github_repository_abi_url(version)
]

# Private

def _download_abi_file_by_version(
self,
version: str,
exceptions: list[str]
) -> str | None:
for abi_url in self.get_abi_urls(version):
response = requests.get(abi_url, timeout=NETWORK_TIMEOUT)
if response.status_code != 200:
exceptions.append(f"Can't download abi file from {abi_url}")
else:
return response.text
return None

def _download_alternative_abi_file(
self,
version: str,
exceptions: list[str]
) -> str | None:
abi_file: str | None = None
for alternative_version in alternative_versions_generator(version):
alternative_abi_file = self._download_abi_file_by_version(
alternative_version,
exceptions
)
if alternative_abi_file:
abi_file = alternative_abi_file
else:
# If abiFile is none
# the previous one is the latest
break

return abi_file

def _get_github_release_abi_url(self, version: str) -> str:
return f'{self.github_repo}releases/download/{version}/{
self.get_abi_filename(version)}'

def _get_github_repository_abi_url(self, version: str) -> str:
return f'{self.github_repo.replace(
'github.com',
'raw.githubusercontent.com')}abi/{self.get_abi_filename(version)}'
7 changes: 4 additions & 3 deletions typescript/base/src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
import { ProjectMetadata } from "./metadata";
import { REPOSITORY_URL } from "./domain/constants";

const getAlternativeVersions =
function *getAlternativeVersions (version: string) {
const alternativeVersionsGenerator =
function *alternativeVersionsGenerator (version: string) {
const semVersion = semver.parse(version);
const wordIndex = 0;
const nextIndex = 1;
Expand Down Expand Up @@ -142,7 +142,8 @@ export abstract class Project<ContractType> {
exceptions: string[]
) {
let abiFile: SkaleABIFile | null = null;
for (const alternativeVersion of getAlternativeVersions(version)) {
for (const alternativeVersion
of alternativeVersionsGenerator(version)) {
// Await expression must be executed sequentially
// eslint-disable-next-line no-await-in-loop
const alternativeAbiFile = await this.downloadAbiFileByVersion(
Expand Down

0 comments on commit 5106c9c

Please sign in to comment.