Hi!

Thanks Anne and Travis for starting the discussion!

On Sun, Nov 03, 2013 at 05:48:19PM -0800, Anne Schilling wrote:
> Here is an initial list of discussion points regarding the Sage-combinat 
> queue:
> 
> - Should we use a fork for sage-combinat? Or branches for the various patches
>   or projects?
>   * If we do use a fork, how to sync the combinat fork with the main sage
>     fork? In particular, once branches are merged in the main fork, can they
>     merge in the fork as well?
>   * If we don't fork, then is there some way we can tie all of the
>     combinat branches together? Specifically can we list all branches
>     which don't have ticket numbers.

At the beginning we were a relatively small community and there were
lots of interactions across the whole "combinat" code base, because we
had to build the foundations. Hence there was a relatively clear
notion of "combinat patch" (which somehow included categories) and it
was good to have a relatively centralized workflow. Now the core is
stabilizing and the community has grown quite much both in terms of
number of contributors and of breadth of topics. It's thus naturally
evolving from a tightly knit community into a continuum of overlapping
subcommunities of Sage developers that gather together at the occasion
of specific projects. And that's great!

Now, we want the workflow to reflect that. The dichotomy "in
Sage-Combinat or not" that the queue enforces has become a bother,
especially for borderline people like Simon.

With that in mind, I would aim for just using a bunch of branches in
the sage git repository, with a way to group those in collections that
would model our subcommunities: combinat / cluster_algebras /
categories / tableaux / crystals / dynamics / semigroups / ...
As Simon points out, some tags mechanism would be great for this.

Here is what feels like the largest hurdles we might face; I might be
completely wrong though, and we probably can only know for sure
through experimenting at a large scale with the new workflow:

- Switching from one branch to the other.

  As Simon pointed out, this will be easy. However whether it's
  practical or not will depend on how much time we will have to wait
  for recompilation in average.  Part of the answer will be in the
  "compilation cache"[1] infrastructure that Andrew & co have been
  exploring, but I don't know how far this project progressed.

- Mitigation of the divergence between parallel development branches.

  An important feature of the workflow is to be able to request things
  like ``pull on my local Sage all the experimental features about
  tableaux, categories, and semigroups''.

  Typical applications: I want to run a particular calculation for
  which I need a bunch of different in-development features. Or I want
  to share with a non-programmer colleague the latest semigroup
  code. That's what "sage -combinat install" was about; granted it
  very was far from 100% robust, but it worked relatively often.

  In theory, this is easy: it's just about creating a temporary merge
  point for a bunch of branches. But will this be robust in practice?
  That is will we be able to maintain the state of our branches in a
  consistent enough state that the most-often-needed combinations of
  branches will actually merge without conflicts?

  Of course the new workflow, and the fact that the development is
  progressively moving from the core to the periphery, is likely to
  reduce the life span of branches, which in turn will reduce the need
  for the above.

- Dependency handling

> - How do we transform the queue into git branches,
>   how do we handle dependencies?

Back in March, I wrote a script which was based on the sage
development tools and did just this (attached; see the
import_mercurial_queue function). With it, I was able to import most
of the Sage-Combinat queue [2] as a bunch of branches with
dependencies (see the graph attached to [2]).

So, in principle that should be easy technically. However:

- The sage dev tools have evolved quite much since then, and I have
  not played with the script since then. So it certainly needs to be
  rebased on the latest dev tools. And it also deserves some cleanup.

- A good part of the work was to annotate the series file with
  explicit dependencies information. Part of this information is on
  trac, but in practice it's often outdated or incomplete, especially
  for the more experimental patches. Thus that required quite some
  manual trial-and-error work (oh, it does not apply! hmm, let's see
  why ...). And now this information needs to be updated again
  w.r.t. all the changes in the queue in the past six months. Note
  that this is not wasted time, as we need to update this dependency
  information on trac anyway at some point.

- We need to decide whether we do the migration all at once, or
  instead we let the patch developers migrate progressively their own
  patches. It's probably easier to do it all at once, if we can afford
  it (essentially if there is a clear line between those patches to
  finalize right now in mercurial, and those patches that we want to
  develop further in git).

> - When will the change occur?
>   * Will we freeze the hg queue at that point?

Probably yes? It would be a nice feature if we could leave the queue
in a state where it would install smoothly on, say, Sage 5.12 and Sage
5.13, so that the Sage-Combinat users could keep playing with it for a
while.

Maybe we should leave it open for tiny changes like the finalization
of patches that are just about to go into Sage 5.13 (typically if the
release manager notices a glitch in a positively reviewed patch, we
don't want this to bump that patch to 5.14). I am of course thinking
about #10963 here in case the migration would occur soon.

Looking forward the progress this week! Have fun!

Cheers,
                                Nicolas

[1] http://fr.wikipedia.org/wiki/Ccache
[2] https://groups.google.com/d/msg/sage-combinat-devel/hGsalRNWZ3U/c3Uk_1RK6OQJ

--
Nicolas M. ThiƩry "Isil" <nthi...@users.sf.net>
http://Nicolas.Thiery.name/

-- 
You received this message because you are subscribed to the Google Groups 
"sage-combinat-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-combinat-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-combinat-devel@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-combinat-devel.
For more options, visit https://groups.google.com/groups/opt_out.
import io
import os
import re
import sagedev
import subprocess

"""
    sage: import sagedev
    sage: %attach sage-combinat.py
    sage: cd /opt/sage-git
    sage: patch_dir = "/opt/sage/devel/sage/.hg/patches/"
    sage: s = sagedev.SageDev()
    sage: git = s.git
    sage: git.checkout("master")

    sage: git.branch("-D", "t/9107")
    Deleted branch t/9107 (was 031ee52).

    sage: s.import_patch(local_file=patch_dir+"trac9107_nesting_nested_classes.patch", ticketnum=9107)
    sage: s.import_patch(local_file=patch_dir+"trac_9107_fix_cross_reference.patch", ticketnum=9107)

    sage: git.checkout("master")

# Breaks due to the removal of new lines

    sage: git.branch("-D", "t/14140")
    sage: s.import_patch(local_file=patch_dir+"trac_14140-remove_cc_set_partitions-ts.patch", ticketnum=14140)

    sage: git.checkout("master")
    sage: s.import_patch(local_file=patch_dir+"trac_14248-global_options_case-ts.patch", ticketnum=14248)

    sage: git.checkout("master")
    sage: s.import_patch(local_file=patch_dir+"trac_14299-gelfand_tsetlin_patterns-ts.patch", ticketnum=14299)

    sage: git.checkout("master")
    sage: s.import_patch(local_file=patch_dir+"trac_13624-dot2tex-verb_workaround-nt.patch", ticketnum=13624)

"""

sage_hg_dir="/opt/sage/devel/sage-combinat/"
sage_git_dir="/opt/sage-git/"

def ticket_and_branch_of_patch(name):
    ticket = get_ticket(name)
    if ticket:
        branch = "t/%s"%ticket
    else:
        branch = "p/%s"%name
    return ticket, branch

def branch_of_patch(name):
    return ticket_and_branch_of_patch(name)[1]

def import_patch(patches, depends=[], patch_dir=sage_hg_dir+".hg/patches/"):
    """
    EXAMPLES::

        sage: %attach sage-combinat.py
        sage: import sagedev
        sage: cd /opt/sage-git
        sage: destroy_all_branches()
        sage: import_patch("trac9107_nesting_nested_classes.patch")
        sage: import_patch("trac_12876_category-fix_abstract_class-nt-rel11521.patch")
        sage: import_patch("trac_12876_category-fix_abstract_class-nt-rel11521-review-nt.patch", append=True)
        sage: import_patch("trac11935_weak_pickling_by_construction_rel11943-nt.patch", depends=[12876])
        sage: import_patch("trac11935_share_on_base_category.patch", append=True)
        sage: import_patch("trac_12894-classcall_setter-nt.patch")

    """
    print patches
    assert patches
    if isinstance(patches, str):
        name = patches
        patches = [name]
    else:
        name = patches[0]
    print "== Importing %s "%short_name(name) + "="*max(60-len(name), 0)
    ticket, branch = ticket_and_branch_of_patch(name)
    s = sagedev.SageDev()
    s.git.checkout("master")
    if s.git.branch_exists(branch):
        s.git.branch("-D", branch)
    #s.git.create_branch(branch)
    s.git.create_branch(branch, remote_branch=False)
    if ticket:
        s.git._ticket[branch] = ticket
    assert s.git.branch_exists(branch)
    s.git.checkout(branch)
    for dependency in depends:
        print "* Applying dependency: %s"%dependency
        branch = branch_of_patch(dependency)
        s.git.merge(branch)
    for patch in patches:
        if os.path.getsize(patch_dir+patch) > 0:
            print "* Applying patch %s"%patch
            s.import_patch(local_file=patch_dir+patch)
        else:
            print "* Empty patch; nothing to do!"


def destroy_all_branches():
    s = sagedev.SageDev()
    branches = s.git.local_branches()
    s.git.checkout("master")
    for branch in branches:
        if branch != "master":
            s.git.branch("-D", branch)

def git_reset():
    s = sagedev.SageDev()
    s.git.am("--abort")
    s.git.stash()
    s.git.checkout("master")
    s.git.clean("-f", "-d")

HG_SERIES_REGEXP="(\S+)\s*#.*?deps: (.*?)(?:#.*)?$"

"""

    sage: re.match(HG_SERIES_REGEXP, "bla.patch #+1 depends: 1111 trac_111.patch").groups()[0].split()
    ['1111', 'trac_111.patch']
"""

def ticket_or_patch(s):
    """

    EXAMPLES::

        sage: ticket_or_patch(u"123")
        123
        sage: ticket_or_patch(u"trac_123.patch")
        u'trac_123.patch'
    """
    try:
        return int(s)
    except ValueError:
        return s

def get_dependencies(sage_hg_dir=sage_hg_dir):
    """
    Extract the dependencies encoded in the series file of a mercurial patch queue

    The dependencies should be expressed by adding in the series file
    a comment after the patch of the form ``deps: dep1 ... ``. For
    example:

        ``blah.patch # deps: 12344 blih.patch # trivial``
        ``blah.patch #+foo  deps: 12344 blih.patch # trivial``

    EXAMPLES::

        sage: get_dependencies("/opt/sage/devel/sage/")
        {u'12940': ['8392'],
         u'14143': ['4327', '14252'],
         u'14192': ['14252', '14143']}
    """
    sage_patch_dir = sage_hg_dir+"/.hg/patches/"
    series = list(io.open(sage_patch_dir+"series"))
    dependencies = {}
    for line in series:
        match = re.match(HG_SERIES_REGEXP, line)
        if match:
            patch, deps = match.groups()
            name = short_name(patch)
            deps = map(short_name, deps.split())
            if name in dependencies:
                dependencies[name].extend(deps)
            else:
                dependencies[name] = deps
    return dependencies

def get_patches(sage_hg_dir=sage_hg_dir):
    """
    Return the list of active patches (applied or not).

    EXAMPLES::

        sage: get_patches()
        ['trac9107_nesting_nested_classes.patch',
         'trac_9107_fix_cross_reference.patch',
         ...
         'trac_13855_planar_binary_trees_hopf_algebra-EliX-jbp.patch']
    """
    return (subprocess.check_output(["hg", "qapplied", "--cwd", sage_hg_dir]) +
            subprocess.check_output(["hg", "qunapplied", "--cwd", sage_hg_dir])).split()

def get_ticket(patch):
    """
    Return the ticket number for this patch, or None

    EXAMPLES::

        sage: get_ticket("trac_13423_bla-vt.patch")
        13423
        sage: get_ticket("bla-vt.patch")
    """
    match = re.match(".*?(\d\d\d\d+)",patch)
    if match:
        return int(match.groups()[0])
    return None

def short_name(patch):
    """
    Return a short name for the patch

    If the patch corresponds to a ticket, return the ticket number;
    otherwise return the patch name.

    EXAMPLES::

        sage: short_name("trac_13423_bla-vt.patch")
        '13423'
        sage: short_name("bla-vt.patch")
        'bla-vt.patch'
    """
    ticket = get_ticket(patch)
    if ticket:
        return str(ticket)
    else:
        return patch

def dependency_graph(sage_hg_dir=sage_hg_dir):
    """
    Return the dependency graph for the given mercurial patch queue

    EXAMPLES::

        sage: dependency_graph()
    """
    G = DiGraph()
    G.add_vertices(short_name(patch) for patch in get_patches(sage_hg_dir))
    for name, deps in get_dependencies(sage_hg_dir).iteritems():
        for dep in deps:
            G.add_edge(name, dep)
    return G

def import_mercurial_queue(sage_hg_dir=sage_hg_dir, sage_git_dir=sage_git_dir, resume=False):
    """
    Import the patches in a mercurial queue

    INPUT:

    - ``resume`` -- a boolean

      Whether to skip existing branches, or recreate them from scratch

    EXAMPLES::

        sage: %attach sage-combinat.py
        sage: cd /opt/sage-git
        sage: import_mercurial_queue(sage_hg_dir="/opt/sage/devel/sage-combinat/")
    """
    os.chdir(sage_git_dir)
    #destroy_all_branches()
    s = sagedev.SageDev()
    git_reset()
    dependencies = get_dependencies()

    def handle(patches):
        if not patches:
            return
        name = patches[0]
        ticket, branch = ticket_and_branch_of_patch(name)
        if s.git.branch_exists(branch):
            if resume:
                return
            else:
                s.git.branch("-D", branch)
        deps = dependencies.get(short_name(name), [])
        import_patch(patches, depends=deps, patch_dir=sage_hg_dir+".hg/patches/")

    patches = []
    previous_ticket = None
    for patch in get_patches():
        ticket = get_ticket(patch)
        if ticket is not None and ticket == previous_ticket:
            patches.append(patch)
            previous_ticket = ticket
        else:
            handle(patches)
            patches = [patch]
            previous_ticket = ticket
    handle(patches)
    return

    #patches = (subprocess.check_output(["hg", "qapplied", "--cwd", sage_hg_dir]) +
    #           subprocess.check_output(["hg", "qapplied", "--cwd", sage_hg_dir])).split()

    import_patch("trac9107_nesting_nested_classes.patch")
    import_patch("trac_2023-dynkin_graphs-ts.patch")
    # Applies on second thought
    import_patch("trac_14252-KRLS-as.patch", )
    import_patch("trac_14094-partition_iterator-mh.patch")
    import_patch("trac_14094-partition_iterator-review-ts.patch", append=True)

    import_patch("trac_14145-fix_contains_tableau-ts.patch")
    import_patch("trac_8392-check_permutation-ts.patch")

    import_patch("trac_13871-virtual_cartan_type-ts.patch")
    import_patch("trac_13838-virtual_kleber_alg-ts.patch")

    import_patch("trac_13872-RC_bijections-ts.patch", depends=[13838])

    import_patch("trac9107_nesting_nested_classes.patch")
    import_patch("trac_9107_fix_cross_reference.patch", append=True)

    import_patch("trac_14140-remove_cc_set_partitions-ts.patch")

    import_patch("trac_14094-partition_iterator-mh.patch")
    import_patch("trac_14094-partition_iterator-review-ts.patch", append=True)


    import_patch("trac_14248-global_options_case-ts.patch")
    import_patch("trac_14299-gelfand_tsetlin_patterns-ts.patch")
    import_patch("trac_13624-dot2tex-verb_workaround-nt.patch")

    import_patch("trac_10054-parent_gen_words-ts.patch")
    import_patch("trac_14141-knutson_tao_puzzles-fs.patch")
    import_patch("trac_14223-plot-aspect_ratio-nt.patch")
    import_patch("trac_4327-root_system_plot_refactor-nt.patch")
    import_patch("trac_14143-alcove-path-al.patch", depends=[14252])
    import_patch("trac_14192-infinity_crystal-bs.patch", depends=[14252,14143]) # Trivial textual dependencies
    import_patch("trac_10170-bell_number_improvements-ts.patch")
    import_patch("dynamics-iet-tutorial.patch") # causes problem?
    import_patch("trac_10193-graded_enumerated_sets-vd_no_more_nt.patch")
    import_patch("trac_10193-review-nb.patch", append=True)
    import_patch("trac_10193-more-vd.patch", append=True)
    import_patch("trac_10194-factories_policy-fh.patch")
    import_patch("trac_12940_affine_permutations-td.patch", depends=[8392]) # Trivial dependency in sage.combinat.all
    import_patch("trac_12876_category-fix_abstract_class-nt-rel11521.patch")        # Does not apply yet (end-of-file whitespace)
    import_patch("trac_12876_category-fix_abstract_class-nt-rel11521-review-nt.patch", append=True)
    import_patch("trac11935_weak_pickling_by_construction_rel11943-nt.patch", depends=[12876])
    import_patch("trac11935_share_on_base_category.patch", append=True)
    import_patch("trac_12894-classcall_setter-nt.patch")

    import_patch("trac_12895-subcategory-methods-nt.patch", depends=[11935,12894])

    import_patch("trac_13580-map_reduce-old-fh.patch")        # Does not apply yet (end-of-file whitespace)
    import_patch("trac_13433-lazy_power_serie_gen_fix-fh.patch")
    import_patch("finite_set_map-isomorphic_cartesian_product-nt.patch")
    import_patch("trac_12848-posets-order_ideal_complement_generators_fix-nt.patch")
    import_patch("trac_12920-is_test_methods-nt.patch")
    import_patch("doc_underscore-fh.patch")
    import_patch("trac_8703-trees-fh.patch", depends=[8392])     # in permutations.py
    import_patch("trac_13987_mary_trees-vp.patch", depends=[8703])
    import_patch("trac_11407-list_clone_improve-fh.patch", depends=[8703])
    import_patch("mutator-fh.patch", depends=[11407])
    import_patch("trac_9280-graded-algebras-example-fs.patch")
    import_patch("coercion_graph-nt.patch") # No ticket
    import_patch("finiteenumset_random_improve-fh.patch")
    import_patch("trac_12250-ktableaux-as.patch")
    import_patch("missing-doc-includes-nt.patch")
    import_patch("dyck_word_to_binary_tree-fh.patch")
    import_patch("trac_10963-more_functorial_constructions-nt.patch", depends=[10193,12895,9280])
    import_patch("trac_14102-nonsymmetric-macdonald.patch", depends=[4327,14143,10963])
    import_patch("ncsf-qsym-new-bases-fs.patch")
    import_patch("crystal_isomorphism-ts.patch")
    import_patch("hall_littlewood_yt-ts.patch", depends=[14141])
    import_patch("trac_11285-decompose_vecspace-ts.patch")
    import_patch("12630_quivers.patch")
    import_patch("12630_quivers_review-fs.patch")
    import_patch("qpa_interface-fs.patch")
    import_patch("dynamic-fh.patch")
    import_patch("element_compare_consistency-fh.patch")
    import_patch("trees_symmetry_factor-fh.patch", depends=[8703])
    import_patch("trac_10950-hash_matrices-nt.patch")
    import_patch("trac_13232-plot_latex-nt.patch")
    import_patch("kschur-as.patch")
    import_patch("trac_8678-module_morphisms-nt.patch", depends=[10963])
    import_patch("trac_13317-species_unique_representation.patch")
    import_patch("trac_10227-species_fixes-mh.patch", depends=[13317])
    import_patch("categories-tutorial.patch")
    import_patch("trac_11111-finite_dimensional_modules-nt.patch", depends=[10963,8678]) # still causing problem
    import_patch("trac_8822-family_constructor-fh.patch")
    import_patch("trac_6484-ranker-improvements-nt.patch")
    import_patch("selector-fh.patch")
    import_patch("trac_11529-rooted_trees-fh.patch", depends=[8703,13987]) # causing problem
    import_patch("shape_tree-fc.patch", depends=[11529])
    import_patch("shuffle_overlap_generic-fh.patch")
    import_patch("operads-fh.patch", depends=[8703])
    import_patch("operads_more-fc.patch",depends=[11529, "operads-fh.patch"])
    import_patch("mupad-interface-improve-fh.patch")
    import_patch("combinat-quickref-jb.patch")
    import_patch("partition_k_boundary_speedup-fh.patch")
    import_patch("partition_leg_length_speedup-fh.patch")
    import_patch("kshape-om.patch")
    import_patch("bintrees_leaf_paths-fh.patch", depends=[8703])
    import_patch("trac_11109-stable-grothendieck-polynomials-nt.patch", depends=[10963]) # really depends on it?
    import_patch("add_cache-nt.patch", depends=[10963])
    import_patch("games_dao-nt.patch")
    import_patch("finite-subquotients-nt.patch", depends=[10963])
    import_patch("finite_set_map_mul-nt.patch")
    import_patch("automatic_monoid-nt.patch", depends=[10963]) # Trivial dependency in sage.combinat.all
    import_patch("discrete_function-nt.patch", depends=["automatic_monoid-nt.patch"])
    import_patch("discrete_function_exper-fh.patch", depends=["discrete_function-nt.patch"])
    import_patch("finite_semigroup-nt.patch", depends=[10963])
    import_patch("finite_semigroup-subcategory-methods-nt.patch", depends=["finite_semigroup-nt.patch"])
    import_patch("digraphs-as-automatons-nt.patch")
    import_patch("category-symmetric_groups-nt.patch")
    import_patch("ndpf_mult_side-fh.patch", depends=["finite_semigroup-nt.patch"])
    import_patch("graph-latex-nt.patch")
    import_patch("weyl_characters-nt.patch")
    import_patch("test_len_object-fh.patch")
    import_patch("invariant_ring_permutation_group-nb.patch") # failing
    import_patch("permutation_inverse-vd.patch")
    import_patch("conjugacy_class_iterator-vd.patch")
    import_patch("wang_tile_set-tm.patch")
    import_patch("trac_9439-hyperbolic_geometry-vd.patch")
    import_patch("trac_9557-fundamental_domains-vd.patch", depends=[9439])
    import_patch("trac_9806-constellations-vd.patch", depends=[9557])
    import_patch("trac_9806-constellations-doc-patch-fc.patch", append=True)
    import_patch("permutation_groups_stabilizer_chains-rm.patch")
    import_patch("trac_7983_tableau_fixes-jb.patch")
    import_patch("refactor_sf-jb.patch")
    import_patch("trac_8581_multivariate_schubert_step_1-nb.patch", depends=["invariant_ring_permutation_group-nb.patch"])  # trivial dependency in setup.py
    import_patch("trac_6629_abstract_ring_of_multivariate_polynomials_with_several_bases_vp.patch", depends=["trac_8581_multivariate_schubert_step_1-nb.patch"])
    import_patch("trac_12460_polynomial_module_on_sym-nb-vp.patch", depends=["trac_6629_abstract_ring_of_multivariate_polynomials_with_several_bases_vp.patch"])
    # roughly got up to there ...
    import_patch("sage-demos-and-tutorials-nt.patch", depends=[10963,"combinat-quickref-jb.patch"])
    import_patch("descents_composition_of_empty_permutation_jyt.patch")
    import_patch("exterior_algebra-vd.patch")
    import_patch("nested_lists_jb.patch")
    import_patch("trac_7980-multiple-realizations-extra_do_not_merge-nt.patch")
    import_patch("hopf_algebra_of_supercharacters-fs.patch")
    import_patch("permutations_descent_values-fh.patch")
    import_patch("sf_principal_specialization-mr.patch")
    import_patch("trac_9123-schur-algebra-and-gln-characters-ht.patch")
    import_patch("trac_11386_bracelet_class-dr.patch")
    import_patch("trac_11571_catalan_objects-nm.patch")
    import_patch("catalan_quasi_symmetric-fc.patch")
    import_patch("catalan_quasi_symmetric-rebase-cs.patch")
    import_patch("tableaux-combinatorics-am.patch")
    import_patch("cartesian_product_improvements-nt.patch")
    import_patch("extended_affine_weyl_groups_sd40.patch")
    import_patch("affine_iwahori_hecke_algebras.patch")
    import_patch("q_tree_factorial-fc.patch")
    import_patch("trac_12916_completion_by_cuts-fc.patch")
    import_patch("algebras_over_operads-fc.patch", depends=["operads_more-fc.patch"])
    import_patch("shuffle-operads-fc.patch",depends=["algebras_over_operads-fc.patch"])
    import_patch("trac_Kleshchev-partitions-am.patch")
    import_patch("hgignore_eclipse_project-EliX-jbp.patch")
    import_patch("trac_13935_coercion_of_coproduct_of_Hopf_algebra-EliX-jbp.patch")
    import_patch("trac_13793-some-hopf-algebra-f-w-pqsym-EliX-jbp.patch", depends=[11571,13935]) # Trivial dependency upon #11571 in setup.py Trivial dependency on invariant_ring_permutation_group-nb.patch in doc/en/reference/combinat/index.rst
    import_patch("trac_14104--html_display-am.patch")
    import_patch("trac_14103--labelled_matrices-am.patch")
    import_patch("trac_13855_planar_binary_trees_hopf_algebra-EliX-jbp.patch", depends=[8703,13793]) # and q_tree_factorial-fc.patch and trees_symmetry_factor-fh.patch

Reply via email to