Add concepts as specified in a dataset's associated Concepticon concept list or in
        etc/concepts.csv

        :param id_factory: A callable taking a pyconcepticon.api.Concept object as argument and \
        returning a value to be used as ID for the concept.
        :return: The set of concept IDs which have been added.

def add_concepts(self, id_factory=lambda d: d.number):
        """
        Add concepts as specified in a dataset's associated Concepticon concept list or in
        etc/concepts.csv

        :param id_factory: A callable taking a pyconcepticon.api.Concept object as argument and \
        returning a value to be used as ID for the concept.
        :return: The set of concept IDs which have been added.
        """
        ids, concepts = set(), []
        if self.dataset.conceptlist:
            concepts = self.dataset.conceptlist.concepts.values()
        else:
            fields = Concept.public_fields()
            for i, concept in enumerate(self.dataset.concepts, start=1):
                kw, attrs = {}, {}
                for k, v in concept.items():
                    if k.lower() in fields:
                        kw[k.lower()] = v
                    else:
                        attrs[k.lower()] = v

                if not kw.get('id'):
                    kw['id'] = str(i)
                if not kw.get('number'):
                    kw['number'] = str(i)
                concepts.append(Concept(attributes=attrs, **kw))

        fieldnames = {f.lower(): f for f in self.dataset.concept_class.fieldnames()}
        for c in concepts:
            attrs = dict(
                ID=id_factory(c),
                Name=c.label,
                Concepticon_ID=c.concepticon_id,
                Concepticon_Gloss=c.concepticon_gloss)
            for fl, f in fieldnames.items():
                if fl in c.attributes:
                    attrs[f] = c.attributes[fl]
            ids.add(attrs['ID'])
            self.add_concept(**attrs)
        return ids