ledgered 0.6.3.dev2__tar.gz → 0.6.4.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/.github/workflows/build_and_tests.yml +6 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/CHANGELOG.md +7 -0
- {ledgered-0.6.3.dev2/src/ledgered.egg-info → ledgered-0.6.4.dev2}/PKG-INFO +2 -1
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/pyproject.toml +1 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/__version__.py +2 -2
- ledgered-0.6.4.dev2/src/ledgered/github.py +129 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2/src/ledgered.egg-info}/PKG-INFO +2 -1
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered.egg-info/SOURCES.txt +4 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered.egg-info/requires.txt +1 -0
- ledgered-0.6.4.dev2/tests/functional/conftest.py +27 -0
- ledgered-0.6.4.dev2/tests/functional/test_github.py +51 -0
- ledgered-0.6.4.dev2/tests/unit/test_github.py +48 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/.github/workflows/codeql-analysis.yml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/.github/workflows/fast-checks.yml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/.gitignore +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/LICENSE +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/README.md +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/doc/binary.md +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/doc/manifest.md +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/setup.cfg +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/binary.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/app.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/cli.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/constants.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/errors.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/manifest.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/tests.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/use_cases.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/manifest/utils.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/serializers.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered/utils/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered.egg-info/dependency_links.txt +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered.egg-info/entry_points.txt +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/src/ledgered.egg-info/top_level.txt +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/Cargo.toml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/Makefile +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/full_correct.toml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/ledger_app.toml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/minimal.toml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/_data/one_leaf.toml +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/functional/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/functional/manifest/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/functional/manifest/test_cli.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/manifest/__init__.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/manifest/test_app.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/manifest/test_manifest.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/manifest/test_tests.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/manifest/test_use_cases.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/test_binary.py +0 -0
- {ledgered-0.6.3.dev2 → ledgered-0.6.4.dev2}/tests/unit/test_serializers.py +0 -0
|
@@ -43,6 +43,12 @@ jobs:
|
|
|
43
43
|
- name: Run tests and generate coverage
|
|
44
44
|
run: pytest -v --tb=short tests/ --cov ledgered --cov-report xml
|
|
45
45
|
|
|
46
|
+
- name: Run unit tests and generate coverage
|
|
47
|
+
run: pytest -v --tb=short tests/unit --cov ledgered --cov-report xml
|
|
48
|
+
|
|
49
|
+
- name: Run functional tests and generate coverage
|
|
50
|
+
run: pytest -v --tb=short tests/functional --cov ledgered --cov-report xml --cov-append --token "${{ secrets.GITHUB_TOKEN }}"
|
|
51
|
+
|
|
46
52
|
- name: Upload coverage to Codecov
|
|
47
53
|
uses: codecov/codecov-action@v4
|
|
48
54
|
with:
|
|
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
## [0.7.0] - 2024-04-12
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added wrapper around GitHub API to ease manipulating Ledger application repositories
|
|
14
|
+
|
|
15
|
+
|
|
9
16
|
## [0.6.3] - 2024-03-26
|
|
10
17
|
|
|
11
18
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ledgered
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4.dev2
|
|
4
4
|
Summary: Python tools, utils, libraries, to be used with Ledger cryptodevices
|
|
5
5
|
Author-email: Ledger <hello@ledger.fr>
|
|
6
6
|
License: MIT License
|
|
@@ -39,6 +39,7 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: toml
|
|
41
41
|
Requires-Dist: pyelftools
|
|
42
|
+
Requires-Dist: pygithub
|
|
42
43
|
Provides-Extra: dev
|
|
43
44
|
Requires-Dist: pytest; extra == "dev"
|
|
44
45
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -12,5 +12,5 @@ __version__: str
|
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
|
13
13
|
version_tuple: VERSION_TUPLE
|
|
14
14
|
|
|
15
|
-
__version__ = version = '0.6.
|
|
16
|
-
__version_tuple__ = version_tuple = (0, 6,
|
|
15
|
+
__version__ = version = '0.6.4.dev2'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 6, 4, 'dev2')
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from enum import IntEnum, auto
|
|
2
|
+
from github import ContentFile as PyContentFile, Github as PyGithub, Repository as PyRepository
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
|
|
7
|
+
from ledgered.manifest import MANIFEST_FILE_NAME, Manifest
|
|
8
|
+
|
|
9
|
+
LEDGER_ORG_NAME = "ledgerhq"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Condition(IntEnum):
|
|
13
|
+
WITH = auto()
|
|
14
|
+
WITHOUT = auto()
|
|
15
|
+
ONLY = auto()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AppRepository(PyRepository.Repository):
|
|
19
|
+
|
|
20
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
21
|
+
super().__init__(*args, **kwargs)
|
|
22
|
+
self._manifest: Optional[Manifest] = None
|
|
23
|
+
self._makefile: Optional[str] = None
|
|
24
|
+
self._branch: str = self.default_branch
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def manifest(self) -> Manifest:
|
|
28
|
+
if self._manifest is None:
|
|
29
|
+
manifest = self.get_contents(MANIFEST_FILE_NAME, ref=self.current_branch)
|
|
30
|
+
# `get_contents` can return a list, but here there can only be one manifest
|
|
31
|
+
assert isinstance(manifest, PyContentFile.ContentFile)
|
|
32
|
+
manifest_content = manifest.decoded_content.decode()
|
|
33
|
+
self._manifest = Manifest.from_string(manifest_content)
|
|
34
|
+
return self._manifest
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def makefile_path(self) -> Path:
|
|
38
|
+
location = self.manifest.app.build_directory
|
|
39
|
+
if self.manifest.app.is_rust:
|
|
40
|
+
location /= "Cargo.toml"
|
|
41
|
+
else:
|
|
42
|
+
location /= "Makefile"
|
|
43
|
+
return location
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def makefile(self) -> str:
|
|
47
|
+
if self._makefile is None:
|
|
48
|
+
# paths on Windows contain "\" which are not compatible with GitHub remote paths
|
|
49
|
+
makefile = self.get_contents(str(self.makefile_path).replace("\\", "/"),
|
|
50
|
+
ref=self.current_branch)
|
|
51
|
+
# `get_contents` can return a list, but here there can only be one Makefile / Cargo.toml
|
|
52
|
+
assert isinstance(makefile, PyContentFile.ContentFile)
|
|
53
|
+
self._makefile = makefile.decoded_content.decode()
|
|
54
|
+
return self._makefile
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def variants(self) -> List[str]:
|
|
58
|
+
variants = []
|
|
59
|
+
for line in self.makefile.splitlines():
|
|
60
|
+
if "VARIANTS" in line:
|
|
61
|
+
variants.extend(line.split(' ')[3:])
|
|
62
|
+
elif "VARIANT_VALUES = " in line:
|
|
63
|
+
variants.extend(line.split(" = ")[1].split(' '))
|
|
64
|
+
return variants
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def current_branch(self) -> str:
|
|
68
|
+
return self._branch
|
|
69
|
+
|
|
70
|
+
@current_branch.setter
|
|
71
|
+
def current_branch(self, new_branch: str) -> None:
|
|
72
|
+
self._branch = self.get_branch(new_branch).name
|
|
73
|
+
# invalidating previously fetched info, as they may differ on another branch
|
|
74
|
+
self._manifest = None
|
|
75
|
+
self._makefile = None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class GitHubApps(list):
|
|
79
|
+
|
|
80
|
+
def __init__(self, apps: List[AppRepository]):
|
|
81
|
+
super().__init__([r for r in apps if r.name.startswith("app-")])
|
|
82
|
+
|
|
83
|
+
def filter(self,
|
|
84
|
+
name: Optional[str] = None,
|
|
85
|
+
archived: Condition = Condition.WITH,
|
|
86
|
+
private: Condition = Condition.WITH) -> "GitHubApps":
|
|
87
|
+
new_list = [i for i in self]
|
|
88
|
+
# archived filtering
|
|
89
|
+
if archived == Condition.WITHOUT:
|
|
90
|
+
new_list = [r for r in new_list if not r.archived]
|
|
91
|
+
elif archived == Condition.ONLY:
|
|
92
|
+
new_list = [r for r in new_list if r.archived]
|
|
93
|
+
# private filtering
|
|
94
|
+
if private == Condition.WITHOUT:
|
|
95
|
+
new_list = [r for r in new_list if not r.private]
|
|
96
|
+
elif private == Condition.ONLY:
|
|
97
|
+
new_list = [r for r in new_list if r.private]
|
|
98
|
+
# name filtering
|
|
99
|
+
if name is not None:
|
|
100
|
+
new_list = [r for r in new_list if name.lower() in r.name.lower()]
|
|
101
|
+
return GitHubApps(new_list)
|
|
102
|
+
|
|
103
|
+
def first(self, *args, **kwargs) -> Optional[AppRepository]:
|
|
104
|
+
results = self.filter(*args, **kwargs)
|
|
105
|
+
return results[0] if results else None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class GitHubLedgerHQ(PyGithub):
|
|
109
|
+
|
|
110
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
111
|
+
super().__init__(*args, **kwargs)
|
|
112
|
+
self._org = self.get_organization(LEDGER_ORG_NAME)
|
|
113
|
+
self._apps: Optional[GitHubApps] = None
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def apps(self) -> GitHubApps:
|
|
117
|
+
if self._apps is None:
|
|
118
|
+
with patch("github.Repository.Repository", AppRepository):
|
|
119
|
+
self._apps = GitHubApps(self._org.get_repos())
|
|
120
|
+
return self._apps
|
|
121
|
+
|
|
122
|
+
def get_app(self, name) -> AppRepository:
|
|
123
|
+
"""
|
|
124
|
+
Fetch a specific application repository on GitHub.
|
|
125
|
+
The name must be exact.
|
|
126
|
+
"""
|
|
127
|
+
assert name.startswith("app-"), f"'{name}' is not prefixed with 'app-'!"
|
|
128
|
+
with patch("github.Repository.Repository", AppRepository):
|
|
129
|
+
return self._org.get_repo(name)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ledgered
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4.dev2
|
|
4
4
|
Summary: Python tools, utils, libraries, to be used with Ledger cryptodevices
|
|
5
5
|
Author-email: Ledger <hello@ledger.fr>
|
|
6
6
|
License: MIT License
|
|
@@ -39,6 +39,7 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: toml
|
|
41
41
|
Requires-Dist: pyelftools
|
|
42
|
+
Requires-Dist: pygithub
|
|
42
43
|
Provides-Extra: dev
|
|
43
44
|
Requires-Dist: pytest; extra == "dev"
|
|
44
45
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -11,6 +11,7 @@ doc/manifest.md
|
|
|
11
11
|
src/ledgered/__init__.py
|
|
12
12
|
src/ledgered/__version__.py
|
|
13
13
|
src/ledgered/binary.py
|
|
14
|
+
src/ledgered/github.py
|
|
14
15
|
src/ledgered/serializers.py
|
|
15
16
|
src/ledgered.egg-info/PKG-INFO
|
|
16
17
|
src/ledgered.egg-info/SOURCES.txt
|
|
@@ -35,10 +36,13 @@ tests/_data/ledger_app.toml
|
|
|
35
36
|
tests/_data/minimal.toml
|
|
36
37
|
tests/_data/one_leaf.toml
|
|
37
38
|
tests/functional/__init__.py
|
|
39
|
+
tests/functional/conftest.py
|
|
40
|
+
tests/functional/test_github.py
|
|
38
41
|
tests/functional/manifest/__init__.py
|
|
39
42
|
tests/functional/manifest/test_cli.py
|
|
40
43
|
tests/unit/__init__.py
|
|
41
44
|
tests/unit/test_binary.py
|
|
45
|
+
tests/unit/test_github.py
|
|
42
46
|
tests/unit/test_serializers.py
|
|
43
47
|
tests/unit/manifest/__init__.py
|
|
44
48
|
tests/unit/manifest/test_app.py
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from github.Auth import Token
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from ledgered.github import GitHubLedgerHQ
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def pytest_addoption(parser):
|
|
9
|
+
parser.addoption("--token", required=False, default=None,
|
|
10
|
+
help="Provide a GitHub token so that functional test won't trigger API "
|
|
11
|
+
"restrictions too fast")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture(scope="session")
|
|
15
|
+
def token(pytestconfig) -> Optional[Token]:
|
|
16
|
+
token = pytestconfig.getoption("token")
|
|
17
|
+
return None if token is None else Token(token)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture(scope="session")
|
|
21
|
+
def gh(token: Token):
|
|
22
|
+
return GitHubLedgerHQ() if token is None else GitHubLedgerHQ(auth=token)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture(scope="session")
|
|
26
|
+
def exchange(gh):
|
|
27
|
+
return gh.get_app("app-exchange")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import requests
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from unittest import TestCase
|
|
5
|
+
|
|
6
|
+
from github.GithubException import GithubException
|
|
7
|
+
from ledgered.github import AppRepository, Condition, GitHubApps, GitHubLedgerHQ
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_apps(gh):
|
|
11
|
+
assert isinstance(gh.apps, list)
|
|
12
|
+
assert isinstance(gh.apps, GitHubApps)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_get_app(gh):
|
|
16
|
+
name = "app-exchange"
|
|
17
|
+
app = gh.get_app(name)
|
|
18
|
+
assert isinstance(app, AppRepository)
|
|
19
|
+
assert app.name == name
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_exchange_manifest(exchange):
|
|
23
|
+
assert exchange.manifest.app.sdk == "c"
|
|
24
|
+
assert len(exchange.manifest.app.devices) == 4
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_exchange_makefile_path(exchange):
|
|
28
|
+
assert exchange.makefile_path == Path("./Makefile")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_exchange_makefile(exchange):
|
|
32
|
+
makefile = requests.get("https://raw.githubusercontent.com/LedgerHQ/app-exchange/develop/Makefile").content.decode()
|
|
33
|
+
assert exchange.makefile == makefile
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_exchange_branches(exchange):
|
|
37
|
+
assert exchange.current_branch == "develop"
|
|
38
|
+
exchange.current_branch = "master"
|
|
39
|
+
assert exchange.current_branch == "master"
|
|
40
|
+
|
|
41
|
+
with pytest.raises(GithubException):
|
|
42
|
+
exchange.current_branch = "does not exists"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_exchange_variant(exchange):
|
|
46
|
+
assert exchange.variants == ["exchange"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_starknet_makefile_path(gh):
|
|
50
|
+
app = gh.get_app("app-starknet")
|
|
51
|
+
assert app.makefile_path == Path("./Cargo.toml")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from unittest import TestCase
|
|
3
|
+
from unittest.mock import patch, MagicMock
|
|
4
|
+
|
|
5
|
+
from ledgered.github import AppRepository, Condition, GitHubApps, GitHubLedgerHQ
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class AppRepositoryMock:
|
|
10
|
+
name: str
|
|
11
|
+
archived: bool = False
|
|
12
|
+
private: bool = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestGitHubApps(TestCase):
|
|
16
|
+
|
|
17
|
+
def setUp(self):
|
|
18
|
+
self.app1 = AppRepositoryMock("app-1")
|
|
19
|
+
self.app2 = AppRepositoryMock("not-app")
|
|
20
|
+
self.app3 = AppRepositoryMock("app-3", private=True)
|
|
21
|
+
self.app4 = AppRepositoryMock("app-4", archived=True)
|
|
22
|
+
self.apps = GitHubApps([self.app1, self.app2, self.app3, self.app4])
|
|
23
|
+
|
|
24
|
+
def test___init__(self):
|
|
25
|
+
self.assertListEqual(self.apps, [self.app1, self.app3, self.app4])
|
|
26
|
+
|
|
27
|
+
def test_filter(self):
|
|
28
|
+
self.assertCountEqual(self.apps.filter(), self.apps)
|
|
29
|
+
self.assertCountEqual(self.apps.filter(name="3"), [self.app3])
|
|
30
|
+
self.assertCountEqual(self.apps.filter(name="app"), self.apps)
|
|
31
|
+
self.assertCountEqual(self.apps.filter(archived=Condition.WITHOUT), [self.app1, self.app3])
|
|
32
|
+
self.assertCountEqual(self.apps.filter(archived=Condition.ONLY), [self.app4])
|
|
33
|
+
self.assertCountEqual(self.apps.filter(private=Condition.WITHOUT), [self.app1, self.app4])
|
|
34
|
+
self.assertCountEqual(self.apps.filter(private=Condition.ONLY), [self.app3])
|
|
35
|
+
|
|
36
|
+
def test_first(self):
|
|
37
|
+
self.assertEqual(self.apps.first("3"), self.app3)
|
|
38
|
+
self.assertEqual(self.apps.first(), self.app1)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestGitHubLedgerHQ(TestCase):
|
|
42
|
+
|
|
43
|
+
def setUp(self):
|
|
44
|
+
self.g = GitHubLedgerHQ()
|
|
45
|
+
|
|
46
|
+
def test_get_app_wrong_name(self):
|
|
47
|
+
with self.assertRaises(AssertionError):
|
|
48
|
+
self.g.get_app("not-starting-with-app-")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|