Skip to content

Commit a60cde4

Browse files
committed
Merge branch 'bugfix/conftest_fix' into devel
2 parents 8077d35 + ef1e8c9 commit a60cde4

33 files changed

+276
-299
lines changed

.travis.yml

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
11
language: python
2-
python:
3-
- "3.4"
4-
- "3.5"
5-
- "3.5-dev" # 3.5 development branch
2+
matrix:
3+
include:
4+
- os: linux
5+
python: "3.4"
6+
- os: linux
7+
python: "3.5"
8+
- os: linux
9+
python: "3.5-dev"
10+
- os: linux
11+
python: "3.6-dev"
12+
- os: linux
13+
python: "nightly"
14+
- os: linux
15+
python: "pypy3"
16+
17+
- os: osx
18+
sudo: required
19+
language: generic
20+
21+
allow_failures:
22+
- python: "3.6-dev"
23+
- python: "nightly"
24+
- python: "pypy3"
25+
- os: "osx"
626
addons:
727
apt:
828
packages:
929
- pandoc
30+
before_install: |
31+
if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
32+
brew update;
33+
brew install python3 pandoc;
34+
python3 -m venv venv;
35+
source venv/bin/activate;
36+
pip install . test
37+
fi
1038
# command to install dependencies
1139
install:
1240
- "pip install --upgrade pip" # upgrade to latest pip (needed on py3.4)

tests/conftest.py

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,54 @@
77

88
record_mode = 'once'
99

10+
from git_repo.services.service import RepositoryService
11+
services = list(RepositoryService.service_map.keys())
12+
1013
if os.environ.get('TRAVIS_GH3'):
1114
# create default bogus values for tokens and namespaces if missing for pytest
1215
# to run without environment values
1316
# also if an environment variable is not set, then we don't want to record cassettes
1417
record_mode = 'never'
15-
for service_name in ('github', 'gitlab', 'bitbucket'):
16-
token_name = 'PRIVATE_KEY_{}'.format(service_name.upper())
17-
namespace_name = '{}_NAMESPACE'.format(service_name.upper())
18+
for service in services:
19+
token_name = 'PRIVATE_KEY_{}'.format(service.upper())
20+
namespace_name = '{}_NAMESPACE'.format(service.upper())
1821
if token_name not in os.environ:
19-
os.environ[token_name] = 'not_configured:test' # using a : for bitbucket's case
22+
os.environ[token_name] = '_namespace_{}_:_private_'.format(service) # using a : for bitbucket's case
2023
if namespace_name not in os.environ:
21-
os.environ[namespace_name] = 'not_configured'
24+
os.environ[namespace_name] = '_namespace_{}_'.format(service)
2225
else:
26+
# if running tests "locally" and not in travis, let's try to extract the keys from
27+
# the local configuration if there is some local configuration. And exposes them as
28+
# environment variables.
2329
import git, getpass
2430
config = git.config.GitConfigParser(os.path.join(os.environ['HOME'], '.gitconfig'))
25-
conf_section = list(filter(lambda n: 'gitrepo' in n, config.sections()))
26-
key_dict = {section.split('"')[1] :config.get_value(section, 'privatekey') for section in conf_section}
27-
for service, key in key_dict.items():
31+
32+
# handle the different forms of token configuration item (yup, technical debt bites here)
33+
get_section = lambda s: 'gitrepo "{}"'.format(s)
34+
get_token = lambda s: config.get_value(get_section(s), 'token',
35+
config.get_value(get_section(s), 'private_token',
36+
config.get_value(get_section(s), 'privatekey',
37+
'_namespace_{}_:_private_'.format(s) # using a : for bitbucket's case
38+
)))
39+
# XXX temporary fix that should not be necessary when refactoring with pybitbucket
40+
get_default_namespace = lambda s: os.environ[token_name].split(':')[0] if s == 'bitbucket' else '_namespace_{}_'.format(s)
41+
42+
for service in services:
2843
token_name = 'PRIVATE_KEY_{}'.format(service.upper())
2944
namespace_name = '{}_NAMESPACE'.format(service.upper())
30-
os.environ[token_name] = key
31-
os.environ[namespace_name] = os.environ.get('GITREPO_NAMESPACE', getpass.getuser())
32-
33-
api_token_github = os.environ['PRIVATE_KEY_GITHUB']
34-
api_token_gitlab = os.environ['PRIVATE_KEY_GITLAB']
35-
api_token_bitbucket = os.environ['PRIVATE_KEY_BITBUCKET']
36-
37-
github_namespace = os.environ['GITHUB_NAMESPACE']
38-
gitlab_namespace = os.environ['GITLAB_NAMESPACE']
39-
bitbucket_namespace = os.environ['BITBUCKET_NAMESPACE']
45+
if token_name not in os.environ:
46+
os.environ[token_name] = get_token(service)
47+
if namespace_name not in os.environ:
48+
os.environ[namespace_name] = os.environ.get('GITREPO_NAMESPACE', get_default_namespace(service))
4049

4150
betamax.Betamax.register_serializer(pretty_json.PrettyJSONSerializer)
4251

4352
with betamax.Betamax.configure() as config:
4453
config.default_cassette_options['record_mode'] = record_mode
4554
config.cassette_library_dir = 'tests/integration/cassettes'
4655
config.default_cassette_options['serialize_with'] = 'prettyjson'
47-
config.define_cassette_placeholder('<PRIVATE_KEY_GITHUB>', api_token_github)
48-
config.define_cassette_placeholder('<PRIVATE_KEY_GITLAB>', api_token_gitlab)
49-
config.define_cassette_placeholder('<PRIVATE_KEY_BITBUCKET>', api_token_bitbucket)
50-
config.define_cassette_placeholder('<GITHUB_NAMESPACE>', github_namespace)
51-
config.define_cassette_placeholder('<GITLAB_NAMESPACE>', gitlab_namespace)
52-
config.define_cassette_placeholder('<BITBUCKET_NAMESPACE>', bitbucket_namespace)
53-
54-
56+
# generating placeholders in betamax configuration for each service's key and default namespace
57+
for service in services:
58+
config.define_cassette_placeholder('<PRIVATE_KEY_{}>'.format(service.upper()), os.environ.get('PRIVATE_KEY_{}'.format(service.upper())))
59+
config.define_cassette_placeholder('<{}_NAMESPACE>'.format(service.upper()), os.environ.get('{}_NAMESPACE'.format(service.upper())))
5560

tests/helpers.py

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from contextlib import contextmanager
1010

1111
import os
12+
import sys
1213
import logging
1314
import betamax
1415

@@ -378,6 +379,17 @@ def teardown_method(self, method):
378379
self.log.info('GitRepoTestCase.teardown_method({})'.format(method))
379380
self.tempdir.cleanup()
380381

382+
'''cassette name helper'''
383+
384+
def _make_cassette_name(self):
385+
# returns the name of the function calling the function calling this one
386+
# in other words, when used in an helper function, returns the name of
387+
# the test function calling the helper function, to make a cassette name.
388+
test_function_name = sys._getframe(2).f_code.co_name
389+
if test_function_name.startswith('test'):
390+
return '_'.join(['test', self.service.name, test_function_name])
391+
raise Exception("Helpers functions shall be used only within test functions!")
392+
381393
'''popen helper'''
382394

383395
def set_mock_popen_commands(self, cmd_list):
@@ -435,7 +447,7 @@ def assert_tracking_remote(self, remote_name=None, branch_name='master'):
435447

436448
'''test cases templates'''
437449

438-
def action_fork(self, cassette_name, local_namespace, remote_namespace, repository):
450+
def action_fork(self, local_namespace, remote_namespace, repository):
439451
# hijack subprocess call
440452
with self.mockup_git(local_namespace, repository):
441453
# prepare output for git commands
@@ -458,15 +470,15 @@ def action_fork(self, cassette_name, local_namespace, remote_namespace, reposito
458470
' * [new branch] master -> {}/master'.format(self.service.name)]).encode('utf-8'),
459471
0)
460472
])
461-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
473+
with self.recorder.use_cassette(self._make_cassette_name()):
462474
self.service.connect()
463475
self.service.fork(remote_namespace, repository)
464476
# emulate the outcome of the git actions
465477
self.service.repository.create_remote('upstream', url=remote_slug)
466478
self.service.repository.create_remote('all', url=local_slug)
467479
self.service.repository.create_remote(self.service.name, url=local_slug)
468480

469-
def action_fork__no_clone(self, cassette_name, local_namespace, remote_namespace, repository):
481+
def action_fork__no_clone(self, local_namespace, remote_namespace, repository):
470482
# hijack subprocess call
471483
with self.mockup_git(local_namespace, repository):
472484
# prepare output for git commands
@@ -489,15 +501,15 @@ def action_fork__no_clone(self, cassette_name, local_namespace, remote_namespace
489501
' * [new branch] master -> {}/master'.format(self.service.name)]).encode('utf-8'),
490502
0)
491503
])
492-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
504+
with self.recorder.use_cassette(self._make_cassette_name()):
493505
self.service.connect()
494506
self.service.fork(remote_namespace, repository)
495507
# emulate the outcome of the git actions
496508
self.service.repository.create_remote('upstream', url=remote_slug)
497509
self.service.repository.create_remote('all', url=local_slug)
498510
self.service.repository.create_remote(self.service.name, url=local_slug)
499511

500-
def action_clone(self, cassette_name, namespace, repository):
512+
def action_clone(self, namespace, repository):
501513
# hijack subprocess call
502514
with self.mockup_git(namespace, repository):
503515
local_slug = self.service.format_path(namespace=namespace, repository=repository, rw=True)
@@ -517,30 +529,30 @@ def action_clone(self, cassette_name, namespace, repository):
517529
' * [new branch] master -> {}/master'.format(self.service.name)]).encode('utf-8'),
518530
0)
519531
])
520-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
532+
with self.recorder.use_cassette(self._make_cassette_name()):
521533
self.service.connect()
522534
self.service.clone(namespace, repository)
523535
self.service.repository.create_remote('all', url=local_slug)
524536
self.service.repository.create_remote(self.service.name, url=local_slug)
525537

526-
def action_create(self, cassette_name, namespace, repository):
527-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
538+
def action_create(self, namespace, repository):
539+
with self.recorder.use_cassette(self._make_cassette_name()):
528540
self.service.connect()
529541
self.service.create(namespace, repository, add=True)
530542
#
531543
self.assert_repository_exists(namespace, repository)
532544
self.assert_added_remote_defaults()
533545

534-
def action_create__no_add(self, cassette_name, namespace, repository):
535-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
546+
def action_create__no_add(self, namespace, repository):
547+
with self.recorder.use_cassette(self._make_cassette_name()):
536548
self.service.connect()
537549
self.service.create(namespace, repository, add=False)
538550
#
539551
self.assert_repository_exists(namespace, repository)
540552
self.assert_added_remote_defaults()
541553

542-
def action_delete(self, cassette_name, repository, namespace=None):
543-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
554+
def action_delete(self, repository, namespace=None):
555+
with self.recorder.use_cassette(self._make_cassette_name()):
544556
self.service.connect()
545557
if namespace:
546558
self.service.delete(user=namespace, repo=repository)
@@ -551,8 +563,8 @@ def action_delete(self, cassette_name, repository, namespace=None):
551563
namespace = self.service.user
552564
self.assert_repository_not_exists(namespace, repository)
553565

554-
def action_add(self, cassette_name, namespace, repository, alone=False, name=None, tracking='master'):
555-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
566+
def action_add(self, namespace, repository, alone=False, name=None, tracking='master'):
567+
with self.recorder.use_cassette(self._make_cassette_name()):
556568
# init git in the repository's destination
557569
self.repository.init()
558570
self.service.connect()
@@ -583,16 +595,16 @@ def action_add(self, cassette_name, namespace, repository, alone=False, name=Non
583595
self.assert_added_remote(name)
584596
self.assert_tracking_remote(name, tracking)
585597

586-
def action_request_list(self, cassette_name, namespace, repository, rq_list_data=[]):
587-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
598+
def action_request_list(self, namespace, repository, rq_list_data=[]):
599+
with self.recorder.use_cassette(self._make_cassette_name()):
588600
self.service.connect()
589601
requests = list(self.service.request_list(user=namespace, repo=repository))
590602
for i, rq in enumerate(rq_list_data):
591603
assert requests[i] == rq
592604

593-
def action_request_fetch(self, cassette_name, namespace, repository, request, pull=False, fail=False):
605+
def action_request_fetch(self, namespace, repository, request, pull=False, fail=False):
594606
local_slug = self.service.format_path(namespace=namespace, repository=repository, rw=False)
595-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
607+
with self.recorder.use_cassette(self._make_cassette_name()):
596608
with self.mockup_git(namespace, repository):
597609
self.set_mock_popen_commands([
598610
('git remote add all {}'.format(local_slug), b'', b'', 0),
@@ -642,7 +654,7 @@ def action_request_fetch(self, cassette_name, namespace, repository, request, pu
642654
])
643655
self.service.request_fetch(repository, namespace, request)
644656

645-
def action_request_create(self, cassette_name,
657+
def action_request_create(self,
646658
namespace, repository, branch,
647659
title, description,
648660
create_repository='test_create_requests',
@@ -670,7 +682,7 @@ def action_request_create(self, cassette_name,
670682
671683
So all the contextual work is only done
672684
'''
673-
cassette_name = '_'.join(['test', self.service.name, cassette_name])
685+
cassette_name = self._make_cassette_name()
674686
will_record = 'never' != self.recorder.config.default_cassette_options['record_mode'] \
675687
and not os.path.exists(os.path.join(self.recorder.config.cassette_library_dir, cassette_name+'.json'))
676688

@@ -713,8 +725,8 @@ def prepare_project_for_test():
713725
)
714726
return request
715727

716-
def action_gist_list(self, cassette_name, gist=None, gist_list_data=[]):
717-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
728+
def action_gist_list(self, gist=None, gist_list_data=[]):
729+
with self.recorder.use_cassette(self._make_cassette_name()):
718730
self.service.connect()
719731
if gist is None:
720732
gists = list(self.service.gist_list())
@@ -725,7 +737,7 @@ def action_gist_list(self, cassette_name, gist=None, gist_list_data=[]):
725737
for i, gf in enumerate(gist_list_data):
726738
assert gist_files[i] == gf
727739

728-
def action_gist_clone(self, cassette_name, gist):
740+
def action_gist_clone(self, gist):
729741
with self.mockup_git(None, None):
730742
self.set_mock_popen_commands([
731743
('git version', b'git version 2.8.0', b'', 0),
@@ -741,28 +753,28 @@ def action_gist_clone(self, cassette_name, gist):
741753
b' * branch master -> FETCH_HEAD']),
742754
0),
743755
])
744-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
756+
with self.recorder.use_cassette(self._make_cassette_name()):
745757
self.service.connect()
746758
self.service.gist_clone(gist)
747759

748760

749-
def action_gist_fetch(self, cassette_name, gist, gist_file=None):
750-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
761+
def action_gist_fetch(self, gist, gist_file=None):
762+
with self.recorder.use_cassette(self._make_cassette_name()):
751763
self.service.connect()
752764
content = self.service.gist_fetch(gist, gist_file)
753765
return content
754766

755-
def action_gist_create(self, cassette_name, description, gist_files, secret):
756-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
767+
def action_gist_create(self, description, gist_files, secret):
768+
with self.recorder.use_cassette(self._make_cassette_name()):
757769
self.service.connect()
758770
content = self.service.gist_create(gist_files, description, secret)
759771

760-
def action_gist_delete(self, cassette_name, gist):
761-
with self.recorder.use_cassette('_'.join(['test', self.service.name, cassette_name])):
772+
def action_gist_delete(self, gist):
773+
with self.recorder.use_cassette(self._make_cassette_name()):
762774
self.service.connect()
763775
content = self.service.gist_delete(gist)
764776

765-
def action_open(self, cassette_name, namespace, repository):
777+
def action_open(self, namespace, repository):
766778
self.set_mock_popen_commands([
767779
('xdg-open {}'.format(self.service.format_path(namespace=namespace, repository=repository)), b'', b'', 0),
768780
('open {}'.format(self.service.format_path(namespace=namespace, repository=repository)), b'', b'', 0),

0 commit comments

Comments
 (0)