diff --git a/.circleci/config.yml b/.circleci/config.yml index bbc07faff..a4ecf7ae7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ orbs: jobs: build: docker: - - image: cimg/python:3.7 + - image: cimg/python:3.10 working_directory: /home/circleci/msprime steps: - checkout diff --git a/.github/workflows/docker/shared.env b/.github/workflows/docker/shared.env index 0b031b88d..4eb04ae32 100644 --- a/.github/workflows/docker/shared.env +++ b/.github/workflows/docker/shared.env @@ -1,7 +1,6 @@ PYTHON_VERSIONS=( cp39-cp39 cp38-cp38 - cp37-cp37m cp310-cp310 cp311-cp311 ) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 24bd90945..6ac5f61dc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: [ 3.7, 3.11 ] + python: [ 3.8, 3.11 ] os: [ macos-latest, ubuntu-latest, windows-latest ] defaults: run: @@ -62,7 +62,6 @@ jobs: channels: conda-forge channel-priority: strict auto-update-conda: true - use-only-tar-bz2: true - name: Fix windows symlinks # This is horrible, but the "git config core.symlinks true" didn't work. diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7b203f530..1a51c4fba 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -15,7 +15,7 @@ jobs: runs-on: macos-latest strategy: matrix: - python: [3.7, 3.8, 3.9, "3.10", 3.11] + python: [3.8, 3.9, "3.10", 3.11] steps: - name: Checkout uses: actions/checkout@v2 @@ -79,7 +79,7 @@ jobs: runs-on: macos-latest strategy: matrix: - python: [3.7, 3.8, 3.9, "3.10", 3.11] + python: [3.8, 3.9, "3.10", 3.11] steps: - name: Download wheels uses: actions/download-artifact@v2 @@ -105,7 +105,7 @@ jobs: needs: ['manylinux'] strategy: matrix: - python: [3.7, 3.8, 3.9, "3.10", 3.11] + python: [3.8, 3.9, "3.10", 3.11] steps: - name: Download wheels uses: actions/download-artifact@v2 diff --git a/.mergify.yml b/.mergify.yml index b02ef2778..3e3fddae4 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -4,11 +4,11 @@ queue_rules: - "#approved-reviews-by>=1" - status-success=Docs - status-success=Lint - - status-success=Python (3.7, macos-latest) + - status-success=Python (3.8, macos-latest) - status-success=Python (3.11, macos-latest) - - status-success=Python (3.7, ubuntu-latest) + - status-success=Python (3.8, ubuntu-latest) - status-success=Python (3.11, ubuntu-latest) - - status-success=Python (3.7, windows-latest) + - status-success=Python (3.8, windows-latest) - status-success=Python (3.11, windows-latest) - "status-success=ci/circleci: build" pull_request_rules: @@ -20,11 +20,11 @@ pull_request_rules: - label=AUTOMERGE-REQUESTED - status-success=Docs - status-success=Lint - - status-success=Python (3.7, macos-latest) + - status-success=Python (3.8, macos-latest) - status-success=Python (3.11, macos-latest) - - status-success=Python (3.7, ubuntu-latest) + - status-success=Python (3.8, ubuntu-latest) - status-success=Python (3.11, ubuntu-latest) - - status-success=Python (3.7, windows-latest) + - status-success=Python (3.8, windows-latest) - status-success=Python (3.11, windows-latest) - "status-success=ci/circleci: build" #- status-success=codecov/patch diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21500f3ab..26c74690c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: rev: v3.2.2 hooks: - id: pyupgrade - args: [--py37-plus] + args: [--py38-plus] - repo: https://github.com/psf/black rev: 22.10.0 hooks: diff --git a/CHANGELOG.md b/CHANGELOG.md index a21a03b4a..3561af77d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,8 +22,13 @@ {user}`GertjanBisschop`) **Maintenance**: + - Automatically flush edges whenever an edge with a different parent is added to the edge buffer. ({issue}`2182`, {pr}`2183`, {user}`GertjanBisschop`) +**Breaking changes**: + +- msprime no longer supports Python 3.7 + ## [1.2.0] - 2022-05-18 **New features** diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py index 17315ecdc..e60f5d370 100644 --- a/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -35,7 +35,6 @@ class LargeSimulationBenchmark: - # ASV is designed to accurately time functions that execute in a fraction # of a second. But, we're interested in profiling large simulations that # run in 10s of seconds (at least). We want to run the target function diff --git a/msprime/ancestry.py b/msprime/ancestry.py index e62b66a4f..2774d30ee 100644 --- a/msprime/ancestry.py +++ b/msprime/ancestry.py @@ -403,6 +403,8 @@ def _parse_random_seed(seed): """ if seed is None: seed = core.get_random_seed() + if isinstance(seed, np.ndarray): + seed = seed[0] seed = int(seed) return seed diff --git a/msprime/demography.py b/msprime/demography.py index dc5e5f583..6af33fb17 100644 --- a/msprime/demography.py +++ b/msprime/demography.py @@ -2984,7 +2984,6 @@ class PopulationParametersChange(ParameterChangeEvent): _type_str: ClassVar[str] = "Population parameter change" def __post_init__(self): - if self.population_id is not None and self.population is not None: raise ValueError( "population_id and population are aliases; cannot supply both." diff --git a/msprime/pedigrees.py b/msprime/pedigrees.py index 21d989d76..09c5399ab 100644 --- a/msprime/pedigrees.py +++ b/msprime/pedigrees.py @@ -215,7 +215,6 @@ def parse_pedigree( def write_pedigree(ts, out): - print("# id\tparent0\tparent1\ttime\tis_sample\tpopulation", file=out) for ind in ts.individuals(): if len(ind.nodes) != 2: diff --git a/requirements/CI-complete/requirements.txt b/requirements/CI-complete/requirements.txt index 8aeaf55f0..8d57f3358 100644 --- a/requirements/CI-complete/requirements.txt +++ b/requirements/CI-complete/requirements.txt @@ -1,17 +1,13 @@ bintrees==2.2.0 -daiquiri==3.0.1 -demes==0.2.1 -mypy==0.910 -newick==1.3.2 -numpy==1.21.6 -pytest==6.2.5 -pytest-cov==3.0.0 -pytest-xdist==2.5.0 -# https://github.com/tskit-dev/msprime/issues/1860 -# Required by python_jsonschema_objects -jsonschema<4.0 -python_jsonschema_objects==0.4.1 -scipy==1.7.3 +daiquiri==3.2.1 +demes==0.2.3 +mypy==1.6.0 +newick==1.9.0 +pytest==7.4.2 +pytest-cov==4.1.0 +pytest-xdist==3.3.1 +python_jsonschema_objects==0.5.0 +scipy==1.11.3 stdpopsim==0.1.2 -tskit==0.5.3 +tskit==0.5.6 kastore==0.3.2 diff --git a/requirements/CI-docs/requirements.txt b/requirements/CI-docs/requirements.txt index 91b75ce59..f76253621 100644 --- a/requirements/CI-docs/requirements.txt +++ b/requirements/CI-docs/requirements.txt @@ -2,12 +2,12 @@ jupyter-book==0.15.1 sphinx-issues==3.0.1 sphinx-argparse==0.4.0 sphinx-book-theme # not pinned to enable easy updates -numpy==1.25.2 -tskit==0.5.5 +numpy==1.26.0 +tskit==0.5.6 demes==0.2.3 -matplotlib==3.7.2 +matplotlib==3.8.0 networkx==3.1 -scipy==1.11.1 +scipy==1.11.3 daiquiri==3.2.1 demesdraw==0.4.0 newick==1.9.0 \ No newline at end of file diff --git a/requirements/CI-tests-conda/requirements.txt b/requirements/CI-tests-conda/requirements.txt index 8cdad8123..ca7b28cec 100644 --- a/requirements/CI-tests-conda/requirements.txt +++ b/requirements/CI-tests-conda/requirements.txt @@ -1,8 +1,3 @@ -# https://github.com/tskit-dev/msprime/issues/1860 -# Version < 4 is required by python_jsonschema_objects, -# but demes will pull in the latest so we pin here. -jsonschema<4.0 gsl -tskit==0.5.3 stdpopsim==0.1.2 -demes==0.2.1 +demes==0.2.3 diff --git a/requirements/CI-tests-pip/requirements.txt b/requirements/CI-tests-pip/requirements.txt index f676c6a4a..cba1d46da 100644 --- a/requirements/CI-tests-pip/requirements.txt +++ b/requirements/CI-tests-pip/requirements.txt @@ -1,14 +1,9 @@ bintrees==2.2.0 -daiquiri==3.0.1 -newick==1.3.1 -numpy==1.21.6; python_version < '3.11' # Held at 1.21.6 for Python 3.7 compatibility -numpy==1.24.1; python_version > '3.10' -pytest==6.2.5 -pytest-xdist==2.4.0 -# https://github.com/tskit-dev/msprime/issues/1860 -# Required by python_jsonschema_objects -jsonschema<5.0 -python_jsonschema_objects==0.4.1 -scipy==1.7.3; python_version < '3.11' -scipy==1.9.3; python_version > '3.10' -tskit==0.5.3 +daiquiri==3.2.1 +newick==1.9.0 +pytest==7.4.2 +pytest-xdist==3.3.1 +python_jsonschema_objects==0.5.0 +scipy==1.11.3; python_version > '3.8' +scipy==1.10.1; python_version <= '3.8' +tskit==0.5.6 diff --git a/requirements/development.txt b/requirements/development.txt index 941a789b7..ffbcdb119 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -26,10 +26,5 @@ sphinx-argparse sphinx-issues jupyter-book networkx - newick>=1.3.0 -# https://github.com/tskit-dev/msprime/issues/1860 -# Required by python_jsonschema_objects -jsonschema<4.0 -# We use JSON-schema to test out metadata handling. python_jsonschema_objects diff --git a/setup.cfg b/setup.cfg index 4f646a6b6..d02577e8a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,7 +17,6 @@ classifiers = Programming Language :: C Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -45,7 +44,7 @@ platforms = [options] packages = msprime -python_requires = >=3.7 +python_requires = >=3.8 include_package_data = True install_requires = numpy diff --git a/tests/test_ancestry.py b/tests/test_ancestry.py index ec8c769a7..82e20e1f9 100644 --- a/tests/test_ancestry.py +++ b/tests/test_ancestry.py @@ -1337,7 +1337,6 @@ def test_initial_state_errors(self): msprime.sim_ancestry(initial_state=ts1, random_seed=2) def test_initial_state(self): - ts = msprime.sim_ancestry(10, end_time=0.01, random_seed=2) # Same if we use either the tables or tree sequence object. sim = ancestry._parse_sim_ancestry(initial_state=ts, population_size=1) diff --git a/tests/test_cli.py b/tests/test_cli.py index 21f3de613..a8fb40f5e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1398,7 +1398,6 @@ def test_short_args(self, tmp_path): assert tree_sequence.get_num_mutations() == 0 def test_run_yaml(self, tmp_path): - yaml = """\ time_units: generations demes: diff --git a/tests/test_demography.py b/tests/test_demography.py index 7183d2e04..6d468ae57 100644 --- a/tests/test_demography.py +++ b/tests/test_demography.py @@ -2597,7 +2597,6 @@ def test_full_arg_migration(self): def test_full_arg_migration_smc(self): for model in ["smc", "smc_prime"]: - population_configurations = [ msprime.PopulationConfiguration(10), msprime.PopulationConfiguration(10), @@ -4262,7 +4261,6 @@ def test_debug(self): assert str(dbg1) == str(dbg2) def test_population_name(self): - demography = msprime.Demography.isolated_model([1]) assert demography.populations[0].name == "pop_0" diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index 85d03637c..9c483a61e 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -1318,7 +1318,6 @@ def test_non_parametric_simulation_models(self): assert sim.model == model def test_dirac_simulation_model(self): - for bad_type in [None, str, "sdf"]: model = get_simulation_model("dirac", psi=bad_type, c=1.0) with pytest.raises(TypeError): @@ -2453,7 +2452,6 @@ def test_seed_bounds(self): gen.seed = overflow def test_seed(self): - for s in [1, 10, 2**32 - 1]: rng = _msprime.RandomGenerator() rng.seed = s diff --git a/tests/test_mutations.py b/tests/test_mutations.py index e0121af0d..882646600 100644 --- a/tests/test_mutations.py +++ b/tests/test_mutations.py @@ -202,8 +202,8 @@ def validate_state_independent(self, method, **kwargs): def verify_models_equivalent(self, model1, model2): assert len(model1.alleles) == len(model2.alleles) - assert np.alltrue(np.equal(model1.root_distribution, model2.root_distribution)) - assert np.alltrue(np.equal(model1.transition_matrix, model2.transition_matrix)) + assert np.all(np.equal(model1.root_distribution, model2.root_distribution)) + assert np.all(np.equal(model1.transition_matrix, model2.transition_matrix)) def test_bad_alleles(self): for alleles, err in [ @@ -1519,7 +1519,6 @@ def test_layer_mutation_models(self): class StatisticalTestMixin: - p_threshold = 0.001 def chisquare(self, observed, expected, p_th=p_threshold): @@ -1604,7 +1603,6 @@ def run_mutate( mutation_id=0, slim_generation=1, ): - model = msprime.SLiMMutationModel( type=mutation_type, next_id=mutation_id, slim_generation=slim_generation ) @@ -1719,7 +1717,6 @@ def validate_unique_alleles(self, ts): assert len(alleles) == len(set(alleles)) def run_mutate(self, ts, rate=1, random_seed=42, start_allele=0): - model = msprime.InfiniteAlleles(start_allele=start_allele) mts1 = msprime.sim_mutations( ts, rate=rate, random_seed=random_seed, model=model, discrete_genome=True @@ -2132,7 +2129,10 @@ def populate_tables(self, tables): mutation.derived_state, parent=parent_id, metadata=mutation.metadata, - time=mutation.time, + # Not sure why, but sometimes the time is a single-element array + time=mutation.time[0] + if isinstance(mutation.time, np.ndarray) + else mutation.time, ) assert mutation_id > parent_id mutation.id = mutation_id diff --git a/tests/test_pedigree.py b/tests/test_pedigree.py index 8aaf5b98e..8cd2dcb4c 100644 --- a/tests/test_pedigree.py +++ b/tests/test_pedigree.py @@ -414,7 +414,6 @@ def test_two_pedigrees(self): ) def test_three_pedigrees(self): - tables1 = simulate_pedigree( num_founders=2, num_generations=2, @@ -778,7 +777,6 @@ class TestContinueSimulateThroughPedigree(TestSimulateThroughPedigree): """ def verify(self, input_tables, recombination_rate=0): - ts1 = msprime.sim_ancestry( model="fixed_pedigree", initial_state=input_tables, diff --git a/tests/test_provenance.py b/tests/test_provenance.py index 68e8a6e58..805235155 100644 --- a/tests/test_provenance.py +++ b/tests/test_provenance.py @@ -78,7 +78,10 @@ class TestBuildObjects: """ def decode(self, prov): - builder = pjs.ObjectBuilder(tskit.provenance.get_schema()) + # Supress warnings about schemas here - it's no big deal and + # not easy to fix + with pytest.warns(UserWarning): + builder = pjs.ObjectBuilder(tskit.provenance.get_schema()) ns = builder.build_classes() return ns.TskitProvenance.from_json(prov) diff --git a/verification.py b/verification.py index 6feffdeca..e671bc650 100644 --- a/verification.py +++ b/verification.py @@ -1662,7 +1662,6 @@ def run_dtwf_pedigree_comparison( df = pd.DataFrame() def replicates_data(replicates, model): - data = collections.defaultdict(list) for ts in replicates: t_mrca = np.zeros(ts.num_trees) @@ -1704,7 +1703,6 @@ def replicates_data(replicates, model): return df def plot_coalescent_stats(self, df): - df_ped = df[df.model == "dtwf|ped"] df_dtwf = df[df.model == "dtwf"] for stat in ["tmrca_mean", "num_trees", "num_roots"]: @@ -1793,7 +1791,6 @@ def run_dtwf_pedigree_comparison( df = pd.DataFrame() def replicates_data(replicates, model): - data = collections.defaultdict(list) for ts in replicates: t_mrca = np.zeros(ts.num_trees) @@ -1845,7 +1842,6 @@ def replicates_data(replicates, model): return df def plot_coalescent_stats(self, df): - df_ped = df[df.model == "dtwf|ped"] df_dtwf = df[df.model == "dtwf"] for stat in ["tmrca_mean", "num_trees"]: @@ -2224,7 +2220,6 @@ def test_dtwf_vs_coalescent_3_pops_asymm_mig(self): ) def test_dtwf_vs_coalescent_2_pops_high_asymm_mig(self): - migration_matrix = [[0, 0.5], [0.7, 0]] self._run( [1000, 1000], @@ -2394,7 +2389,6 @@ class DtwfVsCoalescentRandom(DtwfVsCoalescent): """ def _run(self, num_populations=1, num_replicates=200, num_demographic_events=0): - # Make this deterministic np.random.seed(42) random.seed(42) @@ -2823,7 +2817,6 @@ def _run( self.compare_sfs(sample_size, ploidy, model, num_replicates, sfs, name) def test_xi_dirac_expected_sfs_psi_0_1_c_1(self): - self._run( psi=0.1, c=1, @@ -3135,7 +3128,6 @@ def _run(self, sample_size, ploidy, alpha, sfs, num_replicates=1000): self.compare_sfs(sample_size, ploidy, model, num_replicates, sfs, name) def test_xi_beta_expected_sfs_alpha1_1(self): - self._run( num_replicates=100000, sample_size=10, @@ -3468,7 +3460,6 @@ class ArgRecordTest(Test): """ def _run(self, num_replicates=1000, **kwargs): - ts_node_counts = np.array([]) arg_node_counts = np.array([]) ts_tree_counts = np.array([]) @@ -4269,7 +4260,6 @@ def test_smc_oldest_time(self): msp_mean = np.zeros_like(rho) msp_smc_mean = np.zeros_like(rho) for j in range(len(num_loci)): - cmd = "{} {} -L -r {} {} -p 14".format( n, num_replicates, rho[j], num_loci[j] ) @@ -5288,7 +5278,6 @@ class SeqGenTest(MutationTest): _seq_gen_executable = ["./data/seq-gen"] def _run_seq_gen(self, tree, args, model, alleles, num_sites, mutation_rate, Q): - ts = tree.tree_sequence newick = tree.newick() cmd = self._seq_gen_executable + args @@ -5556,7 +5545,6 @@ def replace_variants(variants): return (py_counts, transitions_py, roots_d_py, expected) def _run_pyvolve_stats(self, model, length=20, num_samples=10): - model_dict = { "JC69": { "model_id": msprime.JC69(), @@ -6180,7 +6168,6 @@ def setup_logging(args): def run_tests(suite, args): - setup_logging(args) runner = TestRunner()