44import braceexpand
55import itertools
66
7+ from tox .config import _split_factor_expr
8+
79MAX_JOBS = 50
810
9- def expand_factors (value ):
11+ def expand_envlist (value ):
1012 for line in value .splitlines ():
1113 line = line .strip ()
1214
@@ -18,65 +20,117 @@ def expand_factors(value):
1820
1921
2022def find_dependencies (deps , env ):
21- parts = env .split ("-" )
22-
23- for combo in itertools .product ((True , False ), repeat = len (parts )):
24- key = "-" .join (parts [i ] for i , include in enumerate (combo ) if include )
25-
26- if key in deps :
27- yield deps [key ]
23+ env_factors = set (env .split ("-" ))
24+ for (matcher , dependency ) in deps .items ():
25+ for (included , excluded ) in _split_factor_expr (matcher ):
26+ if included <= env_factors and not env_factors & excluded :
27+ yield dependency
2828
2929def parse_tox ():
3030 config = configparser .ConfigParser ()
3131 config .read ("tox.ini" )
3232
3333 dependencies = {}
3434
35- for declaration in expand_factors (config ['testenv' ]['deps' ]):
36- if declaration .startswith ("-r " ):
35+ for line in config ['testenv' ]['deps' ].splitlines ():
36+ line = line .strip ()
37+ if not line or line .startswith (("-r" , "#" )):
3738 continue
3839
39- env_matcher , dependency = declaration .split (":" , 1 )
40+ env_matcher , dependency = line .split (":" , 1 )
4041 dependencies [env_matcher .strip ()] = dependency
4142
42- jobs = {}
43+ batch_jobs = {}
44+ single_jobs = []
4345
44- for env in expand_factors (config ['tox' ]['envlist' ]):
46+ for env in expand_envlist (config ['tox' ]['envlist' ]):
4547 python_version , integration , framework_version , * _ = (
4648 list (env .split ("-" )) + [None , None ]
4749 )
4850
49- python_version_jobs = jobs .setdefault (python_version , [])
50- for job in python_version_jobs :
51- if job . setdefault ( integration , framework_version ) == framework_version :
52- break
51+ python_version_jobs = batch_jobs .setdefault (python_version , [])
52+
53+ if integration is None :
54+ python_version_jobs . append ({})
5355 else :
54- python_version_jobs .append ({integration : framework_version })
56+ for job in python_version_jobs :
57+ if job and job .setdefault (integration , framework_version ) == framework_version :
58+ break
59+ else :
60+ python_version_jobs .append ({integration : framework_version })
61+
62+ single_jobs .append ((python_version , integration , framework_version ))
5563
56- return dependencies , jobs
64+ return dependencies , batch_jobs , single_jobs
5765
5866
59- def generate_sessions (_locals ):
60- dependencies , jobs = parse_tox ()
67+ def _format_job_name (python_version , integration , framework_version ):
68+ if integration is not None :
69+ return f"{ python_version } -{ integration } -{ framework_version } "
70+ else :
71+ return f"{ python_version } "
72+
73+
74+ def generate_test_sessions ():
75+ dependencies , batch_jobs , single_jobs = parse_tox ()
76+
77+ def add_nox_job (job_name , integrations , python_version , deps ):
78+ job_name = job_name .replace ("." , "" ).replace ("-" , "_" )
79+
80+ def func (session ):
81+ session .install ("-e" , "." )
82+ session .install ("-r" , "test-requirements.txt" , * deps )
83+ session .env ['COVERAGE_FILE' ] = f'.coverage-{ job_name } '
84+ session .run (
85+ "pytest" ,
86+ * [f"tests/integrations/{ integration } " for integration in integrations ],
87+ * session .posargs
88+ )
6189
62- for python_version , batches in jobs .items ():
90+ assert python_version .startswith ("py" )
91+ nox_python_version = "pypy" if python_version == "pypy" else python_version [2 :]
92+
93+ globals ()[job_name ] = nox .session (
94+ func = func , reuse_venv = True , python = nox_python_version , name = job_name
95+ )
96+
97+ for (python_version , integration , framework_version ) in single_jobs :
98+ job_name = _format_job_name (python_version ,integration ,framework_version )
99+ deps = list (find_dependencies (dependencies , job_name ))
100+
101+ add_nox_job (f"test-{ job_name } " , [integration ], python_version , deps )
102+
103+ for python_version , batches in batch_jobs .items ():
63104 for batch_name , integrations in enumerate (batches ):
64- job_name = f"{ python_version } -{ batch_name } "
105+ job_name = f"batchtest- { python_version } -{ batch_name } "
65106 deps = []
66- for integration , version in integrations .items ():
107+ for integration , framework_version in integrations .items ():
67108 deps .extend (find_dependencies (
68- dependencies , f"{ python_version } -{ integration } -{ version } "
109+ dependencies ,
110+ _format_job_name (python_version , integration , framework_version )
69111 ))
70112
71- def func (session , deps = deps ):
72- session .install ("-r" , "test-requirements.txt" , * deps )
113+ add_nox_job (job_name , integrations , python_version , deps )
73114
74- assert python_version .startswith ("py" )
75- nox_python_version = "pypy" if python_version == "pypy" else python_version [2 :]
76115
77- _locals [job_name ] = nox .session (
78- func = func , reuse_venv = True , python = nox_python_version , name = job_name
79- )
116+ @nox .session (python = "3.8" )
117+ def linters (session ):
118+ session .install ("-r" , "linter-requirements.txt" )
119+
120+ session .run (* "flake8 tests examples sentry_sdk" .split ())
121+ session .run (* "black --check tests examples sentry_sdk" .split ())
122+ session .run (* "mypy examples sentry_sdk" .split ())
123+
124+
125+ import os
126+ travis_python = os .environ .get ("TRAVIS_PYTHON_VERSION" )
127+
128+ if travis_python :
129+ @nox .session (python = travis_python )
130+ def travis_test (session ):
131+ for name , f in globals ().items ():
132+ if name .startswith (f"test-{ travis_python } " ):
133+ f (session )
80134
81135
82- generate_sessions ( locals () )
136+ generate_test_sessions ( )
0 commit comments