<commit_before>/* 
 * Seahorse
 * 
 * Copyright (C) 2008 <NAME>
 * 
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.  
 */

#include "config.h"

#include "seahorse-object.h"

#include "seahorse-context.h"
#include "seahorse-source.h"

#include "string.h"

#include <glib/gi18n.h>

/**
 * _SeahorseObjectProps:
 * @PROP_0:
 * @PROP_CONTEXT:
 * @PROP_SOURCE:
 * @PROP_PREFERRED:
 * @PROP_PARENT:
 * @PROP_ID:
 * @PROP_TAG:
 * @PROP_LABEL:
 * @PROP_MARKUP:
 * @PROP_NICKNAME:
 * @PROP_DESCRIPTION:
 * @PROP_ICON:
 * @PROP_IDENTIFIER:
 * @PROP_LOCATION:
 * @PROP_USAGE:
 * @PROP_FLAGS:
 */
enum _SeahorseObjectProps {
	PROP_0,
	PROP_CONTEXT,
	PROP_SOURCE,
	PROP_PREFERRED,
	PROP_PARENT,
	PROP_ID,
	PROP_TAG,
	PROP_LABEL,
	PROP_MARKUP,
	PROP_NICKNAME,
	PROP_DESCRIPTION,
	PROP_ICON,
	PROP_IDENTIFIER,
	PROP_LOCATION,
	PROP_USAGE,
	PROP_FLAGS
};

/**
 * _SeahorseObjectPrivate:
 * @id: the id of the object
 * @tag: DBUS: "ktype"
 * @tag_explicit: If TRUE the tag will not be set automatically
 * @source: Where did the object come from ?
 * @context:
 * @preferred: Points to the object to prefer over this one
 * @parent: the object's parent
 * @children: a list of children the object has
 * @label: DBUS: "display-name"
 * @markup: Markup text
 * @markup_explicit: If TRUE the markup will not be set automatically
 * @nickname: DBUS: "simple-name"
 * @nickname_explicit: If TRUE the nickname will not be set automatically
 * @description:  Description text DBUS: "key-desc"
 * @description_explicit: If TRUE the description will not be set automatically
 * @icon: DBUS: "stock-id"
 * @identifier: DBUS: "key-id", "display-id", "raw-id"
 * @identifier_explicit:
 * @location: describes the loaction of the object (local, remte, invalid...)
 * @usage: DBUS: "etype"
 * @flags:
 * @realizing: set while the object is realizing
 * @realized: set as soon as the object is realized
 */
struct _SeahorseObjectPrivate {
	GQuark id;
	GQuark tag;
	gboolean tag_explicit;

	SeahorseSource *source;
	SeahorseContext *context;
	SeahorseObject *preferred;
	SeahorseObject *parent;
	GList *children;
	
    gchar *label;             
    gchar *markup;
    gboolean markup_explicit;
    gchar *nickname;
    gboolean nickname_explicit;
    gchar *description;
    gboolean description_explicit;
    gchar *icon;
    gchar *identifier;
    gboolean identifier_explicit;

    SeahorseLocation location;
    SeahorseUsage usage;
    guint flags;

	gboolean realized;
	gboolean realizing;
};

G_DEFINE_TYPE (SeahorseObject, seahorse_object, G_TYPE_OBJECT);

/* -----------------------------------------------------------------------------
 * INTERNAL 
 */

/**
 * register_child:
 * @self: The parent
 * @child: The new child
 *
 *
 * Sets @child as a child of @self
 */
static void 
register_child (SeahorseObject* self, SeahorseObject* child) 
{
	g_assert (SEAHORSE_IS_OBJECT (self));
	g_assert (SEAHORSE_IS_OBJECT (child));
	g_assert (self != child);
	g_assert (child->pv->parent == NULL);
	
	child->pv->parent = self;
	self->pv->children = g_list_append (self->pv->children, child);
}

/**
 * unregister_child:
 * @self: The parent
 * @child: child to remove
 *
 *
 * removes @child from the children list in @self
 */
static void 
unregister_child (SeahorseObject* self, SeahorseObject* child) 
{
	g_assert (SEAHORSE_IS_OBJECT (self));
	g_assert (SEAHORSE_IS_OBJECT (child));
	g_assert (self != child);
	g_assert (child->pv->parent == self);
	
	child->pv->parent = NULL;
	self->pv->children = g_list_remove (self->pv->children, child);
}

/**
 * set_string_storage:
 * @value: The value to store
 * @storage: The datastore to write the value to
 *
 * When storing, new memory will be allocated and the value copied
 *
 * Returns: TRUE if the value has been set new, FALSE else
 */
static gboolean
set_string_storage (const gchar *value, gchar **storage)
{
	g_assert (storage);

	if (value == NULL)
		value = "";
	
	if (!value || !*storage || !g_str_equal (value, *storage)) {
		g_free (*storage);
		*storage = g_strdup (value);
		return TRUE;
	}
	
	return FALSE;
}

/**
 * take_string_storage:
 * @value: The value to store
 * @storage: The datastore to write the value to
 *
 * When storing, the pointer to value is used. No new memory will be allocated
 *
 * Returns: TRUE if the value has been set new, FALSE else
 */
static gboolean
take_string_storage (gchar *value, gchar **storage)
{
	g_assert (storage);
	
	if (value == NULL)
		value = g_strdup ("");
	
	if (!value || !*storage || !g_str_equal (value, *storage)) {
		g_free (*storage);
		*storage = value;
		return TRUE;
	}
	
	g_free (value);
	return FALSE;
}

/**
 * recalculate_id:
 * @self: object to calculate for
 *
 * recalculates tag and identifier from id
 *
 */
static void
recalculate_id (SeahorseObject *self)
{
	const gchar *str;
	const gchar *at;
	GQuark tag;
	gchar *result;
	gsize len;

	/* No id, clear any tag and auto generated identifer */
	if (!self->pv->id) {
		if (!self->pv->tag_explicit) {
			self->pv->tag = 0;
			g_object_notify (G_OBJECT (self), "tag");
		}
			
		if (!self->pv->identifier_explicit) {
			if (set_string_storage ("", &self->pv->identifier))
				g_object_notify (G_OBJECT (self), "identifier");
		}
		
	/* Have hande, configure tag and auto generated identifer */
	} else {
		str = g_quark_to_string (self->pv->id);
		len = strlen (str);
		at = strchr (str, ':');
		
		if (!self->pv->tag_explicit) {
			result = g_strndup (str, at ? at - str : len);
			tag = g_quark_from_string (result);
			g_free (result);
			
			if (tag != self->pv->tag) {
				self->pv->tag = tag;
				g_object_notify (G_OBJECT (self), "tag");
			}
		}
		
		if (!self->pv->identifier_explicit) {
			if (set_string_storage (at ? at + 1 : "", &self->pv->identifier))
				g_object_notify (G_OBJECT (self), "identifier");
		}
	}
}

/**
 * recalculate_label:
 * @self: object to recalculate label for
 *
 * Recalculates nickname and markup from the label
 *
 */
static void
recalculate_label (SeahorseObject *self)
{
	if (!self->pv->markup_explicit) {
		if (take_string_storage (g_markup_escape_text (self->pv->label ? self->pv->label : "", -1),
		                         &self->pv->markup))
			g_object_notify (G_OBJECT (self), "markup");
	}

	if (!self->pv->nickname_explicit) {
		if (set_string_storage (self->pv->label, &self->pv->nickname))
			g_object_notify (G_OBJECT (self), "nickname");
	}
}

/**
 * recalculate_usage:
 * @self: The #SeahorseObject to recalculate the usage decription for
 *
 * Basing on the usage identifiere this function will calculate a usage
 * description and store it in the object.
 *
 */
static void
recalculate_usage (SeahorseObject *self)
{
	const gchar *desc;
	
	if (!self->pv->description_explicit) {
		
		switch (self->pv->usage) {
		case SEAHORSE_USAGE_SYMMETRIC_KEY:
			desc = _("Symmetric Key");
			break;
		case SEAHORSE_USAGE_PUBLIC_KEY:
			desc = _("Public Key");
			break;
		case SEAHORSE_USAGE_PRIVATE_KEY:
			desc = _("Private Key");
			break;
		case SEAHORSE_USAGE_CREDENTIALS:
			desc = _("Credentials");
			break;
		case SEAHORSE_USAGE_IDENTITY:
		    /*
		     * Translators: "This object is a means of storing items such as 
		     * name, email address, etc. that make up one's digital identity.
		     */
			desc = _("Identity");
			break;
		default:
			desc = "";
			break;
		}
		
		if (set_string_storage (desc, &self->pv->description))
			g_object_notify (G_OBJECT (self), "description");
	}
}


/* -----------------------------------------------------------------------------
 * OBJECT 
 */

/**
 * seahorse_object_init:
 * @self: The object to initialise
 *
 * Initialises the object with default data
 *
 */
static void
seahorse_object_init (SeahorseObject *self)
{
	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_OBJECT, 
	                                        SeahorseObjectPrivate);
	self->pv->label = g_strdup ("");
	self->pv->markup = g_strdup ("");
	self->pv->description = g_strdup ("");
	self->pv->icon = g_strdup ("gtk-missing-image");
	self->pv->identifier = g_strdup ("");
	self->pv->location = SEAHORSE_LOCATION_INVALID;
	self->pv->usage = SEAHORSE_USAGE_NONE;
}


/**
 * seahorse_object_dispose:
 * @obj: A #SeahorseObject to dispose
 *
 * Before this object is disposed, all it's children get new parents
 *
 */
static void
seahorse_object_dispose (GObject *obj)
{
	SeahorseObject *self = SEAHORSE_OBJECT (obj);
	SeahorseObject *parent;
	GList *l;
	
	if (self->pv->context != NULL) {
		seahorse_context_remove_object (self->pv->context, self);
		g_assert (self->pv->context == NULL);
	}
	
	if (self->pv->source != NULL) {
		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->source);
		self->pv->source = NULL;
	}
	
	if (self->pv->preferred != NULL) {
		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->preferred);
		self->pv->preferred = NULL;
	}

	/* 
	 * When an object is destroyed, we reparent all
	 * children to this objects parent. If no parent
	 * of this object, all children become root objects.
	 */

	parent = self->pv->parent;
	if (parent)
		g_object_ref (parent);
	
	for (l = self->pv->children; l; l = g_list_next (l)) {
		g_return_if_fail (SEAHORSE_IS_OBJECT (l->data));
		seahorse_object_set_parent (l->data, parent);
	}

	if (parent)
		g_object_unref (parent);
	
	g_assert (self->pv->children == NULL);
	
	/* Now remove this object from its parent */
	seahorse_object_set_parent (self, NULL);
	
	G_OBJECT_CLASS (seahorse_object_parent_class)->dispose (obj);	
}

/**
 * seahorse_object_finalize:
 * @obj: #SeahorseObject to finalize
 *
 */
static void
seahorse_object_finalize (GObject *obj)
{
	SeahorseObject *self = SEAHORSE_OBJECT (obj);
	
	g_assert (self->pv->source == NULL);
	g_assert (self->pv->preferred == NULL);
	g_assert (self->pv->parent == NULL);
	g_assert (self->pv->context == NULL);
	g_assert (self->pv->children == NULL);
	
	g_free (self->pv->label);
	self->pv->label = NULL;
	<commit_msg>Fix assertion when destroying object with children.<commit_after>/* 
 * Seahorse
 * 
 * Copyright (C) 2008 <NAME>
 * 
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.  
 */

#include "config.h"

#include "seahorse-object.h"

#include "seahorse-context.h"
#include "seahorse-source.h"

#include "string.h"

#include <glib/gi18n.h>

/**
 * _SeahorseObjectProps:
 * @PROP_0:
 * @PROP_CONTEXT:
 * @PROP_SOURCE:
 * @PROP_PREFERRED:
 * @PROP_PARENT:
 * @PROP_ID:
 * @PROP_TAG:
 * @PROP_LABEL:
 * @PROP_MARKUP:
 * @PROP_NICKNAME:
 * @PROP_DESCRIPTION:
 * @PROP_ICON:
 * @PROP_IDENTIFIER:
 * @PROP_LOCATION:
 * @PROP_USAGE:
 * @PROP_FLAGS:
 */
enum _SeahorseObjectProps {
	PROP_0,
	PROP_CONTEXT,
	PROP_SOURCE,
	PROP_PREFERRED,
	PROP_PARENT,
	PROP_ID,
	PROP_TAG,
	PROP_LABEL,
	PROP_MARKUP,
	PROP_NICKNAME,
	PROP_DESCRIPTION,
	PROP_ICON,
	PROP_IDENTIFIER,
	PROP_LOCATION,
	PROP_USAGE,
	PROP_FLAGS
};

/**
 * _SeahorseObjectPrivate:
 * @id: the id of the object
 * @tag: DBUS: "ktype"
 * @tag_explicit: If TRUE the tag will not be set automatically
 * @source: Where did the object come from ?
 * @context:
 * @preferred: Points to the object to prefer over this one
 * @parent: the object's parent
 * @children: a list of children the object has
 * @label: DBUS: "display-name"
 * @markup: Markup text
 * @markup_explicit: If TRUE the markup will not be set automatically
 * @nickname: DBUS: "simple-name"
 * @nickname_explicit: If TRUE the nickname will not be set automatically
 * @description:  Description text DBUS: "key-desc"
 * @description_explicit: If TRUE the description will not be set automatically
 * @icon: DBUS: "stock-id"
 * @identifier: DBUS: "key-id", "display-id", "raw-id"
 * @identifier_explicit:
 * @location: describes the loaction of the object (local, remte, invalid...)
 * @usage: DBUS: "etype"
 * @flags:
 * @realizing: set while the object is realizing
 * @realized: set as soon as the object is realized
 */
struct _SeahorseObjectPrivate {
	GQuark id;
	GQuark tag;
	gboolean tag_explicit;

	SeahorseSource *source;
	SeahorseContext *context;
	SeahorseObject *preferred;
	SeahorseObject *parent;
	GList *children;
	
    gchar *label;             
    gchar *markup;
    gboolean markup_explicit;
    gchar *nickname;
    gboolean nickname_explicit;
    gchar *description;
    gboolean description_explicit;
    gchar *icon;
    gchar *identifier;
    gboolean identifier_explicit;

    SeahorseLocation location;
    SeahorseUsage usage;
    guint flags;

	gboolean realized;
	gboolean realizing;
};

G_DEFINE_TYPE (SeahorseObject, seahorse_object, G_TYPE_OBJECT);

/* -----------------------------------------------------------------------------
 * INTERNAL 
 */

/**
 * register_child:
 * @self: The parent
 * @child: The new child
 *
 *
 * Sets @child as a child of @self
 */
static void 
register_child (SeahorseObject* self, SeahorseObject* child) 
{
	g_assert (SEAHORSE_IS_OBJECT (self));
	g_assert (SEAHORSE_IS_OBJECT (child));
	g_assert (self != child);
	g_assert (child->pv->parent == NULL);
	
	child->pv->parent = self;
	self->pv->children = g_list_append (self->pv->children, child);
}

/**
 * unregister_child:
 * @self: The parent
 * @child: child to remove
 *
 *
 * removes @child from the children list in @self
 */
static void 
unregister_child (SeahorseObject* self, SeahorseObject* child) 
{
	g_assert (SEAHORSE_IS_OBJECT (self));
	g_assert (SEAHORSE_IS_OBJECT (child));
	g_assert (self != child);
	g_assert (child->pv->parent == self);
	
	child->pv->parent = NULL;
	self->pv->children = g_list_remove (self->pv->children, child);
}

/**
 * set_string_storage:
 * @value: The value to store
 * @storage: The datastore to write the value to
 *
 * When storing, new memory will be allocated and the value copied
 *
 * Returns: TRUE if the value has been set new, FALSE else
 */
static gboolean
set_string_storage (const gchar *value, gchar **storage)
{
	g_assert (storage);

	if (value == NULL)
		value = "";
	
	if (!value || !*storage || !g_str_equal (value, *storage)) {
		g_free (*storage);
		*storage = g_strdup (value);
		return TRUE;
	}
	
	return FALSE;
}

/**
 * take_string_storage:
 * @value: The value to store
 * @storage: The datastore to write the value to
 *
 * When storing, the pointer to value is used. No new memory will be allocated
 *
 * Returns: TRUE if the value has been set new, FALSE else
 */
static gboolean
take_string_storage (gchar *value, gchar **storage)
{
	g_assert (storage);
	
	if (value == NULL)
		value = g_strdup ("");
	
	if (!value || !*storage || !g_str_equal (value, *storage)) {
		g_free (*storage);
		*storage = value;
		return TRUE;
	}
	
	g_free (value);
	return FALSE;
}

/**
 * recalculate_id:
 * @self: object to calculate for
 *
 * recalculates tag and identifier from id
 *
 */
static void
recalculate_id (SeahorseObject *self)
{
	const gchar *str;
	const gchar *at;
	GQuark tag;
	gchar *result;
	gsize len;

	/* No id, clear any tag and auto generated identifer */
	if (!self->pv->id) {
		if (!self->pv->tag_explicit) {
			self->pv->tag = 0;
			g_object_notify (G_OBJECT (self), "tag");
		}
			
		if (!self->pv->identifier_explicit) {
			if (set_string_storage ("", &self->pv->identifier))
				g_object_notify (G_OBJECT (self), "identifier");
		}
		
	/* Have hande, configure tag and auto generated identifer */
	} else {
		str = g_quark_to_string (self->pv->id);
		len = strlen (str);
		at = strchr (str, ':');
		
		if (!self->pv->tag_explicit) {
			result = g_strndup (str, at ? at - str : len);
			tag = g_quark_from_string (result);
			g_free (result);
			
			if (tag != self->pv->tag) {
				self->pv->tag = tag;
				g_object_notify (G_OBJECT (self), "tag");
			}
		}
		
		if (!self->pv->identifier_explicit) {
			if (set_string_storage (at ? at + 1 : "", &self->pv->identifier))
				g_object_notify (G_OBJECT (self), "identifier");
		}
	}
}

/**
 * recalculate_label:
 * @self: object to recalculate label for
 *
 * Recalculates nickname and markup from the label
 *
 */
static void
recalculate_label (SeahorseObject *self)
{
	if (!self->pv->markup_explicit) {
		if (take_string_storage (g_markup_escape_text (self->pv->label ? self->pv->label : "", -1),
		                         &self->pv->markup))
			g_object_notify (G_OBJECT (self), "markup");
	}

	if (!self->pv->nickname_explicit) {
		if (set_string_storage (self->pv->label, &self->pv->nickname))
			g_object_notify (G_OBJECT (self), "nickname");
	}
}

/**
 * recalculate_usage:
 * @self: The #SeahorseObject to recalculate the usage decription for
 *
 * Basing on the usage identifiere this function will calculate a usage
 * description and store it in the object.
 *
 */
static void
recalculate_usage (SeahorseObject *self)
{
	const gchar *desc;
	
	if (!self->pv->description_explicit) {
		
		switch (self->pv->usage) {
		case SEAHORSE_USAGE_SYMMETRIC_KEY:
			desc = _("Symmetric Key");
			break;
		case SEAHORSE_USAGE_PUBLIC_KEY:
			desc = _("Public Key");
			break;
		case SEAHORSE_USAGE_PRIVATE_KEY:
			desc = _("Private Key");
			break;
		case SEAHORSE_USAGE_CREDENTIALS:
			desc = _("Credentials");
			break;
		case SEAHORSE_USAGE_IDENTITY:
		    /*
		     * Translators: "This object is a means of storing items such as 
		     * name, email address, etc. that make up one's digital identity.
		     */
			desc = _("Identity");
			break;
		default:
			desc = "";
			break;
		}
		
		if (set_string_storage (desc, &self->pv->description))
			g_object_notify (G_OBJECT (self), "description");
	}
}


/* -----------------------------------------------------------------------------
 * OBJECT 
 */

/**
 * seahorse_object_init:
 * @self: The object to initialise
 *
 * Initialises the object with default data
 *
 */
static void
seahorse_object_init (SeahorseObject *self)
{
	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_OBJECT, 
	                                        SeahorseObjectPrivate);
	self->pv->label = g_strdup ("");
	self->pv->markup = g_strdup ("");
	self->pv->description = g_strdup ("");
	self->pv->icon = g_strdup ("gtk-missing-image");
	self->pv->identifier = g_strdup ("");
	self->pv->location = SEAHORSE_LOCATION_INVALID;
	self->pv->usage = SEAHORSE_USAGE_NONE;
}


/**
 * seahorse_object_dispose:
 * @obj: A #SeahorseObject to dispose
 *
 * Before this object is disposed, all it's children get new parents
 *
 */
static void
seahorse_object_dispose (GObject *obj)
{
	SeahorseObject *self = SEAHORSE_OBJECT (obj);
	SeahorseObject *parent;
	GList *l, *children;
	
	if (self->pv->context != NULL) {
		seahorse_context_remove_object (self->pv->context, self);
		g_assert (self->pv->context == NULL);
	}
	
	if (self->pv->source != NULL) {
		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->source);
		self->pv->source = NULL;
	}
	
	if (self->pv->preferred != NULL) {
		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->preferred);
		self->pv->preferred = NULL;
	}

	/* 
	 * When an object is destroyed, we reparent all
	 * children to this objects parent. If no parent
	 * of this object, all children become root objects.
	 */

	parent = self->pv->parent;
	if (parent)
		g_object_ref (parent);

	children = g_list_copy (self->pv->children);
	for (l = children; l; l = g_list_next (l)) {
		g_return_if_fail (SEAHORSE_IS_OBJECT (l->data));
		seahorse_object_set_parent (l->data, parent);
	}
	g_list_free (children);

	if (parent)
		g_object_unref (parent);
	
	g_assert (self->pv->children == NULL);
	
	/* Now remove this object from its parent */
	seahorse_object_set_parent (self, NULL);
	
	G_OBJECT_CLASS (seahorse_object_parent_class)->dispose (obj);	
}

/**
 * seahorse_object_finalize:
 * @obj: #SeahorseObject to finalize
 *
 */
static void
seahorse_object_finalize (GObject *obj)
{
	SeahorseObject *self = SEAHORSE_OBJECT (obj);
	
	g_assert (self->pv->source == NULL);
	g_assert (self->pv->preferred == NULL);
	g_assert (self->pv->parent == NULL);
	g_assert (self->pv->context == NULL);
	g_assert (self->pv->children == NULL);
	
	g_free (self->pv->label);
	self->pv->label = NULL;
	
{'fraction_non_alphanumeric': 0.14376024350269256, 'fraction_numerical': 0.002528681807539218, 'mean_word_length': 3.54189706507869, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 243, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5423452', 'n_tokens_mistral': 7758, 'n_tokens_neox': 7282, 'n_words': 2038}