Skip to content

Commit 58b1ab7

Browse files
authored
Merge pull request #302 from andrey-yantsen/enable_test_for_pr
Run tests over unclaimed server
2 parents 8c26cc6 + c63790a commit 58b1ab7

File tree

5 files changed

+95
-61
lines changed

5 files changed

+95
-61
lines changed

.travis.yml

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
language: python
22

33
stages:
4-
- syntax
5-
- name: test
6-
if: type != pull_request
4+
- test
75
- name: deploy
86
if: tag = present
97

@@ -28,8 +26,10 @@ before_install:
2826
- pip install --upgrade pytest pytest-cov coveralls
2927
install:
3028
- pip install -r requirements_dev.txt
31-
- PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-bootstraptest.py --destination plex --advertise-ip=127.0.0.1
32-
--bootstrap-timeout 540 --docker-tag $PLEX_CONTAINER_TAG
29+
- '[ -z "${PLEXAPI_AUTH_MYPLEX_USERNAME}" ] && PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-bootstraptest.py
30+
--destination plex --advertise-ip=127.0.0.1 --bootstrap-timeout 540 --docker-tag $PLEX_CONTAINER_TAG --unclaimed ||
31+
PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-bootstraptest.py --destination plex --advertise-ip=127.0.0.1
32+
--bootstrap-timeout 540 --docker-tag $PLEX_CONTAINER_TAG'
3333

3434
script:
3535
- py.test tests -rxXs --ignore=tests/test_sync.py --tb=native --verbose --cov-config .coveragerc --cov=plexapi
@@ -38,28 +38,32 @@ script:
3838
--cov=plexapi --cov-append
3939

4040
after_success:
41-
- coveralls
41+
- COVERALLS_PARALLEL=true coveralls
4242

4343
after_script:
44-
- PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-teardowntest.py
44+
- '[ -z "${PLEXAPI_AUTH_MYPLEX_USERNAME}" ] || PYTHONPATH="$PWD:$PYTHONPATH" python -u tools/plex-teardowntest.py'
4545

4646
jobs:
4747
include:
48-
- stage: syntax
49-
python: 3.6
48+
- python: 3.6
5049
name: "Flake8"
5150
install:
5251
- pip install -r requirements_dev.txt
5352
script: flake8 plexapi --exclude=compat.py --max-line-length=120 --ignore=E128,E701,E702,E731,W293
54-
after_success: true
55-
after_script: true
53+
after_success: skip
5654
env:
5755
- PLEX_CONTAINER_TAG=latest
5856
- stage: test
5957
python: 3.6
6058
env:
6159
- PLEX_CONTAINER_TAG=1.3.2.3112-1751929
6260
- TEST_ACCOUNT_ONCE=1
61+
- stage: test
62+
python: 3.6
63+
if: type != 'pull_request' # pull requests always run over unclaimed server
64+
after_success: skip
65+
env:
66+
- PLEX_CONTAINER_TAG=latest PLEXAPI_AUTH_MYPLEX_USERNAME=
6367
- stage: deploy
6468
name: "Deploy to PyPi"
6569
python: 3.6

tests/conftest.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,52 @@
4242
RESOLUTIONS = {'sd', '480', '576', '720', '1080'}
4343
ENTITLEMENTS = {'ios', 'cpms', 'roku', 'android', 'xbox_one', 'xbox_360', 'windows', 'windows_phone'}
4444

45+
TEST_AUTHENTICATED = 'authenticated'
46+
TEST_ANONYMOUSLY = 'anonymously'
47+
48+
49+
ANON_PARAM = pytest.param(TEST_ANONYMOUSLY, marks=pytest.mark.anonymous)
50+
AUTH_PARAM = pytest.param(TEST_AUTHENTICATED, marks=pytest.mark.authenticated)
51+
4552

4653
def pytest_addoption(parser):
4754
parser.addoption('--client', action='store_true', default=False, help='Run client tests.')
4855

4956

57+
def pytest_generate_tests(metafunc):
58+
if 'plex' in metafunc.fixturenames:
59+
if 'account' in metafunc.fixturenames or TEST_AUTHENTICATED in metafunc.definition.keywords:
60+
metafunc.parametrize('plex', [AUTH_PARAM], indirect=True)
61+
else:
62+
metafunc.parametrize('plex', [ANON_PARAM, AUTH_PARAM], indirect=True)
63+
elif 'account' in metafunc.fixturenames:
64+
metafunc.parametrize('account', [AUTH_PARAM], indirect=True)
65+
66+
5067
def pytest_runtest_setup(item):
5168
if 'client' in item.keywords and not item.config.getvalue('client'):
5269
return pytest.skip('Need --client option to run.')
70+
if TEST_AUTHENTICATED in item.keywords and not (MYPLEX_USERNAME and MYPLEX_PASSWORD):
71+
return pytest.skip('You have to specify MYPLEX_USERNAME and MYPLEX_PASSWORD to run authenticated tests')
72+
if TEST_ANONYMOUSLY in item.keywords and MYPLEX_USERNAME and MYPLEX_PASSWORD:
73+
return pytest.skip('Anonymous tests should be ran on unclaimed server, without providing MYPLEX_USERNAME and '
74+
'MYPLEX_PASSWORD')
5375

5476

5577
# ---------------------------------
5678
# Fixtures
5779
# ---------------------------------
5880

81+
82+
def get_account():
83+
return MyPlexAccount()
84+
85+
5986
@pytest.fixture(scope='session')
6087
def account():
6188
assert MYPLEX_USERNAME, 'Required MYPLEX_USERNAME not specified.'
6289
assert MYPLEX_PASSWORD, 'Required MYPLEX_PASSWORD not specified.'
63-
return MyPlexAccount()
90+
return get_account()
6491

6592

6693
@pytest.fixture(scope='session')
@@ -89,10 +116,14 @@ def account_synctarget(account_plexpass):
89116

90117

91118
@pytest.fixture(scope='session')
92-
def plex(account):
119+
def plex(request):
93120
assert SERVER_BASEURL, 'Required SERVER_BASEURL not specified.'
94121
session = requests.Session()
95-
return PlexServer(SERVER_BASEURL, account.authenticationToken, session=session)
122+
if request.param == TEST_AUTHENTICATED:
123+
token = get_account().authenticationToken
124+
else:
125+
token = None
126+
return PlexServer(SERVER_BASEURL, token, session=session)
96127

97128

98129
@pytest.fixture()

tests/test_library.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def test_library_MovieSection_onDeck(movie, movies, tvshows, episode):
146146
movie.updateProgress(movie.duration * 1000 / 10) # set progress to 10%
147147
assert movies.onDeck()
148148
movie.markUnwatched()
149-
episode.markWatched()
149+
episode.updateProgress(episode.duration * 1000 / 10)
150150
assert tvshows.onDeck()
151151
episode.markUnwatched()
152152

tests/test_server.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,18 @@ def test_server_history(plex, movie):
121121
movie.markUnwatched()
122122

123123

124+
@pytest.mark.anonymously
124125
def test_server_Server_query(plex):
125126
assert plex.query('/')
126127
with pytest.raises(BadRequest):
127128
assert plex.query('/asdf/1234/asdf', headers={'random_headers': '1234'})
129+
130+
131+
@pytest.mark.authenticated
132+
def test_server_Server_query_authenticated(plex):
133+
assert plex.query('/')
134+
with pytest.raises(BadRequest):
135+
assert plex.query('/asdf/1234/asdf', headers={'random_headers': '1234'})
128136
with pytest.raises(BadRequest):
129137
# This is really requests.exceptions.HTTPError
130138
# 401 Client Error: Unauthorized for url
@@ -142,6 +150,7 @@ def __init__(self):
142150
assert hasattr(plex._session, 'plexapi_session_test')
143151

144152

153+
@pytest.mark.authenticated
145154
def test_server_token_in_headers(plex):
146155
headers = plex._headers()
147156
assert 'X-Plex-Token' in headers
@@ -223,6 +232,7 @@ def test_server_clients(plex):
223232
assert client.version == '2.12.5'
224233

225234

235+
@pytest.mark.authenticated
226236
def test_server_account(plex):
227237
account = plex.account()
228238
assert account.authToken

tools/plex-bootstraptest.py

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
from plexapi.compat import which, makedirs
1717
from plexapi.exceptions import BadRequest, NotFound
1818
from plexapi.myplex import MyPlexAccount
19+
from plexapi.server import PlexServer
1920
from plexapi.utils import download, SEARCHTYPES
2021

2122
DOCKER_CMD = [
2223
'docker', 'run', '-d',
23-
'--name', 'plex-test-%(image_tag)s',
24+
'--name', 'plex-test-%(container_name_extra)s%(image_tag)s',
2425
'--restart', 'on-failure',
2526
'-p', '32400:32400/tcp',
2627
'-p', '3005:3005/tcp',
@@ -43,30 +44,6 @@
4344
]
4445

4546

46-
def get_claim_token(myplex):
47-
"""
48-
Returns a str, a new "claim-token", which you can use to register your new Plex Server instance to your account
49-
See: https://hub.docker.com/r/plexinc/pms-docker/, https://www.plex.tv/claim/
50-
51-
Arguments:
52-
myplex (:class:`~plexapi.myplex.MyPlexAccount`)
53-
"""
54-
retry = 0
55-
status_code = None
56-
while retry < 3 and status_code not in (200, 201, 204):
57-
if retry > 0:
58-
sleep(2)
59-
response = myplex._session.get('https://plex.tv/api/claim/token.json', headers=myplex._headers(),
60-
timeout=plexapi.TIMEOUT)
61-
status_code = response.status_code
62-
retry += 1
63-
64-
if status_code not in (200, 201, 204):
65-
errtext = response.text.replace('\n', ' ')
66-
raise BadRequest('(%s) unable to get status code %s; %s' % (response.status_code, response.url, errtext))
67-
return response.json()['token']
68-
69-
7047
def get_ips():
7148
import socket
7249
return list(set([i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)
@@ -146,9 +123,15 @@ def alert_callback(data):
146123
default_ip = available_ips[0]
147124

148125
parser = argparse.ArgumentParser(description=__doc__)
149-
parser.add_argument('--username', help='Your Plex username')
150-
parser.add_argument('--password', help='Your Plex password')
151-
parser.add_argument('--token', help='Plex.tv authentication token', default=plexapi.CONFIG.get('auth.server_token'))
126+
127+
mg = parser.add_mutually_exclusive_group()
128+
129+
g = mg.add_argument_group()
130+
g.add_argument('--username', help='Your Plex username')
131+
g.add_argument('--password', help='Your Plex password')
132+
mg.add_argument('--token', help='Plex.tv authentication token', default=plexapi.CONFIG.get('auth.server_token'))
133+
mg.add_argument('--unclaimed', help='Do not claim the server', default=False, action='store_true')
134+
152135
parser.add_argument('--timezone', help='Timezone to set inside plex', default='UTC')
153136
parser.add_argument('--destination', help='Local path where to store all the media',
154137
default=os.path.join(os.getcwd(), 'plex'))
@@ -176,33 +159,40 @@ def alert_callback(data):
176159
print('Got an error when executing docker pull!')
177160
exit(1)
178161

179-
if opts.token:
180-
account = MyPlexAccount(token=opts.token)
181-
else:
182-
account = plexapi.utils.getMyPlexAccount(opts)
162+
account = None
163+
if not opts.unclaimed:
164+
if opts.token:
165+
account = MyPlexAccount(token=opts.token)
166+
else:
167+
account = plexapi.utils.getMyPlexAccount(opts)
183168
path = os.path.realpath(os.path.expanduser(opts.destination))
184169
makedirs(os.path.join(path, 'media'), exist_ok=True)
185170
arg_bindings = {
186171
'destination': path,
187172
'hostname': opts.server_name,
188-
'claim_token': get_claim_token(account),
173+
'claim_token': account.claimToken() if account else '',
189174
'timezone': opts.timezone,
190175
'advertise_ip': opts.advertise_ip,
191176
'image_tag': opts.docker_tag,
177+
'container_name_extra': '' if account else 'unclaimed-'
192178
}
179+
193180
docker_cmd = [c % arg_bindings for c in DOCKER_CMD]
194181
exit_code = call(docker_cmd)
195182

196183
if exit_code != 0:
197184
exit(exit_code)
198185

199-
print('Let`s wait while the instance register in your plex account...')
186+
print('Let`s wait while the instance boots...')
200187
start_time = time()
201188
server = None
202189
while not server and (time() - start_time < opts.bootstrap_timeout):
203190
try:
204-
device = account.device(opts.server_name)
205-
server = device.connect()
191+
if account:
192+
device = account.device(opts.server_name)
193+
server = device.connect()
194+
else:
195+
server = PlexServer('http://%s:32400' % opts.advertise_ip)
206196
if opts.accept_eula:
207197
server.settings.get('acceptedEULA').set(True)
208198
server.settings.save()
@@ -351,18 +341,17 @@ def get_movie_path(name, year):
351341
for section in sections:
352342
create_section(server, section)
353343

354-
import logging
355-
logging.basicConfig(level=logging.INFO)
356-
shared_username = os.environ.get('SHARED_USERNAME', 'PKKid')
357-
try:
358-
user = account.user(shared_username)
359-
account.updateFriend(user, server)
360-
print('The server was shared with user "%s"' % shared_username)
361-
except NotFound:
362-
pass
344+
if account:
345+
shared_username = os.environ.get('SHARED_USERNAME', 'PKKid')
346+
try:
347+
user = account.user(shared_username)
348+
account.updateFriend(user, server)
349+
print('The server was shared with user "%s"' % shared_username)
350+
except NotFound:
351+
pass
363352

364353
print('Base URL is %s' % server.url('', False))
365-
if opts.show_token:
354+
if account and opts.show_token:
366355
print('Auth token is %s' % account.authenticationToken)
367356

368357
print('Server %s is ready to use!' % opts.server_name)

0 commit comments

Comments
 (0)