stats package#

Subpackages#

Submodules#

stats.admin module#

class stats.admin.BranchAdmin(model, admin_site)#

Bases: ModelAdmin

class stats.admin.BranchInline(parent_model, admin_site)#

Bases: TabularInline

model#

alias of Branch

class stats.admin.CategoryAdmin(model, admin_site)#

Bases: ModelAdmin

class stats.admin.CategoryInline(parent_model, admin_site)#

Bases: TabularInline

model#

alias of Category

class stats.admin.DomainAdmin(model, admin_site)#

Bases: ModelAdmin

form#

alias of DomainForm

class stats.admin.DomainForm(*args, **kwargs)#

Bases: ModelForm

property media#

Return all media required to render the widgets on this form.

class stats.admin.DomainInline(parent_model, admin_site)#

Bases: StackedInline

form#

alias of DomainForm

formfield_for_dbfield(db_field, **kwargs)#

Hook for specifying the form Field instance for a given database Field instance.

If kwargs are given, they’re passed to the form Field’s constructor.

formfield_for_foreignkey(db_field, request, **kwargs)#

Get a form Field for a ForeignKey.

get_formset(request, obj=None, **kwargs)#

Return a BaseInlineFormSet class for use in admin add/change views.

model#

alias of Domain

class stats.admin.InformationInline(parent_model, admin_site)#

Bases: TabularInline

model#

alias of Information

class stats.admin.ModuleAdmin(model, admin_site)#

Bases: ModelAdmin

form#

alias of ModuleForm

formfield_for_dbfield(db_field, **kwargs)#

Hook for specifying the form Field instance for a given database Field instance.

If kwargs are given, they’re passed to the form Field’s constructor.

Given the HttpRequest, the parent ModelForm instance, the list of inline formsets and a boolean value based on whether the parent is being added or changed, save the related objects to the database. Note that at this point save_form() and save_model() have already been called.

class stats.admin.ModuleForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)#

Bases: ModelForm

property media#

Return all media required to render the widgets on this form.

save(**kwargs)#

Save this form’s self.instance object if commit=True. Otherwise, add a save_m2m() method to the form which can be called after the instance is saved manually at a later time. Return the model instance.

class stats.admin.PoFileAdmin(model, admin_site)#

Bases: ModelAdmin

class stats.admin.ReleaseAdmin(model, admin_site)#

Bases: ModelAdmin

copy_release(request, queryset)#

Copy an existing release and use master branches

delete_release(request, queryset)#

Admin action to delete releases with branches which are not linked to another release

class stats.admin.StatisticsAdmin(model, admin_site)#

Bases: ModelAdmin

stats.doap module#

exception stats.doap.DOAPElementNotFound#

Bases: Exception

When the DOAP element is not found in the DOAP Document.

exception stats.doap.DOAPFileParseError#

Bases: Exception

When the file cannot be parsed.

class stats.doap.DOAPMaintainer(name: str, email: str | None = None, account: str | None = None)#

Bases: object

class stats.doap.DOAPParser(doap_path: Path)#

Bases: object

Parser for DOAP files. A DOAP (Description of A Project) file describes, amongst other elements, the maintainers of the projects, the issue tracker, the root of the project, etc.

See the GNOME documentation about DOAP: https://wiki.gnome.org/Git/FAQ See the GitHub reference: https://github.com/ewilderj/doap (or Software Heritage: https://archive.softwareheritage.org/swh:1:dir:44cc2d8776dbb9dcab40d87211f59700a48991d9)

Raises:

DOAPFileParseError: when there is at least one error parsing the DOAP document.

property homepage: str#

Homepage of the project.

Raises:

DOAPElementNotFound: when no homepage is found in the DOAP document.

property maintainers: list[DOAPMaintainer]#

The maintainers, as a dictionary containing ‘name’, ‘email’ and ‘account’. Only the ‘name’ key is mandatory, reflecting the name of the contributor, but people are invited to fill the foaf:mbox and gnome:user_id elements.

Raises:

DOAPElementNotFound: when no maintainer is found in the DOAP document.

stats.doap.update_doap_infos(module: Module)#

Should only be called inside an “update-stats” context of a master branch, so there is no need for any extra checkout/locking strategy

stats.forms module#

class stats.forms.ModuleBranchForm(module, *args, **kwargs)#

Bases: Form

clean()#

Hook for doing any extra form-wide cleaning after Field.clean() has been called on every field. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field named ‘__all__’.

property media#

Return all media required to render the widgets on this form.

class stats.forms.ReleaseField(*args, **kwargs)#

Bases: ModelChoiceField

stats.models module#

class stats.models.Branch(*args, **kwargs)#

Bases: Model

Branch of a module as in any Version Control System. For instance with Git: https://git-scm.com/docs/git-branch

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

_get_pot_statistics_connected_to_domains(domain_primary_keys: list[int]) Collection[Statistics]#

POT Statistics object are objects without any language given.

Parameters:

domain_primary_keys (List[int]) – the domain primary keys for which to look for statistics

Returns:

a collection of Statistic objects

Return type:

QuerySet

_get_translation_statistics_connected_to_domains(domain_primary_keys: list[int]) Collection[Statistics]#

Language Statistics objects.

Parameters:

domain_primary_keys (List[int]) – the domain primary keys for which to look for statistics

Returns:

a collection of Statistic objects

Return type:

QuerySet

checkout()#

Do a checkout or an update of the VCS files

checkout_path#

Returns the path of the local checkout for the branch

cherrypick_commit(commit_hash: str) bool#

Try to cherry-pick a branch commit commit_hash into main branch.

Parameters:

commit_hash – the hash of the git commit in the same repository to cherry-pick.

Returns:

whether the cherry-picking succeeded or not.

clean()#

Checkout the branch and clear all the non-committed changes.

commit_po(po_file: Path, domain: Domain, language: Language, author: Person) str#

Commit the file ‘po_file’ in the branch VCS repository

Parameters:
  • po_file – the po file path to commit

  • domain – domain of the po file to commit

  • language – language of the po file

  • author – author of the commit

Returns:

the commit hash

property connected_domains: dict[str, Domain]#

Return all domains that this branch applies to.

delete_checkout()#

Remove the repository checkout.

documentation_statistics#

The documentation statistics. For the return format, see Branch.get_branch_statistics

domain_path(domain: Domain) Path#

Associated domain path. Concatenation of the Branch checkout path and the Domain base directory.

file_changed(file_path: Path) bool#

Determines if some file has changed based on its hash Always returns true if this is the first time the path is checked.

Parameters:

file_path (Path) – the release path in the checkout directory

Returns:

whether a file in the repository has changed.

Return type:

bool

get_documentation_statistics(mandatory_languages: tuple[Language] | None = ()) OrderedDict[str, list[StatisticsBase]]#

The documentation statistics in languages. For the return format, see Branch.get_branch_statistics

get_statistics(domain_type: str, mandatory_languages: Iterable[Language] = ()) OrderedDict[str, list[StatisticsBase]]#

Get statistics list of type domain_type (ui or doc), in a dict of lists, key is domain.name (POT in 1st position)

Parameters:
  • domain_type (str) – Domain.DOMAIN_TYPE_CHOICES. ‘ui’ or ‘doc’.

  • mandatory_languages (Iterable[Language]) – an iterable of Languages in which we wish statistics even if no translation exists.

Returns:

statistics list of type domain_type

Return type:

stats = {'po':      [potstat, polang1, polang2, ...],
         'po-tips': [potstat, polang1, polang2, ...]}

get_ui_statistics(mandatory_languages: tuple[Language] | None = ()) OrderedDict[str, list[StatisticsBase]]#

The user interface statistics in languages. For the return format, see Branch.get_branch_statistics

property has_string_frozen#

Indicates whether the branch is contained in at least one string frozen release.

property is_archive_only: bool#

Indicates whether the branch only appears in ‘archived’ releases.

is_domain_connected(domain: Domain) bool#

Indicates whether the domain is connected to the branch. A domain may apply on a branch if it’s connected to it.

property name_escaped: str#

Branch name suitable for including in file system paths.

output_directory(domain_type: str) Path#

Directory where generated pot and po files are written on local system

Parameters:

domain_type (str) – Domain.DOMAIN_TYPE_CHOICES. ‘ui’ or ‘doc’.

Returns:

where generated pot and po files are written on local system

Return type:

Path

save(update_statistics=True, **kwargs)#

Save the current instance. Override this in a subclass if you want to control the saving process.

The ‘force_insert’ and ‘force_update’ parameters can be used to insist that the “save” must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set.

ui_statistics#

The user interface statistics. For the return format, see Branch.get_branch_statistics

update_repository()#

Update existing repository checkout. This cleans the current changes and updates the repository with the latest changes.

Warning

the calling method should acquire a lock for the module to not mix checkouts in different threads/processes.

update_statistics(force: bool, checkout: bool = True, domain: Domain = None)#

Update statistics for all po files from the branch

vcs_web_file_url_root(ref=None)#

Root of the link to view a file in the VCS web interface. The path to the file needs to be added at the end to have the full link.

Parameters:

ref – the reference at which to view the file.

property vcs_web_log_url#

Link to browsable commit log

class stats.models.Category(id, release, branch, name)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

class stats.models.CategoryName(id, name)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

class stats.models.Domain(id, module, name, description, dtype, layout, pot_method, pot_params, extra_its_dirs, linguas_location, red_filter, branch_from, branch_to)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

property base_directory: str#

Directory where are stored all the PO files and the POT files in a ‘normal’ project structure.

commit_info(branch: Branch, language: Language) tuple[Path, bool, Path]#
Returns:

a 3-tuple:

  • absolute path to po file,

  • boolean telling if the file is new,

  • linguas_path -> if linguas edition needed, else None

Raises:

UnableToCommit – file cannot be committed.

doc_format(branch)#

Return a DocFormat instance, or None.

generate_pot_file(current_branch: Branch) tuple[str, tuple[tuple[str, Any]]]#

Return the pot file generated (in the checkout tree), and the error if any

Parameters:

current_branch – the module’s branch from which to refresh the POT file.

get_lang_files(base_path)#

Returns a list of language files on filesystem, as a list of tuples: [(lang, lang_file), …] -> lang_file as Path.

get_linguas(branch)#

Return a linguas dict like this: {‘langs’:[‘lang1’, lang2], ‘error’:”Error”}

get_po_path(locale)#

Return the relative filesystem path to the po file, existing or not.

pot_base() str#

Name of the generated pot file, without extension. (–default-domain for xgettext, –gettext-package for intltool)

For instance, ‘ui’, ‘gimp-help’, etc.

For GIMP specifically, there are subdomains as listed here: https://gitlab.gnome.org/GNOME/gimp, that are ‘po-python’ and, for instance, returned as ‘gimp-po-python’.

pot_generation_type(branch: Branch) str#

Get the POT generation method after inferring the auto method to extract messages.

class stats.models.FakeLangStatistics(pot_statistics: Statistics, language: Language)#

Bases: StatisticsBase

Statistics class for a non-existing lang stats. It renders the statistics based on what is found in the original POT statistics.

class stats.models.FakeSummaryStatistics(module, branch, dtype)#

Bases: object

Statistics class that sums up an entire module stats

class stats.models.Information(id, statistics, type, description)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

classmethod get_info_dict(lang)#

Return a dict (of lists) with all Information objects for a lang, with statistics_id as the key Used for caching and preventing db access when requesting these objects for a long list of stats

class stats.models.InformationArchived(id, statistics, type, description)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

class stats.models.Module(id, name, homepage, description, comment, bugs_base, vcs_root, vcs_web, ext_platform, archived)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

can_edit_branches(user)#

Returns True for superusers, users with adequate permissions or maintainers of the module

get_branches(reverse=False)#

Return module branches, in ascending order by default (descending order if reverse == True)

get_head_branch() Branch#

Returns the HEAD (trunk, master, …) branch of the module

reset_hard()#

Remove all module checkouts and re-create them.

class stats.models.ModuleLock(mod)#

Bases: object

Weird things happen when multiple updates run in parallel for the same module We use filesystem directories creation/deletion to act as global lock mechanism

class stats.models.PoFile(id, path, updated, translated, fuzzy, untranslated, figures, translated_words, fuzzy_words, untranslated_words)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

fig_count()#

If stat of a document type, get the number of figures in the document

class stats.models.Release(id, name, description, string_frozen, status, weight)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

get_global_stats()#

Get statistics for all languages in a release, grouped by language Returns a sorted list: (language name and locale, ui, ui-part and doc stats dictionaries)

get_lang_files(lang, dtype)#

Return a list of all po files of a lang for this release, preceded by the more recent modification date It uses the POT file if there is no po for a module

get_lang_stats(lang)#

Get statistics for a specific language, producing the stats data structure Used for displaying the language-release template

classmethod total_by_releases(dtype, releases)#

Get summary stats for all languages and releases

Returns:

stats dict with each language locale as the key

Return type:

stats{
  'll': {'lang': <language object>,
         'stats': [percentage for release 1, percentage for release 2, ...],
         'diff': difference in % between first and last release,
        }
  'll': ...
}

total_for_lang(lang)#

Returns total translated/fuzzy/untranslated strings for a specific language

total_part_for_all_langs()#

Return total partial UI strings for each language

total_part_for_lang(lang, all_pots=None, all_stats_d=None)#

For partial UI stats, the total number can differ from lang to lang, so we are bound to iterate each stats to sum it

total_strings()#

Returns the total number of strings in the release as a tuple (doc_total, ui_total)

class stats.models.Statistics(id, branch, domain, language, full_po, part_po)#

Bases: Model, StatisticsBase

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

get_figures()#

Return an enriched list of figure dicts (used in module_images.html): [{‘path’:, ‘hash’:, ‘fuzzy’:, ‘translated’:, ‘translated_file’:}, …]

classmethod get_lang_stats_by_type(lang, dtype, release)#

Cook statistics for an entire release, a domain type dtype and the language lang.

Returns:

stats dictionary

Return type:

stats = {
    'dtype':dtype, # 'ui' or 'doc'
    'total': 0,
    'totaltrans': 0,
    'totalfuzzy': 0,
    'totaluntrans': 0,
    'totaltransperc': 0,
    'totalfuzzyperc': 0,
    'totaluntransperc': 0,
    'categs': {  # OrderedDict
        <categkey>: {
            'catname': <catname>, # translated category name
            'cattotal': 0,
            'cattrans': 0,
            'catfuzzy': 0,
            'catuntrans': 0,
            'cattransperc': 0,
            'modules': { # OrderedDict
                <module>: {
                    <branchname>:
                        [(<domname>, <stat>), ...], # List of tuples (domain name, Statistics object)
                               # First element is a placeholder for a FakeSummaryStatistics object
                               # only used for summary if module has more than 1 domain
                    }
                }
            }
        }
    },
    'all_errors':[]
}

get_type()#

Returns the type of the domain (ui, docbook, mallard)

most_important_message()#

Return a message of type 1.’error’, or 2.’warn, or 3.’warn

po_path(potfile=False, reduced=False)#

Return path of (merged) po file on local filesystem

po_url(pot_file=False, reduced=False)#

Return URL of (merged) po file, e.g. for downloading the file

pot_stats_summary() str#

Returns a string with the statistics of the po file. For instance: (20 messages — 0 words, 2 figures) — updated 09/09/2015 18:27+0000

update_statistics(file_path=None)#

Update the Statistics instance with the gettext stats of the target po/pot file. Also try to generate a “reduced” po file.

vcs_web_path()#

Return the Web interface path of file on remote vcs

class stats.models.StatisticsArchived(id, module, type, domain, branch, language, date, translated, fuzzy, untranslated)#

Bases: Model

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

exception stats.models.UnableToCommit#

Bases: Exception

stats.potdiff module#

class stats.potdiff.FileLocation(location: str)#

Bases: object

A location in a file.

property display_str#

The string representation to display the location.

The returning format is:

path:line

The link to the location, with the given prefix.

The returning format is:

prefix/path#Lline

markdown(link_prefix: str)#

The markdown representation of the location.

The returning format is:

[display_str](link)

class stats.potdiff.PoDiffState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)#

Bases: Enum

class stats.potdiff.PoEntry(unit: pounit, diff_state: PoDiffState)#

Bases: object

An entry in a PO/POT file.

property display_str#

The string representation to display the entry.

It also supports msgctxt (GNU gettext 0.15) and plural forms, the returning format is:

[msgctxt::]msgid[/msgid_plural]

markdown(location_link_prefix: str)#

The markdown representation of the entry, including the location.

The returning format is:

display_str (location.markdown{, location.markdown…})

class stats.potdiff.PoFileDiffStatus(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)#

Bases: Enum

stats.repos module#

class stats.repos.GitRepository(branch: Branch)#

Bases: VCSRepository

static _clean_repository(working_directory: str)#

Try to reset the git repository to a usable state

static _reset_repository_using_remote_branch(working_directory: str, branch_name: str)#

Reset the repository to match what’s present on origin/branch_name

commit_files(files: list[Path], message: str, author: Person = None) str#

Commit the files using the message as commit message and the person as author of this commit.

Returns:

the hash of the resulting commit

class stats.repos.VCSRepository(branch: Branch)#

Bases: ABC

class stats.repos.VCSRepositoryType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)#

Bases: Enum

stats.signals module#

stats.utils module#

class stats.utils.Notification#

Bases: ABC

class stats.utils.StringFreezeBreakNotification(branch, new_entries: list[PoEntry])#

Bases: Notification

class stats.utils.StringFreezeBreakNotifier#

Bases: ABC

An abstract base class to implement string freeze break notification.

class stats.utils.StringFreezeBreakNotifierOnGitLab#

Bases: StringFreezeBreakNotifier

Implementation of a tool to notify user that a string freeze break occurred. It uses the GitLab API.

exception stats.utils.UndetectableDocFormat#

Bases: Exception

stats.utils.add_custom_header(po_path, header, value)#

Add a custom po file header

stats.utils.check_po_conformity(pofile)#

Return errors/warnings about pofile conformity.

stats.utils.check_po_quality(pofile, filters)#

Check po file quality with the translate-toolkit pofilter tool. http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/pofilter.html

stats.utils.check_potfiles(po_path)#

Check if there were any problems regenerating a POT file (intltool-update -m). Return a list of errors

stats.utils.check_program_presence(prog_name)#

Test if prog_name is an available command on the system

stats.utils.collect_its_data()#

Fill a data directory with *.loc/*its files needed by gettext to extract XML strings for GNOME modules.

stats.utils.exclude_untrans_messages(potfile)#

Exclude translatable strings matching some translator comments.

stats.utils.generate_doc_pot_file(branch: Branch, domain: Domain) tuple[str, list[tuple[str, str]]]#

Return the pot file for a document-type domain, and the error if any

stats.utils.get_doc_linguas(branch, subdir)#

Get language list in one Makefile.am (either path)

stats.utils.get_fig_stats(pofile, doc_format)#

Extract image strings from pofile and return a list of figures dict: [{‘path’:, ‘hash’:, ‘fuzzy’:, ‘translated’:}, …]

stats.utils.get_ui_linguas(branch, subdir)#

Get language list in one of po/LINGUAS, configure.ac or configure.in

stats.utils.po_file_statistics(pofile)#

Compute pofile translation statistics.

stats.utils.read_linguas_file(full_path)#

Read a LINGUAS file (each language code on a line by itself)

stats.utils.sort_object_list(lst, sort_meth)#

Sort an object list with sort_meth (which should return a translated string)

stats.utils.url_join(base, *args)#

Create an url in joining base with arguments. A lot nicer than urlparse.urljoin!

stats.views module#

stats.views.can_refresh_branch(user)#

Return True if user is authorized to force statistics refresh

stats.views.dynamic_po(request, module_name, branch_name, domain_name, filename)#

Generates a dynamic po file from the POT file of a branch

stats.views.module_branch(request, module_name, branch_name)#

This view is used to dynamically load a specific branch stats (jquery.load)

Module contents#