run unittest on multiple platforms
This commit is contained in:
parent
596ed08395
commit
a042377a7b
7 changed files with 280 additions and 84 deletions
143
.github/workflows/main.yml
vendored
143
.github/workflows/main.yml
vendored
|
@ -10,62 +10,11 @@ jobs:
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: '3.7'
|
python-version: '3.7'
|
||||||
- run: make install tools
|
- run: pip install -e .[lint]
|
||||||
- run: make lint
|
- run: make lint
|
||||||
|
|
||||||
tests-unit:
|
tests-unit:
|
||||||
name: "tests / unit"
|
name: "tests / unit"
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: '3.7'
|
|
||||||
- run: make install tools
|
|
||||||
- working-directory: lbry
|
|
||||||
env:
|
|
||||||
HOME: /tmp
|
|
||||||
run: coverage run -p --source=lbry -m unittest discover -vv tests.unit
|
|
||||||
|
|
||||||
tests-integration:
|
|
||||||
name: "tests / integration"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
test:
|
|
||||||
- datanetwork
|
|
||||||
- blockchain
|
|
||||||
- other
|
|
||||||
db:
|
|
||||||
- postgres
|
|
||||||
- sqlite
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:12
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: postgres
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: '3.7'
|
|
||||||
- if: matrix.test == 'other'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends ffmpeg
|
|
||||||
- run: pip install tox-travis
|
|
||||||
- env:
|
|
||||||
TEST_DB: ${{ matrix.db }}
|
|
||||||
run: tox -e ${{ matrix.test }}
|
|
||||||
|
|
||||||
build:
|
|
||||||
needs: ["lint", "tests-unit", "tests-integration"]
|
|
||||||
name: "build"
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
|
@ -78,19 +27,77 @@ jobs:
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: '3.7'
|
python-version: '3.7'
|
||||||
- name: Setup
|
- run: pip install -e .[test]
|
||||||
run: |
|
- working-directory: lbry
|
||||||
pip install pyinstaller
|
env:
|
||||||
pip install -e .
|
HOME: /tmp
|
||||||
- if: startsWith(matrix.os, 'windows') == false
|
run: coverage run -p --source=lbry -m unittest -vv tests.unit.test_conf
|
||||||
name: Build & Run (Unix)
|
#run: coverage run -p --source=lbry -m unittest discover -vv tests.unit
|
||||||
run: |
|
|
||||||
pyinstaller --onefile --name lbrynet lbry/extras/cli.py
|
# tests-integration:
|
||||||
chmod +x dist/lbrynet
|
# name: "tests / integration"
|
||||||
dist/lbrynet --version
|
# runs-on: ubuntu-latest
|
||||||
- if: startsWith(matrix.os, 'windows')
|
# strategy:
|
||||||
name: Build & Run (Windows)
|
# matrix:
|
||||||
run: |
|
# test:
|
||||||
pip install pywin32
|
# - datanetwork
|
||||||
pyinstaller --additional-hooks-dir=scripts/. --icon=icons/lbry256.ico --onefile --name lbrynet lbry/extras/cli.py
|
# - blockchain
|
||||||
dist/lbrynet.exe --version
|
# - other
|
||||||
|
# db:
|
||||||
|
# - postgres
|
||||||
|
# - sqlite
|
||||||
|
# services:
|
||||||
|
# postgres:
|
||||||
|
# image: postgres:12
|
||||||
|
# env:
|
||||||
|
# POSTGRES_USER: postgres
|
||||||
|
# POSTGRES_PASSWORD: postgres
|
||||||
|
# POSTGRES_DB: postgres
|
||||||
|
# ports:
|
||||||
|
# - 5432:5432
|
||||||
|
# options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v1
|
||||||
|
# - uses: actions/setup-python@v1
|
||||||
|
# with:
|
||||||
|
# python-version: '3.7'
|
||||||
|
# - if: matrix.test == 'other'
|
||||||
|
# run: |
|
||||||
|
# sudo apt-get update
|
||||||
|
# sudo apt-get install -y --no-install-recommends ffmpeg
|
||||||
|
# - run: pip install tox-travis
|
||||||
|
# - env:
|
||||||
|
# TEST_DB: ${{ matrix.db }}
|
||||||
|
# run: tox -e ${{ matrix.test }}
|
||||||
|
#
|
||||||
|
# build:
|
||||||
|
# needs: ["lint", "tests-unit", "tests-integration"]
|
||||||
|
# name: "build"
|
||||||
|
# strategy:
|
||||||
|
# matrix:
|
||||||
|
# os:
|
||||||
|
# - ubuntu-latest
|
||||||
|
# - macos-latest
|
||||||
|
# - windows-latest
|
||||||
|
# runs-on: ${{ matrix.os }}
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v1
|
||||||
|
# - uses: actions/setup-python@v1
|
||||||
|
# with:
|
||||||
|
# python-version: '3.7'
|
||||||
|
# - name: Setup
|
||||||
|
# run: |
|
||||||
|
# pip install pyinstaller
|
||||||
|
# pip install -e .
|
||||||
|
# - if: startsWith(matrix.os, 'windows') == false
|
||||||
|
# name: Build & Run (Unix)
|
||||||
|
# run: |
|
||||||
|
# pyinstaller --onefile --name lbrynet lbry/extras/cli.py
|
||||||
|
# chmod +x dist/lbrynet
|
||||||
|
# dist/lbrynet --version
|
||||||
|
# - if: startsWith(matrix.os, 'windows')
|
||||||
|
# name: Build & Run (Windows)
|
||||||
|
# run: |
|
||||||
|
# pip install pywin32
|
||||||
|
# pyinstaller --additional-hooks-dir=scripts/. --icon=icons/lbry256.ico --onefile --name lbrynet lbry/extras/cli.py
|
||||||
|
# dist/lbrynet.exe --version
|
||||||
|
|
20
Makefile
20
Makefile
|
@ -1,15 +1,4 @@
|
||||||
.PHONY: install tools lint test idea
|
.PHONY: tools lint test idea
|
||||||
|
|
||||||
install:
|
|
||||||
CFLAGS="-DSQLITE_MAX_VARIABLE_NUMBER=2500000" pip install -U https://github.com/rogerbinns/apsw/releases/download/3.30.1-r1/apsw-3.30.1-r1.zip \
|
|
||||||
--global-option=fetch \
|
|
||||||
--global-option=--version --global-option=3.30.1 --global-option=--all \
|
|
||||||
--global-option=build --global-option=--enable --global-option=fts5
|
|
||||||
pip install -e .
|
|
||||||
|
|
||||||
tools:
|
|
||||||
pip install mypy==0.701
|
|
||||||
pip install coverage astroid pylint
|
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
pylint --rcfile=setup.cfg lbry
|
pylint --rcfile=setup.cfg lbry
|
||||||
|
@ -21,3 +10,10 @@ test:
|
||||||
idea:
|
idea:
|
||||||
mkdir -p .idea
|
mkdir -p .idea
|
||||||
cp -r scripts/idea/* .idea
|
cp -r scripts/idea/* .idea
|
||||||
|
|
||||||
|
start:
|
||||||
|
dropdb lbry2
|
||||||
|
createdb lbry2
|
||||||
|
lbrynet start --full-node \
|
||||||
|
--db-url=postgresql:///lbry2 --processes=-1 --console=advanced \
|
||||||
|
--lbrycrd-dir=${HOME}/.lbrycrd --data-dir=/tmp/tmp-lbrynet
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
__version__ = "0.68.0"
|
__version__ = "1.0.0"
|
||||||
from lbry.wallet import Account, Wallet, WalletManager
|
from lbry.wallet import Account, Wallet, WalletManager
|
||||||
from lbry.blockchain import (
|
from lbry.blockchain import (
|
||||||
Ledger, RegTestLedger, TestNetLedger,
|
Ledger, RegTestLedger, TestNetLedger,
|
||||||
|
|
|
@ -7,7 +7,7 @@ from contextlib import contextmanager
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from appdirs import user_data_dir, user_download_dir
|
from lbry.utils.dirs import user_data_dir, user_download_dir
|
||||||
from lbry.error import InvalidCurrencyError
|
from lbry.error import InvalidCurrencyError
|
||||||
from lbry.dht import constants
|
from lbry.dht import constants
|
||||||
from lbry.wallet.coinselection import COIN_SELECTION_STRATEGIES
|
from lbry.wallet.coinselection import COIN_SELECTION_STRATEGIES
|
||||||
|
|
192
lbry/utils/dirs.py
Normal file
192
lbry/utils/dirs.py
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def user_download_dir():
|
||||||
|
r"""Return full path to the user-specific download dir.
|
||||||
|
|
||||||
|
Typical user data directories are:
|
||||||
|
Mac OS X: ~/Downloads
|
||||||
|
Unix: ~/Downloads # or in $XDG_DOWNLOAD_DIR, if defined
|
||||||
|
Win 7: C:\Users\<username>\Downloads
|
||||||
|
|
||||||
|
For Unix, we follow the XDG spec and support $XDG_DOWNLOAD_DIR.
|
||||||
|
That means, by default "~/Downloads".
|
||||||
|
"""
|
||||||
|
if sys.platform == "win32":
|
||||||
|
return os.path.normpath(_get_win_download_folder())
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
return os.path.expanduser('~/Downloads')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
config_dirs = os.path.join(user_config_dir(), 'user-dirs.dirs')
|
||||||
|
with open(config_dirs) as dirs_file:
|
||||||
|
path_match = re.search(r'XDG_DOWNLOAD_DIR=(.+)', dirs_file.read())
|
||||||
|
cleaned_path = path_match.group(1).replace('"', '').replace('$HOME', '~')
|
||||||
|
return os.path.expanduser(cleaned_path)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return os.getenv('XDG_DOWNLOAD_DIR', os.path.expanduser("~/Downloads"))
|
||||||
|
|
||||||
|
|
||||||
|
def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
|
||||||
|
r"""Return full path to the user-specific data dir for this application.
|
||||||
|
|
||||||
|
"appname" is the name of application.
|
||||||
|
If None, just the sys.platform directory is returned.
|
||||||
|
"appauthor" (only used on Windows) is the name of the
|
||||||
|
appauthor or distributing body for this application. Typically
|
||||||
|
it is the owning company name. This falls back to appname. You may
|
||||||
|
pass False to disable it.
|
||||||
|
"version" is an optional version path element to append to the
|
||||||
|
path. You might want to use this if you want multiple versions
|
||||||
|
of your app to be able to run independently. If used, this
|
||||||
|
would typically be "<major>.<minor>".
|
||||||
|
Only applied when appname is present.
|
||||||
|
"roaming" (boolean, default False) can be set True to use the Windows
|
||||||
|
roaming appdata directory. That means that for users on a Windows
|
||||||
|
network setup for roaming profiles, this user data will be
|
||||||
|
sync'd on login. See
|
||||||
|
<http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
|
||||||
|
for a discussion of issues.
|
||||||
|
|
||||||
|
Typical user data directories are:
|
||||||
|
Mac OS X: ~/Library/Application Support/<AppName>
|
||||||
|
Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined
|
||||||
|
Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
|
||||||
|
Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>
|
||||||
|
Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>
|
||||||
|
Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName>
|
||||||
|
|
||||||
|
For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
|
||||||
|
That means, by default "~/.local/share/<AppName>".
|
||||||
|
"""
|
||||||
|
if sys.platform == "win32":
|
||||||
|
if appauthor is None:
|
||||||
|
appauthor = appname
|
||||||
|
const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
|
||||||
|
path = os.path.normpath(_get_win_folder(const))
|
||||||
|
if appname:
|
||||||
|
if appauthor is not False:
|
||||||
|
path = os.path.join(path, appauthor, appname)
|
||||||
|
else:
|
||||||
|
path = os.path.join(path, appname)
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
path = os.path.expanduser("~/Library/Application Support/")
|
||||||
|
if appname:
|
||||||
|
path = os.path.join(path, appname)
|
||||||
|
else:
|
||||||
|
path = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
|
||||||
|
if appname:
|
||||||
|
path = os.path.join(path, appname)
|
||||||
|
if appname and version:
|
||||||
|
path = os.path.join(path, version)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
|
||||||
|
r"""Return full path to the user-specific config dir for this application.
|
||||||
|
|
||||||
|
"appname" is the name of application.
|
||||||
|
If None, just the sys.platform directory is returned.
|
||||||
|
"appauthor" (only used on Windows) is the name of the
|
||||||
|
appauthor or distributing body for this application. Typically
|
||||||
|
it is the owning company name. This falls back to appname. You may
|
||||||
|
pass False to disable it.
|
||||||
|
"version" is an optional version path element to append to the
|
||||||
|
path. You might want to use this if you want multiple versions
|
||||||
|
of your app to be able to run independently. If used, this
|
||||||
|
would typically be "<major>.<minor>".
|
||||||
|
Only applied when appname is present.
|
||||||
|
"roaming" (boolean, default False) can be set True to use the Windows
|
||||||
|
roaming appdata directory. That means that for users on a Windows
|
||||||
|
network setup for roaming profiles, this user data will be
|
||||||
|
sync'd on login. See
|
||||||
|
<http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
|
||||||
|
for a discussion of issues.
|
||||||
|
|
||||||
|
Typical user config directories are:
|
||||||
|
Mac OS X: ~/Library/Preferences/<AppName>
|
||||||
|
Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined
|
||||||
|
Win *: same as user_data_dir
|
||||||
|
|
||||||
|
For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
|
||||||
|
That means, by default "~/.config/<AppName>".
|
||||||
|
"""
|
||||||
|
if sys.platform == "win32":
|
||||||
|
path = user_data_dir(appname, appauthor, None, roaming)
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
path = os.path.expanduser("~/Library/Preferences/")
|
||||||
|
if appname:
|
||||||
|
path = os.path.join(path, appname)
|
||||||
|
else:
|
||||||
|
path = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
|
||||||
|
if appname:
|
||||||
|
path = os.path.join(path, appname)
|
||||||
|
if appname and version:
|
||||||
|
path = os.path.join(path, version)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _get_win_folder(csidl_name):
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
csidl_const = {
|
||||||
|
"CSIDL_APPDATA": 26,
|
||||||
|
"CSIDL_COMMON_APPDATA": 35,
|
||||||
|
"CSIDL_LOCAL_APPDATA": 28,
|
||||||
|
}[csidl_name]
|
||||||
|
|
||||||
|
buf = ctypes.create_unicode_buffer(1024)
|
||||||
|
ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
|
||||||
|
|
||||||
|
# Downgrade to short path name if have highbit chars. See
|
||||||
|
# <http://bugs.activestate.com/show_bug.cgi?id=85099>.
|
||||||
|
has_high_char = False
|
||||||
|
for c in buf:
|
||||||
|
if ord(c) > 255:
|
||||||
|
has_high_char = True
|
||||||
|
break
|
||||||
|
if has_high_char:
|
||||||
|
buf2 = ctypes.create_unicode_buffer(1024)
|
||||||
|
if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
|
||||||
|
buf = buf2
|
||||||
|
|
||||||
|
return buf.value
|
||||||
|
|
||||||
|
|
||||||
|
def _get_win_download_folder():
|
||||||
|
import ctypes
|
||||||
|
from ctypes import windll, wintypes
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
class GUID(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("data1", wintypes.DWORD),
|
||||||
|
("data2", wintypes.WORD),
|
||||||
|
("data3", wintypes.WORD),
|
||||||
|
("data4", wintypes.BYTE * 8)
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, uuidstr):
|
||||||
|
ctypes.Structure.__init__(self)
|
||||||
|
uuid = UUID(uuidstr)
|
||||||
|
self.data1, self.data2, self.data3, \
|
||||||
|
self.data4[0], self.data4[1], rest = uuid.fields
|
||||||
|
for i in range(2, 8):
|
||||||
|
self.data4[i] = rest >> (8-i-1)*8 & 0xff
|
||||||
|
|
||||||
|
SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
|
||||||
|
SHGetKnownFolderPath.argtypes = [
|
||||||
|
ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)
|
||||||
|
]
|
||||||
|
|
||||||
|
FOLDERID_Downloads = '{374DE290-123F-4565-9164-39C4925E467B}'
|
||||||
|
guid = GUID(FOLDERID_Downloads)
|
||||||
|
pathptr = ctypes.c_wchar_p()
|
||||||
|
|
||||||
|
if SHGetKnownFolderPath(ctypes.byref(guid), 0, 0, ctypes.byref(pathptr)):
|
||||||
|
raise Exception('Failed to get download directory.')
|
||||||
|
|
||||||
|
return pathptr.value
|
5
setup.py
5
setup.py
|
@ -39,7 +39,6 @@ setup(
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'aiohttp==3.5.4',
|
'aiohttp==3.5.4',
|
||||||
'aioupnp==0.0.17',
|
'aioupnp==0.0.17',
|
||||||
'appdirs==1.4.3',
|
|
||||||
'certifi>=2018.11.29',
|
'certifi>=2018.11.29',
|
||||||
'colorama==0.3.7',
|
'colorama==0.3.7',
|
||||||
'distro==1.4.0',
|
'distro==1.4.0',
|
||||||
|
@ -62,7 +61,9 @@ setup(
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
'ui': ['pyside2'],
|
'ui': ['pyside2'],
|
||||||
'postgresql': ['psycopg2']
|
'postgresql': ['psycopg2'],
|
||||||
|
'lint': ['mypy', 'pylint'],
|
||||||
|
'test': ['coverage'],
|
||||||
},
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Framework :: AsyncIO',
|
'Framework :: AsyncIO',
|
||||||
|
|
Loading…
Reference in a new issue