run unittest on multiple platforms

This commit is contained in:
Lex Berezhny 2020-06-03 19:43:08 -04:00
parent 596ed08395
commit a042377a7b
7 changed files with 280 additions and 84 deletions

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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
View 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

View file

@ -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',